aboutsummaryrefslogtreecommitdiff
path: root/src/lib/List/MediaRoulette.svelte
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/List/MediaRoulette.svelte')
-rw-r--r--src/lib/List/MediaRoulette.svelte163
1 files changed, 82 insertions, 81 deletions
diff --git a/src/lib/List/MediaRoulette.svelte b/src/lib/List/MediaRoulette.svelte
index 4b498d4f..d6e33d7a 100644
--- a/src/lib/List/MediaRoulette.svelte
+++ b/src/lib/List/MediaRoulette.svelte
@@ -1,85 +1,86 @@
<script lang="ts">
- import type { Media } from '$lib/Data/AniList/media';
- import ParallaxImage from '$lib/Image/ParallaxImage.svelte';
- import { outboundLink } from '$lib/Media/links';
- import settings from '$stores/settings';
- import { mediaTitle } from './mediaTitle';
-
- interface Props {
- media: Media[];
- type: 'anime' | 'manga';
- onClose: () => void;
- spinDuration?: number;
- }
-
- let { media, type, onClose, spinDuration = 2 }: Props = $props();
- let isSpinning = $state(false);
- let selectedIndex = $state(0);
- let displayIndex = $state(0);
- let spinTimeout: ReturnType<typeof setTimeout> | null = $state(null);
- let showResult = $state(false);
- let isClosing = $state(false);
- let currentMedia = $derived(media[displayIndex]);
-
- const startRoulette = () => {
- if (media.length === 0 || isSpinning) return;
-
- isSpinning = true;
- showResult = false;
- selectedIndex = Math.floor(Math.random() * media.length);
-
- const startTime = Date.now();
- const durationMs = spinDuration * 1000;
- const minSpeed = 50;
- const maxSpeed = 350;
- const slowdownStart = 0.8;
-
- const spin = () => {
- displayIndex = (displayIndex + 1) % media.length;
-
- const elapsed = Date.now() - startTime;
- const progress = Math.min(elapsed / durationMs, 1);
- let speed = minSpeed;
-
- if (progress > slowdownStart) {
- const slowdownProgress = (progress - slowdownStart) / (1 - slowdownStart);
-
- speed = minSpeed + slowdownProgress * (maxSpeed - minSpeed);
- }
-
- if (progress >= 1 && displayIndex === selectedIndex) {
- spinTimeout = null;
- isSpinning = false;
- showResult = true;
-
- return;
- }
-
- spinTimeout = setTimeout(spin, speed);
- };
-
- spinTimeout = setTimeout(spin, minSpeed);
- };
-
- const handleClose = () => {
- if (isClosing) return;
-
- if (spinTimeout) {
- clearTimeout(spinTimeout);
-
- spinTimeout = null;
- }
-
- isSpinning = false;
- showResult = false;
- isClosing = true;
-
- setTimeout(() => onClose(), 200);
- };
-
- const handleOverlayClick = (e: MouseEvent) => {
- if (e.target === e.currentTarget) handleClose();
- };
+import type { Media } from "$lib/Data/AniList/media";
+import ParallaxImage from "$lib/Image/ParallaxImage.svelte";
+import { outboundLink } from "$lib/Media/links";
+import settings from "$stores/settings";
+import { mediaTitle } from "./mediaTitle";
+
+interface Props {
+ media: Media[];
+ type: "anime" | "manga";
+ onClose: () => void;
+ spinDuration?: number;
+}
+
+let { media, type, onClose, spinDuration = 2 }: Props = $props();
+let isSpinning = $state(false);
+let selectedIndex = $state(0);
+let displayIndex = $state(0);
+let spinTimeout: ReturnType<typeof setTimeout> | null = $state(null);
+let showResult = $state(false);
+let isClosing = $state(false);
+let currentMedia = $derived(media[displayIndex]);
+
+const startRoulette = () => {
+ if (media.length === 0 || isSpinning) return;
+
+ isSpinning = true;
+ showResult = false;
+ selectedIndex = Math.floor(Math.random() * media.length);
+
+ const startTime = Date.now();
+ const durationMs = spinDuration * 1000;
+ const minSpeed = 50;
+ const maxSpeed = 350;
+ const slowdownStart = 0.8;
+
+ const spin = () => {
+ displayIndex = (displayIndex + 1) % media.length;
+
+ const elapsed = Date.now() - startTime;
+ const progress = Math.min(elapsed / durationMs, 1);
+ let speed = minSpeed;
+
+ if (progress > slowdownStart) {
+ const slowdownProgress = (progress - slowdownStart) / (1 - slowdownStart);
+
+ speed = minSpeed + slowdownProgress * (maxSpeed - minSpeed);
+ }
+
+ if (progress >= 1) {
+ displayIndex = selectedIndex;
+ spinTimeout = null;
+ isSpinning = false;
+ showResult = true;
+
+ return;
+ }
+
+ spinTimeout = setTimeout(spin, speed);
+ };
+
+ spinTimeout = setTimeout(spin, minSpeed);
+};
+
+const handleClose = () => {
+ if (isClosing) return;
+
+ if (spinTimeout) {
+ clearTimeout(spinTimeout);
+
+ spinTimeout = null;
+ }
+
+ isSpinning = false;
+ showResult = false;
+ isClosing = true;
+
+ setTimeout(() => onClose(), 200);
+};
+
+const handleOverlayClick = (e: MouseEvent) => {
+ if (e.target === e.currentTarget) handleClose();
+};
</script>
<svelte:window onkeydown={(e) => e.key === 'Escape' && handleClose()} />