diff --git a/README.md b/README.md index 4309c43..31a8db5 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,13 @@ Os ícones e o ecrã de arranque são gerados a partir de `assets/icon-mark.svg` `npm run build` gera um site estático em `dist/` que funciona em qualquer servidor (caminhos relativos) e offline depois da primeira visita (service worker). No Android, o Chrome permite "Adicionar ao ecrã principal" para jogar como uma app. +### iPhone / iPad + +A versão web funciona no Safari do iOS (iOS 14.5 ou mais recente). Para jogar em ecrã inteiro e sem internet: abrir o site no **Safari → Partilhar → Adicionar ao ecrã principal**. + +- Não há vibração (o iOS não deixa as páginas web vibrar). +- Com o iPhone em **modo silencioso** não há som — é o próprio iOS que silencia os jogos web. +- A web não consegue fixar a rotação do ecrã: se o iPhone rodar ao pousá-lo na mesa, ativem o **bloqueio de rotação** no Centro de Controlo. +- O zoom com dois dedos está bloqueado no jogo, para que dois toques ao mesmo tempo não sejam confundidos com um "beliscar". + O workflow *Publicar versão web* publica automaticamente no **GitHub Pages** a cada push para `main`. Para isso ficar ativo, é preciso ir uma vez a **Settings → Pages → Source** e escolher **GitHub Actions**. diff --git a/src/audio.ts b/src/audio.ts index 79107da..b4bb058 100644 --- a/src/audio.ts +++ b/src/audio.ts @@ -19,7 +19,9 @@ function ac(): AudioContext | null { master.gain.value = 0.5; master.connect(ctx.destination); } - if (ctx.state === 'suspended') void ctx.resume(); + // iOS can leave the context "suspended" or "interrupted" (after a call, the lock screen…). + const state = ctx.state as string; + if (state === 'suspended' || state === 'interrupted') ctx.resume().catch(() => undefined); return ctx; } diff --git a/src/main.ts b/src/main.ts index 389927c..e737afe 100644 --- a/src/main.ts +++ b/src/main.ts @@ -95,6 +95,9 @@ window.addEventListener('resize', () => { window.addEventListener('pointerdown', unlockAudio, { once: true }); window.addEventListener('keydown', unlockAudio, { once: true }); +// iOS only lets audio start from touchend/click, and may pause it again later: retry on every tap. +window.addEventListener('touchend', unlockAudio, { passive: true }); +window.addEventListener('click', unlockAudio); // Avoid long-press menus and pinch zoom getting in the way of fast tapping. window.addEventListener('contextmenu', (e) => e.preventDefault()); document.addEventListener('gesturestart', (e) => e.preventDefault()); diff --git a/src/styles.css b/src/styles.css index 3315be2..58fbd4a 100644 --- a/src/styles.css +++ b/src/styles.css @@ -67,6 +67,8 @@ button { display: flex; padding: var(--sat) var(--sar) var(--sab) var(--sal); animation: screen-in 0.35s ease-out; + /* Two players tapping at once must never become a pinch-zoom (iOS ignores user-scalable=no). */ + touch-action: none; } @keyframes screen-in { @@ -410,6 +412,7 @@ button { width: min(460px, 100%); max-height: 100%; overflow: auto; + touch-action: pan-y; padding: 20px 22px; border-radius: 24px; background: #2a1f6e;