@ibgib/space-gib 0.0.5 → 0.0.7
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/README.md +20 -0
- package/dist/client/bootstrap.mjs +31 -31
- package/dist/client/bootstrap.mjs.map +3 -3
- package/dist/client/chunk-RXFIBFRK.mjs +42 -0
- package/dist/client/chunk-RXFIBFRK.mjs.map +7 -0
- package/dist/client/chunk-ULFNE26Y.mjs +2216 -0
- package/dist/client/chunk-ULFNE26Y.mjs.map +7 -0
- package/dist/client/index.html +35 -14
- package/dist/client/index.mjs +1 -1
- package/dist/client/script.mjs +1 -1
- package/dist/client/style.css +29 -5
- package/dist/server/server.mjs +1447 -270
- package/dist/server/server.mjs.map +4 -4
- package/package.json +5 -5
- package/space-gib.localhost-1783713259760.log +45 -0
- package/src/client/AUTO-GENERATED-version.mts +1 -1
- package/src/client/bootstrap.mts +9 -0
- package/src/client/components/identity-header/identity-header.css +40 -2
- package/src/client/components/identity-header/identity-header.html +3 -2
- package/src/client/components/identity-header/identity-header.mts +127 -49
- package/src/client/components/identity-manager/identity-manager.css +57 -353
- package/src/client/components/identity-manager/identity-manager.html +0 -94
- package/src/client/components/identity-manager/identity-manager.mts +356 -484
- package/src/client/components/keystone-creator/keystone-creator.mts +90 -13
- package/src/client/components/keystone-details/keystone-details.css +472 -0
- package/src/client/components/keystone-details/keystone-details.html +99 -0
- package/src/client/components/keystone-details/keystone-details.mts +821 -0
- package/src/client/components/keystone-scrubber/SCRUBBER_IMPLEMENTATION.md +33 -0
- package/src/client/components/keystone-scrubber/keystone-scrubber.css +46 -0
- package/src/client/components/keystone-scrubber/keystone-scrubber.html +15 -0
- package/src/client/components/keystone-scrubber/keystone-scrubber.mts +356 -0
- package/src/client/dev-tools/common.mts +505 -10
- package/src/client/dev-tools/phase-4-1.mts +19 -4
- package/src/client/dev-tools/phase-4-10.mts +77 -305
- package/src/client/dev-tools/phase-4-2.mts +46 -212
- package/src/client/dev-tools/phase-4-3.mts +57 -198
- package/src/client/dev-tools/phase-4-4.mts +57 -170
- package/src/client/dev-tools/phase-4-5.mts +48 -204
- package/src/client/dev-tools/phase-4-6.mts +37 -103
- package/src/client/dev-tools/phase-4-7.mts +44 -228
- package/src/client/dev-tools/phase-4-8.mts +33 -136
- package/src/client/dev-tools/phase-4-9.mts +33 -137
- package/src/client/dev-tools/phase-4.mts +30 -6
- package/src/client/dev-tools.mts +18 -0
- package/src/client/index.html +35 -14
- package/src/client/style.css +29 -5
- package/src/client/types.mts +4 -1
- package/src/client/ui/shell/space-gib-shell-service.mts +4 -0
- package/src/server/path-constants.mts +12 -0
- package/src/server/serve-gib/handlers/api/keystone/sso-config.handler.mts +66 -0
- package/src/server/serve-gib/handlers/api/keystone/sso-link.handler.mts +119 -0
- package/src/server/serve-gib/handlers/api/keystone/sso-login.handler.mts +189 -0
- package/src/server/server.mts +6 -0
- package/dist/client/chunk-ANGVYAEK.mjs +0 -42
- package/dist/client/chunk-ANGVYAEK.mjs.map +0 -7
- package/dist/client/chunk-IRGFDQRD.mjs +0 -1920
- package/dist/client/chunk-IRGFDQRD.mjs.map +0 -7
- package/dist/respec-gib.node.mjs +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ibgib/space-gib",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ibgib storage and provider service — SaaS at ibgib.space",
|
|
6
6
|
"scripts": {
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
"build:test": "tsc -p tsconfig.test.json"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@ibgib/core-gib": "^0.1.
|
|
15
|
+
"@ibgib/core-gib": "^0.1.64",
|
|
16
16
|
"@ibgib/helper-gib": "^0.0.36",
|
|
17
|
-
"@ibgib/ts-gib": "^0.5.
|
|
18
|
-
"@ibgib/web-gib": "^0.0.
|
|
19
|
-
"@ibgib/node-gib": "^0.0.
|
|
17
|
+
"@ibgib/ts-gib": "^0.5.33",
|
|
18
|
+
"@ibgib/web-gib": "^0.0.50",
|
|
19
|
+
"@ibgib/node-gib": "^0.0.8"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20.0.0"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
script.mjs:7 space-gib early script executing...
|
|
2
|
+
chunk-OVS3VYAL.mjs:27047 [getSpaceGibShellSvc] initializing SpaceGibShellService singleton on globalThis... (I: genuuid)
|
|
3
|
+
chunk-OVS3VYAL.mjs:108 [initialize] does nothing atow (I: 65bb46c88c82b637ad928b8bf1a07225)
|
|
4
|
+
index.mjs:24 [spinOffStartup]: 0.134033203125 ms DOMContentLoaded fired
|
|
5
|
+
index.mjs:26 [spinOffStartup]: 57.553955078125 ms initIbGibStorage complete
|
|
6
|
+
bootstrap.mjs:9643 [space-gib bootstrap] version: 0.0.6
|
|
7
|
+
bootstrap.mjs:7586 [bootstrapIbGibApp] starting...
|
|
8
|
+
bootstrap.mjs:366 [buildArgInfos] starting... (I: f389aaa490796dfd823bc7b9d4e58b23)
|
|
9
|
+
bootstrap.mjs:376 identifier: interactive (I: 519ce129a1e34753a9070d3a205c9a8b)
|
|
10
|
+
bootstrap.mjs:462 [buildArgInfos] complete.
|
|
11
|
+
bootstrap.mjs:7639 [execFromArgs] starting...
|
|
12
|
+
bootstrap.mjs:7681 [initMetaspace] starting...
|
|
13
|
+
chunk-D2MM5RDN.mjs:72 [Violation] 'setTimeout' handler took 70ms
|
|
14
|
+
bootstrap.mjs:2495 [Metaspace_Webspace][initialize] initialized (I: e3b3a9652c09445cb055013166ff089c)
|
|
15
|
+
bootstrap.mjs:7708 [initMetaspace] complete.
|
|
16
|
+
chunk-OVS3VYAL.mjs:20874 [registerFunctionInfos] starting... (I: 14fee8e27384a040494542182031ae25)
|
|
17
|
+
chunk-OVS3VYAL.mjs:20893 [registerFunctionInfos] complete.
|
|
18
|
+
bootstrap.mjs:7725 [execInteractive] starting...
|
|
19
|
+
bootstrap.mjs:7758 [defaultGetOrCreateApp] starting...
|
|
20
|
+
bootstrap.mjs:7826 [defaultGetOrCreateApp] complete.
|
|
21
|
+
bootstrap.mjs:8503 [SpaceGibApp_V1] space-gib initialized and ready.
|
|
22
|
+
bootstrap.mjs:7748 [execInteractive] complete.
|
|
23
|
+
bootstrap.mjs:7671
|
|
24
|
+
[execFromArgs] complete.
|
|
25
|
+
chunk-OVS3VYAL.mjs:27020 [SpaceGibShellService][onEngineReady] SpaceGib Shell Service is ready.
|
|
26
|
+
bootstrap.mjs:7629
|
|
27
|
+
[bootstrapIbGibApp] complete.
|
|
28
|
+
index.mjs:28 [spinOffStartup]: 920.193115234375 ms dynamicallyLoadBootstrapScript complete
|
|
29
|
+
index.mjs:30 [spinOffStartup]: 924.22314453125 ms initDevTools complete
|
|
30
|
+
index.mjs:31 [spinOffStartup]: 924.443115234375 ms
|
|
31
|
+
chunk-OVS3VYAL.mjs:26572 yes this is being updated! I am just wondering if I am seeing old code in the browser, i.e., if refresh is happening or just getting cache (I: 6599db11c1086062b8f5e86db89cba26)
|
|
32
|
+
chunk-OVS3VYAL.mjs:26575 KeystoneScrubberComponentInstance[ctor] (I: 3adca837d5c898d8e839d23c59538126)
|
|
33
|
+
chunk-OVS3VYAL.mjs:26583 [KeystoneScrubberComponentInstance][initialize] starting... (I: 75eecfc01af7f3fa9897932ec5457526)
|
|
34
|
+
chunk-OVS3VYAL.mjs:26638 [KeystoneScrubberComponentInstance][loadIbGib] starting... (I: a4a9181bbb58a22cc71c8745a91ec426)
|
|
35
|
+
chunk-OVS3VYAL.mjs:26648 [KeystoneScrubberComponentInstance][loadIbGib] complete.
|
|
36
|
+
chunk-OVS3VYAL.mjs:26592 [KeystoneScrubberComponentInstance][initialize] complete.
|
|
37
|
+
chunk-OVS3VYAL.mjs:26600 [KeystoneScrubberComponentInstance][created] starting... (I: bc16e6212928658ed8034c75b6279526)
|
|
38
|
+
chunk-OVS3VYAL.mjs:26572 yes this is being updated! I am just wondering if I am seeing old code in the browser, i.e., if refresh is happening or just getting cache (I: 6599db11c1086062b8f5e86db89cba26)
|
|
39
|
+
chunk-OVS3VYAL.mjs:26575 KeystoneScrubberComponentInstance[ctor] (I: 3adca837d5c898d8e839d23c59538126)
|
|
40
|
+
chunk-OVS3VYAL.mjs:26583 [KeystoneScrubberComponentInstance][initialize] starting... (I: 75eecfc01af7f3fa9897932ec5457526)
|
|
41
|
+
chunk-OVS3VYAL.mjs:26638 [KeystoneScrubberComponentInstance][loadIbGib] starting... (I: a4a9181bbb58a22cc71c8745a91ec426)
|
|
42
|
+
chunk-OVS3VYAL.mjs:26648 [KeystoneScrubberComponentInstance][loadIbGib] complete.
|
|
43
|
+
chunk-OVS3VYAL.mjs:26592 [KeystoneScrubberComponentInstance][initialize] complete.
|
|
44
|
+
chunk-OVS3VYAL.mjs:26600 [KeystoneScrubberComponentInstance][created] starting... (I: bc16e6212928658ed8034c75b6279526)
|
|
45
|
+
chunk-OVS3VYAL.mjs:24584 [IdentityManagerComponentInstance][activateIbGib] same tab already active. returning early. childInfo.addr: keystone^442D637B4066E3D0A73A467C14F71FE9FDAA5C5A7FC7EA28064877A63A914C44.5D0EC2067890F88736364BBE9BD59C80DCB99FC85132B3637072D274077D8CA6 (user just clicked on the same tab) (I: e67c0d02f3143c49c7a20c82d0730225)
|
package/src/client/bootstrap.mts
CHANGED
|
@@ -23,6 +23,15 @@ import { registerDeprecatedFunctionNamesAndFunctionInfos_Web } from "./api/funct
|
|
|
23
23
|
|
|
24
24
|
import { getSpaceGibShellSvc } from "./ui/shell/space-gib-shell-service.mjs";
|
|
25
25
|
|
|
26
|
+
// Early check: if we are in an OAuth callback popup redirect, notify parent window and close immediately.
|
|
27
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
28
|
+
if (urlParams.has('code') && urlParams.has('state') && window.opener) {
|
|
29
|
+
const code = urlParams.get('code');
|
|
30
|
+
const state = urlParams.get('state');
|
|
31
|
+
window.opener.postMessage({ type: 'sso-oauth-callback', code, state }, window.location.origin);
|
|
32
|
+
window.close();
|
|
33
|
+
}
|
|
34
|
+
|
|
26
35
|
console.log(`[space-gib bootstrap] version: ${AUTO_GENERATED_VERSION}`);
|
|
27
36
|
|
|
28
37
|
// ---------------------------------------------------------------------------
|
|
@@ -18,14 +18,13 @@
|
|
|
18
18
|
background: var(--tab-background-color-active, rgba(255, 255, 255, 0.1));
|
|
19
19
|
border: 1px solid var(--tab-border-color-active, rgba(80, 250, 123, 0.3));
|
|
20
20
|
border-radius: var(--radius-lg, 20px);
|
|
21
|
-
cursor:
|
|
21
|
+
cursor: default;
|
|
22
22
|
transition: all 0.2s ease-in-out;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
.identity-pill:hover {
|
|
26
26
|
background: rgba(80, 250, 123, 0.15);
|
|
27
27
|
border-color: var(--clr-accent, #50fa7b);
|
|
28
|
-
transform: translateY(-1px);
|
|
29
28
|
box-shadow: 0 2px 8px rgba(80, 250, 123, 0.1);
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -72,3 +71,42 @@
|
|
|
72
71
|
.hidden {
|
|
73
72
|
display: none !important;
|
|
74
73
|
}
|
|
74
|
+
|
|
75
|
+
/* Styled selector dropdown */
|
|
76
|
+
.identity-select {
|
|
77
|
+
font-family: var(--font-sans, sans-serif);
|
|
78
|
+
font-size: 0.85rem;
|
|
79
|
+
color: var(--clr-text-primary, #ffffff);
|
|
80
|
+
background: transparent;
|
|
81
|
+
border: none;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
font-weight: 500;
|
|
84
|
+
outline: none;
|
|
85
|
+
padding: 0 0.2rem;
|
|
86
|
+
max-width: 150px;
|
|
87
|
+
text-overflow: ellipsis;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.identity-select option {
|
|
91
|
+
background: var(--clr-bg-surface, #1e1e2e);
|
|
92
|
+
color: var(--clr-text-primary, #ffffff);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Gear manage button */
|
|
96
|
+
.manage-btn {
|
|
97
|
+
background: transparent;
|
|
98
|
+
border: none;
|
|
99
|
+
font-size: 1rem;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
padding: 0 0.2rem;
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
color: var(--clr-text-secondary, #b3b3b3);
|
|
106
|
+
transition: color 0.2s ease, transform 0.2s ease;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.manage-btn:hover {
|
|
110
|
+
color: var(--clr-accent, #50fa7b);
|
|
111
|
+
transform: rotate(45deg);
|
|
112
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<div id="container" class="header-widget-container">
|
|
2
2
|
<!-- Active Identity Pill -->
|
|
3
|
-
<div id="active-identity-pill" class="identity-pill hidden"
|
|
3
|
+
<div id="active-identity-pill" class="identity-pill hidden">
|
|
4
4
|
<div id="identity-avatar" class="avatar-circle">-</div>
|
|
5
|
-
<
|
|
5
|
+
<select id="identity-selector" class="identity-select" title="Switch active identity"></select>
|
|
6
|
+
<button id="btn-manage-identities" class="manage-btn" title="Manage Identities">⚙️</button>
|
|
6
7
|
</div>
|
|
7
8
|
|
|
8
9
|
<!-- Fallback Action Button -->
|
|
@@ -68,7 +68,8 @@ export class IdentityHeaderComponentMeta extends IbGibDynamicComponentMetaBase {
|
|
|
68
68
|
interface IdentityHeaderElements extends ElementsBase {
|
|
69
69
|
containerEl: HTMLDivElement;
|
|
70
70
|
activeIdentityPillEl: HTMLDivElement;
|
|
71
|
-
|
|
71
|
+
identitySelectorEl: HTMLSelectElement;
|
|
72
|
+
btnManageIdentitiesEl: HTMLButtonElement;
|
|
72
73
|
btnCreateIdentityEl: HTMLButtonElement;
|
|
73
74
|
identityAvatarEl: HTMLDivElement;
|
|
74
75
|
}
|
|
@@ -83,34 +84,34 @@ export class IdentityHeaderComponentInstance
|
|
|
83
84
|
protected lc: string = `[IdentityHeaderComponentInstance]`;
|
|
84
85
|
private activeAddr: string | null = null;
|
|
85
86
|
private _onRequestIdentityChange: ((e: any) => void) | null = null;
|
|
86
|
-
private keystoneCache: Map<string, { username: string, description: string }> = new Map();
|
|
87
|
+
private keystoneCache: Map<string, { username: string, description: string, isPrimary: boolean }> = new Map();
|
|
87
88
|
|
|
88
89
|
constructor() {
|
|
89
90
|
super();
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
private async getKeystoneDetails(addr: string): Promise<{ username: string, description: string }> {
|
|
93
|
+
private async getKeystoneDetails(addr: string): Promise<{ username: string, description: string, isPrimary: boolean }> {
|
|
93
94
|
const cached = this.keystoneCache.get(addr);
|
|
94
95
|
if (cached) return cached;
|
|
95
96
|
|
|
96
97
|
const metaspace = getIbGibGlobalThis_SpaceGib(APP_CONFIG).metaspace;
|
|
97
|
-
if (!metaspace) return { username: '', description: '' };
|
|
98
|
+
if (!metaspace) return { username: '', description: '', isPrimary: false };
|
|
98
99
|
const space = await metaspace.getLocalUserSpace({ lock: false });
|
|
99
|
-
if (!space) return { username: '', description: '' };
|
|
100
|
+
if (!space) return { username: '', description: '', isPrimary: false };
|
|
100
101
|
|
|
101
102
|
try {
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
103
|
+
const keystoneSvc = new KeystoneService_V1();
|
|
104
|
+
const info = await keystoneSvc.getKeystoneCommonInfo({
|
|
105
|
+
addr,
|
|
106
|
+
metaspace,
|
|
107
|
+
space
|
|
108
|
+
});
|
|
109
|
+
if (info) {
|
|
110
|
+
const details = {
|
|
111
|
+
username: info.name,
|
|
112
|
+
description: info.description,
|
|
113
|
+
isPrimary: info.isPrimary
|
|
114
|
+
};
|
|
114
115
|
this.keystoneCache.set(addr, details);
|
|
115
116
|
return details;
|
|
116
117
|
}
|
|
@@ -118,7 +119,7 @@ export class IdentityHeaderComponentInstance
|
|
|
118
119
|
console.warn(`Error getting details for keystone ${addr}: ${extractErrorMsg(err)}`);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
return { username: '', description: '' };
|
|
122
|
+
return { username: '', description: '', isPrimary: false };
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
|
|
@@ -132,7 +133,8 @@ export class IdentityHeaderComponentInstance
|
|
|
132
133
|
const shadow = this.shadowRoot!;
|
|
133
134
|
this.elements.containerEl = shadow.getElementById('container') as HTMLDivElement;
|
|
134
135
|
this.elements.activeIdentityPillEl = shadow.getElementById('active-identity-pill') as HTMLDivElement;
|
|
135
|
-
this.elements.
|
|
136
|
+
this.elements.identitySelectorEl = shadow.getElementById('identity-selector') as HTMLSelectElement;
|
|
137
|
+
this.elements.btnManageIdentitiesEl = shadow.getElementById('btn-manage-identities') as HTMLButtonElement;
|
|
136
138
|
this.elements.btnCreateIdentityEl = shadow.getElementById('btn-create-identity') as HTMLButtonElement;
|
|
137
139
|
this.elements.identityAvatarEl = shadow.getElementById('identity-avatar') as HTMLDivElement;
|
|
138
140
|
|
|
@@ -182,9 +184,24 @@ export class IdentityHeaderComponentInstance
|
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
private initHandlers() {
|
|
185
|
-
// Handle clicks: route to the full identity manager
|
|
186
|
-
this.elements!.activeIdentityPillEl.addEventListener('click', () => this.navigateToManager());
|
|
187
187
|
this.elements!.btnCreateIdentityEl.addEventListener('click', () => this.navigateToManager());
|
|
188
|
+
this.elements!.btnManageIdentitiesEl.addEventListener('click', (e) => {
|
|
189
|
+
e.stopPropagation();
|
|
190
|
+
this.navigateToManager();
|
|
191
|
+
});
|
|
192
|
+
this.elements!.identitySelectorEl.addEventListener('click', (e) => {
|
|
193
|
+
e.stopPropagation();
|
|
194
|
+
});
|
|
195
|
+
this.elements!.identitySelectorEl.addEventListener('change', () => {
|
|
196
|
+
const selectedAddr = this.elements!.identitySelectorEl.value;
|
|
197
|
+
if (selectedAddr) {
|
|
198
|
+
window.dispatchEvent(new CustomEvent(EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, {
|
|
199
|
+
detail: { activeIdentityAddr: selectedAddr },
|
|
200
|
+
bubbles: true,
|
|
201
|
+
composed: true
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
});
|
|
188
205
|
}
|
|
189
206
|
|
|
190
207
|
private navigateToManager() {
|
|
@@ -213,16 +230,25 @@ export class IdentityHeaderComponentInstance
|
|
|
213
230
|
|
|
214
231
|
// Verify it is actually one of the registered keystones in the index relations
|
|
215
232
|
const registeredKeystones = this.ibGib?.rel8ns?.keystone ?? [];
|
|
216
|
-
|
|
233
|
+
const detailsPromises = registeredKeystones.map(async addr => {
|
|
234
|
+
const details = await this.getKeystoneDetails(addr);
|
|
235
|
+
return { addr, isPrimary: details?.isPrimary ?? false };
|
|
236
|
+
});
|
|
237
|
+
const resolvedDetails = await Promise.all(detailsPromises);
|
|
238
|
+
const primaryKeystones = resolvedDetails
|
|
239
|
+
.filter(item => item.isPrimary)
|
|
240
|
+
.map(item => item.addr);
|
|
241
|
+
|
|
242
|
+
if (activeAddrInSettings && primaryKeystones.includes(activeAddrInSettings)) {
|
|
217
243
|
this.activeAddr = activeAddrInSettings;
|
|
218
|
-
} else if (
|
|
219
|
-
this.activeAddr =
|
|
244
|
+
} else if (primaryKeystones.length > 0) {
|
|
245
|
+
this.activeAddr = primaryKeystones[0];
|
|
220
246
|
} else {
|
|
221
247
|
this.activeAddr = null;
|
|
222
248
|
}
|
|
223
249
|
|
|
224
250
|
// Sync with globalState.identity
|
|
225
|
-
const globalState = getIbGibGlobalThis_SpaceGib(APP_CONFIG)
|
|
251
|
+
const globalState = getIbGibGlobalThis_SpaceGib(APP_CONFIG);
|
|
226
252
|
if (this.activeAddr) {
|
|
227
253
|
const metaspace = globalState.metaspace;
|
|
228
254
|
if (metaspace) {
|
|
@@ -230,12 +256,44 @@ export class IdentityHeaderComponentInstance
|
|
|
230
256
|
if (space) {
|
|
231
257
|
const res = await metaspace.get({ addr: this.activeAddr, space });
|
|
232
258
|
if (res.success && res.ibGibs && res.ibGibs.length > 0) {
|
|
233
|
-
|
|
259
|
+
const domainIdentity = res.ibGibs[0] as KeystoneIbGib_V1;
|
|
260
|
+
|
|
261
|
+
// Find delegate with the sync allowed verb
|
|
262
|
+
let syncDelegateIdentity: KeystoneIbGib_V1 | undefined;
|
|
263
|
+
const delegates = domainIdentity.data?.delegates;
|
|
264
|
+
if (delegates) {
|
|
265
|
+
for (const delegateInfo of Object.values(delegates)) {
|
|
266
|
+
if (delegateInfo.allowedVerbs?.includes('sync^gib') || (!delegateInfo.allowedVerbs && delegateInfo.delegateTjpAddr)) {
|
|
267
|
+
// Fetch the delegate's latest tip from space
|
|
268
|
+
const delegateLatestAddr = await metaspace.getLatestAddr({
|
|
269
|
+
addr: delegateInfo.delegateTjpAddr,
|
|
270
|
+
space
|
|
271
|
+
});
|
|
272
|
+
if (delegateLatestAddr) {
|
|
273
|
+
const resDelegate = await metaspace.get({ addr: delegateLatestAddr, space });
|
|
274
|
+
if (resDelegate.success && resDelegate.ibGibs && resDelegate.ibGibs.length > 0) {
|
|
275
|
+
syncDelegateIdentity = resDelegate.ibGibs[0] as KeystoneIbGib_V1;
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
globalState.identity = {
|
|
284
|
+
resolved: true,
|
|
285
|
+
authenticated: true,
|
|
286
|
+
domainIdentity,
|
|
287
|
+
syncDelegateIdentity
|
|
288
|
+
};
|
|
234
289
|
}
|
|
235
290
|
}
|
|
236
291
|
}
|
|
237
292
|
} else {
|
|
238
|
-
globalState.identity =
|
|
293
|
+
globalState.identity = {
|
|
294
|
+
resolved: false,
|
|
295
|
+
authenticated: false
|
|
296
|
+
};
|
|
239
297
|
}
|
|
240
298
|
} catch (error) {
|
|
241
299
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
@@ -246,29 +304,60 @@ export class IdentityHeaderComponentInstance
|
|
|
246
304
|
}
|
|
247
305
|
|
|
248
306
|
protected override async renderUI(): Promise<void> {
|
|
249
|
-
if (!this.elements) return;
|
|
307
|
+
if (!this.elements) { return; }
|
|
250
308
|
|
|
251
309
|
// Double check state on render
|
|
252
310
|
await this.resolveActiveIdentity();
|
|
253
311
|
|
|
254
|
-
|
|
312
|
+
const keystones = this.ibGib?.rel8ns?.keystone ?? [];
|
|
313
|
+
const detailsPromises = keystones.map(async addr => {
|
|
314
|
+
const details = await this.getKeystoneDetails(addr);
|
|
315
|
+
return { addr, isPrimary: details?.isPrimary ?? false };
|
|
316
|
+
});
|
|
317
|
+
const resolvedDetails = await Promise.all(detailsPromises);
|
|
318
|
+
const primaryKeystones = resolvedDetails
|
|
319
|
+
.filter(item => item.isPrimary)
|
|
320
|
+
.map(item => item.addr);
|
|
321
|
+
|
|
322
|
+
if (this.activeAddr && primaryKeystones.length > 0) {
|
|
255
323
|
this.elements.activeIdentityPillEl.classList.remove('hidden');
|
|
256
324
|
this.elements.btnCreateIdentityEl.classList.add('hidden');
|
|
257
325
|
|
|
258
326
|
const addr = this.activeAddr;
|
|
259
327
|
|
|
260
|
-
//
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
328
|
+
// Populate the dropdown selector
|
|
329
|
+
this.elements.identitySelectorEl.innerHTML = '';
|
|
330
|
+
for (const kAddr of primaryKeystones) {
|
|
331
|
+
const option = document.createElement('option');
|
|
332
|
+
option.value = kAddr;
|
|
333
|
+
|
|
334
|
+
let displayAddr = kAddr;
|
|
335
|
+
if (displayAddr.length > 14) {
|
|
336
|
+
displayAddr = displayAddr.substring(0, 7) + '...' + displayAddr.substring(displayAddr.length - 5);
|
|
337
|
+
}
|
|
338
|
+
option.textContent = displayAddr;
|
|
339
|
+
|
|
340
|
+
// Load details asynchronously so we don't block
|
|
341
|
+
this.getKeystoneDetails(kAddr).then(details => {
|
|
342
|
+
if (details.username) {
|
|
343
|
+
let name = details.username;
|
|
344
|
+
if (name.length > 14) {
|
|
345
|
+
name = name.substring(0, 11) + '...';
|
|
346
|
+
}
|
|
347
|
+
option.textContent = name;
|
|
348
|
+
}
|
|
349
|
+
}).catch(err => { });
|
|
350
|
+
|
|
351
|
+
this.elements.identitySelectorEl.appendChild(option);
|
|
264
352
|
}
|
|
265
|
-
this.elements.
|
|
353
|
+
this.elements.identitySelectorEl.value = addr;
|
|
354
|
+
|
|
355
|
+
// Render active avatar
|
|
266
356
|
this.elements.identityAvatarEl.textContent = '-';
|
|
267
357
|
this.elements.identityAvatarEl.style.backgroundColor = 'var(--clr-accent)';
|
|
268
358
|
this.elements.identityAvatarEl.style.color = '#11111b';
|
|
269
|
-
this.elements.activeIdentityPillEl.title = `Active Identity: ${addr}\nClick to manage.`;
|
|
270
359
|
|
|
271
|
-
// Load details dynamically
|
|
360
|
+
// Load details dynamically for the active identity
|
|
272
361
|
const details = await this.getKeystoneDetails(addr);
|
|
273
362
|
|
|
274
363
|
// First letter of username, or fallback to first char of address (or 'A')
|
|
@@ -290,16 +379,6 @@ export class IdentityHeaderComponentInstance
|
|
|
290
379
|
this.elements.identityAvatarEl.style.backgroundColor = bg;
|
|
291
380
|
this.elements.identityAvatarEl.style.color = fg;
|
|
292
381
|
|
|
293
|
-
// Set user display name or address in pill
|
|
294
|
-
let displayName = details.username;
|
|
295
|
-
const maxLen = 14;
|
|
296
|
-
if (displayName) {
|
|
297
|
-
if (displayName.length > maxLen) {
|
|
298
|
-
displayName = displayName.substring(0, maxLen - 3) + '...';
|
|
299
|
-
}
|
|
300
|
-
this.elements.identityAddressTruncatedEl.textContent = displayName;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
382
|
// Title with full details
|
|
304
383
|
const titleParts: string[] = [];
|
|
305
384
|
if (details.username) {
|
|
@@ -312,7 +391,6 @@ export class IdentityHeaderComponentInstance
|
|
|
312
391
|
titleParts.push(`Desc: ${desc}`);
|
|
313
392
|
}
|
|
314
393
|
titleParts.push(`Addr: ${addr}`);
|
|
315
|
-
titleParts.push(`Click to manage.`);
|
|
316
394
|
this.elements.activeIdentityPillEl.title = titleParts.join('\n');
|
|
317
395
|
} else {
|
|
318
396
|
this.elements.activeIdentityPillEl.classList.add('hidden');
|
|
@@ -323,10 +401,10 @@ export class IdentityHeaderComponentInstance
|
|
|
323
401
|
private async handleRequestIdentityChange(e: any) {
|
|
324
402
|
const lc = `${this.lc}[handleRequestIdentityChange]`;
|
|
325
403
|
const addr = e.detail?.activeIdentityAddr;
|
|
326
|
-
if (!addr) return;
|
|
404
|
+
if (!addr) { return; }
|
|
327
405
|
devLog(`${lc} Request to change active identity to: ${addr}`);
|
|
328
406
|
try {
|
|
329
|
-
if (!this.settings) return;
|
|
407
|
+
if (!this.settings) { return; }
|
|
330
408
|
const generalSettings = await this.getSettings<Settings_General>({
|
|
331
409
|
settingsType: SettingsType.general,
|
|
332
410
|
useCase: 'current',
|