From b68d2cce63f1c91818e3aa02791d8587678e0d0a Mon Sep 17 00:00:00 2001 From: Joonatan Paalanen Date: Tue, 14 Oct 2025 21:29:41 +0300 Subject: [PATCH 1/6] Add english translation for sponsors --- src/app/(infoscreen)/@sponsors/page.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/(infoscreen)/@sponsors/page.tsx b/src/app/(infoscreen)/@sponsors/page.tsx index 41ddb34..6f85da1 100644 --- a/src/app/(infoscreen)/@sponsors/page.tsx +++ b/src/app/(infoscreen)/@sponsors/page.tsx @@ -1,6 +1,7 @@ 'use client'; import { Slide } from '@/components/Carousel'; +import I18n from '@/components/I18n/I18n'; import { getSponsorData, type SponsorData } from '@/server/sponsors'; import { useEffect, useState } from 'react'; @@ -18,7 +19,7 @@ const Sponsors = () => { return (

- Yhteistyökumppanit + Yhteistyökumppanit // Sponsors

{sponsors?.filter((sponsor) => sponsor.logoUrl).map((sponsor) => ( From edf0e8f7a413b498ac6dca956c20a9de6535181c Mon Sep 17 00:00:00 2001 From: Joonatan Paalanen Date: Tue, 14 Oct 2025 21:33:54 +0300 Subject: [PATCH 2/6] Add shortcut for toggling language --- src/app/LanguageInterval.tsx | 2 +- src/components/Carousel.tsx | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/app/LanguageInterval.tsx b/src/app/LanguageInterval.tsx index 0ca10ef..7f883c9 100644 --- a/src/app/LanguageInterval.tsx +++ b/src/app/LanguageInterval.tsx @@ -10,7 +10,7 @@ export const LanguageInterval = () => { useEffect(() => { // Interval for switching language in event titles etc. const langInterval = setInterval( - () => setlang(((lang + 1) % 2) as 0 | 1), + () => setlang(lang === 0 ? 1 : 0), 10 * 1000 ); diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index e42ff3c..653511a 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -1,9 +1,11 @@ 'use client'; +import { langAtom } from '@/lib/lang'; import { merge } from '@/lib/utils'; import { type EmblaOptionsType } from 'embla-carousel'; import Autoplay from 'embla-carousel-autoplay'; import useEmblaCarousel from 'embla-carousel-react'; +import { useAtom } from 'jotai'; import { Play } from 'lucide-react'; import React, { useCallback, useEffect } from 'react'; @@ -37,6 +39,9 @@ export const Carousel = ({ // Show play button when autoplay is stopped const [autoplay, setAutoplay] = React.useState(true); + //For toggling language with l + const [lang, setLang] = useAtom(langAtom); + useEffect(() => { if (!emblaApi) return; emblaApi.on('autoplay:stop', () => setAutoplay(false)); @@ -59,19 +64,26 @@ export const Carousel = ({ // Register keyboard event listener to document on mount useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { - if (e.key === 'ArrowRight') { + switch (e.key) { + case 'ArrowRight': emblaApi?.scrollNext(); e.preventDefault(); - } - if (e.key === 'ArrowLeft') { + break; + case 'ArrowLeft': emblaApi?.scrollPrev(); e.preventDefault(); + break; + case 'l': + setLang(lang === 0 ? 1 : 0); + e.preventDefault(); + break; + } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); - }, [emblaApi]); + }, [lang, setLang, emblaApi]); return ( <> From 5407f8d422c5ed79f8d9ce759a7dfdbedb3629a0 Mon Sep 17 00:00:00 2001 From: Joonatan Paalanen Date: Tue, 14 Oct 2025 21:35:10 +0300 Subject: [PATCH 3/6] Add slide navigation with number keys --- src/components/Carousel.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index 653511a..62bd345 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -64,6 +64,11 @@ export const Carousel = ({ // Register keyboard event listener to document on mount useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { + const slideNumber = parseInt(e.key); + const slideCount = emblaApi?.slideNodes().length || 0; + if (!isNaN(slideNumber) && slideNumber >= 0 && slideNumber < slideCount) + emblaApi?.scrollTo(slideNumber, true) + switch (e.key) { case 'ArrowRight': emblaApi?.scrollNext(); From 52a9f8c4e1b5d71e98f94b78a0287ba4dd64c344 Mon Sep 17 00:00:00 2001 From: Joonatan Paalanen Date: Tue, 14 Oct 2025 22:18:15 +0300 Subject: [PATCH 4/6] Refactor language toggle key to its own component --- src/app/layout.tsx | 2 ++ src/components/Carousel.tsx | 20 +++++--------------- src/components/LanguageCycle.tsx | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 src/components/LanguageCycle.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 063b294..948b112 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,3 +1,4 @@ +import { LanguageCycle } from '@/components/LanguageCycle'; import { getServerVersion } from '@/server/version'; import { Provider } from 'jotai'; import type { Metadata } from 'next'; @@ -32,6 +33,7 @@ export default async function RootLayout({ {children} + diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index 62bd345..790d7fe 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -1,11 +1,9 @@ 'use client'; -import { langAtom } from '@/lib/lang'; import { merge } from '@/lib/utils'; import { type EmblaOptionsType } from 'embla-carousel'; import Autoplay from 'embla-carousel-autoplay'; import useEmblaCarousel from 'embla-carousel-react'; -import { useAtom } from 'jotai'; import { Play } from 'lucide-react'; import React, { useCallback, useEffect } from 'react'; @@ -39,9 +37,6 @@ export const Carousel = ({ // Show play button when autoplay is stopped const [autoplay, setAutoplay] = React.useState(true); - //For toggling language with l - const [lang, setLang] = useAtom(langAtom); - useEffect(() => { if (!emblaApi) return; emblaApi.on('autoplay:stop', () => setAutoplay(false)); @@ -71,24 +66,19 @@ export const Carousel = ({ switch (e.key) { case 'ArrowRight': - emblaApi?.scrollNext(); - e.preventDefault(); + emblaApi?.scrollNext(); + e.preventDefault(); break; case 'ArrowLeft': - emblaApi?.scrollPrev(); - e.preventDefault(); - break; - case 'l': - setLang(lang === 0 ? 1 : 0); + emblaApi?.scrollPrev(); e.preventDefault(); break; - } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); - }, [lang, setLang, emblaApi]); + }, [emblaApi]); return ( <> @@ -101,7 +91,7 @@ export const Carousel = ({
{/* Continue autoplay button */}
diff --git a/src/components/LanguageCycle.tsx b/src/components/LanguageCycle.tsx new file mode 100644 index 0000000..a8fa589 --- /dev/null +++ b/src/components/LanguageCycle.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { langAtom } from '@/lib/lang'; +import { useAtom } from 'jotai'; +import { useEffect } from 'react'; + +export const LanguageCycle = () => { + // For toggling language with 'l' + const [lang, setLang] = useAtom(langAtom); + + // Register keyboard event listener to document on mount + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'l') { + setLang(lang === 0 ? 1 : 0); + e.preventDefault(); + } + }; + + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + }, [lang, setLang]); + + return null; +}; \ No newline at end of file From 164e63b5733e2274dd6f0bde072dbfe92030ef28 Mon Sep 17 00:00:00 2001 From: Joonatan Paalanen Date: Tue, 14 Oct 2025 22:41:18 +0300 Subject: [PATCH 5/6] Add disabling language cycling for short period after its been manually changed --- src/app/LanguageInterval.tsx | 7 ++++--- src/components/LanguageCycle.tsx | 24 ++++++++++++++++++++---- src/lib/lang.ts | 5 +++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/app/LanguageInterval.tsx b/src/app/LanguageInterval.tsx index 7f883c9..fb350d2 100644 --- a/src/app/LanguageInterval.tsx +++ b/src/app/LanguageInterval.tsx @@ -1,23 +1,24 @@ 'use client'; -import { langAtom } from '@/lib/lang'; +import { doLangCycleAtom, langAtom } from '@/lib/lang'; import { useAtom } from 'jotai'; import { useEffect } from 'react'; export const LanguageInterval = () => { const [lang, setlang] = useAtom(langAtom); + const [doLangCycle] = useAtom(doLangCycleAtom); useEffect(() => { // Interval for switching language in event titles etc. const langInterval = setInterval( - () => setlang(lang === 0 ? 1 : 0), + () => { if (doLangCycle) setlang(lang === 0 ? 1 : 0) }, 10 * 1000 ); return () => { clearInterval(langInterval); }; - }, [lang, setlang]); + }, [doLangCycle, lang, setlang]); return null; }; diff --git a/src/components/LanguageCycle.tsx b/src/components/LanguageCycle.tsx index a8fa589..d2aa29e 100644 --- a/src/components/LanguageCycle.tsx +++ b/src/components/LanguageCycle.tsx @@ -1,25 +1,41 @@ 'use client'; -import { langAtom } from '@/lib/lang'; +import { doLangCycleAtom, langAtom } from '@/lib/lang'; import { useAtom } from 'jotai'; -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; export const LanguageCycle = () => { // For toggling language with 'l' const [lang, setLang] = useAtom(langAtom); + // For disabling language cycling briefly after language has been manually toggled + const [, setDoLangCycle] = useAtom(doLangCycleAtom); + + const timeoutRef = useRef(null); // Register keyboard event listener to document on mount useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'l') { setLang(lang === 0 ? 1 : 0); + setDoLangCycle(false); e.preventDefault(); + + if (timeoutRef.current) + clearTimeout(timeoutRef.current); + + timeoutRef.current = setTimeout( + () => setDoLangCycle(true), + 30 * 1000 + ); } }; document.addEventListener('keydown', handleKeyDown); - return () => document.removeEventListener('keydown', handleKeyDown); - }, [lang, setLang]); + return () => { + document.removeEventListener('keydown', handleKeyDown); + if (timeoutRef.current) clearTimeout(timeoutRef.current); + } + }, [lang, setLang, setDoLangCycle]); return null; }; \ No newline at end of file diff --git a/src/lib/lang.ts b/src/lib/lang.ts index 35f22ba..7583e5d 100644 --- a/src/lib/lang.ts +++ b/src/lib/lang.ts @@ -5,3 +5,8 @@ import { atom, useAtomValue } from 'jotai'; export const langAtom = atom<0 | 1>(0); export const useLang = () => useAtomValue(langAtom); + +//When true language isn't cycled automatically +export const doLangCycleAtom = atom(true); + +export const useLangCycle = () => useAtomValue(doLangCycleAtom); \ No newline at end of file From 00523e48926788aec899ddf22e72e9209b8d8d54 Mon Sep 17 00:00:00 2001 From: Joonatan Paalanen Date: Tue, 14 Oct 2025 22:42:00 +0300 Subject: [PATCH 6/6] Change autoplay color from white to blue for better visibilty --- src/components/Carousel.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index 790d7fe..c1d0345 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -91,10 +91,10 @@ export const Carousel = ({
{/* Continue autoplay button */}
- +
);