import type { EasterEggMeta } from './useFetchEasterEggs' interface UseEasterEggDetectionOptions { onFound: (slug: string) => void } // Konami Code const KONAMI_CODE = [ 'ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'KeyB', 'KeyA', ] export function useEasterEggDetection(options: UseEasterEggDetectionOptions) { const { fetchList } = useFetchEasterEggs() const progressionStore = useProgressionStore() // State const konamiIndex = ref(0) const clickSequence = ref([]) let konamiListenerAdded = false // Load easter eggs on mount onMounted(() => { fetchList() initKonamiListener() }) // === Konami Code === function initKonamiListener() { if (import.meta.client && !konamiListenerAdded) { window.addEventListener('keydown', handleKonamiKey) konamiListenerAdded = true } } function handleKonamiKey(e: KeyboardEvent) { if (e.code === KONAMI_CODE[konamiIndex.value]) { konamiIndex.value++ if (konamiIndex.value === KONAMI_CODE.length) { triggerEasterEgg('konami-master') konamiIndex.value = 0 } } else { konamiIndex.value = 0 } } // === Click Detection === function detectClick(targetSlug: string, requiredClicks: number = 1) { const clicks = ref(0) function handleClick() { clicks.value++ if (clicks.value >= requiredClicks) { triggerEasterEgg(targetSlug) clicks.value = 0 } } return { handleClick, clicks } } // === Hover Detection === function detectHover(targetSlug: string, hoverTime: number = 2000) { let timeoutId: ReturnType | null = null function handleMouseEnter() { timeoutId = setTimeout(() => { triggerEasterEgg(targetSlug) }, hoverTime) } function handleMouseLeave() { if (timeoutId) { clearTimeout(timeoutId) timeoutId = null } } return { handleMouseEnter, handleMouseLeave } } // === Scroll Detection === function detectScrollBottom(targetSlug: string) { let triggered = false function checkScroll() { if (triggered) return const scrollTop = window.scrollY const windowHeight = window.innerHeight const docHeight = document.documentElement.scrollHeight if (scrollTop + windowHeight >= docHeight - 50) { triggerEasterEgg(targetSlug) triggered = true } } onMounted(() => { if (import.meta.client) { window.addEventListener('scroll', checkScroll, { passive: true }) } }) onUnmounted(() => { if (import.meta.client) { window.removeEventListener('scroll', checkScroll) } }) } // === Sequence Detection === function detectSequence(expectedSequence: string[], targetSlug: string) { function addToSequence(item: string) { clickSequence.value.push(item) // Keep only the last N items if (clickSequence.value.length > expectedSequence.length) { clickSequence.value.shift() } // Check if sequence matches if (clickSequence.value.length === expectedSequence.length) { const match = clickSequence.value.every( (val, idx) => val === expectedSequence[idx] ) if (match) { triggerEasterEgg(targetSlug) clickSequence.value = [] } } } return { addToSequence } } // === Trigger Easter Egg === function triggerEasterEgg(slug: string) { // Check if already found if (progressionStore.easterEggsFound.includes(slug)) { return } // Mark as found progressionStore.markEasterEggFound(slug) // Notify options.onFound(slug) } onUnmounted(() => { if (import.meta.client && konamiListenerAdded) { window.removeEventListener('keydown', handleKonamiKey) konamiListenerAdded = false } }) return { detectClick, detectHover, detectScrollBottom, detectSequence, triggerEasterEgg, } }