"use client"; import { useCallback, useEffect, useState } from "react"; import { CheckCircle2, Eraser, Link2, Loader2, Unlink, XCircle, } from "lucide-react"; import { ChromeSessionSync } from "@/components/connections/chrome-session-sync"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { notify } from "@/lib/notifications/store"; import { cn } from "@/lib/utils"; interface SessionStatus { synced?: boolean; valid: boolean; username?: string | null; message: string; } interface ThreadsStatus { connected: boolean; accountName?: string | null; tokenExpiresAt?: string | null; appIdConfigured?: boolean; } export function AccountConnectionCard() { const [session, setSession] = useState(null); const [threads, setThreads] = useState(null); const [clearingSession, setClearingSession] = useState(false); const loadConnections = useCallback(async () => { try { const [sessionRes, threadsRes] = await Promise.all([ fetch("/api/session/status"), fetch("/api/threads/status"), ]); const [sessionData, threadsData] = await Promise.all([ sessionRes.json().catch(() => null), threadsRes.json().catch(() => null), ]); if (sessionData) setSession(sessionData); if (threadsData) setThreads(threadsData); } catch { // 網路異常時保持現狀,不阻塞頁面 } }, []); useEffect(() => { loadConnections(); }, [loadConnections]); async function handleClearSession() { setClearingSession(true); try { const res = await fetch("/api/session/clear", { method: "POST" }); const data = await res.json().catch(() => ({})); notify({ type: data.cleared ? "success" : "info", title: data.cleared ? "已清除瀏覽器 session" : "無需清除", message: data.message, }); window.dispatchEvent(new CustomEvent("haixun:accounts-updated")); loadConnections(); } catch { notify({ type: "error", title: "清除失敗", message: "網路連線異常,請稍後再試" }); } finally { setClearingSession(false); } } async function handleBindApi() { if (!threads?.appIdConfigured) { notify({ type: "warning", title: "無法綁定官方 API", message: "請由管理員在 server 的 .env 設定 THREADS_APP_ID 與 THREADS_APP_SECRET。", }); return; } const res = await fetch("/api/accounts/bind", { method: "POST" }); if (!res.ok) { const data = await res.json().catch(() => ({})); notify({ type: "error", title: "無法開始綁定", message: data.error }); return; } window.location.href = "/api/threads/oauth/authorize"; } async function handleDisconnectApi() { try { const res = await fetch("/api/threads/disconnect", { method: "POST" }); if (!res.ok) { const data = await res.json().catch(() => ({})); notify({ type: "error", title: "中斷失敗", message: data.error }); return; } notify({ type: "success", title: "已中斷官方 API 連線" }); window.dispatchEvent(new CustomEvent("haixun:accounts-updated")); loadConnections(); } catch { notify({ type: "error", title: "中斷失敗", message: "網路連線異常,請稍後再試" }); } } const sessionSynced = session?.synced ?? session?.valid; return ( 帳號連線 這個 Threads 經營帳號各自的登入狀態。Chrome 同步與官方 API OAuth 每帳號各做一次。
{sessionSynced ? ( ) : ( )}

Chrome Session 同步

{sessionSynced ? `已同步${session?.username ? ` · @${session.username}` : ""}` : "尚未同步 — 請在 Chrome 登入 threads.com 後按下方按鈕"}

{session?.message && (

{session.message}

)}

擴充安裝:Chrome → 開發人員模式 → 載入{" "} extension/haixun-threads-sync

{threads?.connected ? ( ) : ( )}

Threads 官方 API

{threads?.connected ? `已授權${threads.accountName ? ` · @${threads.accountName}` : ""}` : "尚未授權(選用,API 模式才需要)"}

{threads?.connected ? ( ) : ( )}

需要重設瀏覽器 session 時可清除,不影響官方 API token。

); }