1 pontos por GN⁺ 2024-01-23 | 1 comentários | Compartilhar no WhatsApp
  • O app pessoal de radar para iOS Aviator 2.0 voltou a funcionar depois da falha do OpenSky Network que vinha desde o início de dezembro, e a atualização também corrige de uma vez vários incômodos percebidos no uso real
  • O novo menu de controles usa uma estrutura de divulgação progressiva para separar as ações principais das ferramentas avançadas, e foi montado com modal detent do SwiftUI e interação com o plano de fundo para cobrir menos a tela do radar
  • O problema de detectar aeronaves distantes demais foi reduzido com um toggle binário de zoom, implementado mudando a distância da câmera do MapKit para 70 km ou 100 km
  • Usando os dados origin_country, altitude e category da API do OpenSky Network, foram adicionados exibição de bandeiras, filtro de baixa altitude para dias nublados e ícones distintos para helicópteros, satélites e tamanhos de aeronaves
  • O usuário pode usar as credenciais do OpenSky Network com autenticação HTTP Basic, mas na versão 2.0 a senha fica salva em User Defaults, então é melhor não reutilizar senhas sensíveis

Contexto da atualização do Aviator 2.0

  • Aviator — Radar on your Phone é um app de radar para iOS criado para procurar aviões com o filho
  • Depois do texto anterior, até daria para pensar em um novo lançamento e em oportunidades de monetização, mas desde o início de dezembro o app estava exibindo erro para os usuários por causa de uma falha no OpenSky Network
  • Ao abrir o app de novo, em vez do erro 502 que aparecia sempre, o som de alerta de detecção de avião confirmou que tudo tinha voltado ao normal
  • Depois disso, o trabalho no Aviator 2.0 avançou ao longo de duas noites com ideias que já estavam sendo consideradas

Nova UI de controles que cobre menos o radar

  • Na versão 2.0, os controles foram movidos para um menu separado, com as ações importantes na frente e as ferramentas avançadas menos usadas posicionadas mais abaixo
  • Essa estrutura usa divulgação progressiva (progressive disclosure)
  • O menu é implementado como um modal do SwiftUI com dois presentationDetents
    • primary: 0.15 da altura da tela
    • extended: 0.4 da altura da tela
  • O indicador de arraste mostra que o menu pode ser expandido, e presentationBackgroundInteraction(.enabled) evita que a UI principal do radar fique coberta pela sombra
  • Em presentationBackground, foi aplicado o efeito emboss de Paul Hudson para dar uma textura metálica de painel de radar real
  • Na versão 2.1, o plano é usar TipKit para que até usuários jovens da Apple percebam melhor a estrutura de divulgação progressiva

Ajuste de nível de zoom e alcance do radar

  • Na versão 1.0, o radar funcionava até bem demais e detectava aeronaves que estavam além do horizonte ou atrás do relevo, portanto invisíveis na prática
  • Em ambientes como os subúrbios de Londres, com relevo em degraus e áreas conectadas como ilhas, isso acabava atrapalhando o uso real
  • Como em espaços abertos era possível ver aviões bem distantes, não era só uma questão simples de sensibilidade
  • A solução foi adicionar uma função de zoom
  • O zoom da superfície é implementado passando distance em metros para a camera do SDK do MapKit
    • quando zoomed é true: 70 * 1_000
    • quando é false: 100 * 1_000
  • Para implementar rápido a tempo do lançamento de fim de semana, um dos círculos do radar foi removido para destacar a UI ampliada
  • No começo, a ideia era usar um Slider para o nível de zoom, mas a taxa de quadros não ficou boa nem em chip A17, então por enquanto foi adotado um toggle binário de zoom

Recursos adicionados com dados do OpenSky Network

  • Exibição de bandeiras

    • A API do OpenSky Network coleta várias informações dos transponders das aeronaves, mas a versão 1.0 não aproveitava bem esses dados
    • Na versão 2.0, foi adicionado um toggle para mostrar o emoji de bandeira do país de origem abaixo de cada ícone de avião
    • A implementação se baseia no valor de origin_country
    • O app recebe a string de texto do país de origem fornecida pela API
    • Depois converte isso para um código de país de 2 letras usando uma lista de nomes de países encontrada online
    • Em seguida, transforma o código do país em escalares Unicode para montar o emoji de bandeira
    • Quando o usuário ativa o recurso, flight.flag é mostrado como texto da annotation do MapKit
  • Modo dia nublado

    • Em dias nublados no Reino Unido, boa parte dos aviões mostrados no app ficava escondida pelas nuvens e não podia ser vista de verdade
    • Foi adicionado um botão para ocultar aeronaves mais altas, permitindo alternar entre modo céu limpo e modo chuvoso
    • O recurso usa os dados de altitude recebidos do OpenSky Network e considera 2,5 km como base de nuvens baixas
    • Se geo_altitude < 2500.0, então isLowAltitude passa a ser true
    • Quando a configuração cloudy está ativada, só aeronaves de baixa altitude aparecem nas annotations do MapKit

