mirror of https://git.sr.ht/~ashkeel/strimertul
feat(wip): add onboarding page
This commit is contained in:
parent
59c02fed49
commit
1c5db13b0d
|
@ -251,6 +251,9 @@
|
|||
"live": "Live!",
|
||||
"x-viewers": "{{count}} viewers",
|
||||
"not-live": "Offline / Not streaming"
|
||||
},
|
||||
"onboarding": {
|
||||
"welcome-header": "Welcome to {{APPNAME}}"
|
||||
}
|
||||
},
|
||||
"form-actions": {
|
||||
|
|
|
@ -12,7 +12,7 @@ import { EventsOff, EventsOn } from '@wailsapp/runtime/runtime';
|
|||
import { t } from 'i18next';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
GetKilovoltBind,
|
||||
|
@ -42,11 +42,9 @@ import ServerSettingsPage from './pages/ServerSettings';
|
|||
import StrimertulPage from './pages/Strimertul';
|
||||
import TwitchSettingsPage from './pages/TwitchSettings';
|
||||
import { styled } from './theme';
|
||||
|
||||
// @ts-expect-error Asset import
|
||||
import spinner from '../assets/icon-loading.svg';
|
||||
import Scrollbar from './components/utils/Scrollbar';
|
||||
import LogViewer from './components/LogViewer';
|
||||
import OnboardingPage from './pages/Onboarding';
|
||||
|
||||
const LoadingDiv = styled('div', {
|
||||
display: 'flex',
|
||||
|
@ -167,6 +165,8 @@ export default function App(): JSX.Element {
|
|||
(state: RootState) => state.api.connectionStatus,
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const connectToKV = async () => {
|
||||
const address = await GetKilovoltBind();
|
||||
|
@ -212,6 +212,11 @@ export default function App(): JSX.Element {
|
|||
}
|
||||
}, [ready, connected]);
|
||||
|
||||
// TODO: Only do this when
|
||||
useEffect(() => {
|
||||
navigate('/setup');
|
||||
}, []);
|
||||
|
||||
if (connected === ConnectionStatus.NotConnected) {
|
||||
return <Loading message={t('special.loading')} />;
|
||||
}
|
||||
|
@ -220,10 +225,12 @@ export default function App(): JSX.Element {
|
|||
return <AuthDialog />;
|
||||
}
|
||||
|
||||
const showSidebar = location.pathname !== '/setup';
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<LogViewer />
|
||||
<Sidebar sections={sections} />
|
||||
{showSidebar ? <Sidebar sections={sections} /> : null}
|
||||
<Scrollbar
|
||||
vertical={true}
|
||||
root={{ flex: 1 }}
|
||||
|
@ -233,6 +240,7 @@ export default function App(): JSX.Element {
|
|||
<PageWrapper role="main">
|
||||
<Routes>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route path="/setup" element={<OnboardingPage />} />
|
||||
<Route path="/about" element={<StrimertulPage />} />
|
||||
<Route path="/debug" element={<DebugPage />} />
|
||||
<Route path="/http" element={<ServerSettingsPage />} />
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
import { keyframes } from '@stitches/react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// @ts-expect-error Asset import
|
||||
import spinner from '~/assets/icon-logo.svg';
|
||||
|
||||
import { styled } from '../theme';
|
||||
|
||||
const Container = styled('div', {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
});
|
||||
|
||||
const TopBanner = styled('div', {
|
||||
backgroundColor: '$gray2',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
transition: 'all 100ms ease-out',
|
||||
});
|
||||
|
||||
const appear = keyframes({
|
||||
'0%': { opacity: 0, transform: 'translate(0, 30px)' },
|
||||
'100%': { opacity: 1, transform: 'translate(0, 0)' },
|
||||
});
|
||||
|
||||
const HeroTitle = styled('h1', {
|
||||
fontSize: '35pt',
|
||||
fontWeight: 200,
|
||||
textAlign: 'center',
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
'@media (prefers-reduced-motion: no-preference)': {
|
||||
opacity: 0,
|
||||
animation: `${appear()} 1s ease-in`,
|
||||
animationDelay: '1s',
|
||||
animationFillMode: 'forwards',
|
||||
},
|
||||
});
|
||||
|
||||
const HeroContainer = styled('div', {
|
||||
maxHeight: '30vh',
|
||||
height: '300px',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
});
|
||||
|
||||
const HeroAnimation = styled('div', {
|
||||
bottom: '-50px',
|
||||
left: '50%',
|
||||
position: 'absolute',
|
||||
});
|
||||
|
||||
const fadeOut = keyframes({
|
||||
'0%': { transform: 'translate(10px, 0px) rotate(-80deg)' },
|
||||
'100%': { opacity: 0, transform: 'translate(-100px, -400px) rotate(30deg)' },
|
||||
});
|
||||
|
||||
const Spinner = styled('img', {
|
||||
width: '100px',
|
||||
position: 'absolute',
|
||||
'@media (prefers-reduced-motion: no-preference)': {
|
||||
animation: `${fadeOut()} 2s ease-in`,
|
||||
animationFillMode: 'forwards',
|
||||
},
|
||||
});
|
||||
|
||||
export default function OnboardingPage() {
|
||||
const { t } = useTranslation();
|
||||
const [animationItems, setAnimationItems] = useState<JSX.Element[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const spinners = new Array<string>(40).fill(spinner as string);
|
||||
setAnimationItems(
|
||||
spinners.map((url, i) => (
|
||||
<Spinner
|
||||
key={i}
|
||||
src={url}
|
||||
css={{
|
||||
marginLeft: `${Math.trunc(Math.random() * 1000) - 500}px`,
|
||||
animationDelay: `${(i / spinners.length) * 1000}ms`,
|
||||
marginTop: `${Math.trunc(Math.random() * 200 - 50)}px`,
|
||||
animationDuration: `${Math.trunc(Math.random() * 1000 + 1000)}ms`,
|
||||
width: `${Math.trunc(100 + Math.random() * 100)}px`,
|
||||
opacity: `${0.2 + Math.random() * 0.5}`,
|
||||
filter: `sepia(100%) saturate(1300%) hue-rotate(${Math.trunc(
|
||||
Math.random() * 180,
|
||||
)}deg) brightness(120%) contrast(120%)`,
|
||||
}}
|
||||
/>
|
||||
)),
|
||||
);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<TopBanner>
|
||||
<HeroContainer>
|
||||
<HeroAnimation>{animationItems}</HeroAnimation>
|
||||
<HeroTitle>{t('pages.onboarding.welcome-header')}</HeroTitle>
|
||||
</HeroContainer>
|
||||
</TopBanner>
|
||||
</Container>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue