v0.9.0 636c44c

omnibox.ts RawHistoryFolder

1/**
2 * Omnibox Module Initialization
3 *
4 * Initializes the Svelte 5 omnibox component system
5 */
6
7import { mount } from "svelte";
8import { Omnibox } from "../../components/omnibox";
9import { ensureShadowMount } from "./shadowHost";
10import type { OmniboxConfig } from "../../components/omnibox/types";
11
12let omniboxComponent: ReturnType<typeof mount> | null = null;
13let isInitialized = false;
14
15export interface OmniboxInitConfig extends OmniboxConfig {
16  // Additional initialization options if needed
17  containerId?: string;
18}
19
20/**
21 * Initialize the omnibox component system
22 */
23export async function initializeOmnibox(
24  _config: OmniboxInitConfig = {},
25): Promise<void> {
26  if (isInitialized) {
27    console.warn("Omnibox already initialized");
28    return;
29  }
30
31  try {
32    // Ensure we're in the main frame (not an iframe)
33    if (window.self !== window.top) {
34      console.log("🚫 Omnibox skipped in iframe");
35      return;
36    }
37
38    // Check if DOM is ready
39    if (!document.body) {
40      console.warn("DOM body not ready for omnibox initialization");
41      return;
42    }
43
44    // Mount omnibox into the shared global Shadow DOM host
45    const mountEl = ensureShadowMount("dumber-omnibox");
46    omniboxComponent = mount(Omnibox, {
47      target: mountEl as unknown as Element,
48    });
49
50    // Wait for the component to mount and set up the global API
51    await new Promise<void>((resolve) => {
52      const checkAPI = () => {
53        if (
54          window.__dumber_omnibox &&
55          typeof window.__dumber_omnibox === "object"
56        ) {
57          console.log("✅ Omnibox component system initialized");
58          console.log(
59            "🔧 Global API is available:",
60            Object.keys(window.__dumber_omnibox),
61          );
62          isInitialized = true;
63          // Notify isolated bundle listeners that omnibox is ready
64          try {
65            document.dispatchEvent(new CustomEvent("dumber:omnibox-ready"));
66          } catch (e) {
67            console.warn("Failed to dispatch omnibox-ready event", e);
68          }
69          resolve();
70        } else {
71          setTimeout(checkAPI, 10); // Check again in 10ms
72        }
73      };
74      checkAPI();
75    });
76
77    // Bridge: listen for page-world events carrying suggestions and forward to API
78    const handleSuggestionsEvent = (e: Event) => {
79      try {
80        const detail = (e as CustomEvent).detail;
81        const suggestions = detail?.suggestions ?? detail;
82        if (
83          Array.isArray(suggestions) &&
84          window.__dumber_omnibox?.setSuggestions
85        ) {
86          console.log(
87            "🔗 [Bridge] Received page-world suggestions event:",
88            suggestions.length,
89          );
90          window.__dumber_omnibox.setSuggestions(suggestions);
91        } else {
92          console.warn(
93            "🔗 [Bridge] Suggestions event received but API not ready or invalid payload",
94          );
95        }
96      } catch (err) {
97        console.warn("🔗 [Bridge] Failed handling suggestions event:", err);
98      }
99    };
100
101    document.addEventListener(
102      "dumber:omnibox-suggestions",
103      handleSuggestionsEvent,
104      false,
105    );
106    // Unified event name
107    document.addEventListener(
108      "dumber:omnibox:suggestions",
109      handleSuggestionsEvent,
110      false,
111    );
112  } catch (error) {
113    console.error("❌ Failed to initialize omnibox component:", error);
114    throw error;
115  }
116}
117
118/**
119 * Get the current initialization status
120 */
121export function isOmniboxInitialized(): boolean {
122  return isInitialized;
123}
124
125/**
126 * Cleanup omnibox component (useful for hot reload during development)
127 */
128export function cleanupOmnibox(): void {
129  if (omniboxComponent) {
130    try {
131      omniboxComponent.$destroy?.();
132    } catch (error) {
133      console.warn("Error destroying omnibox component:", error);
134    }
135    omniboxComponent = null;
136  }
137
138  // The shared shadow host remains persistent; just log cleanup
139
140  isInitialized = false;
141  console.log("🧹 Omnibox component cleaned up");
142}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close