Melhorias nos ícones de aeronaves

  • Durante testes no parque, um helicóptero passou bem acima, mas o Aviator o mostrou com um ícone de avião comum
  • A API do OpenSky Network fornece a propriedade category, que indica o tipo de aeronave ao qual o transponder pertence, se forem adicionados parâmetros de consulta
  • Essa categoria pode incluir itens como:
    • aeronaves leves com menos de 15.500 libras
    • aeronaves pesadas com mais de 300.000 libras
    • aeronaves de asa rotativa, como helicópteros
    • veículos espaciais/transatmosféricos
    • paraquedas ou paraquedistas
  • Na atualização mais recente, foram diferenciadas as classes de tamanho de aeronave, e satélites e helicópteros passaram a ter ícones separados
  • No enum AircraftCategory, os valores de imagem, emoji e escala foram separados
    • rotorcraft usa o SFSymbol xmark.circle.fill
    • spaceTransatmospheric usa o emoji 🛰️
    • small, large e heavy aplicam escalas 0.6, 1 e 1.5, respectivamente
  • O emoji de helicóptero ficou arredondado demais quando convertido para uma forma plana monocromática, então foi escolhido um SFSymbol mais abstrato, com uma cruz dentro de um círculo
  • Para tratar o emoji como imagem, foi feito o scaling de Text e depois usado como máscara de um Rectangle, com aplicação de cor e efeito de tela CRT

Login do usuário no OpenSky Network

  • Foi adicionada a função para o usuário inserir diretamente as credenciais do OpenSky Network
  • Esse era um dos recursos mais pedidos depois da versão para Android, com o objetivo de evitar o rate limiting no uso não autenticado da API
  • O menu completo de controles permite inserir a conta e também oferece um link para a página de cadastro
  • A implementação usa TextField e SecureField do SwiftUI
    • @AppStorage("username")
    • @AppStorage("password")
  • Na versão 2.0, por ter sido colocado rapidamente em produção, a senha é salva em User Defaults
  • A próxima versão deve armazená-la no Keychain, e por enquanto o ideal é não reutilizar senhas sensíveis
  • O nome de usuário e a senha informados são codificados em Base64 e enviados no cabeçalho Authorization das requisições da API com autenticação Basic

Encerramento

  • O Aviator 2.0 é uma atualização que continua aprimorando um app para brincar com o filho
  • O autor pede ideias de recursos e dicas de ASO nos comentários, além de solicitar download e avaliação do Aviator — Radar on your Phone 2.0

