import { useEffect, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useOnboarding } from '../onboarding/OnboardingContext' import { useThreadsAccount } from '../threads/ThreadsAccountContext' import { threadsAccountConnected, threadsAccountLabel, threadsAccountStatusLabel, } from '../lib/threadsAccount' import { ApiError } from '../api/client' import { Button, ErrorText, Field, Input } from './ui' import { AcIcon } from './AcIcon' function AccountAvatar({ connected, size = 'md', }: { connected: boolean size?: 'sm' | 'md' }) { const iconWrap = size === 'sm' ? '!h-7 !w-7' : '!h-8 !w-8' return ( ) } export function AccountSwitcher() { const navigate = useNavigate() const { accounts, activeAccountId, activeAccount, loading, switchAccount, createAccount } = useThreadsAccount() const { hasAccounts, refresh: refreshOnboarding } = useOnboarding() const [open, setOpen] = useState(false) const [panel, setPanel] = useState<'list' | 'create'>('list') const [creating, setCreating] = useState(false) const [displayName, setDisplayName] = useState('') const [error, setError] = useState('') const rootRef = useRef(null) useEffect(() => { if (!open) return const onPointer = (event: MouseEvent) => { if (!rootRef.current?.contains(event.target as Node)) { setOpen(false) setPanel('list') } } const onKey = (event: KeyboardEvent) => { if (event.key === 'Escape') { if (panel === 'create') { setPanel('list') setError('') return } setOpen(false) } } document.addEventListener('mousedown', onPointer) document.addEventListener('keydown', onKey) return () => { document.removeEventListener('mousedown', onPointer) document.removeEventListener('keydown', onKey) } }, [open, panel]) const connected = threadsAccountConnected(activeAccount) const label = loading ? '載入中' : threadsAccountLabel(activeAccount) function openCreatePanel() { setPanel('create') setDisplayName('') setError('') } async function pickAccount(id: string) { setOpen(false) setPanel('list') await switchAccount(id) const snapshot = await refreshOnboarding() navigate(snapshot.isComplete ? `/threads/${id}/publish` : '/settings') } async function handleCreate() { setCreating(true) setError('') try { const created = await createAccount({ displayName: displayName.trim() || undefined, }) setOpen(false) setPanel('list') const snapshot = await refreshOnboarding() navigate(snapshot.isComplete ? `/threads/${created.id}/publish` : '/settings') } catch (e) { setError(e instanceof ApiError ? e.message : '建立帳號失敗') } finally { setCreating(false) } } return (
{open ? (
{panel === 'list' ? ( <>

經營帳號

{accounts.length ? ( accounts.map((account) => { const isActive = account.id === activeAccountId const itemConnected = threadsAccountConnected(account) return ( ) }) ) : (

尚未建立 Threads 帳號

)}
) : (

新增經營帳號

建立後進入連線設定;人設請到側欄「人設庫」建立並綁定。

setDisplayName(e.target.value)} placeholder="側欄顯示用,不填則自動命名" autoFocus />
)}
) : null}
) }