import { lazy, Suspense, useCallback, useState } from 'react'; import { channelPath, navigate, sharePath } from '@/app/navigation'; import { buildInfo } from '@/lib/buildInfo'; import type { ChannelInfo, Share } from '@/core-bridge/types'; import type { ClipboardPayload } from '@/lib/clipboard'; import { useGlobalPaste } from '@/lib/useGlobalPaste'; import { useChannels } from '@/store/channels'; import { useShares } from '@/store/shares'; import { solveCreationCaptcha } from '@/core-bridge/captcha'; import { errorMessage } from '@/core-bridge/errors'; import { Button } from '@/ui/Button'; import { ThemeMenu } from '@/ui/ThemeMenu'; import { ChannelList } from './ChannelList'; import { CreateSheet } from './CreateSheet'; import { QuickShare } from './QuickShare'; import styles from './Home.module.css'; const ScanSheet = lazy(() => import('@/features/scan/ScanSheet').then((m) => ({ default: m.ScanSheet }))); /** 初始状态:什么都没创建时看到的页面。核心是「快速分享」 */ export function Home() { const createDraft = useShares((s) => s.createDraft); const loadDemo = useChannels((s) => s.loadDemo); const loadShareDemo = useShares((s) => s.loadDemo); const [createOpen, setCreateOpen] = useState(false); const [scanOpen, setScanOpen] = useState(false); const [busy, setBusy] = useState(false); const [failedMessage, setFailedMessage] = useState(''); const [shareText, setShareText] = useState(''); const [shareFiles, setShareFiles] = useState([]); const open = useCallback((c: ChannelInfo | Share) => navigate('state' in c ? sharePath(c.id) : channelPath(c.id)), []); const share = useCallback( async (p: ClipboardPayload) => { if (busy || (p.files.length === 0 && !p.text.trim())) return false; setBusy(true); setFailedMessage(''); try { const captchaToken = await solveCreationCaptcha(); open(await createDraft(p, captchaToken)); setShareFiles([]); setShareText(''); return true; } catch (error) { setFailedMessage(errorMessage(error)); return false; } finally { setBusy(false); } }, [busy, createDraft, open], ); const onClipboard = useCallback((p: ClipboardPayload) => { if (p.files.length > 0) setShareFiles((files) => [...files, ...p.files]); if (p.text) setShareText((text) => text ? `${text}\n${p.text}` : p.text); }, []); useGlobalPaste(onClipboard); return (

WebDrop

在自己的设备之间快速传文件和文本,也可以分享给别人。

{failedMessage ?

创建分享失败:{failedMessage}

: null}

设备频道

多台自己的设备之间长期同步

加密频道的密钥只在链接里,服务器看不到内容。持有链接的人可以读取该频道的全部历史。

{import.meta.env.DEV ? ( ) : null}
{createOpen ? setCreateOpen(false)} onCreated={open} /> : null} {scanOpen ? setScanOpen(false)} onChannel={open} onShare={open} /> : null}
); }