import { useState, useEffect, useCallback } from "react" import { createFileRoute } from "@tanstack/react-router" import { useAccount } from "jazz-tools/react" import { ViewerAccount, type GlideCanvasItem } from "@/lib/jazz/schema" import { Image, Trash2, ExternalLink, RefreshCw } from "lucide-react" export const Route = createFileRoute("/glide")({ component: GlidePage, ssr: false, }) function GlidePage() { const me = useAccount(ViewerAccount) const [syncing, setSyncing] = useState(false) const [lastSync, setLastSync] = useState(null) const root = me.$isLoaded ? me.root : null const canvasList = root?.$isLoaded ? root.glideCanvas : null // Auto-sync pending items every 5 seconds useEffect(() => { const interval = setInterval(() => { void syncPendingItems() }, 5000) return () => clearInterval(interval) }, [root]) const syncPendingItems = useCallback(async () => { if (!root?.glideCanvas?.$isLoaded || syncing) return setSyncing(true) try { // Fetch pending items from API const response = await fetch("/api/glide-canvas") if (!response.ok) { console.error("[glide] Failed to fetch pending items") return } const data = (await response.json()) as { items: GlideCanvasItem[] } const pendingItems = data.items if (pendingItems.length === 0) { return } console.log(`[glide] Syncing ${pendingItems.length} pending items to Jazz...`) // Get existing IDs to avoid duplicates const existingIds = new Set( root.glideCanvas.$isLoaded ? [...root.glideCanvas].map((item) => item.id) : [] ) // Push new items to Jazz let addedCount = 0 for (const item of pendingItems) { if (!existingIds.has(item.id)) { root.glideCanvas.$jazz.push(item) addedCount++ } } if (addedCount > 0) { console.log(`[glide] Added ${addedCount} new items to Jazz`) // Clear pending items after successful sync await fetch("/api/glide-canvas", { method: "DELETE" }) setLastSync(new Date()) } } catch (error) { console.error("[glide] Sync error:", error) } finally { setSyncing(false) } }, [root, syncing]) const handleManualSync = () => { void syncPendingItems() } const handleDeleteItem = (index: number) => { if (!root?.glideCanvas?.$isLoaded) return root.glideCanvas.$jazz.splice(index, 1) } if (!me.$isLoaded || !root?.$isLoaded) { return (

Loading Jazz...

) } const canvasItems: GlideCanvasItem[] = canvasList?.$isLoaded ? [...canvasList] : [] return (

Glide Canvas

{lastSync && ( Last sync: {lastSync.toLocaleTimeString()} )}
{canvasItems.length === 0 ? (

No canvas items yet

Capture screenshots from Glide browser (Ctrl+F) to see them here

) : (
{canvasItems.map((item, index) => ( ))}
)}
) } function CanvasItemCard({ item, index, onDelete, }: { item: GlideCanvasItem index: number onDelete: (index: number) => void }) { const imageUrl = item.imageData ? `data:image/png;base64,${item.imageData}` : null const createdAt = new Date(item.createdAt) return (
{imageUrl && (
{item.title}
)}

{item.title}

{item.type} ยท {createdAt.toLocaleDateString()}

{item.sourceUrl && ( )}
{item.metadata?.from && (

From: {item.metadata.from as string}

)} {item.position && (

Position: ({Math.round(item.position.x)}, {Math.round(item.position.y)})

)}
) }