feat(web): connect quick share flow

Signed-off-by: JustMe <mr.toing@outlook.com>
This commit is contained in:
justme committed 2026-10-02 00:59:37 +08:00
1 parent 53768a195d
commit e02e024605
138 files changed
+10614

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
import { useState } from 'react';
import type { ChannelInfo, Share } from '@/core-bridge/types';
import { formatAgo, formatRemaining } from '@/lib/format';
import { useChannels } from '@/store/channels';
import { useShares } from '@/store/shares';
import { Button } from '@/ui/Button';
import { Icon } from '@/ui/Icon';
import styles from './ChannelList.module.css';
interface Props {
kind: 'channel' | 'share';
title: string;
onOpen: (c: ChannelInfo | Share) => void;
}
export function ChannelList({ kind, title, onOpen }: Props) {
const channels = useChannels((s) => s.list);
const forgetChannel = useChannels((s) => s.forget);
const shares = useShares((s) => s.list);
const forgetShare = useShares((s) => s.forget);
const list = kind === 'share' ? shares : channels;
const [confirmId, setConfirmId] = useState<string>();
if (list.length === 0) return null;
return (
<section aria-label={title}>
<h2 className={styles.h}>{title}</h2>
<ul className={styles.list}>
{list.map((c) => (
<li key={c.id} className={styles.row}>
<button type="button" className={styles.open} onClick={() => onOpen(c)}>
<span className={styles.id}>{c.id.slice(0, 8)}…</span>
<span className={styles.meta}>
{'state' in c ? (
<>
<span className={styles.enc}><Icon name="lock" size={12} /> 加密</span>
<span className={c.state === 'sealed' ? styles.enc : styles.raw}>{c.state === 'sealed' ? '已封存' : '草稿'}</span>
<span>{c.mine ? '我创建的' : '收到的'}</span>
<span>{formatRemaining(c.createdAt + c.ttlSeconds * 1000)}</span>
</>
) : (
<>
<span className={c.mode === 'enc' ? styles.enc : styles.raw}>
{c.mode === 'enc' ? <><Icon name="lock" size={12} /> 加密</> : '明文'}
</span>
<span>{c.role === 'owner' ? '所有者' : '成员'}</span>
<span>{c.seats} 台设备</span>
<span>{formatAgo(c.createdAt)}创建</span>
</>
)}
</span>
</button>
{confirmId === c.id ? (
<span className={styles.confirm}>
<Button variant="ghost" onClick={() => { (kind === 'share' ? forgetShare : forgetChannel)(c.id); setConfirmId(undefined); }}>确认移除</Button>
<Button variant="ghost" onClick={() => setConfirmId(undefined)}>取消</Button>
</span>
) : (
<Button variant="ghost" icon="trash" label={kind === 'share' ? '从本机移除' : '从本机移除(不会删除频道)'} onClick={() => setConfirmId(c.id)} />
)}
</li>
))}
</ul>
</section>
);
}