v0.8.0 0fa6785

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

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