Skip to content

fix(web): Safari entra em servidores por IP, toca a voz e mostra os emojis - #886

Merged
lucastaonline merged 1 commit into
mainfrom
lucastaonline-safari-versao-web
Nov 5, 2026
Merged

lucastaonline merged 1 commit into
mainfrom
lucastaonline-safari-versao-web

Conversation

@lucastaonline

Copy link
Copy Markdown
Collaborator

Closes #883

O problema

No Safari, a versão web não entrava no servidor do convite (wss://147.15.118.243:3000), que funcionava no Edge e no Firefox. Reproduzi no Safari 26.3 real, via safaridriver, e encontrei três bugs do Safari em sequência.

1. WebSocket para IP preso em CONNECTING (bug do WebKit 26)

Um new WebSocket() para um host que é um IP literal fica para sempre em CONNECTING sem enviar o SYN: o pcap não mostra nenhum tráfego. Com nome DNS funciona. É um bug conhecido do WebKit (bug 308073, Apple Forums 817697). Já descartei com evidência certificado, CSP, WebCrypto/IDB, servidor e Retransmissão Privada do iCloud.

Contorno: criar um 2º WebSocket para a mesma URL e fechá-lo de imediato destrava o principal. Fechado antes de conectar, ele não manda nada ao servidor: o pcap mostra um único SYN e o servidor registra uma única conexão. O contorno só é aplicado em WebKit que não seja Chromium, com host IP e fora do loopback.

  • NetworkClient.ts: needsWebKitIpSocketNudge e o socket companheiro em connect().
  • serverAddress.ts: nova isIpLiteralHost.

2. Voz conectava, mas não se ouvia ninguém

RemoteMediaRouter.routeAudioOutput lançava Audio output selection unavailable quando AudioContext.setSinkId não existe (o Safari não tem). Isso acontecia antes do play()/resume(). Removi essa checagem: o grafo já toca na saída padrão. O setAudioOutputSink continua recusando uma saída específica sem a API, e nesse caso a seleção reverte, como antes.

3. Seletor de emoji abria vazio

O Safari não tem requestIdleCallback/cancelIdleCallback. O novo utils/idleCallback.ts usa a API nativa quando ela existe; senão, faz fatias de até 8 ms via setTimeout. O helper devolve a função de cancelamento.

Testes

  • Novos testes de regressão, cada um confirmado falhando sem a correção:
    • networkClient.test.ts: socket companheiro no WebKit com IP; socket único no Chromium, com nome DNS e em loopback.
    • serverAddress.test.ts: isIpLiteralHost.
    • voiceConnection.test.ts: voz remota toca sem AudioContext.setSinkId.
    • idleCallback.test.ts: fallback e cancelamento.
    • settingsNavigationSmoke.cjs (Electron/DOM): sem as APIs de idle, o seletor lista e desenha todos os emojis.
  • Comandos rodados localmente (macOS):
  • E2E no Safari 26.3 real, com servidor descartável desta branch por IP de LAN com TLS e um 2º participante no Chromium:
    • entrou no servidor, viu os canais e mandou mensagem;
    • conectou na voz e o áudio remoto tocou (<audio> não pausado, sem warnings);
    • o seletor desenhou os 1898 emojis.

Não testado: iPhone/iPad (mesmo WebKit, deve se beneficiar) e Windows (sem impacto: o contorno só ativa em WebKit que não seja Chromium).

Fora do escopo: o Safari ainda bloqueia o som de "entrar na voz" pela política de autoplay. É só um aviso no console.

Nota de release: release-notes/883-safari-web.json. Não muda o PROTOCOL_VERSION.

…mojis

- WebKit 26 deixa o WebSocket para um IP literal preso em CONNECTING sem enviar SYN;
  um segundo socket para a mesma URL, fechado na hora, destrava o primeiro (#883).
- A voz remota não tocava porque o roteamento exigia AudioContext.setSinkId,
  que o Safari não tem; a saída padrão já funciona sem ele.
- O seletor de emoji abria vazio sem requestIdleCallback; um fallback com
  setTimeout desenha os glifos em fatias curtas.

Closes #883

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lucastaonline
lucastaonline merged commit 666036e into main Nov 5, 2026
39 of 42 checks passed
@lucastaonline
lucastaonline deleted the lucastaonline-safari-versao-web branch November 5, 2026 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Versão web: Safari não consegue entrar no servidor

1 participant