messaging.ts RawHistoryFolder
1/**
2 * Omnibox Message Bridge
3 *
4 * TypeScript interface for Go-JavaScript communication
5 */
6
7import type { OmniboxMessage, OmniboxMessageBridge, Suggestion } from "./types";
8import { omniboxStore } from "./stores.svelte.ts";
9
10export class OmniboxBridge implements OmniboxMessageBridge {
11 // Forward messages to the native WebKit message handler when available
12 // Fallback: for navigate, perform direct location change
13 postMessage(msg: OmniboxMessage): void {
14 console.log("📤 [DEBUG] Posting message to backend:", msg);
15 // NOTE: Do NOT detach postMessage from its receiver. In WKWebView,
16 // postMessage must be called on the UserMessageHandler instance.
17 const bridge = window.webkit?.messageHandlers?.dumber;
18 if (bridge && typeof bridge.postMessage === "function") {
19 try {
20 console.log("📱 [DEBUG] Using webkit message handler");
21 bridge.postMessage(JSON.stringify(msg));
22 return;
23 } catch (e) {
24 console.warn(
25 "postMessage to native handler failed, using fallback:",
26 e,
27 );
28 }
29 }
30 console.log("⚠️ [DEBUG] No webkit bridge available");
31 // Fallback navigation if no native bridge is available
32 if (msg.type === "navigate" && typeof msg.url === "string" && msg.url) {
33 try {
34 window.location.href = msg.url;
35 } catch (e) {
36 console.error("Fallback navigation failed:", e);
37 }
38 }
39 }
40
41 /**
42 * Update suggestions from Go backend
43 */
44 setSuggestions(suggestions: Suggestion[]): void {
45 console.log("📝 [DEBUG] Received suggestions from backend:", suggestions);
46 omniboxStore.updateSuggestions(suggestions);
47 }
48
49 /**
50 * Handle navigation request
51 */
52 navigate(url: string): void {
53 console.log("🚀 Omnibox navigate called with:", url);
54 this.postMessage({ type: "navigate", url });
55 }
56
57 /**
58 * Handle search query
59 */
60 query(searchTerm: string, limit?: number): void {
61 const q = searchTerm ?? "";
62 const lim = limit || omniboxStore.config.defaultLimit;
63 console.log("🔍 [DEBUG] Sending query to backend:", { q, limit: lim });
64 // Send to native handler; Go will compute suggestions and call setSuggestions
65 this.postMessage({ type: "query", q, limit: lim });
66 }
67
68 // Suggestions are returned via setSuggestions() when native handler responds
69}
70
71// Singleton instance
72export const omniboxBridge = new OmniboxBridge();
73
74/**
75 * Debounced query function for search input
76 */
77export function debouncedQuery(searchTerm: string): void {
78 omniboxStore.clearDebounceTimer();
79
80 const timerId = window.setTimeout(() => {
81 omniboxBridge.query(searchTerm);
82 }, omniboxStore.config.debounceDelay);
83
84 omniboxStore.setDebounceTimer(timerId);
85}
86
87// Extend global window interface for Go bridge compatibility
88declare global {
89 interface Window {
90 webkit?: {
91 messageHandlers?: {
92 dumber?: {
93 postMessage: (message: string) => void;
94 };
95 };
96 };
97 // Omnibox API for Go bridge
98 __dumber_omnibox?: {
99 setSuggestions: (suggestions: Suggestion[]) => void;
100 toggle: () => void;
101 open: (mode?: string, query?: string) => void;
102 close: () => void;
103 findQuery: (query: string) => void;
104 setActive: (active: boolean) => void;
105 };
106 }
107}