Skip to content

Commit 7e33ff2

Browse files
committed
Extract fullscreen logic to dedicated store
- Move fullscreen state and toggle function to `useFullscreenStore` - Centralize fullscreen management and event listeners for better reusability - Add a fullscreen logo and exit button within the background component
1 parent 5b9aca7 commit 7e33ff2

File tree

3 files changed

+85
-41
lines changed

3 files changed

+85
-41
lines changed

src/app.jsx

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Router, A } from "@solidjs/router";
22
import { FileRoutes } from "@solidjs/start/router";
3-
import { Suspense, createSignal, onMount, onCleanup } from "solid-js";
3+
import { Suspense } from "solid-js";
44
import { clientOnly } from "@solidjs/start";
55
import { useThemeStore } from "~/stores/theme";
66
import { useAnimationStore } from "~/stores/animation";
7+
import { useFullscreenStore } from "~/stores/fullscreen";
78
import { BsFullscreen } from '@aminya/solid-icons/bs/BsFullscreen';
89
import { BsFullscreenExit } from '@aminya/solid-icons/bs/BsFullscreenExit';
910
import TopMenu from "~/components/TopMenu";
@@ -22,52 +23,15 @@ const ClientAnimationModeToggle = clientOnly(() =>
2223
);
2324

2425
export default function App() {
25-
const [isFullscreen, setIsFullscreen] = createSignal(false);
26-
const { isAnimationOn, setIsAnimationOn } = useAnimationStore();
27-
28-
const toggleFullscreen = () => {
29-
const canvas = document.getElementById('background');
30-
if (!canvas) return;
31-
32-
if (!document.fullscreenElement) {
33-
canvas.requestFullscreen().then(() => {
34-
setIsFullscreen(true);
35-
// Ensure animation is on when entering fullscreen
36-
if (!isAnimationOn()) {
37-
setIsAnimationOn(true);
38-
}
39-
}).catch(err => {
40-
console.error(`Error attempting to enable fullscreen: ${err.message}`);
41-
});
42-
} else {
43-
document.exitFullscreen().then(() => {
44-
setIsFullscreen(false);
45-
}).catch(err => {
46-
console.error(`Error attempting to exit fullscreen: ${err.message}`);
47-
});
48-
}
49-
};
50-
51-
// Listen for fullscreen change events
52-
onMount(() => {
53-
const handleFullscreenChange = () => {
54-
setIsFullscreen(!!document.fullscreenElement);
55-
};
56-
57-
document.addEventListener('fullscreenchange', handleFullscreenChange);
58-
59-
onCleanup(() => {
60-
document.removeEventListener('fullscreenchange', handleFullscreenChange);
61-
});
62-
});
26+
const { isFullscreen, toggleFullscreen } = useFullscreenStore();
6327
return (
6428
<>
6529
{/* Background. Mounting point for lava animation - only rendered on client */}
6630
<ClientLavaBackground />
6731

6832
{/* Fullscreen button - desktop only */}
6933
<button
70-
onClick={toggleFullscreen}
34+
onClick={() => toggleFullscreen('background-container')}
7135
class="fixed top-4 right-4 z-[9999] p-2 text-white/0 hover:text-white/80 transition-opacity hidden md:block cursor-pointer"
7236
aria-label={isFullscreen() ? "Exit fullscreen" : "Enter fullscreen and start animation"}
7337
title={isFullscreen() ? "Exit fullscreen" : "Enter fullscreen and start animation"}

src/components/LavaBackground.jsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { onMount, onCleanup, createEffect, createSignal } from "solid-js";
22
import { startLavaAnimation } from "~/lava/app";
33
import { useThemeStore, colorSchemes } from "~/stores/theme";
44
import { useAnimationStore } from "~/stores/animation";
5+
import { useFullscreenStore } from "~/stores/fullscreen";
6+
import { Logo } from "~/components/Logo";
7+
import { BsFullscreen } from '@aminya/solid-icons/bs/BsFullscreen';
8+
import { BsFullscreenExit } from '@aminya/solid-icons/bs/BsFullscreenExit';
59

610
/**
711
* A component that renders the lava animation background.
@@ -10,8 +14,11 @@ import { useAnimationStore } from "~/stores/animation";
1014
export default function LavaBackground() {
1115
const { currentTheme } = useThemeStore();
1216
const { isAnimationOn } = useAnimationStore();
17+
const { isFullscreen, toggleFullscreen } = useFullscreenStore();
18+
1319
let animation = null;
1420

21+
1522
// Handle window resize
1623
const handleResize = () => {
1724
// If animation is stopped, render a single frame to update with new dimensions
@@ -55,7 +62,30 @@ export default function LavaBackground() {
5562

5663
return (
5764
<>
58-
<canvas id="background" class="fixed inset-0 w-screen h-screen" />
65+
<div id="background-container" class="fixed inset-0 w-screen h-screen">
66+
<canvas id="background" class="w-full h-full" />
67+
{isFullscreen() && (
68+
<div
69+
id="fullscreen-logo"
70+
class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-1/2 h-1/2 pointer-events-none"
71+
>
72+
<Logo />
73+
</div>
74+
)}
75+
76+
{/* Exit Fullscreen button - desktop only */}
77+
{isFullscreen() &&
78+
<button
79+
onClick={() => toggleFullscreen('background-container')}
80+
class="fixed top-4 right-4 z-[9999] p-2 text-white/0 hover:text-white/80 transition-opacity hidden md:block cursor-pointer"
81+
aria-label={isFullscreen() ? "Exit fullscreen" : "Enter fullscreen and start animation"}
82+
title={isFullscreen() ? "Exit fullscreen" : "Enter fullscreen and start animation"}
83+
>
84+
{isFullscreen() ? <BsFullscreenExit size={20} /> : <BsFullscreen size={20} />}
85+
</button>
86+
}
87+
88+
</div>
5989
</>
6090
);
6191
}

src/stores/fullscreen.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { createSignal, createEffect, onMount, onCleanup } from 'solid-js';
2+
import { useAnimationStore } from './animation';
3+
4+
// Initialize signals with default values
5+
const [isFullscreen, setIsFullscreen] = createSignal(false);
6+
7+
export const useFullscreenStore = () => {
8+
const { isAnimationOn, setIsAnimationOn } = useAnimationStore();
9+
// Listen for fullscreen change events
10+
onMount(() => {
11+
const handleFullscreenChange = () => {
12+
setIsFullscreen(!!document.fullscreenElement);
13+
};
14+
15+
document.addEventListener('fullscreenchange', handleFullscreenChange);
16+
17+
onCleanup(() => {
18+
document.removeEventListener('fullscreenchange', handleFullscreenChange);
19+
});
20+
});
21+
22+
// Toggle fullscreen function
23+
const toggleFullscreen = (elementId) => {
24+
const element = document.getElementById(elementId);
25+
if (!element) return;
26+
27+
if (!document.fullscreenElement) {
28+
element.requestFullscreen().then(() => {
29+
setIsFullscreen(true);
30+
// Ensure animation is on when entering fullscreen
31+
if (!isAnimationOn()) {
32+
setIsAnimationOn(true);
33+
}
34+
}).catch(err => {
35+
console.error(`Error attempting to enable fullscreen: ${err.message}`);
36+
});
37+
} else {
38+
document.exitFullscreen().then(() => {
39+
setIsFullscreen(false);
40+
}).catch(err => {
41+
console.error(`Error attempting to exit fullscreen: ${err.message}`);
42+
});
43+
}
44+
};
45+
46+
return {
47+
isFullscreen,
48+
toggleFullscreen
49+
};
50+
};

0 commit comments

Comments
 (0)