hide fullscreen controls on iOS/devices without Fullscreen API
iOS Safari doesn't support requestFullscreen. Detect support and: - Intro page: show single START button instead of FULLSCREEN/WINDOWED - AppLayout: hide the global fullscreen button entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>main
parent
3190891d6e
commit
e5552e72f7
|
|
@ -1,15 +1,18 @@
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { Outlet } from 'react-router-dom'
|
import { Outlet } from 'react-router-dom'
|
||||||
|
import { supportsFullscreen } from '../lib/platform'
|
||||||
import styles from './AppLayout.module.css'
|
import styles from './AppLayout.module.css'
|
||||||
|
|
||||||
export function AppLayout() {
|
export function AppLayout() {
|
||||||
|
const canFullscreen = supportsFullscreen()
|
||||||
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement)
|
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!canFullscreen) return
|
||||||
const onChange = () => setIsFullscreen(!!document.fullscreenElement)
|
const onChange = () => setIsFullscreen(!!document.fullscreenElement)
|
||||||
document.addEventListener('fullscreenchange', onChange)
|
document.addEventListener('fullscreenchange', onChange)
|
||||||
return () => document.removeEventListener('fullscreenchange', onChange)
|
return () => document.removeEventListener('fullscreenchange', onChange)
|
||||||
}, [])
|
}, [canFullscreen])
|
||||||
|
|
||||||
const goFullscreen = useCallback(() => {
|
const goFullscreen = useCallback(() => {
|
||||||
document.documentElement.requestFullscreen().catch(() => {})
|
document.documentElement.requestFullscreen().catch(() => {})
|
||||||
|
|
@ -20,7 +23,7 @@ export function AppLayout() {
|
||||||
<main className={styles.main}>
|
<main className={styles.main}>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
{!isFullscreen && (
|
{canFullscreen && !isFullscreen && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={styles.fullscreenBtn}
|
className={styles.fullscreenBtn}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function supportsFullscreen(): boolean {
|
||||||
|
return !!document.documentElement.requestFullscreen
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { ROUTE_PATHS } from '../app/route-paths'
|
import { ROUTE_PATHS } from '../app/route-paths'
|
||||||
import { playSound, SFX_BUTTON_DEFAULT } from '../lib/sounds'
|
import { playSound, SFX_BUTTON_DEFAULT } from '../lib/sounds'
|
||||||
|
import { supportsFullscreen } from '../lib/platform'
|
||||||
import styles from './IntroPage.module.css'
|
import styles from './IntroPage.module.css'
|
||||||
|
|
||||||
const SPONSORS = [
|
const SPONSORS = [
|
||||||
|
|
@ -121,26 +122,41 @@ export function IntroPage() {
|
||||||
|
|
||||||
{cameraReady && (
|
{cameraReady && (
|
||||||
<div className={styles.actionsRow}>
|
<div className={styles.actionsRow}>
|
||||||
<button
|
{supportsFullscreen() ? (
|
||||||
type="button"
|
<>
|
||||||
className={`${styles.btn} ${styles.btnPrimary} font-title`}
|
<button
|
||||||
onClick={() => {
|
type="button"
|
||||||
playSound(SFX_BUTTON_DEFAULT)
|
className={`${styles.btn} ${styles.btnPrimary} font-title`}
|
||||||
goFullscreen()
|
onClick={() => {
|
||||||
}}
|
playSound(SFX_BUTTON_DEFAULT)
|
||||||
>
|
goFullscreen()
|
||||||
FULLSCREEN
|
}}
|
||||||
</button>
|
>
|
||||||
<button
|
FULLSCREEN
|
||||||
type="button"
|
</button>
|
||||||
className={`${styles.btn} ${styles.btnSecondary} font-title`}
|
<button
|
||||||
onClick={() => {
|
type="button"
|
||||||
playSound(SFX_BUTTON_DEFAULT)
|
className={`${styles.btn} ${styles.btnSecondary} font-title`}
|
||||||
goWindowed()
|
onClick={() => {
|
||||||
}}
|
playSound(SFX_BUTTON_DEFAULT)
|
||||||
>
|
goWindowed()
|
||||||
WINDOWED
|
}}
|
||||||
</button>
|
>
|
||||||
|
WINDOWED
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`${styles.btn} ${styles.btnPrimary} font-title`}
|
||||||
|
onClick={() => {
|
||||||
|
playSound(SFX_BUTTON_DEFAULT)
|
||||||
|
goWindowed()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
START
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue