@ibgib/space-gib 0.0.32 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/bootstrap.mjs +24 -51
- package/dist/client/chunk-25PXC4HP.mjs +9914 -0
- package/dist/client/chunk-RXWLL2AI.mjs +30 -0
- package/dist/client/css/activity-bar.css +417 -0
- package/dist/client/css/base.css +167 -0
- package/dist/client/css/components.css +218 -0
- package/dist/client/css/cosmic.css +557 -0
- package/dist/client/css/dev-tools.css +163 -0
- package/dist/client/css/landing.css +184 -0
- package/dist/client/css/layout.css +896 -0
- package/dist/client/css/onboarding.css +181 -0
- package/dist/client/css/repos.css +740 -0
- package/dist/client/css/variables.css +64 -0
- package/dist/client/index.html +202 -31
- package/dist/client/index.mjs +31 -31
- package/dist/client/script.mjs +1 -1
- package/dist/client/style.css +11 -1056
- package/dist/respec-gib.node.mjs +5 -0
- package/dist/server/server.mjs +6879 -3109
- package/package.json +6 -6
- package/src/client/AUTO-GENERATED-version.mts +1 -1
- package/src/client/cosmos/seed-cosmos-workspace.mts +69 -0
- package/src/client/css/activity-bar.css +417 -0
- package/src/client/css/base.css +167 -0
- package/src/client/css/components.css +218 -0
- package/src/client/css/cosmic.css +557 -0
- package/src/client/css/dev-tools.css +163 -0
- package/src/client/css/landing.css +184 -0
- package/src/client/css/layout.css +896 -0
- package/src/client/css/onboarding.css +181 -0
- package/src/client/css/repos.css +740 -0
- package/src/client/css/variables.css +64 -0
- package/src/client/dev-tools/vcs-workspace.mts +3 -3
- package/src/client/index.html +202 -31
- package/src/client/style.css +11 -1056
- package/src/client/ui/component/chat-view/IMPLEMENTATION.md +48 -0
- package/src/client/ui/component/chat-view/chat-view.css +381 -0
- package/src/client/ui/component/chat-view/chat-view.html +104 -0
- package/src/client/ui/component/chat-view/chat-view.mts +277 -0
- package/src/client/ui/component/chat-view/index.mts +9 -0
- package/src/client/ui/component/clone/IMPLEMENTATION.md +68 -0
- package/src/client/ui/component/clone/clone-constants.mts +16 -0
- package/src/client/ui/component/clone/clone-types.mts +60 -0
- package/src/client/ui/component/clone/clone.css +383 -0
- package/src/client/ui/component/clone/clone.html +89 -0
- package/src/client/ui/component/clone/clone.mts +620 -0
- package/src/client/ui/component/clone/index.mts +11 -0
- package/src/client/ui/component/code-editor/IMPLEMENTATION.md +89 -0
- package/src/client/ui/component/code-editor/code-editor.css +275 -0
- package/src/client/ui/component/code-editor/code-editor.html +54 -0
- package/src/client/ui/component/code-editor/code-editor.mts +427 -0
- package/src/client/ui/component/code-editor/index.mts +9 -0
- package/src/client/ui/component/cosmos-navigator/IMPLEMENTATION.md +31 -0
- package/src/client/ui/component/cosmos-navigator/cosmos-navigator.css +864 -0
- package/src/client/ui/component/cosmos-navigator/cosmos-navigator.html +97 -0
- package/src/client/ui/component/cosmos-navigator/cosmos-navigator.mts +1084 -0
- package/src/client/ui/component/cosmos-navigator/index.mts +18 -0
- package/src/client/ui/component/file-explorer/IMPLEMENTATION.md +42 -0
- package/src/client/ui/component/file-explorer/file-explorer.css +256 -0
- package/src/client/ui/component/file-explorer/file-explorer.html +75 -0
- package/src/client/ui/component/file-explorer/file-explorer.mts +346 -0
- package/src/client/ui/component/file-explorer/index.mts +9 -0
- package/src/client/ui/component/nested-chat/IMPLEMENTATION.md +18 -0
- package/src/client/ui/component/nested-chat/chat/IMPLEMENTATION.md +14 -0
- package/src/client/ui/component/nested-chat/chat/chat-constants.mts +14 -0
- package/src/client/ui/component/nested-chat/chat/chat-helpers.mts +66 -0
- package/src/client/ui/component/nested-chat/chat/chat.css +654 -0
- package/src/client/ui/component/nested-chat/chat/chat.html +90 -0
- package/src/client/ui/component/nested-chat/chat/chat.mts +646 -0
- package/src/client/ui/component/nested-chat/chat/index.mts +7 -0
- package/src/client/ui/component/nested-chat/index.mts +14 -0
- package/src/client/ui/component/nested-chat/nested-chat-constants.mts +12 -0
- package/src/client/ui/component/nested-chat/nested-chat-types.mts +53 -0
- package/src/client/ui/component/nested-chat/nested-chat.css +142 -0
- package/src/client/ui/component/nested-chat/nested-chat.html +11 -0
- package/src/client/ui/component/nested-chat/nested-chat.mts +393 -0
- package/src/client/ui/component/notes-explorer/index.mts +9 -0
- package/src/client/ui/component/notes-explorer/notes-explorer.css +313 -0
- package/src/client/ui/component/notes-explorer/notes-explorer.html +136 -0
- package/src/client/ui/component/notes-explorer/notes-explorer.mts +240 -0
- package/src/client/ui/component/notes-inspector/index.mts +9 -0
- package/src/client/ui/component/notes-inspector/notes-inspector.css +244 -0
- package/src/client/ui/component/notes-inspector/notes-inspector.html +97 -0
- package/src/client/ui/component/notes-inspector/notes-inspector.mts +152 -0
- package/src/client/ui/component/pitch/IMPLEMENTATION.md +48 -0
- package/src/client/ui/component/pitch/index.mts +9 -0
- package/src/client/ui/component/pitch/pitch.css +295 -0
- package/src/client/ui/component/pitch/pitch.html +97 -0
- package/src/client/ui/component/pitch/pitch.mts +135 -0
- package/src/client/ui/component/timeline/IMPLEMENTATION.md +33 -0
- package/src/client/ui/component/timeline/index.mts +9 -0
- package/src/client/ui/component/timeline/timeline.css +264 -0
- package/src/client/ui/component/timeline/timeline.html +23 -0
- package/src/client/ui/component/timeline/timeline.mts +317 -0
- package/src/client/ui/component/timeline-item-details/IMPLEMENTATION.md +28 -0
- package/src/client/ui/component/timeline-item-details/index.mts +9 -0
- package/src/client/ui/component/timeline-item-details/timeline-item-details.css +286 -0
- package/src/client/ui/component/timeline-item-details/timeline-item-details.html +64 -0
- package/src/client/ui/component/timeline-item-details/timeline-item-details.mts +194 -0
- package/src/client/ui/router/index.mts +3 -0
- package/src/client/ui/router/space-gib-router-helpers.mts +272 -0
- package/src/client/ui/router/space-gib-router-helpers.respec.mts +353 -0
- package/src/client/ui/router/space-gib-router-service.mts +186 -0
- package/src/client/ui/router/space-gib-router-types.mts +93 -0
- package/src/client/ui/shell/cosmic-big-bang.mts +844 -0
- package/src/client/ui/shell/space-gib-shell-constants.mts +7 -0
- package/src/client/ui/shell/space-gib-shell-service.mts +1728 -31
- package/src/server/server.mts +20 -1
- package/tsconfig.test.json +5 -1
- package/dist/client/chunk-AX6BROMT.mjs +0 -1
- package/dist/client/chunk-CIQUGV7U.mjs +0 -25
- package/dist/client/chunk-YPCHYDKL.mjs +0 -3102
|
@@ -1,32 +1,96 @@
|
|
|
1
1
|
import { extractErrorMsg } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
|
|
2
|
+
import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
|
|
2
3
|
import { ROOT_ADDR } from "@ibgib/ts-gib/dist/V1/constants.mjs";
|
|
3
4
|
import { getComponentSvc } from "@ibgib/web-gib/dist/ui/component/ibgib-component-service.mjs";
|
|
4
|
-
import { IbGibDynamicComponentMeta } from "@ibgib/web-gib/dist/ui/component/component-types.mjs";
|
|
5
|
-
|
|
6
|
-
import { APP_CONFIG } from "../../constants.mjs";
|
|
7
|
-
import { getIbGibGlobalThis_SpaceGib } from "../../helpers.web.mjs";
|
|
8
|
-
import {
|
|
9
|
-
ID_APP_ROOT, ID_HEADER_PANEL, ID_LEFT_PANEL, ID_CENTER_PANEL,
|
|
10
|
-
ID_RIGHT_PANEL, ID_FOOTER_PANEL, ID_LEFT_RESIZER, ID_RIGHT_RESIZER,
|
|
11
|
-
ID_FOOTER_RESIZER, ID_BTN_LEFT_PANEL_TOGGLE, ID_BTN_RIGHT_PANEL_TOGGLE,
|
|
12
|
-
ID_BTN_CREATE_KEYSTONE, ID_CENTER_PANEL_CONTENT
|
|
13
|
-
} from "./space-gib-shell-constants.mjs";
|
|
14
5
|
import {
|
|
15
6
|
EVENT_IBGIB_SHELL_READY, EVENT_IBGIB_UI_BUSY, EVENT_IBGIB_UI_MESSAGE,
|
|
16
|
-
|
|
17
|
-
UI_ACTION_SHOW_ADD_DEVICE,
|
|
7
|
+
EVENT_IBGIB_IDENTITY_CHANGED, UI_ACTION_SHOW_IDENTITY_MANAGER,
|
|
8
|
+
UI_ACTION_SHOW_KEYSTONE_CREATOR, UI_ACTION_SHOW_ADD_DEVICE,
|
|
9
|
+
UI_ACTION_SHOW_PRIVACY_POLICY
|
|
18
10
|
} from "@ibgib/web-gib/dist/ui/ui-constants.mjs";
|
|
19
11
|
import { showFullscreenDialog, FullscreenDialogController } from "@ibgib/web-gib/dist/ui/ui-helpers.mjs";
|
|
20
|
-
import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
|
|
21
12
|
import { getKeystoneSyncService } from "@ibgib/web-gib/dist/identity/keystone-sync-service.mjs";
|
|
22
|
-
import { PanelState } from "./space-gib-shell-types.mjs";
|
|
23
13
|
import { registerStandardIdentityComponents } from "@ibgib/web-gib/dist/ui/component/identity/index.mjs";
|
|
24
14
|
import { registerPrivacyPolicyComponent } from "@ibgib/web-gib/dist/ui/component/privacy-policy/index.mjs";
|
|
15
|
+
import { registerAdminReviewComponent } from "@ibgib/web-gib/dist/ui/component/admin/admin-review/index.mjs";
|
|
16
|
+
|
|
17
|
+
import { APP_CONFIG } from "../../constants.mjs";
|
|
18
|
+
import { getIbGibGlobalThis_SpaceGib } from "../../helpers.web.mjs";
|
|
19
|
+
import {
|
|
20
|
+
ID_HEADER_PANEL, ID_LEFT_PANEL, ID_CENTER_PANEL, ID_RIGHT_PANEL,
|
|
21
|
+
ID_FOOTER_PANEL, ID_LEFT_RESIZER, ID_RIGHT_RESIZER, ID_FOOTER_RESIZER,
|
|
22
|
+
ID_BTN_LEFT_PANEL_TOGGLE, ID_BTN_RIGHT_PANEL_TOGGLE, ID_BTN_CREATE_KEYSTONE,
|
|
23
|
+
ID_CENTER_PANEL_CONTENT,
|
|
24
|
+
} from "./space-gib-shell-constants.mjs";
|
|
25
|
+
import { PanelState } from "./space-gib-shell-types.mjs";
|
|
26
|
+
import {
|
|
27
|
+
registerCosmosNavigatorComponent, COSMOS_NAVIGATOR_COMPONENT_NAME,
|
|
28
|
+
CosmosNavigatorComponentInstance, CosmosInfo,
|
|
29
|
+
} from "../component/cosmos-navigator/index.mjs";
|
|
30
|
+
import {
|
|
31
|
+
registerFileExplorerComponent, FILE_EXPLORER_COMPONENT_NAME,
|
|
32
|
+
FileExplorerComponentInstance,
|
|
33
|
+
} from "../component/file-explorer/index.mjs";
|
|
34
|
+
import {
|
|
35
|
+
registerTimelineComponent, TIMELINE_COMPONENT_NAME,
|
|
36
|
+
TimelineComponentInstance, TimelineItem,
|
|
37
|
+
} from "../component/timeline/index.mjs";
|
|
38
|
+
import {
|
|
39
|
+
registerTimelineItemDetailsComponent, TIMELINE_ITEM_DETAILS_COMPONENT_NAME,
|
|
40
|
+
TimelineItemDetailsComponentInstance,
|
|
41
|
+
} from "../component/timeline-item-details/index.mjs";
|
|
42
|
+
import {
|
|
43
|
+
registerChatViewComponent, ChatViewComponentInstance,
|
|
44
|
+
} from "../component/chat-view/index.mjs";
|
|
45
|
+
import {
|
|
46
|
+
registerNestedChatComponent, NESTED_CHAT_COMPONENT_NAME,
|
|
47
|
+
NestedChatComponentInstance,
|
|
48
|
+
} from "../component/nested-chat/index.mjs";
|
|
49
|
+
import {
|
|
50
|
+
registerPitchComponent, PITCH_COMPONENT_NAME, PitchComponentInstance,
|
|
51
|
+
} from "../component/pitch/index.mjs";
|
|
52
|
+
import {
|
|
53
|
+
registerCodeEditorComponent, CODE_EDITOR_COMPONENT_NAME,
|
|
54
|
+
CodeEditorComponentInstance,
|
|
55
|
+
} from "../component/code-editor/index.mjs";
|
|
56
|
+
import {
|
|
57
|
+
registerCloneComponent, CLONE_COMPONENT_NAME, CloneComponentInstance,
|
|
58
|
+
CloneModalOptions, EVENT_SPACE_GIB_CLONE_CLOSED,
|
|
59
|
+
} from "../component/clone/index.mjs";
|
|
60
|
+
import {
|
|
61
|
+
registerNotesExplorerComponent, NOTES_EXPLORER_COMPONENT_NAME,
|
|
62
|
+
NotesExplorerComponentInstance,
|
|
63
|
+
} from "../component/notes-explorer/index.mjs";
|
|
64
|
+
import {
|
|
65
|
+
registerNotesInspectorComponent, NOTES_INSPECTOR_COMPONENT_NAME,
|
|
66
|
+
NotesInspectorComponentInstance,
|
|
67
|
+
} from "../component/notes-inspector/index.mjs";
|
|
68
|
+
import {
|
|
69
|
+
getSpaceGibRouterSvc,
|
|
70
|
+
SpaceGibRouteInfo,
|
|
71
|
+
SpaceGibTenant,
|
|
72
|
+
RawAddrRouteInfo,
|
|
73
|
+
RawTjpRouteInfo,
|
|
74
|
+
} from "../router/index.mjs";
|
|
75
|
+
import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
|
|
76
|
+
import { prewarmPlaygroundMetaspace } from "../../cosmos/seed-cosmos-workspace.mjs";
|
|
77
|
+
|
|
25
78
|
|
|
26
79
|
export class SpaceGibShellService {
|
|
27
80
|
private lc: string = `[SpaceGibShellService]`;
|
|
28
81
|
|
|
29
82
|
public initialized: Promise<void>;
|
|
83
|
+
private isApplyingRoute: boolean = false;
|
|
84
|
+
private cosmosNavigatorInstance?: CosmosNavigatorComponentInstance;
|
|
85
|
+
private fileExplorerInstance?: FileExplorerComponentInstance;
|
|
86
|
+
private timelineInstance?: TimelineComponentInstance;
|
|
87
|
+
private timelineItemDetailsInstance?: TimelineItemDetailsComponentInstance;
|
|
88
|
+
private chatViewInstance?: ChatViewComponentInstance;
|
|
89
|
+
private nestedChatInstance?: NestedChatComponentInstance;
|
|
90
|
+
private pitchInstance?: PitchComponentInstance;
|
|
91
|
+
private codeEditorInstance?: CodeEditorComponentInstance;
|
|
92
|
+
private notesExplorerInstance?: NotesExplorerComponentInstance;
|
|
93
|
+
private notesInspectorInstance?: NotesInspectorComponentInstance;
|
|
30
94
|
|
|
31
95
|
// Panel States
|
|
32
96
|
private leftPanelState: PanelState = 'collapsed';
|
|
@@ -37,6 +101,9 @@ export class SpaceGibShellService {
|
|
|
37
101
|
private isResizingRight = false;
|
|
38
102
|
private isResizingFooter = false;
|
|
39
103
|
|
|
104
|
+
// Playground Banner State
|
|
105
|
+
private hasBigBangExploded = false;
|
|
106
|
+
|
|
40
107
|
constructor() {
|
|
41
108
|
this.initialized = this.initialize();
|
|
42
109
|
}
|
|
@@ -45,6 +112,12 @@ export class SpaceGibShellService {
|
|
|
45
112
|
this.initElements();
|
|
46
113
|
this.initEventHandlers();
|
|
47
114
|
await this.registerComponents();
|
|
115
|
+
await this.initCosmosNavigator();
|
|
116
|
+
await this.initFileExplorer();
|
|
117
|
+
await this.initTimeline();
|
|
118
|
+
await this.initChatView();
|
|
119
|
+
await this.initCodeEditor();
|
|
120
|
+
await this.initPitch();
|
|
48
121
|
}
|
|
49
122
|
|
|
50
123
|
private initElements(): void {
|
|
@@ -60,6 +133,14 @@ export class SpaceGibShellService {
|
|
|
60
133
|
private initEventHandlers(): void {
|
|
61
134
|
const lc = `${this.lc}[${this.initEventHandlers.name}]`;
|
|
62
135
|
try {
|
|
136
|
+
// Playground Mode Banner actions
|
|
137
|
+
const btnBannerCreate = document.getElementById('btn-banner-create-identity');
|
|
138
|
+
if (btnBannerCreate) {
|
|
139
|
+
btnBannerCreate.addEventListener('click', () => {
|
|
140
|
+
this.showKeystoneCreator();
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
63
144
|
// Left Panel Toggle
|
|
64
145
|
const btnLeft = document.getElementById(ID_BTN_LEFT_PANEL_TOGGLE);
|
|
65
146
|
if (btnLeft) {
|
|
@@ -123,6 +204,8 @@ export class SpaceGibShellService {
|
|
|
123
204
|
this.showAddDevice();
|
|
124
205
|
} else if (action === UI_ACTION_SHOW_PRIVACY_POLICY) {
|
|
125
206
|
this.showPrivacyPolicy();
|
|
207
|
+
} else if (action === 'show-admin-review' || action === 'admin-review') {
|
|
208
|
+
this.showAdminReview();
|
|
126
209
|
}
|
|
127
210
|
});
|
|
128
211
|
|
|
@@ -162,11 +245,47 @@ export class SpaceGibShellService {
|
|
|
162
245
|
}
|
|
163
246
|
});
|
|
164
247
|
|
|
248
|
+
// Mode Switcher (Spaces vs Repositories)
|
|
249
|
+
this.initModeSwitcher();
|
|
250
|
+
|
|
165
251
|
} catch (error) {
|
|
166
252
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
167
253
|
}
|
|
168
254
|
}
|
|
169
255
|
|
|
256
|
+
private currentMode: 'spaces' | 'repos' | 'notes' = 'spaces';
|
|
257
|
+
|
|
258
|
+
private setMode(mode: 'spaces' | 'repos' | 'notes', notesTitle?: string): void {
|
|
259
|
+
this.currentMode = mode;
|
|
260
|
+
if (mode === 'repos') {
|
|
261
|
+
this.showCode();
|
|
262
|
+
} else if (mode === 'notes') {
|
|
263
|
+
this.showNotes(notesTitle);
|
|
264
|
+
} else {
|
|
265
|
+
this.showCosmos();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private initModeSwitcher(): void {
|
|
270
|
+
const lc = `${this.lc}[${this.initModeSwitcher.name}]`;
|
|
271
|
+
try {
|
|
272
|
+
// URL param mode check (spaces by default, in-memory)
|
|
273
|
+
let initialMode: 'spaces' | 'repos' = 'spaces';
|
|
274
|
+
try {
|
|
275
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
276
|
+
const urlMode = urlParams.get('mode');
|
|
277
|
+
if (urlMode === 'repos') {
|
|
278
|
+
initialMode = 'repos';
|
|
279
|
+
}
|
|
280
|
+
} catch {
|
|
281
|
+
// ignore
|
|
282
|
+
}
|
|
283
|
+
this.setMode(initialMode);
|
|
284
|
+
} catch (error) {
|
|
285
|
+
console.error(`${lc} ${extractErrorMsg(error)} (E: c8e054e0639221c7b673949d9b2a2d26)`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
170
289
|
public async showIdentityManager() {
|
|
171
290
|
const lc = `${this.lc}[${this.showIdentityManager.name}]`;
|
|
172
291
|
try {
|
|
@@ -262,6 +381,37 @@ export class SpaceGibShellService {
|
|
|
262
381
|
}
|
|
263
382
|
}
|
|
264
383
|
|
|
384
|
+
public async showAdminReview(tjpGib?: string) {
|
|
385
|
+
const lc = `${this.lc}[${this.showAdminReview.name}]`;
|
|
386
|
+
try {
|
|
387
|
+
const componentSvc = await getComponentSvc();
|
|
388
|
+
|
|
389
|
+
// create the component
|
|
390
|
+
const adminReviewComponent = await componentSvc.getComponentInstance({
|
|
391
|
+
path: 'ibgib-admin-review',
|
|
392
|
+
ibGibAddr: ROOT_ADDR, // Virtual address for initial render
|
|
393
|
+
useRegExpPrefilter: true,
|
|
394
|
+
});
|
|
395
|
+
if (!adminReviewComponent) { throw new Error(`(UNEXPECTED) adminReviewComponent falsy? (E: 8392a019bb2819827364810293847199)`); }
|
|
396
|
+
|
|
397
|
+
if (tjpGib && typeof (adminReviewComponent as any).setTjpGib === 'function') {
|
|
398
|
+
(adminReviewComponent as any).setTjpGib(tjpGib);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// get a ref to the parent container
|
|
402
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
403
|
+
if (!centerPanel) { throw new Error(`(UNEXPECTED) centerPanel falsy? (E: 9392a019bb2819827364810293847199)`); }
|
|
404
|
+
|
|
405
|
+
// inject via componentSvc
|
|
406
|
+
await componentSvc.inject({
|
|
407
|
+
parentEl: centerPanel,
|
|
408
|
+
componentToInject: adminReviewComponent
|
|
409
|
+
});
|
|
410
|
+
} catch (error) {
|
|
411
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
265
415
|
private toggleLeftPanel() {
|
|
266
416
|
this.leftPanelState = this.leftPanelState === 'expanded' ? 'collapsed' : 'expanded';
|
|
267
417
|
const panel = document.getElementById(ID_LEFT_PANEL);
|
|
@@ -326,40 +476,1587 @@ export class SpaceGibShellService {
|
|
|
326
476
|
try {
|
|
327
477
|
await registerStandardIdentityComponents();
|
|
328
478
|
await registerPrivacyPolicyComponent();
|
|
479
|
+
await registerAdminReviewComponent();
|
|
480
|
+
await registerCosmosNavigatorComponent();
|
|
481
|
+
await registerFileExplorerComponent();
|
|
482
|
+
await registerTimelineComponent();
|
|
483
|
+
await registerTimelineItemDetailsComponent();
|
|
484
|
+
await registerChatViewComponent();
|
|
485
|
+
await registerNestedChatComponent();
|
|
486
|
+
await registerPitchComponent();
|
|
487
|
+
await registerCodeEditorComponent();
|
|
488
|
+
await registerCloneComponent();
|
|
489
|
+
await registerNotesExplorerComponent();
|
|
490
|
+
await registerNotesInspectorComponent();
|
|
329
491
|
} catch (error) {
|
|
330
492
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
331
493
|
}
|
|
332
494
|
}
|
|
333
495
|
|
|
334
|
-
|
|
335
|
-
const lc = `${this.lc}[${this.
|
|
496
|
+
private async initCosmosNavigator(): Promise<void> {
|
|
497
|
+
const lc = `${this.lc}[${this.initCosmosNavigator.name}]`;
|
|
336
498
|
try {
|
|
337
|
-
await
|
|
338
|
-
|
|
499
|
+
const componentSvc = await getComponentSvc();
|
|
500
|
+
this.cosmosNavigatorInstance = await componentSvc.getComponentInstance({
|
|
501
|
+
path: COSMOS_NAVIGATOR_COMPONENT_NAME,
|
|
502
|
+
ibGibAddr: ROOT_ADDR,
|
|
503
|
+
useRegExpPrefilter: true,
|
|
504
|
+
}) as CosmosNavigatorComponentInstance;
|
|
339
505
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
506
|
+
if (!this.cosmosNavigatorInstance) {
|
|
507
|
+
throw new Error(`Failed to instantiate ${COSMOS_NAVIGATOR_COMPONENT_NAME}`);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
this.bindCosmosNavigatorEvents();
|
|
511
|
+
this.bindCosmosChromeEvents();
|
|
512
|
+
|
|
513
|
+
// Initial state sync
|
|
514
|
+
const activeCosmos = this.cosmosNavigatorInstance.getActiveCosmos();
|
|
515
|
+
if (activeCosmos) {
|
|
516
|
+
this.updateActiveCosmosDisplay(activeCosmos);
|
|
517
|
+
}
|
|
518
|
+
const allCosmoses = this.cosmosNavigatorInstance.getCosmoses();
|
|
519
|
+
if (allCosmoses.length > 0) {
|
|
520
|
+
this.revealChrome();
|
|
521
|
+
}
|
|
522
|
+
this.updatePolycosmosList(allCosmoses, activeCosmos?.id || null);
|
|
523
|
+
|
|
524
|
+
// Inject directly into center panel on startup
|
|
525
|
+
await this.showCosmos();
|
|
526
|
+
|
|
527
|
+
} catch (error) {
|
|
528
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
public async showCosmos(): Promise<void> {
|
|
533
|
+
const lc = `${this.lc}[${this.showCosmos.name}]`;
|
|
534
|
+
try {
|
|
535
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
536
|
+
if (!centerPanel) {
|
|
537
|
+
console.warn(`${lc} ${ID_CENTER_PANEL_CONTENT} element not found.`);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (!this.cosmosNavigatorInstance) {
|
|
542
|
+
const componentSvc = await getComponentSvc();
|
|
543
|
+
this.cosmosNavigatorInstance = await componentSvc.getComponentInstance({
|
|
544
|
+
path: COSMOS_NAVIGATOR_COMPONENT_NAME,
|
|
545
|
+
ibGibAddr: ROOT_ADDR,
|
|
546
|
+
useRegExpPrefilter: true,
|
|
547
|
+
}) as CosmosNavigatorComponentInstance;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (this.cosmosNavigatorInstance) {
|
|
551
|
+
const componentSvc = await getComponentSvc();
|
|
552
|
+
await componentSvc.inject({
|
|
553
|
+
parentEl: centerPanel,
|
|
554
|
+
componentToInject: this.cosmosNavigatorInstance,
|
|
555
|
+
});
|
|
556
|
+
this.cosmosNavigatorInstance.ensureStars();
|
|
557
|
+
}
|
|
558
|
+
} catch (error) {
|
|
559
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
private async initFileExplorer(): Promise<void> {
|
|
564
|
+
const lc = `${this.lc}[${this.initFileExplorer.name}]`;
|
|
565
|
+
try {
|
|
566
|
+
const container = document.getElementById('code-file-explorer-container');
|
|
567
|
+
if (!container) {
|
|
568
|
+
console.warn(`${lc} code-file-explorer-container element not found.`);
|
|
569
|
+
return;
|
|
344
570
|
}
|
|
345
571
|
|
|
346
|
-
// Mount identity-header component in the header bar
|
|
347
572
|
const componentSvc = await getComponentSvc();
|
|
348
|
-
|
|
349
|
-
path:
|
|
573
|
+
this.fileExplorerInstance = await componentSvc.getComponentInstance({
|
|
574
|
+
path: FILE_EXPLORER_COMPONENT_NAME,
|
|
350
575
|
ibGibAddr: ROOT_ADDR,
|
|
351
576
|
useRegExpPrefilter: true,
|
|
577
|
+
}) as FileExplorerComponentInstance;
|
|
578
|
+
|
|
579
|
+
if (!this.fileExplorerInstance) {
|
|
580
|
+
throw new Error(`Failed to instantiate ${FILE_EXPLORER_COMPONENT_NAME}`);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
await componentSvc.inject({
|
|
584
|
+
parentEl: container,
|
|
585
|
+
componentToInject: this.fileExplorerInstance,
|
|
352
586
|
});
|
|
353
587
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
588
|
+
this.bindFileExplorerEvents();
|
|
589
|
+
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
private bindFileExplorerEvents(): void {
|
|
596
|
+
window.addEventListener('space-gib-file-selected', (e: any) => {
|
|
597
|
+
const { branch, path, filename } = e.detail || {};
|
|
598
|
+
console.log(`${this.lc} File selected: ${path || filename} on worktree branch ${branch}`);
|
|
599
|
+
const fullFile = path || filename || 'src/index.ts';
|
|
600
|
+
const branchName = branch || 'main';
|
|
601
|
+
const tipAddr = '7f8a1b2';
|
|
602
|
+
this.chatViewInstance?.setTargetFile(fullFile, `${branchName} @ ${tipAddr}`);
|
|
603
|
+
this.nestedChatInstance?.activateIbGib({ addr: `file ${fullFile}^${tipAddr}` });
|
|
604
|
+
|
|
605
|
+
let mockContent: string | undefined = undefined;
|
|
606
|
+
if (fullFile === 'src/helper.ts') {
|
|
607
|
+
mockContent = `/**\n * @module my-app/helper\n * Utility functions for space-gib in-memory VCS.\n */\n\nexport function add(a: number, b: number): number {\n return a + b;\n}\n\nexport function multiply(a: number, b: number): number {\n return a * b;\n}\n`;
|
|
608
|
+
} else if (fullFile === 'README.md') {
|
|
609
|
+
mockContent = `# my-app\n\nDecentralized version-controlled application running on **space-gib**.\n\n- Zero SaaS lock-in\n- Inverted soft rel8ns for living companion discussions\n- Merkle DAG branch worktrees\n`;
|
|
610
|
+
} else if (fullFile === 'tsconfig.json') {
|
|
611
|
+
mockContent = `{\n "compilerOptions": {\n "target": "ES2022",\n "module": "NodeNext",\n "strict": true,\n "esModuleInterop": true\n }\n}\n`;
|
|
358
612
|
}
|
|
359
613
|
|
|
360
|
-
|
|
614
|
+
this.showCode(fullFile, branchName).then(() => {
|
|
615
|
+
this.codeEditorInstance?.loadFile({
|
|
616
|
+
filepath: fullFile,
|
|
617
|
+
branch: branchName,
|
|
618
|
+
tipAddr,
|
|
619
|
+
content: mockContent,
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// Reveal discussions in right panel
|
|
624
|
+
this.expandRightPanel();
|
|
625
|
+
|
|
626
|
+
const activeCosmos = this.cosmosNavigatorInstance?.getActiveCosmos();
|
|
627
|
+
if (activeCosmos) {
|
|
628
|
+
const tenant = this.getActiveTenant();
|
|
629
|
+
getSpaceGibRouterSvc().navigate({
|
|
630
|
+
kind: 'code-galaxy',
|
|
631
|
+
cosmos: activeCosmos.id || activeCosmos.name,
|
|
632
|
+
galaxyId: 'code-1',
|
|
633
|
+
branch: branchName,
|
|
634
|
+
filePath: fullFile,
|
|
635
|
+
...(tenant ? { tenant } : {}),
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
window.addEventListener('space-gib-new-file-requested', (e: any) => {
|
|
641
|
+
const { branch } = e.detail || {};
|
|
642
|
+
const filename = prompt(`Create new file on branch [${branch || 'main'}]:`, 'untitled.ts');
|
|
643
|
+
if (filename) {
|
|
644
|
+
console.log(`${this.lc} New file requested: ${filename} on branch ${branch}`);
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
window.addEventListener('space-gib-new-folder-requested', (e: any) => {
|
|
649
|
+
const { branch } = e.detail || {};
|
|
650
|
+
const foldername = prompt(`Create new folder on branch [${branch || 'main'}]:`, 'components');
|
|
651
|
+
if (foldername) {
|
|
652
|
+
console.log(`${this.lc} New folder requested: ${foldername} on branch ${branch}`);
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
private async initTimeline(): Promise<void> {
|
|
658
|
+
const lc = `${this.lc}[${this.initTimeline.name}]`;
|
|
659
|
+
try {
|
|
660
|
+
const container = document.getElementById('code-timeline-container');
|
|
661
|
+
if (!container) {
|
|
662
|
+
console.warn(`${lc} code-timeline-container element not found.`);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const componentSvc = await getComponentSvc();
|
|
667
|
+
this.timelineInstance = await componentSvc.getComponentInstance({
|
|
668
|
+
path: TIMELINE_COMPONENT_NAME,
|
|
669
|
+
ibGibAddr: ROOT_ADDR,
|
|
670
|
+
useRegExpPrefilter: true,
|
|
671
|
+
}) as TimelineComponentInstance;
|
|
672
|
+
|
|
673
|
+
if (!this.timelineInstance) {
|
|
674
|
+
throw new Error(`Failed to instantiate ${TIMELINE_COMPONENT_NAME}`);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
await componentSvc.inject({
|
|
678
|
+
parentEl: container,
|
|
679
|
+
componentToInject: this.timelineInstance,
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
this.bindTimelineEvents();
|
|
683
|
+
|
|
684
|
+
} catch (error) {
|
|
685
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
private bindTimelineEvents(): void {
|
|
690
|
+
window.addEventListener('space-gib-timeline-item-selected', (e: any) => {
|
|
691
|
+
const item: TimelineItem = e.detail?.item;
|
|
692
|
+
if (item) {
|
|
693
|
+
console.log(`${this.lc} Timeline snapshot selected: ${item.shortHash} - ${item.message}`);
|
|
694
|
+
this.showTimelineItemDetails(item);
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
window.addEventListener('space-gib-timeline-details-closed', () => {
|
|
699
|
+
console.log(`${this.lc} Timeline details closed. Returning to previous view.`);
|
|
700
|
+
const currentRoute = getSpaceGibRouterSvc().getCurrentRoute();
|
|
701
|
+
if (currentRoute && (currentRoute.kind === 'raw-addr' || currentRoute.kind === 'raw-tjp')) {
|
|
702
|
+
const tenant = this.getActiveTenant() || currentRoute.tenant;
|
|
703
|
+
getSpaceGibRouterSvc().navigate({
|
|
704
|
+
kind: 'cosmos',
|
|
705
|
+
cosmos: currentRoute.cosmos,
|
|
706
|
+
...(tenant ? { tenant } : {}),
|
|
707
|
+
});
|
|
708
|
+
} else {
|
|
709
|
+
this.showCode();
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
private async initChatView(): Promise<void> {
|
|
715
|
+
const lc = `${this.lc}[${this.initChatView.name}]`;
|
|
716
|
+
try {
|
|
717
|
+
const container = document.getElementById('code-chat-view-container');
|
|
718
|
+
if (!container) {
|
|
719
|
+
console.warn(`${lc} code-chat-view-container element not found.`);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
const componentSvc = await getComponentSvc();
|
|
724
|
+
this.nestedChatInstance = await componentSvc.getComponentInstance({
|
|
725
|
+
path: NESTED_CHAT_COMPONENT_NAME,
|
|
726
|
+
ibGibAddr: ROOT_ADDR,
|
|
727
|
+
useRegExpPrefilter: true,
|
|
728
|
+
}) as NestedChatComponentInstance;
|
|
729
|
+
|
|
730
|
+
if (!this.nestedChatInstance) {
|
|
731
|
+
throw new Error(`Failed to instantiate ${NESTED_CHAT_COMPONENT_NAME}`);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
await componentSvc.inject({
|
|
735
|
+
parentEl: container,
|
|
736
|
+
componentToInject: this.nestedChatInstance,
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
this.bindChatViewEvents();
|
|
740
|
+
|
|
741
|
+
} catch (error) {
|
|
742
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
private bindChatViewEvents(): void {
|
|
747
|
+
window.addEventListener('space-gib-chat-close-requested', () => {
|
|
748
|
+
this.toggleRightPanel();
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
window.addEventListener('space-gib-chat-closed', () => {
|
|
752
|
+
if (this.rightPanelState === 'expanded') {
|
|
753
|
+
this.toggleRightPanel();
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
window.addEventListener('space-gib-chat-message-sent', (e: any) => {
|
|
758
|
+
const { message, targetFile, contextAddr } = e.detail || {};
|
|
759
|
+
console.log(`${this.lc} Chat message sent on context ${contextAddr || targetFile}:`, message);
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
private async initCodeEditor(): Promise<void> {
|
|
764
|
+
const lc = `${this.lc}[${this.initCodeEditor.name}]`;
|
|
765
|
+
try {
|
|
766
|
+
const componentSvc = await getComponentSvc();
|
|
767
|
+
this.codeEditorInstance = await componentSvc.getComponentInstance({
|
|
768
|
+
path: CODE_EDITOR_COMPONENT_NAME,
|
|
769
|
+
ibGibAddr: ROOT_ADDR,
|
|
770
|
+
useRegExpPrefilter: true,
|
|
771
|
+
}) as CodeEditorComponentInstance;
|
|
772
|
+
|
|
773
|
+
if (!this.codeEditorInstance) {
|
|
774
|
+
throw new Error(`Failed to instantiate ${CODE_EDITOR_COMPONENT_NAME}`);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
this.bindCodeEditorEvents();
|
|
778
|
+
|
|
779
|
+
} catch (error) {
|
|
780
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
public async showCode(filePath?: string, branch?: string): Promise<void> {
|
|
785
|
+
const lc = `${this.lc}[${this.showCode.name}]`;
|
|
786
|
+
try {
|
|
787
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
788
|
+
if (!centerPanel) {
|
|
789
|
+
console.warn(`${lc} ${ID_CENTER_PANEL_CONTENT} element not found.`);
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (!this.codeEditorInstance) {
|
|
794
|
+
const componentSvc = await getComponentSvc();
|
|
795
|
+
this.codeEditorInstance = await componentSvc.getComponentInstance({
|
|
796
|
+
path: CODE_EDITOR_COMPONENT_NAME,
|
|
797
|
+
ibGibAddr: ROOT_ADDR,
|
|
798
|
+
useRegExpPrefilter: true,
|
|
799
|
+
}) as CodeEditorComponentInstance;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if (this.codeEditorInstance) {
|
|
803
|
+
const componentSvc = await getComponentSvc();
|
|
804
|
+
await componentSvc.inject({
|
|
805
|
+
parentEl: centerPanel,
|
|
806
|
+
componentToInject: this.codeEditorInstance,
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
if (filePath) {
|
|
810
|
+
let content: string | undefined = undefined;
|
|
811
|
+
if (filePath === 'src/helper.ts') {
|
|
812
|
+
content = `/**\n * @module my-app/helper\n * Utility functions for space-gib in-memory VCS.\n */\n\nexport function add(a: number, b: number): number {\n return a + b;\n}\n\nexport function multiply(a: number, b: number): number {\n return a * b;\n}\n`;
|
|
813
|
+
} else if (filePath === 'README.md') {
|
|
814
|
+
content = `# my-app\n\nDecentralized version-controlled application running on **space-gib**.\n\n- Zero SaaS lock-in\n- Inverted soft rel8ns for living companion discussions\n- Merkle DAG branch worktrees\n`;
|
|
815
|
+
} else if (filePath === 'tsconfig.json') {
|
|
816
|
+
content = `{\n "compilerOptions": {\n "target": "ES2022",\n "module": "NodeNext",\n "strict": true,\n "esModuleInterop": true\n }\n}\n`;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
this.codeEditorInstance.loadFile({
|
|
820
|
+
filepath: filePath,
|
|
821
|
+
branch: branch || 'main',
|
|
822
|
+
tipAddr: '7f8a1b2',
|
|
823
|
+
content,
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
const codeChatContainer = document.getElementById('code-chat-view-container');
|
|
829
|
+
const notesInspectorContainer = document.getElementById('notes-inspector-container');
|
|
830
|
+
if (notesInspectorContainer) { notesInspectorContainer.style.display = 'none'; }
|
|
831
|
+
if (codeChatContainer) {
|
|
832
|
+
codeChatContainer.style.display = 'block';
|
|
833
|
+
if (this.nestedChatInstance && this.nestedChatInstance.parentElement !== codeChatContainer) {
|
|
834
|
+
codeChatContainer.appendChild(this.nestedChatInstance as any);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
this.expandRightPanel();
|
|
839
|
+
} catch (error) {
|
|
840
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
public async showNotes(
|
|
845
|
+
title?: string,
|
|
846
|
+
opts?: {
|
|
847
|
+
trail?: string[];
|
|
848
|
+
trailMode?: 'tjp' | 'addr';
|
|
849
|
+
query?: Record<string, string | undefined>;
|
|
850
|
+
}
|
|
851
|
+
): Promise<void> {
|
|
852
|
+
const lc = `${this.lc}[${this.showNotes.name}]`;
|
|
853
|
+
try {
|
|
854
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
855
|
+
if (!centerPanel) {
|
|
856
|
+
console.warn(`${lc} ${ID_CENTER_PANEL_CONTENT} element not found.`);
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// In Notes mode, Center Panel is the primary nested chat topic stream!
|
|
861
|
+
if (!this.nestedChatInstance) {
|
|
862
|
+
const componentSvc = await getComponentSvc();
|
|
863
|
+
this.nestedChatInstance = await componentSvc.getComponentInstance({
|
|
864
|
+
path: NESTED_CHAT_COMPONENT_NAME,
|
|
865
|
+
ibGibAddr: ROOT_ADDR,
|
|
866
|
+
useRegExpPrefilter: true,
|
|
867
|
+
}) as NestedChatComponentInstance;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
if (this.nestedChatInstance) {
|
|
871
|
+
const componentSvc = await getComponentSvc();
|
|
872
|
+
await componentSvc.inject({
|
|
873
|
+
parentEl: centerPanel,
|
|
874
|
+
componentToInject: this.nestedChatInstance,
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
if (opts?.trail && opts.trail.length > 0) {
|
|
878
|
+
for (const step of opts.trail) {
|
|
879
|
+
const stepAddr = opts.trailMode === 'addr' ? step : `topic ${step}^gib_notes`;
|
|
880
|
+
await this.nestedChatInstance.activateIbGib({ addr: stepAddr });
|
|
881
|
+
}
|
|
882
|
+
} else {
|
|
883
|
+
await this.nestedChatInstance.activateIbGib({ addr: `topic ${title || 'Notes Space 1'}^gib_notes` });
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// In Notes mode, Right Panel is the contextual inspector!
|
|
888
|
+
await this.initNotesInspector();
|
|
889
|
+
const codeChatContainer = document.getElementById('code-chat-view-container');
|
|
890
|
+
const notesInspectorContainer = document.getElementById('notes-inspector-container');
|
|
891
|
+
if (codeChatContainer) { codeChatContainer.style.display = 'none'; }
|
|
892
|
+
if (notesInspectorContainer) { notesInspectorContainer.style.display = 'block'; }
|
|
893
|
+
|
|
894
|
+
if (opts?.query?.inspect && this.notesInspectorInstance) {
|
|
895
|
+
const inspectVal = opts.query.inspect;
|
|
896
|
+
if (inspectVal.includes('#L')) {
|
|
897
|
+
const [file, lineStr] = inspectVal.split('#L');
|
|
898
|
+
this.notesInspectorInstance.inspectFileAnchor({
|
|
899
|
+
file,
|
|
900
|
+
line: Number(lineStr) || 1,
|
|
901
|
+
snippet: `// Anchor in ${file} at line ${lineStr}`,
|
|
902
|
+
});
|
|
903
|
+
} else {
|
|
904
|
+
this.notesInspectorInstance.inspectNode({ addr: inspectVal });
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
this.expandRightPanel();
|
|
909
|
+
} catch (error) {
|
|
910
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
private async initNotesExplorer(title?: string): Promise<void> {
|
|
915
|
+
const lc = `${this.lc}[${this.initNotesExplorer.name}]`;
|
|
916
|
+
try {
|
|
917
|
+
const container = document.getElementById('notes-explorer-container');
|
|
918
|
+
if (!container) {
|
|
919
|
+
console.warn(`${lc} notes-explorer-container element not found.`);
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
if (!this.notesExplorerInstance) {
|
|
924
|
+
const componentSvc = await getComponentSvc();
|
|
925
|
+
this.notesExplorerInstance = await componentSvc.getComponentInstance({
|
|
926
|
+
path: NOTES_EXPLORER_COMPONENT_NAME,
|
|
927
|
+
ibGibAddr: ROOT_ADDR,
|
|
928
|
+
useRegExpPrefilter: true,
|
|
929
|
+
}) as NotesExplorerComponentInstance;
|
|
930
|
+
|
|
931
|
+
if (this.notesExplorerInstance) {
|
|
932
|
+
await componentSvc.inject({
|
|
933
|
+
parentEl: container,
|
|
934
|
+
componentToInject: this.notesExplorerInstance,
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (title && this.notesExplorerInstance) {
|
|
940
|
+
this.notesExplorerInstance.setTitle(title);
|
|
941
|
+
}
|
|
942
|
+
} catch (error) {
|
|
943
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
private async initNotesInspector(): Promise<void> {
|
|
948
|
+
const lc = `${this.lc}[${this.initNotesInspector.name}]`;
|
|
949
|
+
try {
|
|
950
|
+
const container = document.getElementById('notes-inspector-container');
|
|
951
|
+
if (!container) { return; }
|
|
952
|
+
|
|
953
|
+
if (!this.notesInspectorInstance) {
|
|
954
|
+
const componentSvc = await getComponentSvc();
|
|
955
|
+
this.notesInspectorInstance = await componentSvc.getComponentInstance({
|
|
956
|
+
path: NOTES_INSPECTOR_COMPONENT_NAME,
|
|
957
|
+
ibGibAddr: ROOT_ADDR,
|
|
958
|
+
useRegExpPrefilter: true,
|
|
959
|
+
}) as NotesInspectorComponentInstance;
|
|
960
|
+
|
|
961
|
+
if (this.notesInspectorInstance) {
|
|
962
|
+
await componentSvc.inject({
|
|
963
|
+
parentEl: container,
|
|
964
|
+
componentToInject: this.notesInspectorInstance,
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
} catch (error) {
|
|
969
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
public async showTimelineItemDetails(item: TimelineItem): Promise<void> {
|
|
974
|
+
const lc = `${this.lc}[${this.showTimelineItemDetails.name}]`;
|
|
975
|
+
try {
|
|
976
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
977
|
+
if (!centerPanel) {
|
|
978
|
+
console.warn(`${lc} ${ID_CENTER_PANEL_CONTENT} element not found.`);
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
if (!this.timelineItemDetailsInstance) {
|
|
983
|
+
const componentSvc = await getComponentSvc();
|
|
984
|
+
this.timelineItemDetailsInstance = await componentSvc.getComponentInstance({
|
|
985
|
+
path: TIMELINE_ITEM_DETAILS_COMPONENT_NAME,
|
|
986
|
+
ibGibAddr: ROOT_ADDR,
|
|
987
|
+
useRegExpPrefilter: true,
|
|
988
|
+
}) as TimelineItemDetailsComponentInstance;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
if (this.timelineItemDetailsInstance) {
|
|
992
|
+
const componentSvc = await getComponentSvc();
|
|
993
|
+
await componentSvc.inject({
|
|
994
|
+
parentEl: centerPanel,
|
|
995
|
+
componentToInject: this.timelineItemDetailsInstance,
|
|
996
|
+
});
|
|
997
|
+
|
|
998
|
+
this.timelineItemDetailsInstance.setTimelineItem(item);
|
|
999
|
+
}
|
|
1000
|
+
} catch (error) {
|
|
1001
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
private bindCodeEditorEvents(): void {
|
|
1006
|
+
window.addEventListener('space-gib-code-changed', (e: any) => {
|
|
1007
|
+
const { filepath, lineCount } = e.detail || {};
|
|
1008
|
+
console.log(`${this.lc} Code changed in ${filepath} (${lineCount} lines)`);
|
|
1009
|
+
});
|
|
1010
|
+
|
|
1011
|
+
window.addEventListener('space-gib-code-copied', (e: any) => {
|
|
1012
|
+
const { filepath } = e.detail || {};
|
|
1013
|
+
console.log(`${this.lc} Code copied from ${filepath}`);
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
private async initPitch(): Promise<void> {
|
|
1018
|
+
const lc = `${this.lc}[${this.initPitch.name}]`;
|
|
1019
|
+
try {
|
|
1020
|
+
const componentSvc = await getComponentSvc();
|
|
1021
|
+
this.pitchInstance = await componentSvc.getComponentInstance({
|
|
1022
|
+
path: PITCH_COMPONENT_NAME,
|
|
1023
|
+
ibGibAddr: ROOT_ADDR,
|
|
1024
|
+
useRegExpPrefilter: true,
|
|
1025
|
+
}) as PitchComponentInstance;
|
|
1026
|
+
|
|
1027
|
+
if (!this.pitchInstance) {
|
|
1028
|
+
throw new Error(`Failed to instantiate ${PITCH_COMPONENT_NAME}`);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
this.bindPitchEvents();
|
|
1032
|
+
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
private bindPitchEvents(): void {
|
|
1039
|
+
window.addEventListener('space-gib-pitch-closed', () => {
|
|
1040
|
+
this.closePitch();
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
public collapsePanels(): void {
|
|
1045
|
+
this.leftPanelState = 'collapsed';
|
|
1046
|
+
const leftPanel = document.getElementById(ID_LEFT_PANEL);
|
|
1047
|
+
if (leftPanel) {
|
|
1048
|
+
leftPanel.classList.add('collapsed');
|
|
1049
|
+
}
|
|
1050
|
+
this.rightPanelState = 'collapsed';
|
|
1051
|
+
const rightPanel = document.getElementById(ID_RIGHT_PANEL);
|
|
1052
|
+
if (rightPanel) {
|
|
1053
|
+
rightPanel.classList.add('collapsed');
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
public async showPitch(): Promise<void> {
|
|
1058
|
+
const lc = `${this.lc}[${this.showPitch.name}]`;
|
|
1059
|
+
try {
|
|
1060
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
1061
|
+
if (!centerPanel) {
|
|
1062
|
+
console.warn(`${lc} ${ID_CENTER_PANEL_CONTENT} element not found.`);
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
if (!this.pitchInstance) {
|
|
1067
|
+
const componentSvc = await getComponentSvc();
|
|
1068
|
+
this.pitchInstance = await componentSvc.getComponentInstance({
|
|
1069
|
+
path: PITCH_COMPONENT_NAME,
|
|
1070
|
+
ibGibAddr: ROOT_ADDR,
|
|
1071
|
+
useRegExpPrefilter: true,
|
|
1072
|
+
}) as PitchComponentInstance;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
if (this.pitchInstance) {
|
|
1076
|
+
const componentSvc = await getComponentSvc();
|
|
1077
|
+
await componentSvc.inject({
|
|
1078
|
+
parentEl: centerPanel,
|
|
1079
|
+
componentToInject: this.pitchInstance,
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
this.collapsePanels();
|
|
1084
|
+
} catch (error) {
|
|
1085
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
public closePitch(): void {
|
|
1090
|
+
this.showCosmos();
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
public async openCloneModal(options?: CloneModalOptions): Promise<void> {
|
|
1094
|
+
const lc = `${this.lc}[${this.openCloneModal.name}]`;
|
|
1095
|
+
try {
|
|
1096
|
+
const componentSvc = await getComponentSvc();
|
|
1097
|
+
const cloneInstance = await componentSvc.getComponentInstance({
|
|
1098
|
+
path: CLONE_COMPONENT_NAME,
|
|
1099
|
+
ibGibAddr: ROOT_ADDR,
|
|
1100
|
+
useRegExpPrefilter: true,
|
|
1101
|
+
}) as CloneComponentInstance;
|
|
1102
|
+
|
|
1103
|
+
if (!cloneInstance) {
|
|
1104
|
+
throw new Error(`Failed to instantiate ${CLONE_COMPONENT_NAME}`);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
const activeCosmos = this.cosmosNavigatorInstance?.getActiveCosmos();
|
|
1108
|
+
const effectiveOpts: CloneModalOptions = {
|
|
1109
|
+
cosmosId: activeCosmos?.id || 'cosmos-1',
|
|
1110
|
+
cosmosName: activeCosmos?.name || 'Cosmos 1',
|
|
1111
|
+
...options,
|
|
1112
|
+
};
|
|
1113
|
+
cloneInstance.setOptions(effectiveOpts);
|
|
1114
|
+
|
|
1115
|
+
document.body.appendChild(cloneInstance);
|
|
1116
|
+
|
|
1117
|
+
cloneInstance.addEventListener(EVENT_SPACE_GIB_CLONE_CLOSED, () => {
|
|
1118
|
+
cloneInstance.remove();
|
|
1119
|
+
});
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
public revealChrome(): void {
|
|
1126
|
+
const header = document.getElementById(ID_HEADER_PANEL);
|
|
1127
|
+
const footer = document.getElementById(ID_FOOTER_PANEL);
|
|
1128
|
+
const footerResizer = document.getElementById(ID_FOOTER_RESIZER);
|
|
1129
|
+
|
|
1130
|
+
header?.classList.remove('pre-bang-hidden');
|
|
1131
|
+
header?.classList.add('chrome-fade-in');
|
|
1132
|
+
|
|
1133
|
+
footer?.classList.remove('pre-bang-hidden');
|
|
1134
|
+
footer?.classList.add('chrome-fade-in');
|
|
1135
|
+
|
|
1136
|
+
footerResizer?.classList.remove('pre-bang-hidden');
|
|
1137
|
+
footerResizer?.classList.add('chrome-fade-in');
|
|
1138
|
+
|
|
1139
|
+
setTimeout(() => {
|
|
1140
|
+
header?.classList.remove('chrome-fade-in');
|
|
1141
|
+
header?.classList.add('chrome-revealed');
|
|
1142
|
+
footer?.classList.remove('chrome-fade-in');
|
|
1143
|
+
footer?.classList.add('chrome-revealed');
|
|
1144
|
+
footerResizer?.classList.remove('chrome-fade-in');
|
|
1145
|
+
footerResizer?.classList.add('chrome-revealed');
|
|
1146
|
+
}, 2500);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
public setActiveActivityBarButton(type: 'polycosmos' | 'cosmos' | 'space', spaceId?: string): void {
|
|
1150
|
+
const btnPoly = document.getElementById('activity-btn-polycosmos');
|
|
1151
|
+
const btnCosmos = document.getElementById('activity-btn-cosmos');
|
|
1152
|
+
const activitySpaces = document.getElementById('activity-spaces-container');
|
|
1153
|
+
|
|
1154
|
+
if (type === 'polycosmos') {
|
|
1155
|
+
btnPoly?.classList.add('active');
|
|
1156
|
+
btnCosmos?.classList.remove('active');
|
|
1157
|
+
activitySpaces?.querySelectorAll('.activity-bar-btn').forEach(b => b.classList.remove('active'));
|
|
1158
|
+
} else if (type === 'cosmos') {
|
|
1159
|
+
btnCosmos?.classList.add('active');
|
|
1160
|
+
btnPoly?.classList.remove('active');
|
|
1161
|
+
activitySpaces?.querySelectorAll('.activity-bar-btn').forEach(b => b.classList.remove('active'));
|
|
1162
|
+
} else if (type === 'space') {
|
|
1163
|
+
btnPoly?.classList.remove('active');
|
|
1164
|
+
btnCosmos?.classList.remove('active');
|
|
1165
|
+
if (activitySpaces) {
|
|
1166
|
+
let matched = false;
|
|
1167
|
+
activitySpaces.querySelectorAll('.activity-bar-btn').forEach(b => {
|
|
1168
|
+
const isMatch = b.getAttribute('data-space-id') === spaceId ||
|
|
1169
|
+
b.getAttribute('data-space-type') === spaceId;
|
|
1170
|
+
b.classList.toggle('active', isMatch);
|
|
1171
|
+
if (isMatch) matched = true;
|
|
1172
|
+
});
|
|
1173
|
+
if (!matched && (spaceId === 'code' || spaceId === 'text')) {
|
|
1174
|
+
const firstOfType = activitySpaces.querySelector(`.activity-bar-btn[data-space-type="${spaceId}"]`);
|
|
1175
|
+
firstOfType?.classList.add('active');
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
private bindCosmosNavigatorEvents(): void {
|
|
1182
|
+
window.addEventListener('space-gib-big-bang-exploded', () => {
|
|
1183
|
+
this.hasBigBangExploded = true;
|
|
1184
|
+
this.revealChrome();
|
|
1185
|
+
this.updatePlaygroundBannerVisibility();
|
|
1186
|
+
});
|
|
1187
|
+
|
|
1188
|
+
window.addEventListener('space-gib-identity-docked', () => {
|
|
1189
|
+
const identityContainer = document.getElementById('identity-header-container');
|
|
1190
|
+
if (identityContainer) {
|
|
1191
|
+
if (!this.hasActiveIdentity()) {
|
|
1192
|
+
identityContainer.classList.add('identity-active-highlight');
|
|
1193
|
+
}
|
|
1194
|
+
const btn = identityContainer.querySelector('button') || identityContainer;
|
|
1195
|
+
(btn as HTMLElement).focus?.();
|
|
1196
|
+
}
|
|
1197
|
+
});
|
|
1198
|
+
|
|
1199
|
+
window.addEventListener(EVENT_IBGIB_IDENTITY_CHANGED, () => {
|
|
1200
|
+
const identityContainer = document.getElementById('identity-header-container');
|
|
1201
|
+
if (this.hasActiveIdentity()) {
|
|
1202
|
+
identityContainer?.classList.remove('identity-active-highlight');
|
|
1203
|
+
}
|
|
1204
|
+
this.updatePlaygroundBannerVisibility();
|
|
1205
|
+
});
|
|
1206
|
+
|
|
1207
|
+
window.addEventListener('space-gib-agent-docked', () => {
|
|
1208
|
+
const btnAgent = document.getElementById('btn-footer-agent');
|
|
1209
|
+
if (btnAgent) {
|
|
1210
|
+
btnAgent.classList.add('is-docked');
|
|
1211
|
+
btnAgent.classList.add('agent-btn-docked-pulse');
|
|
1212
|
+
setTimeout(() => {
|
|
1213
|
+
btnAgent.classList.remove('agent-btn-docked-pulse');
|
|
1214
|
+
}, 1800);
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
window.addEventListener('space-gib-pitch-docked', () => {
|
|
1219
|
+
const btnPitch = document.getElementById('btn-header-pitch');
|
|
1220
|
+
if (btnPitch) {
|
|
1221
|
+
btnPitch.classList.add('is-docked');
|
|
1222
|
+
btnPitch.classList.add('pitch-btn-active-pulse');
|
|
1223
|
+
setTimeout(() => {
|
|
1224
|
+
btnPitch.classList.remove('pitch-btn-active-pulse');
|
|
1225
|
+
}, 2000);
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
|
|
1229
|
+
window.addEventListener('space-gib-pitch-requested', () => {
|
|
1230
|
+
this.showPitch();
|
|
1231
|
+
});
|
|
1232
|
+
|
|
1233
|
+
window.addEventListener('space-gib-cosmos-selected', (e: any) => {
|
|
1234
|
+
const cosmos: CosmosInfo = e.detail?.cosmos;
|
|
1235
|
+
if (cosmos) {
|
|
1236
|
+
this.updateActiveCosmosDisplay(cosmos);
|
|
1237
|
+
this.showLeftPanelView('cosmos');
|
|
1238
|
+
if (!this.isApplyingRoute) {
|
|
1239
|
+
const tenant = this.getActiveTenant() || (cosmos.isTemporary ? { type: 'username', siteUsername: 'playground' } : undefined);
|
|
1240
|
+
getSpaceGibRouterSvc().navigate({
|
|
1241
|
+
kind: 'cosmos',
|
|
1242
|
+
cosmos: cosmos.name || cosmos.id,
|
|
1243
|
+
...(tenant ? { tenant } : {}),
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
});
|
|
1248
|
+
|
|
1249
|
+
window.addEventListener('space-gib-activity-bar-expand-requested', () => {
|
|
1250
|
+
this.expandActivityBar();
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1253
|
+
window.addEventListener('space-gib-space-added', (e: any) => {
|
|
1254
|
+
const { space, cosmos } = e.detail;
|
|
1255
|
+
if (cosmos) {
|
|
1256
|
+
this.updateActiveCosmosDisplay(cosmos, space?.id || space?.type);
|
|
1257
|
+
}
|
|
1258
|
+
this.expandActivityBar();
|
|
1259
|
+
this.expandLeftPanel();
|
|
1260
|
+
|
|
1261
|
+
if (space) {
|
|
1262
|
+
this.setActiveActivityBarButton('space', space.id);
|
|
1263
|
+
const dockedBtn = document.querySelector(`.activity-space-btn[data-space-id="${space.id}"]`);
|
|
1264
|
+
if (dockedBtn) {
|
|
1265
|
+
dockedBtn.classList.add('space-btn-docked-pulse');
|
|
1266
|
+
setTimeout(() => {
|
|
1267
|
+
dockedBtn.classList.remove('space-btn-docked-pulse');
|
|
1268
|
+
}, 1800);
|
|
1269
|
+
}
|
|
1270
|
+
if (space.type === 'code') {
|
|
1271
|
+
this.showLeftPanelView('code', space.name);
|
|
1272
|
+
this.switchToReposMode();
|
|
1273
|
+
} else if (space.type === 'text') {
|
|
1274
|
+
this.showLeftPanelView('text', space.name);
|
|
1275
|
+
this.switchToNotesMode(space.name);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
window.addEventListener('space-gib-polycosmos-activated', (e: any) => {
|
|
1281
|
+
const { cosmoses, activeCosmosId } = e.detail;
|
|
1282
|
+
this.updatePolycosmosDisplay(cosmoses || [], activeCosmosId);
|
|
1283
|
+
this.showLeftPanelView('polycosmos');
|
|
1284
|
+
if (!this.isApplyingRoute) {
|
|
1285
|
+
const tenant = this.getActiveTenant();
|
|
1286
|
+
getSpaceGibRouterSvc().navigate({
|
|
1287
|
+
kind: 'polycosmos',
|
|
1288
|
+
...(tenant ? { tenant } : {}),
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
private bindCosmosChromeEvents(): void {
|
|
1295
|
+
const btnHeaderPolycosmos = document.getElementById('btn-header-polycosmos');
|
|
1296
|
+
const btnHeaderCosmosSelect = document.getElementById('btn-header-cosmos-select');
|
|
1297
|
+
const headerCosmosMenu = document.getElementById('header-cosmos-menu');
|
|
1298
|
+
const activityBtnPolycosmos = document.getElementById('activity-btn-polycosmos');
|
|
1299
|
+
const activityBtnCosmos = document.getElementById('activity-btn-cosmos');
|
|
1300
|
+
const btnSideNewCosmos = document.getElementById('btn-side-new-cosmos');
|
|
1301
|
+
const brandGalaxy = document.getElementById('header-brand-galaxy');
|
|
1302
|
+
const btnFooterAgent = document.getElementById('btn-footer-agent');
|
|
1303
|
+
const btnHeaderPitch = document.getElementById('btn-header-pitch');
|
|
1304
|
+
const btnHeaderClone = document.getElementById('btn-header-clone');
|
|
1305
|
+
|
|
1306
|
+
btnHeaderPitch?.addEventListener('click', () => {
|
|
1307
|
+
this.showPitch();
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
btnHeaderClone?.addEventListener('click', () => {
|
|
1311
|
+
this.openCloneModal();
|
|
1312
|
+
});
|
|
1313
|
+
|
|
1314
|
+
window.addEventListener('space-gib-clone-requested', (e: any) => {
|
|
1315
|
+
this.openCloneModal(e.detail);
|
|
1316
|
+
});
|
|
1317
|
+
|
|
1318
|
+
window.addEventListener('space-gib-branch-requested', (e: any) => {
|
|
1319
|
+
const { galaxyName, sourceBranch, newBranchName, scope, itemPath } = e.detail || {};
|
|
1320
|
+
const scopeDesc = scope === 'item' ? `item [${itemPath}]` : `worktree [${sourceBranch}]`;
|
|
1321
|
+
console.log(`${this.lc} [Phase 2 Branch Stub] Created branch: [${newBranchName}] diverging from ${scopeDesc} in ${galaxyName || 'Code Galaxy'}`);
|
|
1322
|
+
this.showLeftPanelView('code', 'Code Space');
|
|
1323
|
+
this.fileExplorerInstance?.setBranch(newBranchName);
|
|
1324
|
+
});
|
|
1325
|
+
|
|
1326
|
+
btnFooterAgent?.addEventListener('click', () => {
|
|
1327
|
+
alert('🤖 ibgib Agent: "Hello! I am your AI assistant across superspaces. How can I help you today?"');
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
const goToPolycosmos = () => {
|
|
1331
|
+
this.switchToSpacesMode();
|
|
1332
|
+
this.cosmosNavigatorInstance?.setZoomState('polycosmos');
|
|
1333
|
+
this.setActiveActivityBarButton('polycosmos');
|
|
1334
|
+
this.showLeftPanelView('polycosmos');
|
|
1335
|
+
const allCosmoses = this.cosmosNavigatorInstance?.getCosmoses() || [];
|
|
1336
|
+
const activeCosmos = this.cosmosNavigatorInstance?.getActiveCosmos();
|
|
1337
|
+
this.updatePolycosmosDisplay(allCosmoses, activeCosmos?.id || null);
|
|
1338
|
+
|
|
1339
|
+
const tenant = this.getActiveTenant();
|
|
1340
|
+
getSpaceGibRouterSvc().navigate({
|
|
1341
|
+
kind: 'polycosmos',
|
|
1342
|
+
...(tenant ? { tenant } : {}),
|
|
1343
|
+
});
|
|
1344
|
+
};
|
|
1345
|
+
|
|
1346
|
+
const goToCosmos = () => {
|
|
1347
|
+
this.switchToSpacesMode();
|
|
1348
|
+
this.cosmosNavigatorInstance?.setZoomState('cosmos');
|
|
1349
|
+
this.setActiveActivityBarButton('cosmos');
|
|
1350
|
+
this.showLeftPanelView('cosmos');
|
|
1351
|
+
const activeCosmos = this.cosmosNavigatorInstance?.getActiveCosmos();
|
|
1352
|
+
if (activeCosmos) {
|
|
1353
|
+
this.updateActiveCosmosDisplay(activeCosmos);
|
|
1354
|
+
const tenant = this.getActiveTenant() || (activeCosmos.isTemporary ? { type: 'username', siteUsername: 'playground' } : undefined);
|
|
1355
|
+
getSpaceGibRouterSvc().navigate({
|
|
1356
|
+
kind: 'cosmos',
|
|
1357
|
+
cosmos: activeCosmos.name || activeCosmos.id,
|
|
1358
|
+
...(tenant ? { tenant } : {}),
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
|
|
1363
|
+
window.addEventListener('space-gib-new-note-requested', async (e: any) => {
|
|
1364
|
+
const { title } = e.detail || {};
|
|
1365
|
+
await this.showNotes();
|
|
1366
|
+
this.nestedChatInstance?.enterNewTopicMode(title);
|
|
1367
|
+
});
|
|
1368
|
+
|
|
1369
|
+
window.addEventListener('space-gib-note-selected', (e: any) => {
|
|
1370
|
+
const { file, line } = e.detail || {};
|
|
1371
|
+
if (file) {
|
|
1372
|
+
this.notesInspectorInstance?.inspectFileAnchor({ file, line });
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
window.addEventListener('space-gib-jump-to-code-requested', (e: any) => {
|
|
1377
|
+
const { file, line } = e.detail || {};
|
|
1378
|
+
this.showLeftPanelView('code', 'Code Galaxy 1');
|
|
1379
|
+
this.showCode(file);
|
|
1380
|
+
this.setActiveActivityBarButton('space', 'space-code-1');
|
|
1381
|
+
});
|
|
1382
|
+
|
|
1383
|
+
window.addEventListener('space-gib-inspector-close-requested', () => {
|
|
1384
|
+
this.toggleRightPanel();
|
|
1385
|
+
});
|
|
1386
|
+
|
|
1387
|
+
btnHeaderPolycosmos?.addEventListener('click', () => goToPolycosmos());
|
|
1388
|
+
activityBtnPolycosmos?.addEventListener('click', () => goToPolycosmos());
|
|
1389
|
+
brandGalaxy?.addEventListener('click', (e) => {
|
|
1390
|
+
e.preventDefault();
|
|
1391
|
+
goToPolycosmos();
|
|
1392
|
+
});
|
|
1393
|
+
const brandTitle = document.querySelector('.brand-title');
|
|
1394
|
+
brandTitle?.addEventListener('click', (e) => {
|
|
1395
|
+
e.preventDefault();
|
|
1396
|
+
goToPolycosmos();
|
|
1397
|
+
});
|
|
1398
|
+
|
|
1399
|
+
activityBtnCosmos?.addEventListener('click', () => goToCosmos());
|
|
1400
|
+
|
|
1401
|
+
btnHeaderCosmosSelect?.addEventListener('click', (e) => {
|
|
1402
|
+
e.stopPropagation();
|
|
1403
|
+
if (headerCosmosMenu) {
|
|
1404
|
+
headerCosmosMenu.classList.toggle('hidden');
|
|
1405
|
+
}
|
|
1406
|
+
});
|
|
1407
|
+
|
|
1408
|
+
document.addEventListener('click', (e) => {
|
|
1409
|
+
if (headerCosmosMenu && !headerCosmosMenu.contains(e.target as Node)) {
|
|
1410
|
+
headerCosmosMenu.classList.add('hidden');
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1413
|
+
|
|
1414
|
+
btnSideNewCosmos?.addEventListener('click', () => {
|
|
1415
|
+
this.switchToSpacesMode();
|
|
1416
|
+
this.cosmosNavigatorInstance?.triggerBigBangSequence(() => {
|
|
1417
|
+
const nextIdx = (this.cosmosNavigatorInstance?.getCosmoses().length || 0) + 1;
|
|
1418
|
+
const newCosmos = this.cosmosNavigatorInstance?.createCosmos(`Cosmos ${nextIdx}`);
|
|
1419
|
+
if (newCosmos) {
|
|
1420
|
+
this.cosmosNavigatorInstance?.selectCosmos(newCosmos.id);
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
|
|
1425
|
+
const btnSideAddSpace = document.getElementById('btn-side-add-space');
|
|
1426
|
+
btnSideAddSpace?.addEventListener('click', () => {
|
|
1427
|
+
this.cosmosNavigatorInstance?.handleSpaceClick('code');
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
private updateActiveCosmosDisplay(cosmos: CosmosInfo, activeSpaceIdOrType?: string): void {
|
|
1432
|
+
const headerName = document.getElementById('header-active-cosmos-name');
|
|
1433
|
+
if (headerName) { headerName.textContent = cosmos.name; }
|
|
1434
|
+
|
|
1435
|
+
const headerBadge = document.getElementById('header-temp-badge');
|
|
1436
|
+
if (headerBadge) {
|
|
1437
|
+
headerBadge.style.display = cosmos.isTemporary ? 'inline-flex' : 'none';
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
const projectName = document.getElementById('cosmos-project-name');
|
|
1441
|
+
if (projectName) { projectName.textContent = cosmos.name; }
|
|
1442
|
+
|
|
1443
|
+
const spacesCount = document.getElementById('cosmos-spaces-count');
|
|
1444
|
+
if (spacesCount) { spacesCount.textContent = String(cosmos.spaces.length); }
|
|
1445
|
+
|
|
1446
|
+
const spacesList = document.getElementById('cosmos-spaces-list');
|
|
1447
|
+
if (spacesList) {
|
|
1448
|
+
if (cosmos.spaces.length === 0) {
|
|
1449
|
+
spacesList.innerHTML = `<p class="empty-list-note">No spaces added yet.<br>Click Code or Text in Cosmos to attach a space.</p>`;
|
|
1450
|
+
} else {
|
|
1451
|
+
spacesList.innerHTML = cosmos.spaces.map(s => `
|
|
1452
|
+
<div class="cosmos-space-item" data-space-id="${s.id}" data-space-type="${s.type}">
|
|
1453
|
+
<span class="space-item-icon">${s.type === 'code' ? '</>' : (s.icon || '📦')}</span>
|
|
1454
|
+
<div class="space-item-info">
|
|
1455
|
+
<span class="space-item-name">${s.name}</span>
|
|
1456
|
+
<span class="space-item-sub">${s.type === 'code' ? 'Code Repository' : 'Metatext Discussion'}</span>
|
|
1457
|
+
</div>
|
|
1458
|
+
</div>
|
|
1459
|
+
`).join('');
|
|
1460
|
+
|
|
1461
|
+
spacesList.querySelectorAll('.cosmos-space-item').forEach(el => {
|
|
1462
|
+
el.addEventListener('click', () => {
|
|
1463
|
+
const type = el.getAttribute('data-space-type');
|
|
1464
|
+
const name = el.querySelector('.space-item-name')?.textContent || '';
|
|
1465
|
+
if (type === 'code') {
|
|
1466
|
+
this.showLeftPanelView('code', name);
|
|
1467
|
+
this.switchToReposMode();
|
|
1468
|
+
} else {
|
|
1469
|
+
this.showLeftPanelView('text', name);
|
|
1470
|
+
this.switchToNotesMode(name);
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
const activitySpaces = document.getElementById('activity-spaces-container');
|
|
1478
|
+
if (activitySpaces) {
|
|
1479
|
+
activitySpaces.innerHTML = cosmos.spaces.map(s => `
|
|
1480
|
+
<button class="activity-bar-btn activity-space-btn" type="button" title="${s.name}" data-space-id="${s.id}" data-space-type="${s.type}">
|
|
1481
|
+
<span class="activity-icon">${s.type === 'code' ? '</>' : (s.icon || '📦')}</span>
|
|
1482
|
+
<span class="activity-label">${s.shortLabel}</span>
|
|
1483
|
+
</button>
|
|
1484
|
+
`).join('');
|
|
1485
|
+
|
|
1486
|
+
activitySpaces.querySelectorAll('.activity-space-btn').forEach(btn => {
|
|
1487
|
+
btn.addEventListener('click', () => {
|
|
1488
|
+
const type = btn.getAttribute('data-space-type');
|
|
1489
|
+
const title = btn.getAttribute('title') || '';
|
|
1490
|
+
const spaceId = btn.getAttribute('data-space-id') || '';
|
|
1491
|
+
this.setActiveActivityBarButton('space', spaceId);
|
|
1492
|
+
|
|
1493
|
+
if (type === 'code') {
|
|
1494
|
+
this.showLeftPanelView('code', title);
|
|
1495
|
+
this.switchToReposMode();
|
|
1496
|
+
} else {
|
|
1497
|
+
this.showLeftPanelView('text', title);
|
|
1498
|
+
this.switchToNotesMode(title);
|
|
1499
|
+
}
|
|
1500
|
+
});
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
if (activeSpaceIdOrType) {
|
|
1505
|
+
this.setActiveActivityBarButton('space', activeSpaceIdOrType);
|
|
1506
|
+
} else {
|
|
1507
|
+
this.setActiveActivityBarButton('cosmos');
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
if (cosmos.spaces.length > 0) {
|
|
1511
|
+
this.expandActivityBar();
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
const allCosmoses = this.cosmosNavigatorInstance?.getCosmoses() || [];
|
|
1515
|
+
this.updateHeaderCosmosMenu(allCosmoses, cosmos.id);
|
|
1516
|
+
this.updatePlaygroundBannerVisibility();
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
public updatePlaygroundBannerVisibility(): void {
|
|
1520
|
+
const banner = document.getElementById('playground-banner');
|
|
1521
|
+
if (!banner) { return; }
|
|
1522
|
+
|
|
1523
|
+
if (this.hasActiveIdentity()) {
|
|
1524
|
+
banner.classList.add('hidden');
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
// On bare landing before the big bang explosion, do not show the banner
|
|
1529
|
+
const currentRoute = getSpaceGibRouterSvc().getCurrentRoute();
|
|
1530
|
+
const isBareLanding = !currentRoute || currentRoute.kind === 'polycosmos';
|
|
1531
|
+
if (isBareLanding && !this.hasBigBangExploded) {
|
|
1532
|
+
banner.classList.add('hidden');
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
// In playground mode (no authenticated identity), the banner is ALWAYS visible
|
|
1537
|
+
banner.classList.remove('hidden');
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
private updatePolycosmosDisplay(cosmoses: CosmosInfo[], activeId: string | null): void {
|
|
1541
|
+
const polyCount = document.getElementById('polycosmos-total-count');
|
|
1542
|
+
if (polyCount) { polyCount.textContent = String(cosmoses.length); }
|
|
1543
|
+
|
|
1544
|
+
this.updatePolycosmosList(cosmoses, activeId);
|
|
1545
|
+
this.setActiveActivityBarButton('polycosmos');
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
private updatePolycosmosList(cosmoses: CosmosInfo[], activeId: string | null): void {
|
|
1549
|
+
const listEl = document.getElementById('polycosmos-projects-list');
|
|
1550
|
+
if (!listEl) { return; }
|
|
1551
|
+
|
|
1552
|
+
if (cosmoses.length === 0) {
|
|
1553
|
+
listEl.innerHTML = `<p class="empty-list-note">No cosmos projects yet.<br>Click "Initiate Big Bang" in the center to create your first cosmos!</p>`;
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
listEl.innerHTML = cosmoses.map(c => `
|
|
1558
|
+
<div class="cosmos-space-item ${c.id === activeId ? 'active' : ''}" data-cosmos-id="${c.id}">
|
|
1559
|
+
<span class="space-item-icon">🌌</span>
|
|
1560
|
+
<div class="space-item-info">
|
|
1561
|
+
<span class="space-item-name">${c.name}</span>
|
|
1562
|
+
<span class="space-item-sub">${c.spaces.length} space${c.spaces.length === 1 ? '' : 's'}</span>
|
|
1563
|
+
</div>
|
|
1564
|
+
</div>
|
|
1565
|
+
`).join('');
|
|
1566
|
+
|
|
1567
|
+
listEl.querySelectorAll('.cosmos-space-item').forEach(el => {
|
|
1568
|
+
el.addEventListener('click', () => {
|
|
1569
|
+
const id = el.getAttribute('data-cosmos-id');
|
|
1570
|
+
if (id) {
|
|
1571
|
+
this.cosmosNavigatorInstance?.selectCosmos(id);
|
|
1572
|
+
}
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
private updateHeaderCosmosMenu(cosmoses: CosmosInfo[], activeId: string | null): void {
|
|
1578
|
+
const menu = document.getElementById('header-cosmos-menu');
|
|
1579
|
+
if (!menu) { return; }
|
|
1580
|
+
|
|
1581
|
+
menu.innerHTML = `
|
|
1582
|
+
${cosmoses.map(c => `
|
|
1583
|
+
<button type="button" class="header-menu-item ${c.id === activeId ? 'active' : ''}" data-cosmos-id="${c.id}">
|
|
1584
|
+
<span>🌌 ${c.name}</span>
|
|
1585
|
+
<span class="orbit-cosmos-badge" style="font-size:0.7rem; padding:1px 6px;">${c.spaces.length}</span>
|
|
1586
|
+
</button>
|
|
1587
|
+
`).join('')}
|
|
1588
|
+
<div class="header-menu-divider"></div>
|
|
1589
|
+
<button type="button" class="header-menu-item" id="btn-header-menu-new-cosmos">
|
|
1590
|
+
<span>+ New Cosmos</span>
|
|
1591
|
+
</button>
|
|
1592
|
+
`;
|
|
1593
|
+
|
|
1594
|
+
menu.querySelectorAll('.header-menu-item[data-cosmos-id]').forEach(btn => {
|
|
1595
|
+
btn.addEventListener('click', () => {
|
|
1596
|
+
const id = btn.getAttribute('data-cosmos-id');
|
|
1597
|
+
if (id) {
|
|
1598
|
+
menu.classList.add('hidden');
|
|
1599
|
+
this.switchToSpacesMode();
|
|
1600
|
+
this.cosmosNavigatorInstance?.selectCosmos(id);
|
|
1601
|
+
}
|
|
1602
|
+
});
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1605
|
+
const btnNew = menu.querySelector('#btn-header-menu-new-cosmos');
|
|
1606
|
+
btnNew?.addEventListener('click', () => {
|
|
1607
|
+
menu.classList.add('hidden');
|
|
1608
|
+
this.switchToSpacesMode();
|
|
1609
|
+
this.cosmosNavigatorInstance?.triggerBigBangExplosion();
|
|
1610
|
+
const nextIdx = cosmoses.length + 1;
|
|
1611
|
+
const newC = this.cosmosNavigatorInstance?.createCosmos(`Cosmos ${nextIdx}`);
|
|
1612
|
+
if (newC) {
|
|
1613
|
+
setTimeout(() => {
|
|
1614
|
+
this.cosmosNavigatorInstance?.selectCosmos(newC.id);
|
|
1615
|
+
}, 300);
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
private showLeftPanelView(viewName: 'polycosmos' | 'cosmos' | 'code' | 'text', title?: string): void {
|
|
1621
|
+
const viewPoly = document.getElementById('left-panel-polycosmos-view');
|
|
1622
|
+
const viewCosmos = document.getElementById('left-panel-cosmos-view');
|
|
1623
|
+
const viewCode = document.getElementById('left-panel-code-view');
|
|
1624
|
+
const viewText = document.getElementById('left-panel-text-view');
|
|
1625
|
+
|
|
1626
|
+
if (viewPoly) { viewPoly.style.display = viewName === 'polycosmos' ? 'block' : 'none'; }
|
|
1627
|
+
if (viewCosmos) { viewCosmos.style.display = viewName === 'cosmos' ? 'block' : 'none'; }
|
|
1628
|
+
if (viewCode) {
|
|
1629
|
+
viewCode.style.display = viewName === 'code' ? 'block' : 'none';
|
|
1630
|
+
if (title) {
|
|
1631
|
+
const titleEl = document.getElementById('left-code-space-title');
|
|
1632
|
+
if (titleEl) { titleEl.textContent = title; }
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
if (viewText) {
|
|
1636
|
+
viewText.style.display = viewName === 'text' ? 'block' : 'none';
|
|
1637
|
+
if (viewName === 'text') {
|
|
1638
|
+
this.initNotesExplorer(title);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
private expandActivityBar(): void {
|
|
1644
|
+
const bar = document.getElementById('activity-bar');
|
|
1645
|
+
if (bar) {
|
|
1646
|
+
bar.classList.remove('collapsed');
|
|
1647
|
+
bar.classList.add('expanded');
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
private expandLeftPanel(): void {
|
|
1652
|
+
const panel = document.getElementById(ID_LEFT_PANEL);
|
|
1653
|
+
if (panel) {
|
|
1654
|
+
panel.classList.remove('collapsed');
|
|
1655
|
+
this.leftPanelState = 'expanded';
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
public expandRightPanel(): void {
|
|
1660
|
+
const panel = document.getElementById(ID_RIGHT_PANEL);
|
|
1661
|
+
if (panel) {
|
|
1662
|
+
panel.classList.remove('collapsed');
|
|
1663
|
+
this.rightPanelState = 'expanded';
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
private switchToSpacesMode(): void {
|
|
1668
|
+
this.setMode('spaces');
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
private switchToReposMode(opts?: { skipNavigate?: boolean }): void {
|
|
1672
|
+
this.setMode('repos');
|
|
1673
|
+
this.expandRightPanel();
|
|
1674
|
+
if (!opts?.skipNavigate && !this.isApplyingRoute) {
|
|
1675
|
+
const activeCosmos = this.cosmosNavigatorInstance?.getActiveCosmos();
|
|
1676
|
+
if (activeCosmos) {
|
|
1677
|
+
const tenant = this.getActiveTenant(activeCosmos);
|
|
1678
|
+
getSpaceGibRouterSvc().navigate({
|
|
1679
|
+
kind: 'code-galaxy',
|
|
1680
|
+
cosmos: activeCosmos.id || activeCosmos.name,
|
|
1681
|
+
galaxyId: 'code-1',
|
|
1682
|
+
branch: 'main',
|
|
1683
|
+
...(tenant ? { tenant } : {}),
|
|
1684
|
+
});
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
private switchToNotesMode(title?: string, opts?: { skipNavigate?: boolean; galaxyId?: string }): void {
|
|
1690
|
+
this.setMode('notes', title);
|
|
1691
|
+
this.expandRightPanel();
|
|
1692
|
+
if (!opts?.skipNavigate && !this.isApplyingRoute) {
|
|
1693
|
+
const activeCosmos = this.cosmosNavigatorInstance?.getActiveCosmos();
|
|
1694
|
+
if (activeCosmos) {
|
|
1695
|
+
const tenant = this.getActiveTenant(activeCosmos);
|
|
1696
|
+
getSpaceGibRouterSvc().navigate({
|
|
1697
|
+
kind: 'notes-galaxy',
|
|
1698
|
+
cosmos: activeCosmos.id || activeCosmos.name,
|
|
1699
|
+
galaxyId: opts?.galaxyId || 'notes-1',
|
|
1700
|
+
...(title ? { topicTjp: title } : {}),
|
|
1701
|
+
...(tenant ? { tenant } : {}),
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
public getActiveTenant(cosmos?: CosmosInfo | string): SpaceGibTenant | undefined {
|
|
1708
|
+
const domainIdentity = (globalThis as any).ibgib?.identity?.domainIdentity;
|
|
1709
|
+
if (domainIdentity) {
|
|
1710
|
+
const siteUsername = domainIdentity.data?.siteUsername || domainIdentity.data?.name || domainIdentity.data?.username;
|
|
1711
|
+
if (siteUsername) {
|
|
1712
|
+
return { type: 'username', siteUsername };
|
|
1713
|
+
}
|
|
1714
|
+
const tjpAddr = domainIdentity.data?.tjp?.tjpAddr || domainIdentity.data?.tjpGib;
|
|
1715
|
+
if (tjpAddr) {
|
|
1716
|
+
return { type: 'keystone', keystoneTjp: tjpAddr };
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
// Without an active authenticated identity, all workspaces and routes are playground-scoped
|
|
1720
|
+
return { type: 'username', siteUsername: 'playground' };
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
private async initRouterIntegration(): Promise<void> {
|
|
1724
|
+
const lc = `${this.lc}[${this.initRouterIntegration.name}]`;
|
|
1725
|
+
try {
|
|
1726
|
+
const router = getSpaceGibRouterSvc();
|
|
1727
|
+
|
|
1728
|
+
// 1. Subscribe to route changes (popstate, direct navigation)
|
|
1729
|
+
router.subscribe(async (route) => {
|
|
1730
|
+
await this.handleRouteActivation(route);
|
|
1731
|
+
});
|
|
1732
|
+
|
|
1733
|
+
// 2. Load current URL from address bar
|
|
1734
|
+
const initialRoute = await router.loadCurrentURL();
|
|
1735
|
+
console.log(`${lc} Initial route activated:`, initialRoute);
|
|
1736
|
+
} catch (err) {
|
|
1737
|
+
console.error(`${lc} Failed to initialize router integration: ${extractErrorMsg(err)}`);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
public async handleRouteActivation(route: SpaceGibRouteInfo): Promise<void> {
|
|
1742
|
+
const lc = `${this.lc}[${this.handleRouteActivation.name}]`;
|
|
1743
|
+
if (this.isApplyingRoute) { return; }
|
|
1744
|
+
this.isApplyingRoute = true;
|
|
1745
|
+
try {
|
|
1746
|
+
if (route.kind !== 'polycosmos') {
|
|
1747
|
+
this.hasBigBangExploded = true;
|
|
1748
|
+
this.revealChrome();
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
// If the route omitted a tenant specifier but the user is authenticated (or in playground),
|
|
1752
|
+
// canonicalize the URL in the address bar so copying and sharing is always fully qualified.
|
|
1753
|
+
if (route.kind !== 'admin-review' && !route.tenant) {
|
|
1754
|
+
const cosmosName = 'cosmos' in route ? route.cosmos : undefined;
|
|
1755
|
+
const activeTenant = this.getActiveTenant(cosmosName);
|
|
1756
|
+
if (activeTenant) {
|
|
1757
|
+
route.tenant = activeTenant;
|
|
1758
|
+
getSpaceGibRouterSvc().navigate(route, { replace: true, silent: true });
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
switch (route.kind) {
|
|
1763
|
+
case 'polycosmos': {
|
|
1764
|
+
await this.showCosmos();
|
|
1765
|
+
this.cosmosNavigatorInstance?.setZoomState('polycosmos');
|
|
1766
|
+
break;
|
|
1767
|
+
}
|
|
1768
|
+
case 'cosmos': {
|
|
1769
|
+
if (this.cosmosNavigatorInstance) {
|
|
1770
|
+
const cosmos = await this.cosmosNavigatorInstance.ensureCosmos(route.cosmos);
|
|
1771
|
+
this.cosmosNavigatorInstance.selectCosmos(cosmos.id);
|
|
1772
|
+
this.updateActiveCosmosDisplay(cosmos);
|
|
1773
|
+
}
|
|
1774
|
+
this.showLeftPanelView('cosmos');
|
|
1775
|
+
this.expandLeftPanel();
|
|
1776
|
+
await this.showCosmos();
|
|
1777
|
+
break;
|
|
1778
|
+
}
|
|
1779
|
+
case 'code-galaxy': {
|
|
1780
|
+
if (this.cosmosNavigatorInstance) {
|
|
1781
|
+
const cosmos = await this.cosmosNavigatorInstance.ensureCosmos(route.cosmos);
|
|
1782
|
+
if (!cosmos.spaces.some(s => s.type === 'code' || s.id === route.galaxyId)) {
|
|
1783
|
+
cosmos.spaces.push({
|
|
1784
|
+
id: route.galaxyId || 'code-1',
|
|
1785
|
+
type: 'code',
|
|
1786
|
+
name: 'Code Space 1',
|
|
1787
|
+
shortLabel: 'Code 1',
|
|
1788
|
+
icon: '</>',
|
|
1789
|
+
});
|
|
1790
|
+
}
|
|
1791
|
+
this.cosmosNavigatorInstance.selectCosmos(cosmos.id);
|
|
1792
|
+
this.updateActiveCosmosDisplay(cosmos, 'code');
|
|
1793
|
+
}
|
|
1794
|
+
this.expandActivityBar();
|
|
1795
|
+
this.expandLeftPanel();
|
|
1796
|
+
this.setActiveActivityBarButton('space', 'code');
|
|
1797
|
+
this.showLeftPanelView('code', route.galaxyId);
|
|
1798
|
+
this.switchToReposMode({ skipNavigate: true });
|
|
1799
|
+
if (route.branch && this.fileExplorerInstance) {
|
|
1800
|
+
this.fileExplorerInstance.setBranch(route.branch);
|
|
1801
|
+
}
|
|
1802
|
+
if (route.filePath && this.fileExplorerInstance) {
|
|
1803
|
+
this.fileExplorerInstance.selectFile(route.filePath);
|
|
1804
|
+
}
|
|
1805
|
+
await this.showCode(route.filePath, route.branch);
|
|
1806
|
+
break;
|
|
1807
|
+
}
|
|
1808
|
+
case 'notes-galaxy': {
|
|
1809
|
+
if (this.cosmosNavigatorInstance) {
|
|
1810
|
+
const cosmos = await this.cosmosNavigatorInstance.ensureCosmos(route.cosmos);
|
|
1811
|
+
if (!cosmos.spaces.some(s => s.type === 'text' || s.id === route.galaxyId)) {
|
|
1812
|
+
cosmos.spaces.push({
|
|
1813
|
+
id: route.galaxyId || 'notes-1',
|
|
1814
|
+
type: 'text',
|
|
1815
|
+
name: 'Text Space 1',
|
|
1816
|
+
shortLabel: 'Text 1',
|
|
1817
|
+
icon: '📝',
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
this.cosmosNavigatorInstance.selectCosmos(cosmos.id);
|
|
1821
|
+
this.updateActiveCosmosDisplay(cosmos, 'text');
|
|
1822
|
+
}
|
|
1823
|
+
this.expandActivityBar();
|
|
1824
|
+
this.expandLeftPanel();
|
|
1825
|
+
this.setActiveActivityBarButton('space', 'text');
|
|
1826
|
+
this.showLeftPanelView('text', route.galaxyId);
|
|
1827
|
+
this.switchToNotesMode(route.topicTjp || route.galaxyId, { skipNavigate: true, galaxyId: route.galaxyId });
|
|
1828
|
+
await this.showNotes(route.topicTjp || route.galaxyId, {
|
|
1829
|
+
trail: route.trail,
|
|
1830
|
+
trailMode: route.trailMode,
|
|
1831
|
+
query: route.query,
|
|
1832
|
+
});
|
|
1833
|
+
break;
|
|
1834
|
+
}
|
|
1835
|
+
case 'raw-addr': {
|
|
1836
|
+
await this.handleRawAddrSnapshotRoute(route);
|
|
1837
|
+
break;
|
|
1838
|
+
}
|
|
1839
|
+
case 'raw-tjp': {
|
|
1840
|
+
await this.handleRawTjpRoute(route);
|
|
1841
|
+
break;
|
|
1842
|
+
}
|
|
1843
|
+
case 'admin-review': {
|
|
1844
|
+
await this.showAdminReview(route.tjpGib);
|
|
1845
|
+
break;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
} catch (err) {
|
|
1849
|
+
console.error(`${lc} Failed to apply route: ${extractErrorMsg(err)}`);
|
|
1850
|
+
} finally {
|
|
1851
|
+
this.isApplyingRoute = false;
|
|
1852
|
+
this.updatePlaygroundBannerVisibility();
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
private async handleRawAddrSnapshotRoute(route: RawAddrRouteInfo): Promise<void> {
|
|
1857
|
+
const lc = `${this.lc}[${this.handleRawAddrSnapshotRoute.name}]`;
|
|
1858
|
+
try {
|
|
1859
|
+
console.log(`${lc} Resolving raw snapshot route: cosmos=${route.cosmos}, spaceId=${route.spaceId}, addr=${route.ibGibAddr}`);
|
|
1860
|
+
if (this.cosmosNavigatorInstance) {
|
|
1861
|
+
const cosmos = await this.cosmosNavigatorInstance.ensureCosmos(route.cosmos);
|
|
1862
|
+
this.cosmosNavigatorInstance.selectCosmos(cosmos.id);
|
|
1863
|
+
this.updateActiveCosmosDisplay(cosmos);
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
1867
|
+
let space = (metaspace as any).localUserSpaces?.find((s: any) => s.data?.uuid === route.spaceId || s.data?.name === route.spaceId);
|
|
1868
|
+
if (!space) {
|
|
1869
|
+
space = (metaspace as any).spaces?.find((s: any) => s.data?.uuid === route.spaceId || s.data?.name === route.spaceId);
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
let targetIbGib: any;
|
|
1873
|
+
if (space) {
|
|
1874
|
+
const getRes = await space.get({ addr: route.ibGibAddr });
|
|
1875
|
+
targetIbGib = getRes?.ibGibs?.[0];
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
if (!targetIbGib) {
|
|
1879
|
+
try {
|
|
1880
|
+
const domainAddr = route.tenant?.type === 'username' ? route.tenant.siteUsername : route.cosmos;
|
|
1881
|
+
const res = await fetch(`/api/ibgib/${encodeURIComponent(domainAddr)}/${encodeURIComponent(route.ibGibAddr)}`);
|
|
1882
|
+
if (res.ok) {
|
|
1883
|
+
const payload = await res.json();
|
|
1884
|
+
targetIbGib = payload?.ibGib;
|
|
1885
|
+
}
|
|
1886
|
+
} catch (netErr) {
|
|
1887
|
+
console.warn(`${lc} Server fetch for raw addr failed: ${extractErrorMsg(netErr)}`);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
await this.showRawSnapshot(route.ibGibAddr, targetIbGib);
|
|
1892
|
+
} catch (err) {
|
|
1893
|
+
console.error(`${lc} ${extractErrorMsg(err)}`);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
private async handleRawTjpRoute(route: RawTjpRouteInfo): Promise<void> {
|
|
1898
|
+
const lc = `${this.lc}[${this.handleRawTjpRoute.name}]`;
|
|
1899
|
+
try {
|
|
1900
|
+
console.log(`${lc} Resolving living tip route: cosmos=${route.cosmos}, spaceId=${route.spaceId}, tjp=${route.tjpAddr}`);
|
|
1901
|
+
if (this.cosmosNavigatorInstance) {
|
|
1902
|
+
const cosmos = await this.cosmosNavigatorInstance.ensureCosmos(route.cosmos);
|
|
1903
|
+
this.cosmosNavigatorInstance.selectCosmos(cosmos.id);
|
|
1904
|
+
this.updateActiveCosmosDisplay(cosmos);
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
1908
|
+
let space = (metaspace as any).localUserSpaces?.find((s: any) => s.data?.uuid === route.spaceId || s.data?.name === route.spaceId);
|
|
1909
|
+
if (!space) {
|
|
1910
|
+
space = (metaspace as any).spaces?.find((s: any) => s.data?.uuid === route.spaceId || s.data?.name === route.spaceId);
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
let tipAddr = route.tjpAddr;
|
|
1914
|
+
let targetIbGib: any;
|
|
1915
|
+
if (space && typeof (space as any).getLatestIbGib === 'function') {
|
|
1916
|
+
const latest = await (space as any).getLatestIbGib({ tjpAddr: route.tjpAddr });
|
|
1917
|
+
if (latest) {
|
|
1918
|
+
targetIbGib = latest;
|
|
1919
|
+
tipAddr = (latest as any).ibGibAddr || getIbGibAddr({ ibGib: latest }) || tipAddr;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
if (!targetIbGib) {
|
|
1924
|
+
try {
|
|
1925
|
+
const domainAddr = route.tenant?.type === 'username' ? route.tenant.siteUsername : route.cosmos;
|
|
1926
|
+
const res = await fetch(`/api/ibgib/${encodeURIComponent(domainAddr)}/${encodeURIComponent(route.tjpAddr)}`);
|
|
1927
|
+
if (res.ok) {
|
|
1928
|
+
const payload = await res.json();
|
|
1929
|
+
targetIbGib = payload?.ibGib;
|
|
1930
|
+
if (targetIbGib) {
|
|
1931
|
+
tipAddr = (targetIbGib as any).ibGibAddr || getIbGibAddr({ ibGib: targetIbGib }) || tipAddr;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
} catch (netErr) {
|
|
1935
|
+
console.warn(`${lc} Server fetch for raw tjp failed: ${extractErrorMsg(netErr)}`);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
await this.showRawSnapshot(tipAddr, targetIbGib, { isLivingTip: true, tjpAddr: route.tjpAddr });
|
|
1940
|
+
} catch (err) {
|
|
1941
|
+
console.error(`${lc} ${extractErrorMsg(err)}`);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
public async showRawSnapshot(
|
|
1946
|
+
addr: string,
|
|
1947
|
+
ibGib?: any,
|
|
1948
|
+
opts?: { isLivingTip?: boolean; tjpAddr?: string }
|
|
1949
|
+
): Promise<void> {
|
|
1950
|
+
const lc = `${this.lc}[${this.showRawSnapshot.name}]`;
|
|
1951
|
+
try {
|
|
1952
|
+
const centerPanel = document.getElementById(ID_CENTER_PANEL_CONTENT);
|
|
1953
|
+
if (!centerPanel) { return; }
|
|
1954
|
+
|
|
1955
|
+
if (!this.timelineItemDetailsInstance) {
|
|
1956
|
+
const componentSvc = await getComponentSvc();
|
|
1957
|
+
this.timelineItemDetailsInstance = await componentSvc.getComponentInstance({
|
|
1958
|
+
path: TIMELINE_ITEM_DETAILS_COMPONENT_NAME,
|
|
1959
|
+
ibGibAddr: ROOT_ADDR,
|
|
1960
|
+
useRegExpPrefilter: true,
|
|
1961
|
+
}) as TimelineItemDetailsComponentInstance;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
if (this.timelineItemDetailsInstance) {
|
|
1965
|
+
const componentSvc = await getComponentSvc();
|
|
1966
|
+
await componentSvc.inject({
|
|
1967
|
+
parentEl: centerPanel,
|
|
1968
|
+
componentToInject: this.timelineItemDetailsInstance,
|
|
1969
|
+
});
|
|
1970
|
+
|
|
1971
|
+
const shortHash = addr.slice(0, 10);
|
|
1972
|
+
const isLiving = opts?.isLivingTip;
|
|
1973
|
+
const message = isLiving
|
|
1974
|
+
? `🌱 Living Tip: ${addr.split('^')[0] || addr}`
|
|
1975
|
+
: `📌 Snapshot (Pinned): ${addr.split('^')[0] || addr}`;
|
|
1976
|
+
const timestamp = isLiving ? 'Latest tip' : 'Pinned point-in-time';
|
|
1977
|
+
const branch = isLiving ? 'living-tip' : 'snapshot';
|
|
1978
|
+
|
|
1979
|
+
let rawData: string;
|
|
1980
|
+
if (ibGib?.data) {
|
|
1981
|
+
if (typeof ibGib.data.text === 'string') {
|
|
1982
|
+
rawData = ibGib.data.text;
|
|
1983
|
+
} else if (typeof ibGib.data.content === 'string') {
|
|
1984
|
+
rawData = ibGib.data.content;
|
|
1985
|
+
} else {
|
|
1986
|
+
rawData = JSON.stringify(ibGib.data, null, 2);
|
|
1987
|
+
}
|
|
1988
|
+
} else if (ibGib) {
|
|
1989
|
+
rawData = JSON.stringify(ibGib, null, 2);
|
|
1990
|
+
} else {
|
|
1991
|
+
rawData = `Address: ${addr}\n(Content not loaded)`;
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
this.timelineItemDetailsInstance.setTimelineItem({
|
|
1995
|
+
hash: addr,
|
|
1996
|
+
shortHash: shortHash,
|
|
1997
|
+
message,
|
|
1998
|
+
author: ibGib?.rel8ns?.ancestor?.[0] || (isLiving ? 'ibgib living tip' : 'ibgib snapshot'),
|
|
1999
|
+
timestamp,
|
|
2000
|
+
branch,
|
|
2001
|
+
diffPreview: rawData,
|
|
2002
|
+
changedFiles: [
|
|
2003
|
+
{ path: addr, status: 'A', additions: 1, deletions: 0 }
|
|
2004
|
+
]
|
|
2005
|
+
});
|
|
2006
|
+
}
|
|
2007
|
+
} catch (error) {
|
|
2008
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
public hasActiveIdentity(): boolean {
|
|
2013
|
+
return Boolean((globalThis as any).ibgib?.identity?.domainIdentity);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
public async onEngineReady(): Promise<void> {
|
|
2017
|
+
const lc = `${this.lc}[${this.onEngineReady.name}]`;
|
|
2018
|
+
try {
|
|
2019
|
+
await this.initialized;
|
|
2020
|
+
console.log(`${lc} SpaceGib Shell Service is ready.`);
|
|
2021
|
+
|
|
2022
|
+
// Ensure the UI removes the loading text
|
|
2023
|
+
const statusSection = document.getElementById('status-section');
|
|
2024
|
+
if (statusSection) {
|
|
2025
|
+
statusSection.style.display = 'none';
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
// Mount identity-header component in the header bar
|
|
2029
|
+
const componentSvc = await getComponentSvc();
|
|
2030
|
+
const identityHeader = await componentSvc.getComponentInstance({
|
|
2031
|
+
path: 'ibgib-identity-header',
|
|
2032
|
+
ibGibAddr: ROOT_ADDR,
|
|
2033
|
+
useRegExpPrefilter: true,
|
|
2034
|
+
});
|
|
2035
|
+
|
|
2036
|
+
const headerContainer = document.getElementById('identity-header-container');
|
|
2037
|
+
if (headerContainer && identityHeader) {
|
|
2038
|
+
headerContainer.innerHTML = '';
|
|
2039
|
+
headerContainer.appendChild(identityHeader as any);
|
|
2040
|
+
if (this.hasActiveIdentity()) {
|
|
2041
|
+
headerContainer.classList.remove('identity-active-highlight');
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
window.dispatchEvent(new CustomEvent(EVENT_IBGIB_SHELL_READY, { detail: { timestamp: Date.now() } }));
|
|
2046
|
+
|
|
2047
|
+
// Connect HTML5 History API router and activate current URL
|
|
2048
|
+
await this.initRouterIntegration();
|
|
2049
|
+
|
|
2050
|
+
// Update playground mode banner visibility
|
|
2051
|
+
this.updatePlaygroundBannerVisibility();
|
|
2052
|
+
|
|
2053
|
+
// Pre-warm in-memory temporary metaspace in background for snappy tutorial/playground mode
|
|
2054
|
+
prewarmPlaygroundMetaspace().catch(err => {
|
|
2055
|
+
console.warn(`${lc} Background prewarm of temporary metaspace failed: ${extractErrorMsg(err)}`);
|
|
2056
|
+
});
|
|
2057
|
+
|
|
2058
|
+
// Trigger 1 (App Boot): On onEngineReady, if active identity exists, check for updates.
|
|
361
2059
|
|
|
362
|
-
// Trigger 1 (App Boot): On onEngineReady, if active identity exists, check for updates.
|
|
363
2060
|
const domainIdentity = (globalThis as any).ibgib?.identity?.domainIdentity;
|
|
364
2061
|
if (domainIdentity) {
|
|
365
2062
|
const activePrimaryAddr = getIbGibAddr({ ibGib: domainIdentity });
|