Files
WebDrop/web/src/app/App.tsx
T

87 lines
3.3 KiB
TypeScript

import { useEffect, useState } from 'react';
import { Home } from '@/features/home/Home';
import { JoinScreen } from '@/features/scan/JoinScreen';
import { AccountChannelAccess } from './AccountChannelAccess';
import { useChannels } from '@/store/channels';
import { useShares } from '@/store/shares';
import { useWorkspace } from '@/store/workspace';
import { ChannelScreen } from './ChannelScreen';
import { ShareScreen } from './ShareScreen';
import { channelPath, navigate, useRoute } from './navigation';
import { Splash } from './Splash';
import { AccountScreen } from '@/features/home/AccountScreen';
import { useAccount } from '@/store/account';
const SEEN_KEY = 'wd.splash';
function splashSeen(): boolean {
try {
return sessionStorage.getItem(SEEN_KEY) === '1';
} catch {
return false;
}
}
export function App() {
const username = useAccount((s) => s.username);
const accountHydrated = useAccount((s) => s.hydrated);
const refreshAccount = useAccount((s) => s.refresh);
useEffect(() => {
const timer = window.setInterval(() => { void refreshAccount(); }, 5000);
return () => window.clearInterval(timer);
}, [refreshAccount]);
const route = useRoute();
const list = useChannels((s) => s.list);
const channelsHydrated = useChannels((s) => s.hydrated);
const pendingLink = useChannels((s) => s.pendingLink);
const setPendingLink = useChannels((s) => s.setPendingLink);
const sharesHydrated = useShares((s) => s.hydrated);
const pendingShareLink = useShares((s) => s.pendingLink);
const wsReady = useWorkspace((s) => s.ready);
const [splash, setSplash] = useState(() => !splashSeen());
const saved = route.name === 'channel' && list.some((c) => c.id === route.id);
// 只有打开已保存的空间才需要等数据;首页与加入页没有加载过程
const waitingOnSavedChannel = route.name === 'channel' && !pendingLink && !channelsHydrated;
const waitingOnSavedShare = route.name === 'share' && pendingShareLink?.id !== route.id && !sharesHydrated;
const ready = accountHydrated && (route.name === 'home' || (route.name === 'channel'
? pendingLink?.id === route.id || (channelsHydrated && (!saved || wsReady))
: pendingShareLink?.id === route.id || sharesHydrated));
function onSplashDone() {
try {
sessionStorage.setItem(SEEN_KEY, '1');
} catch {
/* 无存储时每次都播,不影响功能 */
}
setSplash(false);
}
let screen;
if (!accountHydrated) screen = null;
else if (route.name === 'home') screen = username ? <Home /> : <AccountScreen />;
else if (route.name === 'share' && waitingOnSavedShare) screen = null;
else if (route.name === 'share') screen = <ShareScreen id={route.id} />;
else if (route.name === 'channel' && waitingOnSavedChannel) screen = null;
else if (saved) screen = <ChannelScreen id={route.id} />;
else if (pendingLink?.id === route.id) {
screen = (
<JoinScreen
link={pendingLink}
onJoined={(c) => navigate(channelPath(c.id))}
onCancel={() => {
setPendingLink(null);
navigate('/');
}}
/>
);
} else screen = <AccountChannelAccess id={route.name === 'channel' ? route.id : ''} onHome={() => navigate('/')} />;
return (
<>
{screen}
{splash ? <Splash ready={ready} onDone={onSplashDone} /> : null}
</>
);
}