Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**.
4 changes: 3 additions & 1 deletion src/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
3 changes: 3 additions & 0 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
Loading