@ibgib/web-gib 0.0.52 → 0.0.55

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.
Files changed (150) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/AUTO-GENERATED-version.d.mts +1 -1
  3. package/dist/AUTO-GENERATED-version.mjs +1 -1
  4. package/dist/api/commands/chat/hello-world.mjs.map +1 -1
  5. package/dist/api/commands/command-constants.d.mts +4 -4
  6. package/dist/api/commands/command-constants.d.mts.map +1 -1
  7. package/dist/api/commands/command-service-v1.d.mts.map +1 -1
  8. package/dist/api/commands/command-service-v1.mjs.map +1 -1
  9. package/dist/api/commands/ibgib/get-ibgibs.d.mts.map +1 -1
  10. package/dist/api/commands/ibgib/get-ibgibs.mjs.map +1 -1
  11. package/dist/api/ibgib-api-bridge.d.mts +81 -0
  12. package/dist/api/ibgib-api-bridge.d.mts.map +1 -0
  13. package/dist/api/ibgib-api-bridge.mjs +259 -0
  14. package/dist/api/ibgib-api-bridge.mjs.map +1 -0
  15. package/dist/app-bootstrap/init-orchestration.d.mts +1 -1
  16. package/dist/app-bootstrap/init-orchestration.d.mts.map +1 -1
  17. package/dist/app-bootstrap/init-orchestration.mjs +17 -3
  18. package/dist/app-bootstrap/init-orchestration.mjs.map +1 -1
  19. package/dist/assets/fullscreen-dialog.html +18 -0
  20. package/dist/assumptions.respec.mjs.map +1 -1
  21. package/dist/common/settings/settings-constants.d.mts.map +1 -1
  22. package/dist/helpers.d.mts.map +1 -1
  23. package/dist/helpers.mjs.map +1 -1
  24. package/dist/helpers.web.d.mts.map +1 -1
  25. package/dist/helpers.web.mjs.map +1 -1
  26. package/dist/helpers.web.respec.mjs.map +1 -1
  27. package/dist/identity/keystone-sync-service.d.mts +37 -0
  28. package/dist/identity/keystone-sync-service.d.mts.map +1 -0
  29. package/dist/identity/keystone-sync-service.mjs +211 -0
  30. package/dist/identity/keystone-sync-service.mjs.map +1 -0
  31. package/dist/identity/sso/sso-custodian-service.d.mts.map +1 -1
  32. package/dist/identity/sso/sso-custodian-service.mjs.map +1 -1
  33. package/dist/identity/sso/sso-custodian-service.respec.mjs.map +1 -1
  34. package/dist/index.d.mts +17 -1
  35. package/dist/index.d.mts.map +1 -1
  36. package/dist/index.mjs +21 -26
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/storage/storage-helpers.web.mjs.map +1 -1
  39. package/dist/ui/component/common-component-styles.css +270 -0
  40. package/dist/ui/component/ibgib-component-service.d.mts.map +1 -1
  41. package/dist/ui/component/ibgib-dynamic-component-bases.d.mts.map +1 -1
  42. package/dist/ui/component/ibgib-dynamic-component-bases.mjs.map +1 -1
  43. package/dist/ui/component/identity/add-device/add-device.css +133 -0
  44. package/dist/ui/component/identity/add-device/add-device.d.mts +49 -0
  45. package/dist/ui/component/identity/add-device/add-device.d.mts.map +1 -0
  46. package/dist/ui/component/identity/add-device/add-device.html +52 -0
  47. package/dist/ui/component/identity/add-device/add-device.mjs +321 -0
  48. package/dist/ui/component/identity/add-device/add-device.mjs.map +1 -0
  49. package/dist/ui/component/identity/identity-header/identity-header.css +317 -0
  50. package/dist/ui/component/identity/identity-header/identity-header.d.mts +85 -0
  51. package/dist/ui/component/identity/identity-header/identity-header.d.mts.map +1 -0
  52. package/dist/ui/component/identity/identity-header/identity-header.html +72 -0
  53. package/dist/ui/component/identity/identity-header/identity-header.mjs +546 -0
  54. package/dist/ui/component/identity/identity-header/identity-header.mjs.map +1 -0
  55. package/dist/ui/component/identity/identity-manager/identity-manager.css +178 -0
  56. package/dist/ui/component/identity/identity-manager/identity-manager.d.mts +76 -0
  57. package/dist/ui/component/identity/identity-manager/identity-manager.d.mts.map +1 -0
  58. package/dist/ui/component/identity/identity-manager/identity-manager.html +19 -0
  59. package/dist/ui/component/identity/identity-manager/identity-manager.mjs +591 -0
  60. package/dist/ui/component/identity/identity-manager/identity-manager.mjs.map +1 -0
  61. package/dist/ui/component/identity/index.d.mts +17 -0
  62. package/dist/ui/component/identity/index.d.mts.map +1 -0
  63. package/dist/ui/component/identity/index.mjs +34 -0
  64. package/dist/ui/component/identity/index.mjs.map +1 -0
  65. package/dist/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
  66. package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts +58 -0
  67. package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts.map +1 -0
  68. package/dist/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
  69. package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs +410 -0
  70. package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs.map +1 -0
  71. package/dist/ui/component/identity/keystone-details/keystone-details.css +621 -0
  72. package/dist/ui/component/identity/keystone-details/keystone-details.d.mts +98 -0
  73. package/dist/ui/component/identity/keystone-details/keystone-details.d.mts.map +1 -0
  74. package/dist/ui/component/identity/keystone-details/keystone-details.html +154 -0
  75. package/dist/ui/component/identity/keystone-details/keystone-details.mjs +1377 -0
  76. package/dist/ui/component/identity/keystone-details/keystone-details.mjs.map +1 -0
  77. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
  78. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts +64 -0
  79. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts.map +1 -0
  80. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
  81. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs +300 -0
  82. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs.map +1 -0
  83. package/dist/ui/component/identity/remove-device/remove-device.css +118 -0
  84. package/dist/ui/component/identity/remove-device/remove-device.d.mts +50 -0
  85. package/dist/ui/component/identity/remove-device/remove-device.d.mts.map +1 -0
  86. package/dist/ui/component/identity/remove-device/remove-device.html +31 -0
  87. package/dist/ui/component/identity/remove-device/remove-device.mjs +188 -0
  88. package/dist/ui/component/identity/remove-device/remove-device.mjs.map +1 -0
  89. package/dist/ui/ui-constants.d.mts +1 -0
  90. package/dist/ui/ui-constants.d.mts.map +1 -1
  91. package/dist/ui/ui-constants.mjs +1 -0
  92. package/dist/ui/ui-constants.mjs.map +1 -1
  93. package/dist/ui/ui-types.d.mts +7 -0
  94. package/dist/ui/ui-types.d.mts.map +1 -1
  95. package/dist/witness/agent/agent-constants.d.mts.map +1 -1
  96. package/dist/witness/agent/agent-helpers.mjs.map +1 -1
  97. package/dist/witness/agent/agent-one-file.d.mts.map +1 -1
  98. package/dist/witness/agent/agent-one-file.mjs.map +1 -1
  99. package/dist/witness/agent/agents-service-v1.d.mts.map +1 -1
  100. package/dist/witness/agent/agents-service-v1.mjs.map +1 -1
  101. package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts.map +1 -1
  102. package/dist/witness/agent/gemini/gemini-agent-factory.d.mts.map +1 -1
  103. package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.d.mts.map +1 -1
  104. package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.mjs.map +1 -1
  105. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace-helper.mjs.map +1 -1
  106. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts +4 -0
  107. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts.map +1 -1
  108. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs +40 -1
  109. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs.map +1 -1
  110. package/dist/witness/space/web-filesystem-space/web-filesystem-space-types.d.mts.map +1 -1
  111. package/dist/witness/space/web-filesystem-space/web-filesystem-space-v1.d.mts.map +1 -1
  112. package/package.json +2 -2
  113. package/src/AUTO-GENERATED-version.mts +1 -1
  114. package/src/api/ibgib-api-bridge.mts +292 -0
  115. package/src/app-bootstrap/init-orchestration.mts +17 -6
  116. package/src/custom.d.ts +11 -0
  117. package/src/identity/keystone-sync-service.mts +257 -0
  118. package/src/index.mts +24 -25
  119. package/src/ui/component/README.md +82 -5
  120. package/src/ui/component/common-component-styles.css +270 -0
  121. package/src/ui/component/identity/add-device/add-device.css +133 -0
  122. package/src/ui/component/identity/add-device/add-device.html +52 -0
  123. package/src/ui/component/identity/add-device/add-device.mts +397 -0
  124. package/src/ui/component/identity/identity-header/IMPLEMENTATION.md +45 -0
  125. package/src/ui/component/identity/identity-header/identity-header.css +317 -0
  126. package/src/ui/component/identity/identity-header/identity-header.html +72 -0
  127. package/src/ui/component/identity/identity-header/identity-header.mts +651 -0
  128. package/src/ui/component/identity/identity-manager/IMPLEMENTATION.md +100 -0
  129. package/src/ui/component/identity/identity-manager/identity-manager.css +178 -0
  130. package/src/ui/component/identity/identity-manager/identity-manager.html +19 -0
  131. package/src/ui/component/identity/identity-manager/identity-manager.mts +675 -0
  132. package/src/ui/component/identity/index.mts +36 -0
  133. package/src/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
  134. package/src/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
  135. package/src/ui/component/identity/keystone-creator/keystone-creator.mts +497 -0
  136. package/src/ui/component/identity/keystone-details/keystone-details.css +621 -0
  137. package/src/ui/component/identity/keystone-details/keystone-details.html +154 -0
  138. package/src/ui/component/identity/keystone-details/keystone-details.mts +1506 -0
  139. package/src/ui/component/identity/keystone-scrubber/SCRUBBER_IMPLEMENTATION.md +33 -0
  140. package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
  141. package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
  142. package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.mts +355 -0
  143. package/src/ui/component/identity/remove-device/remove-device.css +118 -0
  144. package/src/ui/component/identity/remove-device/remove-device.html +31 -0
  145. package/src/ui/component/identity/remove-device/remove-device.mts +247 -0
  146. package/src/ui/ui-constants.mts +1 -0
  147. package/src/ui/ui-types.mts +8 -0
  148. package/src/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mts +42 -1
  149. package/tools/auto-generated-agent-skills/skills/ibgib-dependency-graph/SKILL.md +209 -0
  150. package/tools/auto-generated-agent-skills/skills/ibgib-implementation-plan/SKILL.md +102 -0
