| 1 | import type { Prefs } from '../game/prefs'; |
| 2 | import { enterFullscreen, exitFullscreen, fullscreenSupported, useFullscreen } from './fullscreen'; |
| 3 | import { useT } from './lang'; |
| 4 | |
| 5 | interface Props { |
| 6 | prefs: Prefs; |
| 7 | onPrefs: (p: Prefs) => void; |
| 8 | /** Icon only, for the cramped row of controls in the middle of the table. */ |
| 9 | compact?: boolean; |
| 10 | } |
| 11 | |
| 12 | /* Corner brackets rather than a glyph: this has to read on whatever font a |
| 13 | phone happens to have, and the symbols for it are thin on the ground. */ |
| 14 | const Corners = ({ out }: { out: boolean }) => ( |
| 15 | <svg |
| 16 | className="fs-icon" |
| 17 | viewBox="0 0 20 20" |
| 18 | width="15" |
| 19 | height="15" |
| 20 | aria-hidden |
| 21 | fill="none" |
| 22 | stroke="currentColor" |
| 23 | strokeWidth="2" |
| 24 | strokeLinecap="round" |
| 25 | strokeLinejoin="round" |
| 26 | > |
| 27 | {out ? ( |
| 28 | <path d="M2 7V2h5M13 2h5v5M18 13v5h-5M7 18H2v-5" /> |
| 29 | ) : ( |
| 30 | <path d="M7 2v5H2M18 7h-5V2M13 18v-5h5M2 13h5v5" /> |
| 31 | )} |
| 32 | </svg> |
| 33 | ); |
| 34 | |
| 35 | /** |
| 36 | * Takes the screen and gives it back — and remembers which the player wanted. |
| 37 | * The browser drops fullscreen on every reload, and this game is built to be |
| 38 | * put down and resumed, so without that memory you would be reaching for this |
| 39 | * button every single time. |
| 40 | */ |
| 41 | export function FullscreenToggle({ prefs, onPrefs, compact }: Props) { |
| 42 | const t = useT(); |
| 43 | const active = useFullscreen(); |
| 44 | if (!fullscreenSupported()) return null; |
| 45 | |
| 46 | return ( |
| 47 | <button |
| 48 | className={`btn ghost pill fs-toggle ${compact ? 'compact' : ''} ${active ? 'on' : ''}`} |
| 49 | aria-pressed={active} |
| 50 | onClick={() => { |
| 51 | // Made here, inside the click: the same call from an effect is refused. |
| 52 | if (active) exitFullscreen(); |
| 53 | else enterFullscreen(); |
| 54 | onPrefs({ ...prefs, fullscreen: !active }); |
| 55 | }} |
| 56 | > |
| 57 | <Corners out={!active} /> |
| 58 | {!compact && ( |
| 59 | <span>{active ? t('離開全螢幕', 'Exit full screen') : t('全螢幕', 'Full screen')}</span> |
| 60 | )} |
| 61 | </button> |
| 62 | ); |
| 63 | } |