haixunMaster/components/connections/chrome-session-sync.tsx

102 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useCallback, useEffect, useState } from "react";
import { Chrome, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { notify } from "@/lib/notifications/store";
interface ChromeSessionSyncProps {
onSynced?: () => void;
}
export function ChromeSessionSync({ onSynced }: ChromeSessionSyncProps) {
const [extensionReady, setExtensionReady] = useState(false);
const [syncing, setSyncing] = useState(false);
const [activeAccountId, setActiveAccountId] = useState<string | null>(null);
useEffect(() => {
fetch("/api/accounts")
.then((res) => res.json())
.then((data) => setActiveAccountId(data.activeAccountId ?? null))
.catch(() => undefined);
}, []);
const handleMessage = useCallback(
(event: MessageEvent) => {
if (event.source !== window) return;
if (event.data?.type === "HAIXUN_EXTENSION_READY") {
setExtensionReady(true);
return;
}
if (event.data?.type !== "HAIXUN_THREADS_SYNC_RESULT") return;
setSyncing(false);
const data = event.data as {
valid?: boolean;
message?: string;
};
notify({
type: data.valid ? "success" : "error",
title: data.valid ? "已同步到 server" : "同步失敗",
message: data.message,
});
if (data.valid) {
window.dispatchEvent(new CustomEvent("haixun:accounts-updated"));
onSynced?.();
}
},
[onSynced]
);
useEffect(() => {
window.addEventListener("message", handleMessage);
window.postMessage({ type: "HAIXUN_PING_EXTENSION" }, "*");
return () => window.removeEventListener("message", handleMessage);
}, [handleMessage]);
function handleSync() {
setSyncing(true);
window.postMessage(
{
type: "HAIXUN_REQUEST_THREADS_SYNC",
serverUrl: window.location.origin,
accountId: activeAccountId ?? undefined,
},
"*"
);
window.setTimeout(() => {
setSyncing((current) => {
if (current) {
notify({
type: "warning",
title: "尚未收到擴充功能回應",
message: "請在 Chrome 安裝並啟用 extension/haixun-threads-sync 擴充功能。",
});
}
return false;
});
}, 12000);
}
return (
<div className="space-y-3">
<p className="text-xs text-muted-foreground">
{extensionReady ? (
<span className="text-success"></span>
) : (
<span className="text-warning"> extension/haixun-threads-sync</span>
)}
</p>
<Button onClick={handleSync} disabled={syncing} className="w-full sm:w-auto">
{syncing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Chrome className="h-4 w-4" />}
{syncing ? "同步中…" : "從 Chrome 同步到目前帳號"}
</Button>
</div>
);
}