feat(wip): add onboarding page

This commit is contained in:
Ash Keel 2022-12-08 12:27:42 +01:00
parent 59c02fed49
commit 1c5db13b0d
No known key found for this signature in database
GPG Key ID: BAD8D93E7314ED3E
3 changed files with 126 additions and 5 deletions

View File

@ -251,6 +251,9 @@
"live": "Live!",
"x-viewers": "{{count}} viewers",
"not-live": "Offline / Not streaming"
},
"onboarding": {
"welcome-header": "Welcome to {{APPNAME}}"
}
},
"form-actions": {

View File

@ -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 />} />

View File

@ -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>
);
}