1 comentários

 
GN⁺ 2024-01-23
Opiniões no Hacker News
  • Continuação de um post que fez bastante sucesso dois meses atrás
    0: https://news.ycombinator.com/item?id=38435908 My toddler loves planes, so I built her a radar (1304 points, 56 days ago)

  • Ao ver o app, lembrei de um problema que eu enfrentava na época em que programava DVDs. Em botões de alternância, não fica claro qual modo está ativo no momento
    Fica confuso se o ícone da bandeira ou da nuvem mostra o modo atual, ou se é preciso tocar nele para mudar para esse modo. O alternador do tempo também dá a sensação inversa: tocar na nuvem significa que quero ver o modo nublado, ou que quero trocar para uma tela ensolarada?
    No projeto em que estou trabalhando agora, os botões +/- ajustam o tamanho da janela do intervalo de tempo; no horário inicial, o + reduz o valor dos segundos e o - aumenta. No horário final, é o contrário. Do ponto de vista do tamanho da janela, ambos se comportam como esperado; no fim, é preciso deixar clara a perspectiva do usuário

    • Esta é a parte da UX moderna que eu mais odeio, e é especialmente ruim em apps de TV. Se, entre dois itens de menu, um está em branco em negrito e o outro em preto em negrito, não sei no que estou prestes a clicar
      O alternador de legendas do YouTube também fica alternando entre texto branco em fundo preto e texto preto em fundo branco; então primeiro eu aperto e, se a boca está se mexendo mas não vejo legendas, tenho que tentar o outro modo do ícone
      Parece que, com a transição para telas sensíveis ao toque, desapareceu o bom senso sobre feedback de entrada posicional com estado
    • A crítica é justa. Acho que fiquei um pouco preso em fazer parecer um painel de controle, em vez de melhorar a UX
      E, além disso, estava mesmo confuso. Num conserto de bug de última hora, acabei publicando o ícone de nuvem invertido em relação aos outros
  • Seria muito legal se, quando a varredura do radar passasse por um avião, ele piscasse e então fosse desaparecendo aos poucos, com a posição fixa, até a próxima varredura
    Também seria bom usar a altitude e a posição GPS atuais do dispositivo e, com os prédios, morros e elevações ao redor no OpenStreetMap, calcular o skyline visível por azimute. Aí isso poderia ser exibido no mapa como uma espécie de bloqueio de radar. Algo como um sonar de pesca passando por troncos, ou um radar naval com embarcações ocultadas por outros navios
    Se fizerem isso, o pessoal da área vai ficar coçando a cabeça tentando entender como o celular faz uma varredura radial
    [1] https://www.researchgate.net/figure/Occlusion-percentage-for...

    • Todas essas ideias são ótimas. O app atual está mais para uma versão de Pareto de uma versão 100% completa potencialmente possível
  • É algo que comentei no blog: como pai/mãe de criança pequena, concordo que a parte de escolher cores é a mais importante
    Como é um projeto paralelo divertido, tenho algumas ideias de recursos que talvez ainda não tenham sido implementados. Primeiro, uma visualização ao vivo usando a câmera do celular e os recursos de AR do iPhone para marcar um ponto na posição aproximada da aeronave. Já cheguei a escrever um pouco de código para calcular isso com base na localização do usuário e nas informações ADS-B
    Segundo, também daria para marcar a aeronave como “vista” ou “perdida” e usar esse feedback para ajustar o que é exibido
    Terceiro, distintivos e estatísticas. Se sua filha for parecida com meu filho/minha filha, ela vai gostar de ganhar distintivos no app. Seria possível salvar observações anteriores em um banco de dados local e acompanhar coisas como “número de companhias aéreas vistas”, “número de tipos de aeronaves vistos”, “maior tempo de voo”, “menor tempo de voo”. Dito isso, entendo muito bem os problemas de gamificar um app voltado para crianças

    • Pode soar meio antiquado, mas tento repetir sempre para minha filha que espero que ela queira ser produtora de tecnologia, não apenas consumidora
      Conversamos com frequência sobre por que não se deve gastar 30 dólares em moedas digitais como Robux. Explico que isso é diferente de objetos com valor real, como uma raquete de tênis ou um par de tênis
      Por isso resisto à gamificação e tento dar ferramentas para que ela não seja sugada por horas de tarefas repetitivas em busca de distintivos ou artefatos digitais sem valor
      Se for um app para crianças, eu preferiria não incluir esse tipo de recurso. Dá para mostrar que existem apps sem anúncios e sem gamificação que ainda assim acrescentam valor real à vida
    • Muito obrigado pelas ideias. Para a número 1, fico imaginando se consigo arrumar um Vision Pro
  • Será que alguém do HN toparia fazer um projeto open source e crowdsourced para portar isso para Android?
    A licença é só um palpite, mas acho que quem criar o repositório inicial no GitHub poderia usar a frase do autor: “estou esperando que um engenheiro Android empreendedor faça o porte por conta própria. Coloquei detalhes suficientes no texto. Pode fazer, desde que seja oferecido gratuitamente para todos”

    • Obrigado pela sugestão. Nunca criei um app mobile, mas tenho vontade de aprender
      Mesmo que eu não consiga contribuir com um app Android de alta qualidade para este app de radar, acho que valeria a pena dedicar tempo a portar algo alinhado ao paradigma “An app can be a home-cooked meal”[0]. Como ele é construído com uma visão e um paradigma únicos, sem inchaço, anúncios, rastreamento etc., é provável que o código seja fácil de entender
      Essa sugestão talvez possa me levar de volta ao prazer de programar
      0: https://news.ycombinator.com/item?id=38877423
    • Não tenho fôlego para manutenção de longo prazo, mas acho que posso contribuir um pouco. Meu e-mail está no perfil
  • Mudando um pouco de assunto, como alguém com péssimo senso de direção, a função mais importante no celular para mim é o quão precisamente a setinha no mapa mostra para que lado estou olhando
    Uso Android e, quando ele não tem certeza, mostra um cone de incerteza azul, e às vezes pede para eu calibrar movendo o celular em forma de 8 ou apontando para prédios ao redor
    Tecnicamente, qual é a limitação aqui? O iPhone é melhor que Android? O problema está no hardware, no acelerômetro, na bússola, no sinal de GPS ou no software? Ainda me confundo com bastante frequência, porque o cone aparece apontando para o lado errado. Se o iPhone for claramente melhor nisso, é algo importante a ponto de eu quase trocar

    • Fico feliz que você tenha dito isso. Também fiz a mesma observação no texto original
      Achei que haveria alguma limitação do lado do GPS, mas o delegate de direção do CoreLocation retorna a direção perfeitamente, pelo menos na taxa de quadros de 120 Hz do meu dispositivo
      Talvez o Google Maps simplesmente não seja muito bom
    • Como alguém que usa os dois com frequência parecida, o Android tende a repassar os valores brutos dos sensores, enquanto o iOS parece aplicar algum tipo de atraso de debounce e estimativa
      Nos dois, os valores de direção erram com frequência semelhante. Mas isso é só uma impressão baseada na experiência de uso, não um fato definitivo
    • Produtos da Apple e animações em geral aplicam mais suavização e histerese. Parece que escondem a precisão do usuário para evitar que a seta fique tremendo muito, enquanto a UI do Android parece mostrar mais diretamente os artefatos gerados pela fusão ruidosa de GPS/IMU e pela imprecisão inerente do magnetômetro
      Em versões antigas do iOS, a seta lenta incomodava bastante; agora, com o hardware mais rápido, a seta saltitante de outras plataformas chama mais atenção
      Em resumo, a maior parte do hardware moderno tem capacidades parecidas para saber com bastante precisão sua posição no espaço e no tempo. Mas o quão bem ele faz navegação estimada e estimativa de atitude com os dados atuais, e como trata a filtragem de ruído que o usuário espera quando segura o aparelho na mão, varia conforme o software de navegação
  • Entrei no heavy metal por causa dos jogos Tony Hawk. Motörhead, “Ace of Spades”, no THPS3, e Iron Maiden, “Number of the Beast”, no THPS4, foram o gatilho; então pode existir um caminho de migalhas de pão dos jogos de plataforma até o heavy metal

  • Mandou bem por ter deixado claramente feliz a usuária mais importante

  • Muito legal. Além disso, deu vontade de colocar um !remindme para conferir daqui a 18 anos se sua filha passou no exame de controle de tráfego aéreo

    • Ela tem 2 anos agora, e uma licença de piloto estudante pode ser obtida a partir dos 16, então basta configurar o lembrete para daqui a 14 anos
    • Se sua filha virar piloto, dá para ganhar voos grátis? Talvez você esteja perdendo uma oportunidade de conduzi-la discretamente para STEM
  • Fico pensando se, mesmo no mundo pós-11 de setembro, crianças ainda podem ser convidadas para a cabine de comando

    • Meu pai era piloto, e nossas férias em família costumavam ser ajustadas à escala de voos dele. Quando eu era criança, nada me deixou mais orgulhoso do que ser convidado para a cabine depois do pushback para “dar partida nos motores”
      Tenho uma lembrança vaga de apertar um botão e de meu pai apontar os instrumentos em movimento. Mas a sensação de voltar para o meu assento me sentindo a criança mais importante do mundo é nítida
      Depois do 11 de setembro, isso certamente ficou difícil de acontecer
    • Vi uma dica na internet dizendo que, se a criança quiser ver a cabine, é melhor não perguntar antes da decolagem. Nesse momento os pilotos têm muito a fazer com checklists e preparativos
      Por outro lado, se perguntar depois do pouso se a criança pode ver a cabine, a chance de dar certo é bem maior
    • Nossos filhos entraram na cabine mesmo depois do 11 de setembro. Mas precisa ser antes da decolagem
      Durante o voo, quase nem a tripulação entra, e às vezes só o chefe de cabine pode entrar. As crianças perguntam ao embarcar, se a porta da cabine ainda estiver aberta
    • Em 1º de janeiro de 2024, uma criança de seis anos foi convidada pela primeira vez para a cabine. Até aquele momento eu tinha a mesma dúvida
      Foi em um voo doméstico da JetBlue nos EUA
    • Já vi isso acontecer enquanto estávamos no portão. Os pilotos normalmente deixam a porta aberta, então dá para chegar e falar com eles. Na pior das hipóteses, você recebe um não; vale a pena perguntar
      Ainda tenho em algum lugar um broche de asas da Delta que ganhei quando era criança, depois de ver a cabine durante uma viagem em rota. Foi uma experiência incrível de que ainda me lembro, e espero que outras crianças possam viver ao menos parte disso