Reinstate the egg

This commit is contained in:
Ben Grant 2023-05-24 20:31:24 +10:00
parent 90352503b3
commit 00c7ae16f2
5 changed files with 113 additions and 44 deletions

View file

@ -1,5 +1,6 @@
import { Metadata } from 'next' import { Metadata } from 'next'
import Egg from '/src/components/Egg/Egg'
import Settings from '/src/components/Settings/Settings' import Settings from '/src/components/Settings/Settings'
import { fallbackLng } from '/src/i18n/options' import { fallbackLng } from '/src/i18n/options'
import { useTranslation } from '/src/i18n/server' import { useTranslation } from '/src/i18n/server'
@ -31,6 +32,7 @@ const RootLayout = async ({ children }: { children: React.ReactNode }) => {
<body> <body>
<Settings /> <Settings />
{children} {children}
<Egg />
</body> </body>
</html> </html>
} }

View file

@ -1,21 +0,0 @@
import { useState } from 'react'
import { Loading } from '/src/components'
import { Image, Wrapper } from './Egg.styles'
const Egg = ({ eggKey, onClose }) => {
const [isLoading, setIsLoading] = useState(true)
return (
<Wrapper title="Click anywhere to close" onClick={() => onClose()}>
<Image
src={`https://us-central1-flour-app-services.cloudfunctions.net/charliAPI?v=${eggKey}`}
onLoadStart={() => setIsLoading(true)}
onLoad={() => setIsLoading(false)}
/>
{isLoading && <Loading />}
</Wrapper>
)
}
export default Egg

View file

@ -0,0 +1,51 @@
.modal {
background: none;
border: 0;
padding: 0;
outline: none;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
overflow: visible;
&::backdrop {
background: rgba(0,0,0,.6);
}
}
.image {
max-width: 80vw;
max-height: 80vh;
border-radius: 10px;
display: block;
position: absolute;
}
@keyframes load {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loader {
height: 24px;
width: 24px;
border: 3px solid var(--primary);
border-left-color: transparent;
border-radius: 100px;
animation: load .5s linear infinite;
@media (prefers-reduced-motion: reduce) {
animation: none;
border: 0;
&::before {
content: 'loading...';
}
}
}

View file

@ -1,23 +0,0 @@
import { styled } from 'goober'
export const Wrapper = styled('div')`
position: fixed;
background: rgba(0,0,0,.6);
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
cursor: pointer;
`
export const Image = styled('img')`
max-width: 80%;
max-height: 80%;
position: absolute;
`

View file

@ -0,0 +1,60 @@
'use client'
import { useCallback, useEffect, useRef, useState } from 'react'
import styles from './Egg.module.scss'
const PATTERN = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a']
const API_URL = 'https://us-central1-flour-app-services.cloudfunctions.net/charliAPI?v='
const Egg = () => {
const ref = useRef<HTMLDialogElement>(null)
const [isLoading, setIsLoading] = useState(true)
const [patternCompletion, setPatternCompletion] = useState(0)
const [url, setUrl] = useState('')
const [key, setKey] = useState(0)
const keyHandler = useCallback((e: KeyboardEvent) => {
// Key pressed not next in pattern
if (PATTERN.indexOf(e.key) < 0 || e.key !== PATTERN[patternCompletion]) {
return setPatternCompletion(0)
}
setPatternCompletion(patternCompletion + 1)
// Pattern completed
if (PATTERN.length === patternCompletion + 1) {
setUrl(`${API_URL}${key}`)
setKey(key + 1)
setPatternCompletion(0)
setIsLoading(true)
ref.current?.showModal()
}
}, [patternCompletion, key])
// Listen to key presses
useEffect(() => {
document.addEventListener('keyup', keyHandler)
return () => document.removeEventListener('keyup', keyHandler)
}, [keyHandler])
return <dialog
onClick={e => {
e.currentTarget.close()
setUrl('')
}}
className={styles.modal}
ref={ref}
>
<img
className={styles.image}
src={url}
alt="A cute picture of Charli"
onLoadStart={() => setIsLoading(true)}
onLoad={() => setIsLoading(false)}
/>
{isLoading && <div className={styles.loader} />}
</dialog>
}
export default Egg