feat: clone notifications UI and PGlite resync on clone

This commit is contained in:
CREDO23 2026-01-27 10:22:38 +02:00
parent a42780a2ec
commit 988847922f
3 changed files with 50 additions and 1 deletions

View file

@ -7,6 +7,7 @@ import {
Check,
CheckCheck,
CheckCircle2,
Copy,
History,
Inbox,
LayoutGrid,
@ -43,6 +44,8 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
import {
type ConnectorIndexingMetadata,
isChatClonedMetadata,
isChatCloneFailedMetadata,
isConnectorIndexingMetadata,
isNewMentionMetadata,
type NewMentionMetadata,
@ -196,10 +199,15 @@ export function InboxSidebar({
[inboxItems]
);
// Status tab includes: connector indexing, document processing, chat clone notifications
const statusItems = useMemo(
() =>
inboxItems.filter(
(item) => item.type === "connector_indexing" || item.type === "document_processing"
(item) =>
item.type === "connector_indexing" ||
item.type === "document_processing" ||
item.type === "chat_cloned" ||
item.type === "chat_clone_failed"
),
[inboxItems]
);
@ -320,7 +328,17 @@ export function InboxSidebar({
router.push(url);
}
}
} else if (item.type === "chat_cloned") {
// Navigate to the cloned chat
if (isChatClonedMetadata(item.metadata)) {
const { search_space_id, thread_id } = item.metadata;
const url = `/dashboard/${search_space_id}/new-chat/${thread_id}`;
onOpenChange(false);
onCloseMobileSidebar?.();
router.push(url);
}
}
// chat_clone_failed: just mark as read, no navigation
},
[markAsRead, router, onOpenChange, onCloseMobileSidebar]
);
@ -380,6 +398,24 @@ export function InboxSidebar({
);
}
// For chat cloned success, show green copy icon
if (item.type === "chat_cloned") {
return (
<div className="h-8 w-8 flex items-center justify-center rounded-full bg-green-500/10">
<Copy className="h-4 w-4 text-green-500" />
</div>
);
}
// For chat clone failed, show red alert icon
if (item.type === "chat_clone_failed") {
return (
<div className="h-8 w-8 flex items-center justify-center rounded-full bg-red-500/10">
<AlertCircle className="h-4 w-4 text-red-500" />
</div>
);
}
// For status items (connector/document), show status icons
// Safely access status from metadata
const metadata = item.metadata as Record<string, unknown>;

View file

@ -26,6 +26,9 @@ export function PublicChatFooter({ shareToken }: PublicChatFooterProps) {
share_token: shareToken,
});
// Force PGlite to resync notifications on next dashboard load
localStorage.setItem("surfsense_force_notif_resync", "true");
toast.success("Copying chat to your account...", {
description: "You'll be notified when it's ready.",
});

View file

@ -274,6 +274,16 @@ export async function initElectric(userId: string): Promise<ElectricClient> {
CREATE INDEX IF NOT EXISTS idx_new_chat_messages_created_at ON new_chat_messages(created_at);
`);
// Force resync notifications if flagged (e.g., after clone from public page)
if (
typeof window !== "undefined" &&
localStorage.getItem("surfsense_force_notif_resync") === "true"
) {
console.log("[Electric] Force resync flag detected, clearing notifications table");
await db.exec("DELETE FROM notifications");
localStorage.removeItem("surfsense_force_notif_resync");
}
const electricUrl = getElectricUrl();
// STEP 4: Create the client wrapper