@@ -0,0 +1,675 @@
1
+ import thisCss from "./identity-manager.css";
2
+ import thisHtml from "./identity-manager.html";
3
+ import commonComponentStylesCss from "../../common-component-styles.css";
4
+
5
+ import { delay, extractErrorMsg, pretty } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
6
+ import { IbGibAddr } from "@ibgib/ts-gib/dist/types.mjs";
7
+ import { IbGib_V1 } from "@ibgib/ts-gib/dist/V1/types.mjs";
8
+ import { getIbAndGib, getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
9
+ import { ROOT_ADDR } from "@ibgib/ts-gib/dist/V1/constants.mjs";
10
+ import { getGibInfo } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
11
+ import { KeystoneService_V1 } from "@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs";
12
+ import { getTjpAddr } from "@ibgib/core-gib/dist/common/other/ibgib-helper.mjs";
13
+ import { mut8Timeline } from "@ibgib/core-gib/dist/timeline/timeline-api.mjs";
14
+ import { MetaspaceService } from "@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs";
15
+ import {
16
+ IbGibDynamicComponentMetaBase,
17
+ IbGibDynamicComponentInstanceBase_ParentOfTabs,
18
+ } from "../../ibgib-dynamic-component-bases.mjs";
19
+ import {
20
+ ElementsBase, ChildInfoBase, IbGibDynamicComponentInstance,
21
+ IbGibDynamicComponentInstanceInitOpts,
22
+ } from "../../component-types.mjs";
23
+ import { getDeterministicColorInfo, getGlobalMetaspace_waitIfNeeded } from "../../../../helpers.mjs";
24
+ import { SettingsType } from "../../../../common/settings/settings-constants.mjs";
25
+ import { Settings_General, Settings_IdentityManager } from "../../../../common/settings/settings-types.mjs";
26
+ import { getSectionName } from "../../../../common/settings/settings-helpers.mjs";
27
+ import { getComponentSvc } from "../../ibgib-component-service.mjs";
28
+ import { EVENT_IBGIB_IDENTITY_REQUEST_CHANGE, EVENT_IBGIB_IDENTITY_CHANGED, EVENT_IBGIB_UI_MESSAGE } from "../../../ui-constants.mjs";
29
+ import { getComponentCtorArg } from "../../../../app-bootstrap/init-orchestration.mjs";
30
+ import { KEYSTONE_ATOM } from "@ibgib/core-gib/dist/keystone/keystone-constants.mjs";
31
+
32
+ export const IDENTITY_MANAGER_COMPONENT_NAME = 'ibgib-identity-manager';
33
+
34
+ /**
35
+ * Metadata for the Identity Manager component.
36
+ */
37
+ export class IdentityManagerComponentMeta extends IbGibDynamicComponentMetaBase {
38
+ protected lc: string = `[IdentityManagerComponentMeta]`;
39
+
40
+ routeRegExp?: RegExp = new RegExp(`^${IDENTITY_MANAGER_COMPONENT_NAME}$`);
41
+ componentName = IDENTITY_MANAGER_COMPONENT_NAME;
42
+
43
+ constructor() {
44
+ super(getComponentCtorArg());
45
+ if (!customElements.get(this.componentName)) {
46
+ customElements.define(this.componentName, IdentityManagerComponentInstance);
47
+ }
48
+ }
49
+
50
+ async createInstance({
51
+ path,
52
+ ibGibAddr
53
+ }: {
54
+ path: string;
55
+ ibGibAddr: IbGibAddr;
56
+ }): Promise<IbGibDynamicComponentInstance> {
57
+ const lc = `${this.lc}[${this.createInstance.name}]`;
58
+ const component = document.createElement(this.componentName) as IdentityManagerComponentInstance;
59
+ await component.initialize({
60
+ ibGibAddr,
61
+ meta: this,
62
+ html: thisHtml,
63
+ css: [commonComponentStylesCss, thisCss],
64
+ });
65
+ return component;
66
+ }
67
+ }
68
+
69
+ interface IdentityTabInfo extends ChildInfoBase<IbGibDynamicComponentInstance<any, any>> {
70
+ }
71
+
72
+ /**
73
+ * References to DOM elements within the component's shadow root.
74
+ */
75
+ interface IdentityManagerElements extends ElementsBase {
76
+ containerEl: HTMLDivElement;
77
+ titleEl: HTMLHeadingElement;
78
+ tabsListEl: HTMLDivElement;
79
+ btnAddIdentityEl: HTMLButtonElement;
80
+ noIdentityPlaceholderEl: HTMLDivElement;
81
+ btnCreatePlaceholderEl: HTMLButtonElement;
82
+ }
83
+
84
+ /**
85
+ * Concrete implementation of the Identity Manager component.
86
+ */
87
+ export class IdentityManagerComponentInstance
88
+ extends IbGibDynamicComponentInstanceBase_ParentOfTabs<Settings_IdentityManager, IbGib_V1, IdentityManagerElements, IdentityTabInfo>
89
+ implements IbGibDynamicComponentInstance<IbGib_V1, IdentityManagerElements> {
90
+
91
+ protected override lc: string = `[IdentityManagerComponentInstance]`;
92
+
93
+ private globalActiveAddr: string | null = null;
94
+ private _onIdentityChanged: ((e: any) => void) | null = null;
95
+ private _onUiMessage: ((e: any) => void) | null = null;
96
+ private keystoneCache: Map<string, { username: string, description: string, isPrimary: boolean, n: number }> = new Map();
97
+ metaspace: MetaspaceService | undefined;
98
+
99
+ protected get settingsType(): SettingsType {
100
+ return SettingsType.identityManager;
101
+ }
102
+
103
+ constructor() {
104
+ super();
105
+ }
106
+
107
+ private async getKeystoneDetails(addr: string): Promise<{ username: string, description: string, isPrimary: boolean, n: number }> {
108
+ const cached = this.keystoneCache.get(addr);
109
+ if (cached) return cached;
110
+
111
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
112
+ if (!metaspace) return { username: '', description: '', isPrimary: false, n: 0 };
113
+ const space = await metaspace.getLocalUserSpace({ lock: false });
114
+ if (!space) return { username: '', description: '', isPrimary: false, n: 0 };
115
+
116
+ try {
117
+ const keystoneSvc = new KeystoneService_V1();
118
+ const info = await keystoneSvc.getKeystoneCommonInfo({
119
+ addr,
120
+ metaspace,
121
+ space
122
+ });
123
+ if (info) {
124
+ const details = {
125
+ username: info.name,
126
+ description: info.description,
127
+ isPrimary: info.isPrimary,
128
+ n: info.n
129
+ };
130
+ this.keystoneCache.set(addr, details);
131
+ return details;
132
+ }
133
+ } catch (err) {
134
+ console.warn(`Error getting details for keystone ${addr}: ${extractErrorMsg(err)}`);
135
+ }
136
+
137
+ return { username: '', description: '', isPrimary: false, n: 0 };
138
+ }
139
+
140
+ override async initialize(opts: IbGibDynamicComponentInstanceInitOpts): Promise<void> {
141
+ if (!this.metaspace) {
142
+ this.metaspace = await getGlobalMetaspace_waitIfNeeded({ delayIntervalMs: 50 });
143
+ }
144
+ opts.ibGibAddr = await this.metaspace.getLatestAddr({ addr: opts.ibGibAddr }) ?? opts.ibGibAddr;
145
+ await super.initialize(opts);
146
+ }
147
+
148
+ override async created(): Promise<void> {
149
+ this.elements = {} as IdentityManagerElements;
150
+
151
+ const shadow = this.shadowRoot!;
152
+ this.elements.containerEl = shadow.getElementById('container') as HTMLDivElement;
153
+ this.elements.titleEl = shadow.getElementById('title') as HTMLHeadingElement;
154
+ this.elements.tabsListEl = shadow.getElementById('identity-tabs') as HTMLDivElement;
155
+ this.elements.btnAddIdentityEl = shadow.getElementById('btn-add-identity') as HTMLButtonElement;
156
+ this.elements.noIdentityPlaceholderEl = shadow.getElementById('no-identity-placeholder') as HTMLDivElement;
157
+ this.elements.btnCreatePlaceholderEl = shadow.getElementById('btn-create-placeholder') as HTMLButtonElement;
158
+
159
+ // ElementBase requires contentEl
160
+ this.elements.contentEl = shadow.getElementById('identity-manager-content') as HTMLDivElement;
161
+
162
+ this.initHandlers();
163
+
164
+ // Subscribe to global active identity changes
165
+ this._onIdentityChanged = async (e: any) => {
166
+ this.globalActiveAddr = e.detail?.activeIdentityAddr || null;
167
+ this.keystoneCache.clear();
168
+ await this.loadKeystonesIndex();
169
+ if (this.childInfos) {
170
+ for (const childInfo of this.childInfos) {
171
+ if (childInfo.component) {
172
+ try {
173
+ const comp = childInfo.component as any;
174
+ if (typeof comp.loadIbGib === 'function') {
175
+ await comp.loadIbGib({ getLatest: true });
176
+ }
177
+ } catch (err) {
178
+ console.warn(`[IdentityManager] Error reloading child component: ${extractErrorMsg(err)}`);
179
+ }
180
+ }
181
+ }
182
+ }
183
+ await this.renderUI();
184
+ };
185
+ window.addEventListener(EVENT_IBGIB_IDENTITY_CHANGED, this._onIdentityChanged);
186
+
187
+ // Listen for requests to view details of a delegate (from child details component)
188
+ this.addEventListener('ibgib-view-keystone-details', async (e: any) => {
189
+ const addr = e.detail?.addr;
190
+ if (addr) {
191
+ await this.activateIbGib({ addr });
192
+ }
193
+ });
194
+
195
+ // Listen for requests to switch to keystone-creator or add-device
196
+ if (this._onUiMessage) {
197
+ window.removeEventListener(EVENT_IBGIB_UI_MESSAGE, this._onUiMessage);
198
+ }
199
+ this._onUiMessage = (e: any) => {
200
+ const action = e.detail?.action;
201
+ const subAction = e.detail?.subAction;
202
+ if (action === 'show-keystone-creator' || subAction === 'show-keystone-creator') {
203
+ this.handleAddNewIdentityFlow('ibgib-keystone-creator');
204
+ } else if (action === 'show-add-device' || subAction === 'show-add-device') {
205
+ this.handleAddNewIdentityFlow('ibgib-add-device');
206
+ }
207
+ };
208
+ window.addEventListener(EVENT_IBGIB_UI_MESSAGE, this._onUiMessage);
209
+
210
+ if (this.ibGibAddr === ROOT_ADDR || !this.ibGib) {
211
+ await this.loadKeystonesIndex();
212
+ } else {
213
+ await this.initSettings();
214
+ }
215
+
216
+ await this.renderUI();
217
+
218
+ // Spin off tab restore or defaults to allow createdPromise to resolve first
219
+ this.restoreOrInitTabs();
220
+ }
221
+
222
+ private async restoreOrInitTabs(): Promise<void> {
223
+ const settings = await this.getSettings<Settings_IdentityManager>({
224
+ settingsType: this.settingsType,
225
+ useCase: 'current',
226
+ });
227
+ if (settings) {
228
+ const validAddrs = (settings.openChildTjpAddrs ?? []).filter(addr => {
229
+ if (!addr || addr === '^' || addr === 'gib') return false;
230
+ const { gib } = getIbAndGib({ ibGibAddr: addr });
231
+ return !!gib && gib !== 'gib' && gib !== '^';
232
+ });
233
+ if (validAddrs.length !== (settings.openChildTjpAddrs ?? []).length) {
234
+ settings.openChildTjpAddrs = validAddrs;
235
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
236
+ if (metaspace) {
237
+ const sectionName_current = await getSectionName({
238
+ settingsType: this.settingsType,
239
+ useCase: 'current',
240
+ });
241
+ await mut8Timeline({
242
+ timeline: this.settings!.ibGib!,
243
+ metaspace,
244
+ mut8Opts: {
245
+ dataToAddOrPatch: {
246
+ sections: {
247
+ [sectionName_current]: settings,
248
+ }
249
+ },
250
+ },
251
+ });
252
+ }
253
+ }
254
+ }
255
+
256
+ if (!settings || (settings.openChildTjpAddrs ?? []).length === 0) {
257
+ await this.loadDefaultPrimaryIdentityTabs();
258
+ } else {
259
+ await this.reopenOldTabs();
260
+ }
261
+ }
262
+
263
+ override async disconnected(): Promise<void> {
264
+ if (this._onIdentityChanged) {
265
+ window.removeEventListener(EVENT_IBGIB_IDENTITY_CHANGED, this._onIdentityChanged);
266
+ this._onIdentityChanged = null;
267
+ }
268
+ if (this._onUiMessage) {
269
+ window.removeEventListener(EVENT_IBGIB_UI_MESSAGE, this._onUiMessage);
270
+ this._onUiMessage = null;
271
+ }
272
+ }
273
+
274
+ private async loadKeystonesIndex(): Promise<void> {
275
+ const lc = `${this.lc}[loadKeystonesIndex]`;
276
+ try {
277
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
278
+ if (!metaspace) { return; }
279
+ const space = await metaspace.getLocalUserSpace({ lock: false });
280
+ if (!space) { return; }
281
+ const keystonesIndex = await metaspace.getSpecialIbGib({
282
+ type: "keystones",
283
+ space,
284
+ initialize: true,
285
+ });
286
+ if (keystonesIndex) {
287
+ this.ibGibAddr = getIbGibAddr({ ibGib: keystonesIndex });
288
+ await this.loadIbGib({ getLatest: true });
289
+ await this.initSettings();
290
+ }
291
+ } catch (error) {
292
+ console.error(`${lc} ${extractErrorMsg(error)}`);
293
+ }
294
+ }
295
+
296
+ private initHandlers() {
297
+ // Buttons
298
+ this.elements!.btnAddIdentityEl.addEventListener('click', () => this.handleAddNewIdentityFlow('ibgib-keystone-creator'));
299
+ this.elements!.btnCreatePlaceholderEl.addEventListener('click', () => this.handleAddNewIdentityFlow('ibgib-keystone-creator'));
300
+
301
+ // Convert vertical mouse wheel scrolling into horizontal scroll for tabs
302
+ this.elements!.tabsListEl.addEventListener('wheel', (e: WheelEvent) => {
303
+ if (e.deltaY !== 0) {
304
+ e.preventDefault();
305
+ this.elements!.tabsListEl.scrollBy({ left: e.deltaY, behavior: 'smooth' });
306
+ }
307
+ }, { passive: false });
308
+ }
309
+
310
+ protected async handleAddNewIdentityFlow(componentPath: 'ibgib-keystone-creator' | 'ibgib-add-device' = 'ibgib-keystone-creator') {
311
+ const lc = `${this.lc}[${this.handleAddNewIdentityFlow.name}]`;
312
+ console.log(`${lc} Triggering identity creation/import flow (${componentPath})...`);
313
+ try {
314
+ const componentSvc = await getComponentSvc();
315
+ const childComp = await componentSvc.getComponentInstance({
316
+ path: componentPath,
317
+ ibGibAddr: ROOT_ADDR,
318
+ useRegExpPrefilter: true,
319
+ });
320
+ if (childComp) {
321
+ // Hide placeholder
322
+ this.elements!.noIdentityPlaceholderEl.classList.add('hidden');
323
+
324
+ // Clear any previous creator/details/add-device
325
+ const existingCreator = this.elements!.contentEl.querySelector('ibgib-keystone-creator');
326
+ if (existingCreator) { existingCreator.remove(); }
327
+ const existingAddDevice = this.elements!.contentEl.querySelector('ibgib-add-device');
328
+ if (existingAddDevice) { existingAddDevice.remove(); }
329
+
330
+ // Clear active child component inside ParentOfTabs to prevent conflict
331
+ const active = this.activeChildInfo;
332
+ if (active) {
333
+ active.childBtnEl.classList.remove('active');
334
+ active.active = false;
335
+ }
336
+
337
+ this.elements!.contentEl.innerHTML = '';
338
+ this.elements!.contentEl.appendChild(childComp as any);
339
+ console.log(`${lc} Mounted ${componentPath} successfully.`);
340
+ } else {
341
+ throw new Error(`Could not find meta for ${componentPath}`);
342
+ }
343
+ } catch (error) {
344
+ console.error(`${lc} ${extractErrorMsg(error)}`);
345
+ }
346
+ }
347
+
348
+ private async resolveActiveIdentity() {
349
+ const lc = `${this.lc}[resolveActiveIdentity]`;
350
+ try {
351
+ if (!this.settings) {
352
+ this.globalActiveAddr = null;
353
+ return;
354
+ }
355
+ const generalSettings = await this.getSettings<Settings_General>({
356
+ settingsType: SettingsType.general,
357
+ useCase: 'current',
358
+ });
359
+ const activeAddrInSettings = (generalSettings as any)?.activeIdentityAddr;
360
+
361
+ const registeredKeystones = this.ibGib?.rel8ns?.keystone ?? [];
362
+ const detailsPromises = registeredKeystones.map(async addr => {
363
+ const details = await this.getKeystoneDetails(addr);
364
+ return { addr, isPrimary: details?.isPrimary ?? false };
365
+ });
366
+ const resolvedDetails = await Promise.all(detailsPromises);
367
+ const primaryKeystones = resolvedDetails
368
+ .filter(item => item.isPrimary)
369
+ .map(item => item.addr);
370
+
371
+ if (activeAddrInSettings && primaryKeystones.includes(activeAddrInSettings)) {
372
+ this.globalActiveAddr = activeAddrInSettings;
373
+ } else if (primaryKeystones.length > 0) {
374
+ this.globalActiveAddr = primaryKeystones[0];
375
+ } else {
376
+ this.globalActiveAddr = null;
377
+ }
378
+ } catch (error) {
379
+ console.error(`${lc} ${extractErrorMsg(error)}`);
380
+ this.globalActiveAddr = null;
381
+ }
382
+ }
383
+
384
+ protected override async renderUI(): Promise<void> {
385
+ const lc = `${this.lc}[${this.renderUI.name}]`;
386
+ if (!this.elements) { return; }
387
+
388
+ await this.resolveActiveIdentity();
389
+
390
+ const keystones = this.ibGib?.rel8ns?.keystone ?? [];
391
+ if (keystones.length === 0 && this.childInfos.length === 0) {
392
+ this.elements.noIdentityPlaceholderEl.classList.remove('hidden');
393
+ this.elements.contentEl.innerHTML = '';
394
+ return;
395
+ }
396
+
397
+ this.elements.noIdentityPlaceholderEl.classList.add('hidden');
398
+
399
+ // Render tab highlights
400
+ for (const info of this.childInfos) {
401
+ const btn = info.childBtnEl;
402
+ btn.className = `tab-btn ${info.active ? 'active' : ''} ${info.addr === this.globalActiveAddr ? 'global-active' : ''}`;
403
+ }
404
+ }
405
+
406
+ private async loadDefaultPrimaryIdentityTabs() {
407
+ const keystones = (this.ibGib?.rel8ns?.keystone ?? []).filter(addr => {
408
+ if (!addr || addr === '^' || addr === 'gib') return false;
409
+ const { gib } = getIbAndGib({ ibGibAddr: addr });
410
+ return !!gib && gib !== 'gib' && gib !== '^';
411
+ });
412
+ const detailsPromises = keystones.map(async addr => {
413
+ const details = await this.getKeystoneDetails(addr);
414
+ return { addr, isPrimary: details?.isPrimary ?? false };
415
+ });
416
+ const resolvedDetails = await Promise.all(detailsPromises);
417
+ const primaryKeystones = resolvedDetails
418
+ .filter(item => item.isPrimary)
419
+ .map(item => item.addr);
420
+
421
+ if (primaryKeystones.length === 0) {
422
+ this.elements!.noIdentityPlaceholderEl.classList.remove('hidden');
423
+ return;
424
+ }
425
+
426
+ this.elements!.noIdentityPlaceholderEl.classList.add('hidden');
427
+
428
+ this.reloadingTabs = true;
429
+ try {
430
+ for (const addr of primaryKeystones) {
431
+ await this.activateIbGib({ addr });
432
+ }
433
+ } finally {
434
+ this.reloadingTabs = false;
435
+ }
436
+
437
+ // Activate the global active identity (if open), or the first primary one
438
+ const activeToOpen = primaryKeystones.includes(this.globalActiveAddr || '')
439
+ ? this.globalActiveAddr!
440
+ : primaryKeystones[0];
441
+ await this.activateIbGib({ addr: activeToOpen });
442
+ }
443
+
444
+ public override async activateIbGib({ addr, ibGib }: { addr?: IbGibAddr; ibGib?: IbGib_V1; }): Promise<void> {
445
+ const lc = `${this.lc}[activateIbGib]`;
446
+ try {
447
+ if (!this.metaspace) { throw new Error(`(UNEXPECTED) this.metaspace falsy? (E: f9e0e9a1427899eba8e469c18d7ae826)`); }
448
+
449
+ await super.activateIbGib({ addr, ibGib });
450
+
451
+
452
+ if (!this.activeChildInfo) { throw new Error(`(UNEXPECTED) activeChildInfo falsy after activateIbGib? (E: d76bd8bc300f3fdc486d50c8b2644826)`); }
453
+
454
+ ibGib ??= this.activeChildInfo.component?.ibGib;
455
+
456
+ if (!ibGib) { throw new Error(`(UNEXPECTED) ibGib falsy? (E: 5b6ec745dd32fd2128635728e3f35e26)`); }
457
+
458
+ if (!ibGib.ib.startsWith(KEYSTONE_ATOM)) {
459
+ throw new Error(`ibGib.ib (${ibGib.ib}) does not start with keystone atom (${KEYSTONE_ATOM}) (E: e0df410381c8e569eb6da996e79b6826)`);
460
+ }
461
+
462
+ this.elements!.noIdentityPlaceholderEl.classList.add('hidden');
463
+
464
+ if (!this.reloadingTabs) {
465
+ const settings_current = await this.getSettings<Settings_IdentityManager>({
466
+ settingsType: this.settingsType,
467
+ useCase: 'current',
468
+ });
469
+ if (settings_current) {
470
+ let modified = false;
471
+ const tjpAddr = getTjpAddr({ ibGib: this.activeChildInfo.component?.ibGib || ibGib!, defaultIfNone: 'incomingAddr' });
472
+ if (tjpAddr) {
473
+ if (!settings_current.openChildTjpAddrs.includes(tjpAddr)) {
474
+ settings_current.openChildTjpAddrs.push(tjpAddr);
475
+ modified = true;
476
+ }
477
+ if (settings_current.activeChildTjpAddr !== tjpAddr) {
478
+ settings_current.activeChildTjpAddr = tjpAddr;
479
+ modified = true;
480
+ }
481
+ }
482
+ if (modified) {
483
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
484
+ if (metaspace) {
485
+ const sectionName_current = await getSectionName({
486
+ settingsType: this.settingsType,
487
+ useCase: 'current',
488
+ });
489
+ await mut8Timeline({
490
+ timeline: this.settings!.ibGib!,
491
+ metaspace,
492
+ mut8Opts: {
493
+ dataToAddOrPatch: {
494
+ sections: {
495
+ [sectionName_current]: settings_current,
496
+ }
497
+ },
498
+ },
499
+ });
500
+ }
501
+ }
502
+ }
503
+ }
504
+
505
+ await this.renderUI();
506
+ } catch (error) {
507
+ console.error(`${lc} ${extractErrorMsg(error)}`);
508
+ }
509
+ }
510
+
511
+ protected async getLoadedChildInfo({
512
+ addr,
513
+ ibGib,
514
+ }: {
515
+ addr: IbGibAddr,
516
+ ibGib?: IbGib_V1,
517
+ }): Promise<IdentityTabInfo> {
518
+ const lc = `${this.lc}[getLoadedChildInfo]`;
519
+ try {
520
+ if (!addr) { throw new Error(`(UNEXPECTED) addr falsy?`); }
521
+ if (addr === '^' || addr === 'gib' || getIbAndGib({ ibGibAddr: addr }).gib === '^') {
522
+ throw new Error(`Cannot load child info for primitive address ${addr}`);
523
+ }
524
+ const tjpGib = getGibInfo({ ibGibAddr: addr }).tjpGib ?? getIbAndGib({ ibGibAddr: addr }).gib;
525
+
526
+ const fnCreateAndLoadChildComponent = async () => {
527
+ const componentSvc = await getComponentSvc();
528
+ const detailsComponent = await componentSvc.getComponentInstance({
529
+ path: 'ibgib-keystone-scrubber',
530
+ ibGibAddr: addr,
531
+ useRegExpPrefilter: true,
532
+ });
533
+ if (!detailsComponent) {
534
+ throw new Error(`(UNEXPECTED) detailsComponent falsy?`);
535
+ }
536
+ return detailsComponent;
537
+ }
538
+
539
+ let tabInfo: IdentityTabInfo;
540
+
541
+ const filtered = this.childInfos.filter(x => {
542
+ const tabGibInfo = getGibInfo({ ibGibAddr: x.addr });
543
+ const tabTjpGib = tabGibInfo.tjpGib ?? getIbAndGib({ ibGibAddr: x.addr }).gib;
544
+ return tabTjpGib === tjpGib;
545
+ });
546
+
547
+ if (filtered.length > 0) {
548
+ if (filtered.length !== 1) { throw new Error(`(UNEXPECTED) filtered.length !== 1?`); }
549
+ tabInfo = filtered[0];
550
+ if (!tabInfo.component) {
551
+ tabInfo.component = await fnCreateAndLoadChildComponent();
552
+ }
553
+ } else {
554
+ const detailsComponent = await fnCreateAndLoadChildComponent();
555
+ let i = 0;
556
+ while (!detailsComponent.ibGib!) {
557
+ await delay(100);
558
+ i++;
559
+ if (i > 50) { // 5 seconds
560
+ debugger; // error loading details component ibgib
561
+ throw new Error(`(UNEXPECTED) detailsComponent.ibGib falsy? didn't load? (E: de50689834124914f770520f1eccb826)`);
562
+ }
563
+ }
564
+ ibGib = detailsComponent.ibGib!;
565
+ addr = getIbGibAddr({ ibGib });
566
+ const tabBtnEl = await this.addChild({ addr, ibGib: ibGib! });
567
+ tabInfo = {
568
+ addr,
569
+ childBtnEl: tabBtnEl,
570
+ component: detailsComponent,
571
+ active: false,
572
+ };
573
+ this.childInfos.push(tabInfo);
574
+ }
575
+
576
+ return tabInfo;
577
+ } catch (error) {
578
+ console.error(`${lc} ${extractErrorMsg(error)}`);
579
+ throw error;
580
+ }
581
+ }
582
+
583
+ protected override async addChild({
584
+ addr,
585
+ ibGib,
586
+ }: {
587
+ ibGib: IbGib_V1,
588
+ addr?: IbGibAddr,
589
+ }): Promise<HTMLElement> {
590
+ const lc = `${this.lc}[addChild]`;
591
+ try {
592
+ addr ??= getIbGibAddr({ ibGib });
593
+ if (addr === '^' || addr === 'gib' || getIbAndGib({ ibGibAddr: addr }).gib === '^') {
594
+ throw new Error(`Cannot add child tab for primitive address ${addr}`);
595
+ }
596
+ if (!this.elements) { throw new Error(`(UNEXPECTED) this.elements falsy?`); }
597
+ const { tabsListEl } = this.elements;
598
+
599
+ addr ??= getIbGibAddr({ ibGib });
600
+
601
+ const childBtnEl = document.createElement('button');
602
+ childBtnEl.className = 'tab-btn';
603
+ childBtnEl.id = `identity-tab-button-${addr}`;
604
+
605
+ await this.updateTabTitleAndText({ span: childBtnEl, ibGib, addr });
606
+
607
+ const details = await this.getKeystoneDetails(addr);
608
+ if (!details.isPrimary) {
609
+ const closeBtnEl = document.createElement('span');
610
+ closeBtnEl.className = 'close-tab-button';
611
+ closeBtnEl.textContent = ' ×';
612
+ closeBtnEl.style.marginLeft = '0.5rem';
613
+ closeBtnEl.style.cursor = 'pointer';
614
+ childBtnEl.appendChild(closeBtnEl);
615
+ closeBtnEl.addEventListener('click', async (event) => {
616
+ event.stopPropagation(); // Prevent activating the tab
617
+ await this.closeTab({ ibGib });
618
+ });
619
+ }
620
+
621
+ tabsListEl.appendChild(childBtnEl);
622
+ childBtnEl.addEventListener('click', async (event) => {
623
+ await this.activateIbGib({ addr });
624
+ });
625
+
626
+ return childBtnEl;
627
+ } catch (error) {
628
+ console.error(`${lc} ${extractErrorMsg(error)}`);
629
+ throw error;
630
+ }
631
+ }
632
+
633
+ private async updateTabTitleAndText({
634
+ span,
635
+ ibGib,
636
+ addr,
637
+ }: {
638
+ span: HTMLElement,
639
+ ibGib: IbGib_V1,
640
+ addr: string,
641
+ }): Promise<void> {
642
+ const details = await this.getKeystoneDetails(addr);
643
+ let name = details.username;
644
+ const maxTabLen = 16;
645
+ if (name) {
646
+ if (name.length > maxTabLen) {
647
+ name = name.substring(0, maxTabLen - 3) + '...';
648
+ }
649
+ span.textContent = name;
650
+ } else {
651
+ let displayTab = addr;
652
+ if (displayTab.length > 12) {
653
+ displayTab = displayTab.substring(0, 5) + '...' + displayTab.substring(displayTab.length - 4);
654
+ }
655
+ span.textContent = displayTab;
656
+ }
657
+
658
+ const tooltipParts: string[] = [];
659
+ if (details.username) {
660
+ tooltipParts.push(`User: ${details.username}`);
661
+ }
662
+ if (details.description) {
663
+ const desc = details.description.length > 100
664
+ ? details.description.substring(0, 97) + '...'
665
+ : details.description;
666
+ tooltipParts.push(`Desc: ${desc}`);
667
+ }
668
+ tooltipParts.push(`Addr: ${addr}`);
669
+ span.title = tooltipParts.join('\n');
670
+ }
671
+
672
+ protected async removeTabBtn({ tabInfo }: { tabInfo: IdentityTabInfo }): Promise<void> {
673
+ this.elements!.tabsListEl.removeChild(tabInfo.childBtnEl);
674
+ }
675
+ }