@ibgib/space-gib 0.0.34 → 0.0.35
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 +1 -1
- package/dist/client/{chunk-25PXC4HP.mjs → chunk-FIAGRVBY.mjs} +1487 -468
- package/dist/client/chunk-XLQ3UCQY.mjs +53 -0
- package/dist/client/css/activity-bar.css +21 -3
- package/dist/client/css/layout.css +126 -5
- package/dist/client/index.html +6 -0
- package/dist/client/index.mjs +22 -45
- package/dist/client/privacy.html +22 -22
- package/dist/client/script.mjs +1 -1
- package/dist/server/server.mjs +3 -3
- package/package.json +6 -6
- package/src/client/AUTO-GENERATED-version.mts +1 -1
- package/src/client/cosmos/seed-cosmos-workspace.mts +20 -6
- package/src/client/css/activity-bar.css +21 -3
- package/src/client/css/layout.css +126 -5
- package/src/client/dev-tools/vcs-workspace.mts +4 -4
- package/src/client/index.html +6 -0
- package/src/client/privacy.html +22 -22
- package/src/client/ui/component/changes/changes.css +413 -0
- package/src/client/ui/component/changes/changes.html +37 -0
- package/src/client/ui/component/changes/changes.mts +766 -0
- package/src/client/ui/component/changes/index.mts +9 -0
- package/src/client/ui/component/chat-view/chat-view.html +6 -58
- package/src/client/ui/component/chat-view/chat-view.mts +13 -26
- package/src/client/ui/component/clone/clone.mts +67 -39
- package/src/client/ui/component/code-editor/code-editor.css +91 -9
- package/src/client/ui/component/code-editor/code-editor.html +58 -45
- package/src/client/ui/component/code-editor/code-editor.mts +265 -49
- package/src/client/ui/component/cosmos-navigator/cosmos-navigator.css +1 -1
- package/src/client/ui/component/cosmos-navigator/cosmos-navigator.html +5 -10
- package/src/client/ui/component/cosmos-navigator/cosmos-navigator.mts +297 -64
- package/src/client/ui/component/file-explorer/file-explorer.css +475 -11
- package/src/client/ui/component/file-explorer/file-explorer.html +45 -65
- package/src/client/ui/component/file-explorer/file-explorer.mts +1164 -98
- package/src/client/ui/component/nested-chat/chat/chat.mts +5 -90
- package/src/client/ui/component/nested-chat/nested-chat.mts +10 -8
- package/src/client/ui/component/timeline/timeline.css +16 -1
- package/src/client/ui/component/timeline/timeline.mts +37 -93
- package/src/client/ui/router/space-gib-router-helpers.mts +33 -233
- package/src/client/ui/router/space-gib-router-helpers.respec.mts +298 -122
- package/src/client/ui/router/space-gib-router-service.mts +28 -151
- package/src/client/ui/router/space-gib-router-types.mts +32 -76
- package/src/client/ui/shell/cosmic-big-bang.mts +12 -3
- package/src/client/ui/shell/space-gib-shell-service.mts +687 -119
- package/dist/client/chunk-RXWLL2AI.mjs +0 -30
|
@@ -166,106 +166,21 @@ export class ChatComponentInstance
|
|
|
166
166
|
const { ib } = getIbAndGib({ ibGibAddr: addr });
|
|
167
167
|
|
|
168
168
|
if (addr === ROOT_ADDR || ib === 'root' || ib.includes('space-gib')) {
|
|
169
|
-
this.el.contextTitleEl.textContent = 'Thread:
|
|
169
|
+
this.el.contextTitleEl.textContent = 'Thread: Workspace';
|
|
170
170
|
} else if (ib.startsWith('comment')) {
|
|
171
171
|
const pieces = ib.split(' ');
|
|
172
172
|
const preview = pieces.length > 1 ? pieces.slice(1).join(' ') : 'Comment Thread';
|
|
173
173
|
this.el.contextTitleEl.textContent = `Thread: "${preview.slice(0, 24)}..."`;
|
|
174
|
+
} else if (ib.startsWith('file ')) {
|
|
175
|
+
const file = ib.replace('file ', '');
|
|
176
|
+
this.el.contextTitleEl.textContent = `Thread: ${file}`;
|
|
174
177
|
} else {
|
|
175
178
|
this.el.contextTitleEl.textContent = `Thread: ${ib.slice(0, 20)}`;
|
|
176
179
|
}
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
private loadInitialMessages(): void {
|
|
180
|
-
|
|
181
|
-
const { ib } = getIbAndGib({ ibGibAddr: addr });
|
|
182
|
-
|
|
183
|
-
if (ib.includes('boundary') || ib.includes('try/catch') || ib.includes('boot')) {
|
|
184
|
-
// Nested replies for the error boundary comment thread
|
|
185
|
-
this.messages = [
|
|
186
|
-
{
|
|
187
|
-
id: 'submsg-1',
|
|
188
|
-
addr: 'comment boundary-rationale^gib_b1',
|
|
189
|
-
author: 'Charlie',
|
|
190
|
-
avatar: '👩🔬',
|
|
191
|
-
role: 'Peer',
|
|
192
|
-
timestamp: '3m ago',
|
|
193
|
-
text: 'Wrapping boot() in a top-level error boundary prevents uncaught rejections from freezing the virtual canvas.',
|
|
194
|
-
replyCount: 1,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
id: 'submsg-2',
|
|
198
|
-
addr: 'comment boundary-event^gib_b2',
|
|
199
|
-
author: 'Bob',
|
|
200
|
-
avatar: '👨🚀',
|
|
201
|
-
role: 'Peer',
|
|
202
|
-
timestamp: '1m ago',
|
|
203
|
-
text: 'Agreed! Let us also dispatch an EVENT_IBGIB_UI_MESSAGE so the status bar shows the error banner.',
|
|
204
|
-
replyCount: 0,
|
|
205
|
-
}
|
|
206
|
-
];
|
|
207
|
-
} else if (ib.includes('rationale') || ib.includes('index.ts') || ib.includes('indexeddb')) {
|
|
208
|
-
// Nested replies for the architectural rationale comment thread
|
|
209
|
-
this.messages = [
|
|
210
|
-
{
|
|
211
|
-
id: 'submsg-3',
|
|
212
|
-
addr: 'comment offline-merkle^gib_a1',
|
|
213
|
-
author: 'Bob',
|
|
214
|
-
avatar: '👨🚀',
|
|
215
|
-
role: 'Peer',
|
|
216
|
-
timestamp: '5m ago',
|
|
217
|
-
text: 'The local IndexedDB space works completely offline without network roundtrips.',
|
|
218
|
-
replyCount: 0,
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
id: 'submsg-4',
|
|
222
|
-
addr: 'comment sync-keystone^gib_a2',
|
|
223
|
-
author: 'Alice',
|
|
224
|
-
avatar: '👩💻',
|
|
225
|
-
role: 'Keystone',
|
|
226
|
-
timestamp: '2m ago',
|
|
227
|
-
text: 'Exactly! Remote peer hubs synchronize automatically via WebSockets whenever connectivity is detected.',
|
|
228
|
-
replyCount: 0,
|
|
229
|
-
}
|
|
230
|
-
];
|
|
231
|
-
} else {
|
|
232
|
-
// Default file / root comments
|
|
233
|
-
this.messages = [
|
|
234
|
-
{
|
|
235
|
-
id: 'msg-1',
|
|
236
|
-
addr: 'comment index-arch-rationale^gib_1',
|
|
237
|
-
author: 'Alice',
|
|
238
|
-
avatar: '👩💻',
|
|
239
|
-
role: 'Keystone',
|
|
240
|
-
timestamp: '10m ago',
|
|
241
|
-
anchor: 'src/index.ts#L1-18',
|
|
242
|
-
text: 'Architectural Rationale: This entrypoint initializes the virtual repository workspace within the browser’s local IndexedDB metaspace.',
|
|
243
|
-
replyCount: 2,
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
id: 'msg-2',
|
|
247
|
-
addr: 'comment index-try-catch^gib_2',
|
|
248
|
-
author: 'Bob',
|
|
249
|
-
avatar: '👨🚀',
|
|
250
|
-
role: 'Peer',
|
|
251
|
-
timestamp: '6m ago',
|
|
252
|
-
anchor: 'src/index.ts#L36-42',
|
|
253
|
-
text: 'Looks super clean! Should we add an async try/catch boundary around boot() as well?',
|
|
254
|
-
replyCount: 2,
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
id: 'msg-3',
|
|
258
|
-
addr: 'comment index-agent-analysis^gib_3',
|
|
259
|
-
author: 'Agent',
|
|
260
|
-
avatar: '🤖',
|
|
261
|
-
role: 'Agent',
|
|
262
|
-
timestamp: '4m ago',
|
|
263
|
-
anchor: 'src/index.ts#L43-50',
|
|
264
|
-
text: 'Static analysis confirms that initOrchestration provides a root failure boundary.',
|
|
265
|
-
replyCount: 0,
|
|
266
|
-
}
|
|
267
|
-
];
|
|
268
|
-
}
|
|
183
|
+
this.messages = [];
|
|
269
184
|
}
|
|
270
185
|
|
|
271
186
|
private async initEnterBehavior(): Promise<void> {
|
|
@@ -99,7 +99,7 @@ export class NestedChatComponentInstance
|
|
|
99
99
|
|
|
100
100
|
private ensureValidIbGibAddr(addr: string): IbGibAddr {
|
|
101
101
|
if (!addr || addr === ROOT_ADDR) {
|
|
102
|
-
return
|
|
102
|
+
return ROOT_ADDR;
|
|
103
103
|
}
|
|
104
104
|
if (!addr.includes('^')) {
|
|
105
105
|
return `file ${addr}^${addr.replace(/[^a-zA-Z0-9]/g, '_')}_tjp`;
|
|
@@ -123,13 +123,15 @@ export class NestedChatComponentInstance
|
|
|
123
123
|
|
|
124
124
|
this.bindEvents();
|
|
125
125
|
|
|
126
|
-
// Only activate initial thread if an ibGibAddr was explicitly provided
|
|
127
|
-
if (this.ibGibAddr) {
|
|
126
|
+
// Only activate initial thread if an ibGibAddr was explicitly provided (not ROOT_ADDR)
|
|
127
|
+
if (this.ibGibAddr && this.ibGibAddr !== ROOT_ADDR) {
|
|
128
128
|
const rootAddr = this.ensureValidIbGibAddr(this.ibGibAddr);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
if (rootAddr && rootAddr !== ROOT_ADDR) {
|
|
130
|
+
setTimeout(async () => {
|
|
131
|
+
console.log(`${lc} activating initial root thread: ${rootAddr}`);
|
|
132
|
+
await this.activateIbGib({ addr: rootAddr });
|
|
133
|
+
}, 0);
|
|
134
|
+
}
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
} catch (error) {
|
|
@@ -350,7 +352,7 @@ export class NestedChatComponentInstance
|
|
|
350
352
|
|
|
351
353
|
const { ib } = getIbAndGib({ ibGibAddr: addr });
|
|
352
354
|
if (addr === ROOT_ADDR || ib === 'root' || ib.includes('file') || !addr.includes('comment')) {
|
|
353
|
-
const fileTitle = ib.startsWith('file ') ? ib.replace('file ', '') : '
|
|
355
|
+
const fileTitle = ib.startsWith('file ') ? ib.replace('file ', '') : (ib === 'root' || addr === ROOT_ADDR ? 'Workspace' : ib);
|
|
354
356
|
return {
|
|
355
357
|
shortTitle: this.formatShortTitle(fileTitle),
|
|
356
358
|
fullText: `Root Thread: ${fileTitle}`,
|
|
@@ -2,15 +2,25 @@
|
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
min-height: 0;
|
|
5
7
|
box-sizing: border-box;
|
|
6
8
|
margin: 0;
|
|
7
9
|
padding: 0;
|
|
8
10
|
}
|
|
9
11
|
|
|
12
|
+
:host([collapsed]) {
|
|
13
|
+
height: auto !important;
|
|
14
|
+
flex: 0 0 auto !important;
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
.timeline-root {
|
|
11
18
|
display: flex;
|
|
12
19
|
flex-direction: column;
|
|
13
20
|
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
min-height: 0;
|
|
23
|
+
overflow: hidden;
|
|
14
24
|
user-select: none;
|
|
15
25
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
16
26
|
box-sizing: border-box;
|
|
@@ -23,7 +33,7 @@
|
|
|
23
33
|
display: flex;
|
|
24
34
|
align-items: center;
|
|
25
35
|
gap: 0.35rem;
|
|
26
|
-
padding: 0.
|
|
36
|
+
padding: 0.28rem 0.5rem;
|
|
27
37
|
background: rgba(255, 255, 255, 0.04);
|
|
28
38
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
29
39
|
border-radius: 6px;
|
|
@@ -35,6 +45,8 @@
|
|
|
35
45
|
outline: none;
|
|
36
46
|
box-sizing: border-box;
|
|
37
47
|
margin: 0;
|
|
48
|
+
flex: 0 0 auto !important;
|
|
49
|
+
flex-shrink: 0 !important;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
.timeline-header:hover {
|
|
@@ -135,6 +147,9 @@
|
|
|
135
147
|
.timeline-stream-container {
|
|
136
148
|
display: flex;
|
|
137
149
|
flex-direction: column;
|
|
150
|
+
flex: 1 1 0px;
|
|
151
|
+
min-height: 0;
|
|
152
|
+
overflow-y: auto;
|
|
138
153
|
position: relative;
|
|
139
154
|
padding: 0.35rem 0.2rem 0.5rem 0.8rem;
|
|
140
155
|
box-sizing: border-box;
|
|
@@ -87,98 +87,8 @@ export class TimelineComponentInstance
|
|
|
87
87
|
|
|
88
88
|
private branchName: string = 'main';
|
|
89
89
|
private isTimelineExpanded: boolean = true;
|
|
90
|
-
private selectedHash: string = '
|
|
91
|
-
|
|
92
|
-
private snapshots: TimelineItem[] = [
|
|
93
|
-
{
|
|
94
|
-
hash: '3e8f1c2a05d8f99e32b4f17c802e3b4a',
|
|
95
|
-
shortHash: '3e8f1c2',
|
|
96
|
-
message: 'feat: implement cosmos navigation and orbital drift',
|
|
97
|
-
author: 'Bill Raiford <bill@ibgib.space>',
|
|
98
|
-
timestamp: '2m ago',
|
|
99
|
-
isTip: true,
|
|
100
|
-
branch: 'main',
|
|
101
|
-
parentHash: 'a7b4d90',
|
|
102
|
-
changedFiles: [
|
|
103
|
-
{ path: 'src/client/ui/component/cosmos-navigator/cosmos-navigator.mts', status: 'M', additions: 18, deletions: 4 },
|
|
104
|
-
{ path: 'src/client/ui/shell/space-gib-shell-service.mts', status: 'M', additions: 32, deletions: 6 },
|
|
105
|
-
{ path: 'src/client/css/layout.css', status: 'M', additions: 14, deletions: 2 },
|
|
106
|
-
],
|
|
107
|
-
diffPreview: `@@ -848,6 +848,20 @@
|
|
108
|
-
- this.launchProjectile({ ... });
|
|
109
|
-
+ // Make activity bar visible BEFORE zoom flight starts
|
|
110
|
-
+ window.dispatchEvent(new CustomEvent('space-gib-activity-bar-expand-requested'));
|
|
111
|
-
+ setTimeout(() => {
|
|
112
|
-
+ this.launchProjectile({ ... });
|
|
113
|
-
+ }, 180);`
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
hash: 'a7b4d9089f21c4320b9e8471da329188',
|
|
117
|
-
shortHash: 'a7b4d90',
|
|
118
|
-
message: 'style: polish firecracker big bang compression',
|
|
119
|
-
author: 'Bill Raiford <bill@ibgib.space>',
|
|
120
|
-
timestamp: '1h ago',
|
|
121
|
-
branch: 'main',
|
|
122
|
-
parentHash: 'f2098b1',
|
|
123
|
-
changedFiles: [
|
|
124
|
-
{ path: 'src/client/ui/component/cosmos-navigator/cosmos-navigator.css', status: 'M', additions: 24, deletions: 11 },
|
|
125
|
-
{ path: 'src/client/ui/component/cosmos-navigator/cosmos-navigator.mts', status: 'M', additions: 12, deletions: 5 },
|
|
126
|
-
],
|
|
127
|
-
diffPreview: `@@ -430,8 +430,12 @@
|
|
128
|
-
- btn.classList.add('compressing');
|
|
129
|
-
+ // Firecracker high velocity rotation
|
|
130
|
-
+ btn.classList.add('compressing');
|
|
131
|
-
+ this.triggerBigBangExplosion();`
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
hash: 'f2098b191c4998721fae390c91834789',
|
|
135
|
-
shortHash: 'f2098b1',
|
|
136
|
-
message: 'refactor: decouple activity bar and cosmos controls',
|
|
137
|
-
author: 'Bill Raiford <bill@ibgib.space>',
|
|
138
|
-
timestamp: 'yesterday',
|
|
139
|
-
branch: 'main',
|
|
140
|
-
parentHash: 'c019a4e',
|
|
141
|
-
changedFiles: [
|
|
142
|
-
{ path: 'src/client/ui/shell/cosmic-big-bang.mts', status: 'M', additions: 40, deletions: 52 },
|
|
143
|
-
{ path: 'src/client/ui/shell/space-gib-shell-service.mts', status: 'M', additions: 75, deletions: 18 },
|
|
144
|
-
],
|
|
145
|
-
diffPreview: `@@ -120,7 +120,7 @@
|
|
146
|
-
- public toggleActivityBar(): void {
|
|
147
|
-
+ public expandActivityBar(): void {`
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
hash: 'c019a4ee899201bdcf88132582910fa2',
|
|
151
|
-
shortHash: 'c019a4e',
|
|
152
|
-
message: 'feat: primordial singularity and big bang stage',
|
|
153
|
-
author: 'Bill Raiford <bill@ibgib.space>',
|
|
154
|
-
timestamp: '3d ago',
|
|
155
|
-
branch: 'main',
|
|
156
|
-
parentHash: '0000000',
|
|
157
|
-
changedFiles: [
|
|
158
|
-
{ path: 'src/client/ui/component/cosmos-navigator/cosmos-navigator.mts', status: 'A', additions: 450, deletions: 0 },
|
|
159
|
-
{ path: 'src/client/ui/component/cosmos-navigator/cosmos-navigator.html', status: 'A', additions: 95, deletions: 0 },
|
|
160
|
-
],
|
|
161
|
-
diffPreview: `@@ -0,0 +1,95 @@
|
|
162
|
-
+<div id="cosmos-nav-root" class="cosmos-nav-root">
|
|
163
|
-
+ <canvas id="bg-canvas"></canvas>
|
|
164
|
-
+</div>`
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
hash: '00000000000000000000000000000000',
|
|
168
|
-
shortHash: '0000000',
|
|
169
|
-
message: 'Initial commit (empty space genesis)',
|
|
170
|
-
author: 'Bill Raiford <bill@ibgib.space>',
|
|
171
|
-
timestamp: '5d ago',
|
|
172
|
-
branch: 'main',
|
|
173
|
-
changedFiles: [
|
|
174
|
-
{ path: 'package.json', status: 'A', additions: 35, deletions: 0 },
|
|
175
|
-
{ path: 'README.md', status: 'A', additions: 20, deletions: 0 },
|
|
176
|
-
],
|
|
177
|
-
diffPreview: `@@ -0,0 +1,20 @@
|
|
178
|
-
+# space-gib
|
|
179
|
-
+Decentralized VCS and superspaces.`
|
|
180
|
-
}
|
|
181
|
-
];
|
|
90
|
+
private selectedHash: string = '';
|
|
91
|
+
private snapshots: TimelineItem[] = [];
|
|
182
92
|
|
|
183
93
|
get el(): TimelineElements {
|
|
184
94
|
if (!this.elements) {
|
|
@@ -203,6 +113,7 @@ export class TimelineComponentInstance
|
|
|
203
113
|
contentEl: shadow.getElementById('timeline-root') as HTMLDivElement,
|
|
204
114
|
};
|
|
205
115
|
|
|
116
|
+
this.toggleAttribute('collapsed', !this.isTimelineExpanded);
|
|
206
117
|
this.bindHandlers();
|
|
207
118
|
this.renderSnapshots();
|
|
208
119
|
} catch (error) {
|
|
@@ -238,6 +149,15 @@ export class TimelineComponentInstance
|
|
|
238
149
|
if (!container) { return; }
|
|
239
150
|
container.innerHTML = '';
|
|
240
151
|
|
|
152
|
+
if (this.snapshots.length === 0) {
|
|
153
|
+
container.innerHTML = `
|
|
154
|
+
<div class="empty-timeline-msg" style="padding: 16px 12px; font-size: 11px; color: #8a99a8; font-style: italic; text-align: center;">
|
|
155
|
+
No commits on branch [${this.branchName}] yet.
|
|
156
|
+
</div>
|
|
157
|
+
`;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
241
161
|
for (const item of this.snapshots) {
|
|
242
162
|
const row = document.createElement('div');
|
|
243
163
|
row.className = `timeline-item ${item.shortHash === this.selectedHash ? 'selected' : ''} ${item.isTip ? 'is-tip' : ''}`;
|
|
@@ -268,6 +188,11 @@ export class TimelineComponentInstance
|
|
|
268
188
|
}
|
|
269
189
|
}
|
|
270
190
|
|
|
191
|
+
public setSnapshots(snapshots: TimelineItem[]): void {
|
|
192
|
+
this.snapshots = snapshots || [];
|
|
193
|
+
this.renderSnapshots();
|
|
194
|
+
}
|
|
195
|
+
|
|
271
196
|
public selectTimelineItem(hash: string): void {
|
|
272
197
|
this.selectedHash = hash;
|
|
273
198
|
const shadow = this.shadowRoot;
|
|
@@ -288,8 +213,23 @@ export class TimelineComponentInstance
|
|
|
288
213
|
}
|
|
289
214
|
}
|
|
290
215
|
|
|
216
|
+
public addSnapshot(snapshot: TimelineItem): void {
|
|
217
|
+
for (const s of this.snapshots) {
|
|
218
|
+
s.isTip = false;
|
|
219
|
+
}
|
|
220
|
+
snapshot.isTip = true;
|
|
221
|
+
this.snapshots.unshift(snapshot);
|
|
222
|
+
this.renderSnapshots();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public clearSnapshots(): void {
|
|
226
|
+
this.snapshots = [];
|
|
227
|
+
this.renderSnapshots();
|
|
228
|
+
}
|
|
229
|
+
|
|
291
230
|
public toggleTimelineAccordion(): void {
|
|
292
231
|
this.isTimelineExpanded = !this.isTimelineExpanded;
|
|
232
|
+
this.toggleAttribute('collapsed', !this.isTimelineExpanded);
|
|
293
233
|
const chevron = this.el.timelineHeaderEl.querySelector('.chevron-icon');
|
|
294
234
|
|
|
295
235
|
if (this.isTimelineExpanded) {
|
|
@@ -301,9 +241,13 @@ export class TimelineComponentInstance
|
|
|
301
241
|
this.el.timelineHeaderEl.classList.remove('expanded');
|
|
302
242
|
this.el.timelineHeaderEl.classList.add('collapsed');
|
|
303
243
|
this.el.timelineStreamContainerEl.classList.add('hidden');
|
|
304
|
-
// if (chevron) chevron.textContent = '▶';
|
|
305
244
|
if (chevron) { chevron.textContent = '▼'; }
|
|
306
245
|
}
|
|
246
|
+
this.dispatchEvent(new CustomEvent('space-gib-accordion-toggled', {
|
|
247
|
+
detail: { isExpanded: this.isTimelineExpanded },
|
|
248
|
+
bubbles: true,
|
|
249
|
+
composed: true,
|
|
250
|
+
}));
|
|
307
251
|
}
|
|
308
252
|
|
|
309
253
|
override async disconnected(): Promise<void> {
|
|
@@ -2,199 +2,50 @@
|
|
|
2
2
|
* @module client/ui/router/space-gib-router-helpers
|
|
3
3
|
*
|
|
4
4
|
* Route parsing and formatting helpers for the Space-Gib Client Router.
|
|
5
|
-
*
|
|
5
|
+
* Delegates universal Cosmos & Galaxy routes to @ibgib/web-gib,
|
|
6
|
+
* while handling space-gib specific routes (/admin/review).
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
|
-
|
|
10
|
+
parseCosmosRoute,
|
|
11
|
+
formatCosmosRoute,
|
|
12
|
+
isSameCosmosRoute,
|
|
13
|
+
safeDecode,
|
|
14
|
+
ParseCosmosRouteOptions,
|
|
15
|
+
CosmosRouteInfo,
|
|
16
|
+
} from '@ibgib/web-gib/dist/ui/router/index.mjs';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
SpaceGibRouteInfo,
|
|
20
|
+
AdminReviewRouteInfo,
|
|
10
21
|
} from './space-gib-router-types.mjs';
|
|
11
22
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
function safeDecode(str: string): string {
|
|
16
|
-
try {
|
|
17
|
-
return decodeURIComponent(str);
|
|
18
|
-
} catch {
|
|
19
|
-
return str;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
23
|
+
export { safeDecode };
|
|
24
|
+
export type ParseSpaceGibRouteOptions = ParseCosmosRouteOptions;
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* Parses a browser pathname into a structured SpaceGibRouteInfo.
|
|
25
|
-
*
|
|
26
|
-
* Supports:
|
|
27
|
-
* - Polycosmos: / or /polycosmos or /@:siteUsername or /keystone/:keystoneTjp
|
|
28
|
-
* - Cosmos: /:cosmos or /@:siteUsername/:cosmos or /keystone/:keystoneTjp/:cosmos
|
|
29
|
-
* - Code Galaxy: /:cosmos/code/:galaxyId[/:branch[/*filePath]]
|
|
30
|
-
* - Notes Galaxy: /:cosmos/notes/:galaxyId[/:topicTjp]
|
|
31
|
-
* - Raw Addr (Snapshot): /:cosmos/:spaceId/addr/:ibGibAddr
|
|
32
|
-
* - Raw Tjp (Living Tip): /:cosmos/:spaceId/tjp/:tjpAddr
|
|
33
|
-
* - Admin Review: /admin/review[/:tjpGib]
|
|
28
|
+
* Handles /admin/review explicitly, and delegates all Cosmos / Galaxy / Raw routes to @ibgib/web-gib.
|
|
34
29
|
*/
|
|
35
|
-
export function parseSpaceGibRoute(pathname: string): SpaceGibRouteInfo {
|
|
30
|
+
export function parseSpaceGibRoute(pathname: string, opts?: ParseSpaceGibRouteOptions): SpaceGibRouteInfo {
|
|
36
31
|
let p = (pathname || '').trim();
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const q: Record<string, string> = {};
|
|
45
|
-
searchParams.forEach((val, key) => {
|
|
46
|
-
q[key] = val;
|
|
47
|
-
});
|
|
48
|
-
if (Object.keys(q).length > 0) {
|
|
49
|
-
queryObj = q;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const hIdx = p.indexOf('#');
|
|
53
|
-
if (hIdx !== -1) { p = p.substring(0, hIdx); }
|
|
33
|
+
// Check query string/hash for /admin/review prefix
|
|
34
|
+
let cleanPath = p;
|
|
35
|
+
const qIdx = cleanPath.indexOf('?');
|
|
36
|
+
if (qIdx !== -1) { cleanPath = cleanPath.substring(0, qIdx); }
|
|
37
|
+
const hIdx = cleanPath.indexOf('#');
|
|
38
|
+
if (hIdx !== -1) { cleanPath = cleanPath.substring(0, hIdx); }
|
|
54
39
|
|
|
55
|
-
if (
|
|
56
|
-
return { kind: 'polycosmos' };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Special Route: /admin/review
|
|
60
|
-
if (p === '/admin/review') {
|
|
40
|
+
if (cleanPath === '/admin/review') {
|
|
61
41
|
return { kind: 'admin-review' };
|
|
62
42
|
}
|
|
63
|
-
if (
|
|
64
|
-
const tjpGib = safeDecode(
|
|
43
|
+
if (cleanPath.startsWith('/admin/review/')) {
|
|
44
|
+
const tjpGib = safeDecode(cleanPath.slice('/admin/review/'.length)).trim();
|
|
65
45
|
return { kind: 'admin-review', ...(tjpGib ? { tjpGib } : {}) };
|
|
66
46
|
}
|
|
67
47
|
|
|
68
|
-
|
|
69
|
-
if (rawSegments.length === 0) {
|
|
70
|
-
return { kind: 'polycosmos' };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Extract tenant prefix if present (@username or /keystone/tjp)
|
|
74
|
-
let tenant: SpaceGibTenant | undefined;
|
|
75
|
-
let segIdx = 0;
|
|
76
|
-
|
|
77
|
-
if (rawSegments[0].startsWith('@')) {
|
|
78
|
-
const username = safeDecode(rawSegments[0].slice(1)).trim();
|
|
79
|
-
if (username) {
|
|
80
|
-
tenant = { type: 'username', siteUsername: username };
|
|
81
|
-
segIdx = 1;
|
|
82
|
-
}
|
|
83
|
-
} else if (rawSegments[0] === 'keystone' && rawSegments.length > 1) {
|
|
84
|
-
const keystoneTjp = safeDecode(rawSegments[1]).trim();
|
|
85
|
-
if (keystoneTjp) {
|
|
86
|
-
tenant = { type: 'keystone', keystoneTjp };
|
|
87
|
-
segIdx = 2;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const remaining = rawSegments.slice(segIdx);
|
|
92
|
-
|
|
93
|
-
// If only tenant specifier was given (e.g. /@bill or /keystone/tjp123)
|
|
94
|
-
if (remaining.length === 0) {
|
|
95
|
-
return { kind: 'polycosmos', ...(tenant ? { tenant } : {}) };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (remaining.length === 1 && remaining[0] === 'polycosmos') {
|
|
99
|
-
return { kind: 'polycosmos', ...(tenant ? { tenant } : {}) };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const cosmos = safeDecode(remaining[0]).trim();
|
|
103
|
-
|
|
104
|
-
if (remaining.length === 1) {
|
|
105
|
-
return { kind: 'cosmos', ...(tenant ? { tenant } : {}), cosmos };
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const second = safeDecode(remaining[1]).trim();
|
|
109
|
-
|
|
110
|
-
// Code Galaxy: /:cosmos/code/:galaxyId[/:branch[/*filePath]]
|
|
111
|
-
if (second === 'code') {
|
|
112
|
-
const galaxyId = remaining[2] ? safeDecode(remaining[2]).trim() : '';
|
|
113
|
-
if (!galaxyId) {
|
|
114
|
-
return { kind: 'cosmos', ...(tenant ? { tenant } : {}), cosmos };
|
|
115
|
-
}
|
|
116
|
-
const branch = remaining[3] ? safeDecode(remaining[3]).trim() : undefined;
|
|
117
|
-
const filePath = remaining.length > 4 ? remaining.slice(4).map(safeDecode).join('/') : undefined;
|
|
118
|
-
return {
|
|
119
|
-
kind: 'code-galaxy',
|
|
120
|
-
...(tenant ? { tenant } : {}),
|
|
121
|
-
cosmos,
|
|
122
|
-
galaxyId,
|
|
123
|
-
...(branch ? { branch } : {}),
|
|
124
|
-
...(filePath ? { filePath } : {}),
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Notes Galaxy: /:cosmos/notes/:galaxyId[/tjp/:tjp1/:tjp2...] or [/addr/:addr1/:addr2...] or [/:topicTjp]
|
|
129
|
-
if (second === 'notes') {
|
|
130
|
-
const galaxyId = remaining[2] ? safeDecode(remaining[2]).trim() : '';
|
|
131
|
-
if (!galaxyId) {
|
|
132
|
-
return { kind: 'cosmos', ...(tenant ? { tenant } : {}), cosmos };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
let trailMode: 'tjp' | 'addr' | undefined;
|
|
136
|
-
let trail: string[] | undefined;
|
|
137
|
-
let topicTjp: string | undefined;
|
|
138
|
-
|
|
139
|
-
if (remaining.length > 3) {
|
|
140
|
-
const modeCandidate = safeDecode(remaining[3]).trim();
|
|
141
|
-
if (modeCandidate === 'tjp' || modeCandidate === 'addr') {
|
|
142
|
-
trailMode = modeCandidate;
|
|
143
|
-
const trailSegments = remaining.slice(4).map(s => safeDecode(s).trim()).filter(s => s.length > 0);
|
|
144
|
-
if (trailSegments.length > 0) {
|
|
145
|
-
trail = trailSegments;
|
|
146
|
-
topicTjp = trailSegments[0];
|
|
147
|
-
}
|
|
148
|
-
} else {
|
|
149
|
-
// Backward compatibility / shorthand: /notes/:galaxyId/:topicTjp
|
|
150
|
-
topicTjp = modeCandidate;
|
|
151
|
-
trailMode = 'tjp';
|
|
152
|
-
trail = [modeCandidate];
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
kind: 'notes-galaxy',
|
|
158
|
-
...(tenant ? { tenant } : {}),
|
|
159
|
-
cosmos,
|
|
160
|
-
galaxyId,
|
|
161
|
-
...(trailMode ? { trailMode } : {}),
|
|
162
|
-
...(trail ? { trail } : {}),
|
|
163
|
-
...(topicTjp ? { topicTjp } : {}),
|
|
164
|
-
...(queryObj ? { query: queryObj } : {}),
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Mechanism 1: Space-Qualified Raw Addrs
|
|
169
|
-
// /:cosmos/:spaceId/addr/:ibGibAddr
|
|
170
|
-
// /:cosmos/:spaceId/tjp/:tjpAddr
|
|
171
|
-
if (remaining.length >= 4) {
|
|
172
|
-
const third = safeDecode(remaining[2]).trim();
|
|
173
|
-
const spaceId = second;
|
|
174
|
-
if (third === 'addr') {
|
|
175
|
-
const ibGibAddr = safeDecode(remaining.slice(3).join('/')).trim();
|
|
176
|
-
return {
|
|
177
|
-
kind: 'raw-addr',
|
|
178
|
-
...(tenant ? { tenant } : {}),
|
|
179
|
-
cosmos,
|
|
180
|
-
spaceId,
|
|
181
|
-
ibGibAddr,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
if (third === 'tjp') {
|
|
185
|
-
const tjpAddr = safeDecode(remaining.slice(3).join('/')).trim();
|
|
186
|
-
return {
|
|
187
|
-
kind: 'raw-tjp',
|
|
188
|
-
...(tenant ? { tenant } : {}),
|
|
189
|
-
cosmos,
|
|
190
|
-
spaceId,
|
|
191
|
-
tjpAddr,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Fallback: Cosmos route
|
|
197
|
-
return { kind: 'cosmos', ...(tenant ? { tenant } : {}), cosmos };
|
|
48
|
+
return parseCosmosRoute(pathname, opts) as SpaceGibRouteInfo;
|
|
198
49
|
}
|
|
199
50
|
|
|
200
51
|
/**
|
|
@@ -204,62 +55,7 @@ export function formatSpaceGibRoute(route: SpaceGibRouteInfo): string {
|
|
|
204
55
|
if (route.kind === 'admin-review') {
|
|
205
56
|
return `/admin/review${route.tjpGib ? `/${encodeURIComponent(route.tjpGib)}` : ''}`;
|
|
206
57
|
}
|
|
207
|
-
|
|
208
|
-
let prefix = '';
|
|
209
|
-
if (route.tenant) {
|
|
210
|
-
if (route.tenant.type === 'username') {
|
|
211
|
-
prefix = `/@${encodeURIComponent(route.tenant.siteUsername)}`;
|
|
212
|
-
} else if (route.tenant.type === 'keystone') {
|
|
213
|
-
prefix = `/keystone/${encodeURIComponent(route.tenant.keystoneTjp)}`;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
switch (route.kind) {
|
|
218
|
-
case 'polycosmos':
|
|
219
|
-
return prefix ? `${prefix}/polycosmos` : '/';
|
|
220
|
-
|
|
221
|
-
case 'cosmos':
|
|
222
|
-
return `${prefix}/${encodeURIComponent(route.cosmos)}`;
|
|
223
|
-
|
|
224
|
-
case 'code-galaxy': {
|
|
225
|
-
let res = `${prefix}/${encodeURIComponent(route.cosmos)}/code/${encodeURIComponent(route.galaxyId)}`;
|
|
226
|
-
if (route.branch) {
|
|
227
|
-
res += `/${encodeURIComponent(route.branch)}`;
|
|
228
|
-
if (route.filePath) {
|
|
229
|
-
res += `/${route.filePath.split('/').map(encodeURIComponent).join('/')}`;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
return res;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
case 'notes-galaxy': {
|
|
236
|
-
let res = `${prefix}/${encodeURIComponent(route.cosmos)}/notes/${encodeURIComponent(route.galaxyId)}`;
|
|
237
|
-
if (route.trail && route.trail.length > 0) {
|
|
238
|
-
const mode = route.trailMode || 'tjp';
|
|
239
|
-
res += `/${mode}/${route.trail.map(encodeURIComponent).join('/')}`;
|
|
240
|
-
} else if (route.topicTjp) {
|
|
241
|
-
res += `/${encodeURIComponent(route.topicTjp)}`;
|
|
242
|
-
}
|
|
243
|
-
if (route.query && Object.keys(route.query).length > 0) {
|
|
244
|
-
const sp = new URLSearchParams();
|
|
245
|
-
for (const [k, v] of Object.entries(route.query)) {
|
|
246
|
-
if (v !== undefined) { sp.set(k, v); }
|
|
247
|
-
}
|
|
248
|
-
const qs = sp.toString();
|
|
249
|
-
if (qs) { res += `?${qs}`; }
|
|
250
|
-
}
|
|
251
|
-
return res;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
case 'raw-addr':
|
|
255
|
-
return `${prefix}/${encodeURIComponent(route.cosmos)}/${encodeURIComponent(route.spaceId)}/addr/${encodeURIComponent(route.ibGibAddr)}`;
|
|
256
|
-
|
|
257
|
-
case 'raw-tjp':
|
|
258
|
-
return `${prefix}/${encodeURIComponent(route.cosmos)}/${encodeURIComponent(route.spaceId)}/tjp/${encodeURIComponent(route.tjpAddr)}`;
|
|
259
|
-
|
|
260
|
-
default:
|
|
261
|
-
return '/';
|
|
262
|
-
}
|
|
58
|
+
return formatCosmosRoute(route as CosmosRouteInfo);
|
|
263
59
|
}
|
|
264
60
|
|
|
265
61
|
/**
|
|
@@ -268,5 +64,9 @@ export function formatSpaceGibRoute(route: SpaceGibRouteInfo): string {
|
|
|
268
64
|
export function isSameRoute(a?: SpaceGibRouteInfo, b?: SpaceGibRouteInfo): boolean {
|
|
269
65
|
if (!a && !b) { return true; }
|
|
270
66
|
if (!a || !b) { return false; }
|
|
271
|
-
|
|
67
|
+
if (a.kind === 'admin-review' || b.kind === 'admin-review') {
|
|
68
|
+
if (a.kind !== b.kind) { return false; }
|
|
69
|
+
return (a as AdminReviewRouteInfo).tjpGib === (b as AdminReviewRouteInfo).tjpGib;
|
|
70
|
+
}
|
|
71
|
+
return isSameCosmosRoute(a as CosmosRouteInfo, b as CosmosRouteInfo);
|
|
272
72
|
}
|