@ibgib/web-gib 0.0.52 → 0.0.56
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/CHANGELOG.md +7 -0
- package/dist/AUTO-GENERATED-version.d.mts +1 -1
- package/dist/AUTO-GENERATED-version.mjs +1 -1
- package/dist/api/commands/chat/hello-world.mjs.map +1 -1
- package/dist/api/commands/command-constants.d.mts +4 -4
- package/dist/api/commands/command-constants.d.mts.map +1 -1
- package/dist/api/commands/command-service-v1.d.mts.map +1 -1
- package/dist/api/commands/command-service-v1.mjs.map +1 -1
- package/dist/api/commands/ibgib/get-ibgibs.d.mts.map +1 -1
- package/dist/api/commands/ibgib/get-ibgibs.mjs.map +1 -1
- package/dist/api/ibgib-api-bridge.d.mts +81 -0
- package/dist/api/ibgib-api-bridge.d.mts.map +1 -0
- package/dist/api/ibgib-api-bridge.mjs +259 -0
- package/dist/api/ibgib-api-bridge.mjs.map +1 -0
- package/dist/app-bootstrap/init-orchestration.d.mts +1 -1
- package/dist/app-bootstrap/init-orchestration.d.mts.map +1 -1
- package/dist/app-bootstrap/init-orchestration.mjs +17 -3
- package/dist/app-bootstrap/init-orchestration.mjs.map +1 -1
- package/dist/assets/fullscreen-dialog.html +18 -0
- package/dist/assumptions.respec.mjs.map +1 -1
- package/dist/common/settings/settings-constants.d.mts.map +1 -1
- package/dist/helpers.d.mts.map +1 -1
- package/dist/helpers.mjs.map +1 -1
- package/dist/helpers.web.d.mts.map +1 -1
- package/dist/helpers.web.mjs.map +1 -1
- package/dist/helpers.web.respec.mjs.map +1 -1
- package/dist/identity/keystone-sync-service.d.mts +37 -0
- package/dist/identity/keystone-sync-service.d.mts.map +1 -0
- package/dist/identity/keystone-sync-service.mjs +211 -0
- package/dist/identity/keystone-sync-service.mjs.map +1 -0
- package/dist/identity/sso/sso-custodian-service.d.mts.map +1 -1
- package/dist/identity/sso/sso-custodian-service.mjs.map +1 -1
- package/dist/identity/sso/sso-custodian-service.respec.mjs.map +1 -1
- package/dist/index.d.mts +17 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +21 -26
- package/dist/index.mjs.map +1 -1
- package/dist/storage/storage-helpers.web.mjs.map +1 -1
- package/dist/ui/component/common-component-styles.css +270 -0
- package/dist/ui/component/ibgib-component-service.d.mts.map +1 -1
- package/dist/ui/component/ibgib-dynamic-component-bases.d.mts.map +1 -1
- package/dist/ui/component/ibgib-dynamic-component-bases.mjs.map +1 -1
- package/dist/ui/component/identity/add-device/add-device.css +133 -0
- package/dist/ui/component/identity/add-device/add-device.d.mts +49 -0
- package/dist/ui/component/identity/add-device/add-device.d.mts.map +1 -0
- package/dist/ui/component/identity/add-device/add-device.html +52 -0
- package/dist/ui/component/identity/add-device/add-device.mjs +321 -0
- package/dist/ui/component/identity/add-device/add-device.mjs.map +1 -0
- package/dist/ui/component/identity/identity-header/identity-header.css +317 -0
- package/dist/ui/component/identity/identity-header/identity-header.d.mts +85 -0
- package/dist/ui/component/identity/identity-header/identity-header.d.mts.map +1 -0
- package/dist/ui/component/identity/identity-header/identity-header.html +72 -0
- package/dist/ui/component/identity/identity-header/identity-header.mjs +546 -0
- package/dist/ui/component/identity/identity-header/identity-header.mjs.map +1 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.css +178 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.d.mts +76 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.d.mts.map +1 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.html +19 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.mjs +591 -0
- package/dist/ui/component/identity/identity-manager/identity-manager.mjs.map +1 -0
- package/dist/ui/component/identity/index.d.mts +17 -0
- package/dist/ui/component/identity/index.d.mts.map +1 -0
- package/dist/ui/component/identity/index.mjs +34 -0
- package/dist/ui/component/identity/index.mjs.map +1 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts +58 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts.map +1 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs +410 -0
- package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs.map +1 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.css +621 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.d.mts +98 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.d.mts.map +1 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.html +154 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.mjs +1377 -0
- package/dist/ui/component/identity/keystone-details/keystone-details.mjs.map +1 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts +64 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts.map +1 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs +300 -0
- package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs.map +1 -0
- package/dist/ui/component/identity/remove-device/remove-device.css +118 -0
- package/dist/ui/component/identity/remove-device/remove-device.d.mts +50 -0
- package/dist/ui/component/identity/remove-device/remove-device.d.mts.map +1 -0
- package/dist/ui/component/identity/remove-device/remove-device.html +31 -0
- package/dist/ui/component/identity/remove-device/remove-device.mjs +188 -0
- package/dist/ui/component/identity/remove-device/remove-device.mjs.map +1 -0
- package/dist/ui/ui-constants.d.mts +1 -0
- package/dist/ui/ui-constants.d.mts.map +1 -1
- package/dist/ui/ui-constants.mjs +1 -0
- package/dist/ui/ui-constants.mjs.map +1 -1
- package/dist/ui/ui-types.d.mts +7 -0
- package/dist/ui/ui-types.d.mts.map +1 -1
- package/dist/witness/agent/agent-constants.d.mts.map +1 -1
- package/dist/witness/agent/agent-helpers.mjs.map +1 -1
- package/dist/witness/agent/agent-one-file.d.mts.map +1 -1
- package/dist/witness/agent/agent-one-file.mjs.map +1 -1
- package/dist/witness/agent/agents-service-v1.d.mts.map +1 -1
- package/dist/witness/agent/agents-service-v1.mjs.map +1 -1
- package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts.map +1 -1
- package/dist/witness/agent/gemini/gemini-agent-factory.d.mts.map +1 -1
- package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.d.mts.map +1 -1
- package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.mjs.map +1 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace-helper.mjs.map +1 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts +4 -0
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts.map +1 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs +40 -1
- package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs.map +1 -1
- package/dist/witness/space/web-filesystem-space/web-filesystem-space-types.d.mts.map +1 -1
- package/dist/witness/space/web-filesystem-space/web-filesystem-space-v1.d.mts.map +1 -1
- package/package.json +2 -2
- package/src/AUTO-GENERATED-version.mts +1 -1
- package/src/api/ibgib-api-bridge.mts +292 -0
- package/src/app-bootstrap/init-orchestration.mts +17 -6
- package/src/custom.d.ts +11 -0
- package/src/identity/keystone-sync-service.mts +257 -0
- package/src/index.mts +24 -25
- package/src/ui/component/README.md +82 -5
- package/src/ui/component/common-component-styles.css +270 -0
- package/src/ui/component/identity/add-device/add-device.css +133 -0
- package/src/ui/component/identity/add-device/add-device.html +52 -0
- package/src/ui/component/identity/add-device/add-device.mts +397 -0
- package/src/ui/component/identity/identity-header/IMPLEMENTATION.md +45 -0
- package/src/ui/component/identity/identity-header/identity-header.css +317 -0
- package/src/ui/component/identity/identity-header/identity-header.html +72 -0
- package/src/ui/component/identity/identity-header/identity-header.mts +651 -0
- package/src/ui/component/identity/identity-manager/IMPLEMENTATION.md +100 -0
- package/src/ui/component/identity/identity-manager/identity-manager.css +178 -0
- package/src/ui/component/identity/identity-manager/identity-manager.html +19 -0
- package/src/ui/component/identity/identity-manager/identity-manager.mts +675 -0
- package/src/ui/component/identity/index.mts +36 -0
- package/src/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
- package/src/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
- package/src/ui/component/identity/keystone-creator/keystone-creator.mts +497 -0
- package/src/ui/component/identity/keystone-details/keystone-details.css +621 -0
- package/src/ui/component/identity/keystone-details/keystone-details.html +154 -0
- package/src/ui/component/identity/keystone-details/keystone-details.mts +1506 -0
- package/src/ui/component/identity/keystone-scrubber/SCRUBBER_IMPLEMENTATION.md +33 -0
- package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
- package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
- package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.mts +355 -0
- package/src/ui/component/identity/remove-device/remove-device.css +118 -0
- package/src/ui/component/identity/remove-device/remove-device.html +31 -0
- package/src/ui/component/identity/remove-device/remove-device.mts +247 -0
- package/src/ui/ui-constants.mts +1 -0
- package/src/ui/ui-types.mts +8 -0
- package/src/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mts +42 -1
- package/tools/auto-generated-agent-skills/skills/ibgib-dependency-graph/SKILL.md +209 -0
- package/tools/auto-generated-agent-skills/skills/ibgib-implementation-plan/SKILL.md +102 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Keystone Scrubber Implementation Plan
|
|
2
|
+
|
|
3
|
+
> [!WARNING]
|
|
4
|
+
> Skip automated browser testing for these component changes. The user (Bill) will perform manual verification to avoid token usage from screenshots/images.
|
|
5
|
+
|
|
6
|
+
## Driving Problem
|
|
7
|
+
In the previous monolithic parent/child component refactoring, the `<ibgib-keystone-details>` component was designed to handle *both* displaying metadata for a single keystone frame, and managing/scrubbing through the timeline history.
|
|
8
|
+
Because it was a child component managed by the `<ibgib-identity-manager>` tab view, it was instantiated dynamically via `getComponentInstance()`. But since it was not yet injected into the DOM, its custom element `connectedCallback()` and `created()` methods had not run. Consequently, `loadIbGib()` was never triggered, leaving its `this.ibGib` property `undefined` at initialization time and throwing errors when the parent manager attempted to read its backing data.
|
|
9
|
+
|
|
10
|
+
## Solution: Separating Concerns with a Scrubber Parent Component
|
|
11
|
+
To resolve this, we will introduce a new `<ibgib-keystone-scrubber>` component.
|
|
12
|
+
* **`<ibgib-keystone-scrubber>` (Parent)**: Acts as the parent component for a keystone's timeline. It loads history, renders the scrubber navigation toolbar (scrub buttons and status), and acts as a `Parent` component that injects a details view child component for whichever frame address is selected.
|
|
13
|
+
* **`<ibgib-keystone-details>` (Child)**: A simple, static child component that only renders the details of a *single* specific keystone address. It does not manage history or scrubber state. It overrides `initialize()` to call `loadIbGib()`, ensuring `this.ibGib` is populated immediately upon instantiation.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Tasks Checklist
|
|
18
|
+
|
|
19
|
+
- [ ] Register new component metadata
|
|
20
|
+
- [ ] Register `KeystoneScrubberComponentMeta` in [space-gib-shell-service.mts](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/ui/shell/space-gib-shell-service.mts)
|
|
21
|
+
- [ ] Create Scrubber component files
|
|
22
|
+
- [ ] Create [keystone-scrubber.html](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/keystone-scrubber/keystone-scrubber.html) containing the scrubber header layout and a `#keystone-scrubber-content` slot
|
|
23
|
+
- [ ] Create [keystone-scrubber.css](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/keystone-scrubber/keystone-scrubber.css) for scrubber-specific bar and button stylings
|
|
24
|
+
- [ ] Create [keystone-scrubber.mts](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/keystone-scrubber/keystone-scrubber.mts) extending `IbGibDynamicComponentInstanceBase_Parent` to manage the history array and child detail views
|
|
25
|
+
- [ ] Refactor details component to be static
|
|
26
|
+
- [ ] Simplify [keystone-details.html](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/keystone-details/keystone-details.html) to remove all scrubber header elements
|
|
27
|
+
- [ ] Simplify [keystone-details.css](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/keystone-details/keystone-details.css) to remove scrubber styles
|
|
28
|
+
- [ ] Modify [keystone-details.mts](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/keystone-details/keystone-details.mts) to extend standard `IbGibDynamicComponentInstanceBase`, load `loadIbGib()` inside `initialize()`, and remove history/scrubbing logic
|
|
29
|
+
- [ ] Update Parent Identity Manager to point to Scrubber
|
|
30
|
+
- [ ] Update `getLoadedChildInfo` in [identity-manager.mts](file:///c:/Users/billm/antigravity/ibgib/apps/space-gib/src/client/components/identity-manager/identity-manager.mts) to instantiate `ibgib-keystone-scrubber` instead of `ibgib-keystone-details`
|
|
31
|
+
- [ ] Compile and verify
|
|
32
|
+
- [ ] Compile space-gib via `npm run build:space-gib` (and `npm run chain:build:web-gib` if web-gib changes are needed)
|
|
33
|
+
- [ ] Restart space-gib server and manually verify tab switching and timeline scrubbing
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
max-width: 100%;
|
|
5
|
+
margin: 0;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.scrubber-container {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
gap: 1.5rem;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Timeline Scrubber Navigation */
|
|
16
|
+
.scrubber-nav {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
gap: 0.5rem;
|
|
21
|
+
padding: 0.75rem;
|
|
22
|
+
background: rgba(0, 0, 0, 0.2);
|
|
23
|
+
border: 1px solid var(--border-color-base, rgba(255, 255, 255, 0.05));
|
|
24
|
+
border-radius: var(--radius-md, 8px);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.scrubber-info {
|
|
28
|
+
font-family: var(--font-mono, monospace);
|
|
29
|
+
font-size: 0.85rem;
|
|
30
|
+
color: var(--clr-accent, #50fa7b);
|
|
31
|
+
min-width: 120px;
|
|
32
|
+
text-align: center;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.scrubber-btn {
|
|
37
|
+
padding: 0.4rem 0.8rem;
|
|
38
|
+
font-size: 0.8rem;
|
|
39
|
+
min-width: 2.2rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.content {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: 1.5rem;
|
|
46
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<div id="container" class="scrubber-container">
|
|
2
|
+
<div class="scrubber-nav">
|
|
3
|
+
<button id="btn-scrub-first" class="action-btn scrubber-btn" title="First Frame"><<</button>
|
|
4
|
+
<button id="btn-scrub-prev10" class="action-btn scrubber-btn" title="Back 10 Frames">-10</button>
|
|
5
|
+
<button id="btn-scrub-prev" class="action-btn scrubber-btn" title="Previous Frame"><</button>
|
|
6
|
+
<span id="scrubber-status" class="scrubber-info">Loading timeline...</span>
|
|
7
|
+
<button id="btn-scrub-next" class="action-btn scrubber-btn" title="Next Frame">></button>
|
|
8
|
+
<button id="btn-scrub-next10" class="action-btn scrubber-btn" title="Forward 10 Frames">+10</button>
|
|
9
|
+
<button id="btn-scrub-latest" class="action-btn scrubber-btn" title="Latest Frame">>></button>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div id="keystone-scrubber-content" class="content">
|
|
13
|
+
<!-- Details component for the active frame will be injected here -->
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import thisCss from "./keystone-scrubber.css";
|
|
2
|
+
import thisHtml from "./keystone-scrubber.html";
|
|
3
|
+
import commonComponentStylesCss from "../../common-component-styles.css";
|
|
4
|
+
|
|
5
|
+
import { extractErrorMsg } 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 { getGibInfo } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
|
|
9
|
+
import { getIbAndGib, getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
|
|
10
|
+
import { KeystoneIbGib_V1 } from "@ibgib/core-gib/dist/keystone/keystone-types.mjs";
|
|
11
|
+
import {
|
|
12
|
+
IbGibDynamicComponentMetaBase, IbGibDynamicComponentInstanceBase_Parent,
|
|
13
|
+
} from "../../ibgib-dynamic-component-bases.mjs";
|
|
14
|
+
import {
|
|
15
|
+
ElementsBase, ChildInfoBase, IbGibDynamicComponentInstance,
|
|
16
|
+
IbGibDynamicComponentInstanceInitOpts,
|
|
17
|
+
} from "../../component-types.mjs";
|
|
18
|
+
import { getComponentSvc } from "../../ibgib-component-service.mjs";
|
|
19
|
+
import { getComponentCtorArg } from "../../../../app-bootstrap/init-orchestration.mjs";
|
|
20
|
+
import { getGlobalMetaspace_waitIfNeeded } from "../../../../helpers.mjs";
|
|
21
|
+
|
|
22
|
+
const logalot = false;
|
|
23
|
+
|
|
24
|
+
export const KEYSTONE_SCRUBBER_COMPONENT_NAME = 'ibgib-keystone-scrubber';
|
|
25
|
+
|
|
26
|
+
export class KeystoneScrubberComponentMeta extends IbGibDynamicComponentMetaBase {
|
|
27
|
+
protected lc: string = `[KeystoneScrubberComponentMeta]`;
|
|
28
|
+
|
|
29
|
+
routeRegExp?: RegExp = new RegExp(`^${KEYSTONE_SCRUBBER_COMPONENT_NAME}$`);
|
|
30
|
+
componentName = KEYSTONE_SCRUBBER_COMPONENT_NAME;
|
|
31
|
+
|
|
32
|
+
constructor() {
|
|
33
|
+
super(getComponentCtorArg());
|
|
34
|
+
if (!customElements.get(this.componentName)) {
|
|
35
|
+
customElements.define(this.componentName, KeystoneScrubberComponentInstance);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async createInstance({
|
|
40
|
+
path,
|
|
41
|
+
ibGibAddr
|
|
42
|
+
}: {
|
|
43
|
+
path: string;
|
|
44
|
+
ibGibAddr: IbGibAddr;
|
|
45
|
+
}): Promise<IbGibDynamicComponentInstance> {
|
|
46
|
+
const lc = `${this.lc}[${this.createInstance.name}]`;
|
|
47
|
+
const component = document.createElement(this.componentName) as KeystoneScrubberComponentInstance;
|
|
48
|
+
await component.initialize({
|
|
49
|
+
ibGibAddr,
|
|
50
|
+
meta: this,
|
|
51
|
+
html: thisHtml,
|
|
52
|
+
css: [commonComponentStylesCss, thisCss],
|
|
53
|
+
});
|
|
54
|
+
return component;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface ScrubberTabInfo extends ChildInfoBase<IbGibDynamicComponentInstance<any, any>> {
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface KeystoneScrubberElements extends ElementsBase {
|
|
62
|
+
containerEl: HTMLDivElement;
|
|
63
|
+
btnScrubFirstEl: HTMLButtonElement;
|
|
64
|
+
btnScrubPrev10El: HTMLButtonElement;
|
|
65
|
+
btnScrubPrevEl: HTMLButtonElement;
|
|
66
|
+
scrubberStatusEl: HTMLSpanElement;
|
|
67
|
+
btnScrubNextEl: HTMLButtonElement;
|
|
68
|
+
btnScrubNext10El: HTMLButtonElement;
|
|
69
|
+
btnScrubLatestEl: HTMLButtonElement;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export class KeystoneScrubberComponentInstance
|
|
73
|
+
extends IbGibDynamicComponentInstanceBase_Parent<KeystoneIbGib_V1, KeystoneScrubberElements, ScrubberTabInfo>
|
|
74
|
+
implements IbGibDynamicComponentInstance<KeystoneIbGib_V1, KeystoneScrubberElements> {
|
|
75
|
+
|
|
76
|
+
protected override lc: string = `[KeystoneScrubberComponentInstance]`;
|
|
77
|
+
|
|
78
|
+
private history: string[] = [];
|
|
79
|
+
private currentFrameIndex: number = -1;
|
|
80
|
+
private lastLoadedHistoryAddr: string | null = null;
|
|
81
|
+
|
|
82
|
+
constructor() {
|
|
83
|
+
console.log('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)')
|
|
84
|
+
const lc = `${KeystoneScrubberComponentInstance.name}[ctor]`;
|
|
85
|
+
if (logalot) { console.log(`${lc} (I: 3adca837d5c898d8e839d23c59538126)`); }
|
|
86
|
+
super();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override async initialize(opts: IbGibDynamicComponentInstanceInitOpts): Promise<void> {
|
|
90
|
+
const lc = `${this.lc}[${this.initialize.name}]`;
|
|
91
|
+
try {
|
|
92
|
+
if (logalot) { console.log(`${lc} starting... (I: 75eecfc01af7f3fa9897932ec5457526)`); }
|
|
93
|
+
|
|
94
|
+
await super.initialize(opts);
|
|
95
|
+
await this.loadIbGib();
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
99
|
+
throw error;
|
|
100
|
+
} finally {
|
|
101
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
override async created(): Promise<void> {
|
|
106
|
+
const lc = `${this.lc}[${this.created.name}]`;
|
|
107
|
+
try {
|
|
108
|
+
if (logalot) { console.log(`${lc} starting... (I: bc16e6212928658ed8034c75b6279526)`); }
|
|
109
|
+
|
|
110
|
+
this.elements = {} as KeystoneScrubberElements;
|
|
111
|
+
|
|
112
|
+
const shadow = this.shadowRoot!;
|
|
113
|
+
this.elements.containerEl = shadow.getElementById('container') as HTMLDivElement;
|
|
114
|
+
this.elements.btnScrubFirstEl = shadow.getElementById('btn-scrub-first') as HTMLButtonElement;
|
|
115
|
+
this.elements.btnScrubPrev10El = shadow.getElementById('btn-scrub-prev10') as HTMLButtonElement;
|
|
116
|
+
this.elements.btnScrubPrevEl = shadow.getElementById('btn-scrub-prev') as HTMLButtonElement;
|
|
117
|
+
this.elements.scrubberStatusEl = shadow.getElementById('scrubber-status') as HTMLSpanElement;
|
|
118
|
+
this.elements.btnScrubNextEl = shadow.getElementById('btn-scrub-next') as HTMLButtonElement;
|
|
119
|
+
this.elements.btnScrubNext10El = shadow.getElementById('btn-scrub-next10') as HTMLButtonElement;
|
|
120
|
+
this.elements.btnScrubLatestEl = shadow.getElementById('btn-scrub-latest') as HTMLButtonElement;
|
|
121
|
+
|
|
122
|
+
// ElementBase contentEl holds the child component
|
|
123
|
+
this.elements.contentEl = shadow.getElementById('keystone-scrubber-content') as HTMLDivElement;
|
|
124
|
+
|
|
125
|
+
this.initHandlers();
|
|
126
|
+
this.loadHistoryData().catch(err => console.error(`${this.lc} loadHistoryData error: ${extractErrorMsg(err)}`));
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
129
|
+
throw error;
|
|
130
|
+
} finally {
|
|
131
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
override async disconnected(): Promise<void> {
|
|
136
|
+
// No-op
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private initHandlers() {
|
|
140
|
+
this.elements!.btnScrubFirstEl.addEventListener('click', () => this.scrubFirst());
|
|
141
|
+
this.elements!.btnScrubPrev10El.addEventListener('click', () => this.scrubPrev10());
|
|
142
|
+
this.elements!.btnScrubPrevEl.addEventListener('click', () => this.scrubPrev());
|
|
143
|
+
this.elements!.btnScrubNextEl.addEventListener('click', () => this.scrubNext());
|
|
144
|
+
this.elements!.btnScrubNext10El.addEventListener('click', () => this.scrubNext10());
|
|
145
|
+
this.elements!.btnScrubLatestEl.addEventListener('click', () => this.scrubLatest());
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
override async loadIbGib(): Promise<void> {
|
|
149
|
+
const lc = `${this.lc}[${this.loadIbGib.name}]`;
|
|
150
|
+
try {
|
|
151
|
+
if (logalot) { console.log(`${lc} starting... (I: a4a9181bbb58a22cc71c8745a91ec426)`); }
|
|
152
|
+
|
|
153
|
+
if (!this.ibGibAddr) return;
|
|
154
|
+
|
|
155
|
+
await super.loadIbGib();
|
|
156
|
+
await this.loadHistoryData();
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
159
|
+
throw error;
|
|
160
|
+
} finally {
|
|
161
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public override async activateIbGib({
|
|
166
|
+
addr,
|
|
167
|
+
ibGib,
|
|
168
|
+
}: {
|
|
169
|
+
addr?: IbGibAddr,
|
|
170
|
+
ibGib?: IbGib_V1,
|
|
171
|
+
}): Promise<void> {
|
|
172
|
+
const lc = `${this.lc}[activateIbGib]`;
|
|
173
|
+
try {
|
|
174
|
+
if (logalot) { console.log(`${lc} starting... (I: 890a8cb88f72c918a8bcf82c8af63e26)`); }
|
|
175
|
+
if (!addr) return;
|
|
176
|
+
|
|
177
|
+
// Get or create the details component for this specific frame
|
|
178
|
+
const childInfo = await this.getLoadedChildInfo({ addr, ibGib });
|
|
179
|
+
|
|
180
|
+
// Manage active states in childInfos
|
|
181
|
+
const currentlyActive = this.activeChildInfo;
|
|
182
|
+
if (currentlyActive) {
|
|
183
|
+
currentlyActive.active = false;
|
|
184
|
+
}
|
|
185
|
+
childInfo.active = true;
|
|
186
|
+
|
|
187
|
+
// Re-use the framework's content injection code
|
|
188
|
+
const componentSvc = await getComponentSvc();
|
|
189
|
+
await componentSvc.inject({
|
|
190
|
+
parentEl: this.elements!.contentEl,
|
|
191
|
+
componentToInject: childInfo.component!,
|
|
192
|
+
});
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private async loadHistoryData(): Promise<void> {
|
|
199
|
+
if (!this.ibGibAddr || !this.elements) return;
|
|
200
|
+
|
|
201
|
+
if (this.ibGibAddr !== this.lastLoadedHistoryAddr) {
|
|
202
|
+
await this.loadHistory(this.ibGibAddr);
|
|
203
|
+
this.lastLoadedHistoryAddr = this.ibGibAddr;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
await this.scrubTo(this.history.length - 1);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private async loadHistory(tipAddr: string): Promise<void> {
|
|
210
|
+
const lc = `${this.lc}[loadHistory]`;
|
|
211
|
+
this.history = [];
|
|
212
|
+
this.currentFrameIndex = -1;
|
|
213
|
+
|
|
214
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
215
|
+
if (!metaspace) return;
|
|
216
|
+
const space = await metaspace.getLocalUserSpace({ lock: false });
|
|
217
|
+
if (!space) return;
|
|
218
|
+
|
|
219
|
+
let currentAddr: string | undefined = tipAddr;
|
|
220
|
+
const tempHistory: string[] = [];
|
|
221
|
+
|
|
222
|
+
while (currentAddr) {
|
|
223
|
+
const res = await metaspace.get({ addr: currentAddr, space });
|
|
224
|
+
if (!res.success || !res.ibGibs || res.ibGibs.length === 0) {
|
|
225
|
+
console.warn(`${lc} Could not find frame at ${currentAddr}`);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
const keystone = res.ibGibs[0] as KeystoneIbGib_V1;
|
|
229
|
+
tempHistory.push(currentAddr);
|
|
230
|
+
|
|
231
|
+
if (keystone.data?.n === 0) {
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const past = keystone.rel8ns?.past;
|
|
236
|
+
currentAddr = (past && past.length > 0) ? past[past.length - 1] : undefined;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.history = tempHistory.reverse();
|
|
240
|
+
this.currentFrameIndex = this.history.length - 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
private async scrubTo(index: number): Promise<void> {
|
|
244
|
+
if (this.history.length === 0) return;
|
|
245
|
+
this.currentFrameIndex = Math.max(0, Math.min(index, this.history.length - 1));
|
|
246
|
+
|
|
247
|
+
this.updateScrubberUI();
|
|
248
|
+
|
|
249
|
+
const addr = this.history[this.currentFrameIndex];
|
|
250
|
+
await this.activateIbGib({ addr });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private scrubFirst() { this.scrubTo(0); }
|
|
254
|
+
private scrubPrev10() { this.scrubTo(this.currentFrameIndex - 10); }
|
|
255
|
+
private scrubPrev() { this.scrubTo(this.currentFrameIndex - 1); }
|
|
256
|
+
private scrubNext() { this.scrubTo(this.currentFrameIndex + 1); }
|
|
257
|
+
private scrubNext10() { this.scrubTo(this.currentFrameIndex + 10); }
|
|
258
|
+
private scrubLatest() { this.scrubTo(this.history.length - 1); }
|
|
259
|
+
|
|
260
|
+
private updateScrubberUI() {
|
|
261
|
+
if (!this.elements) return;
|
|
262
|
+
this.elements.scrubberStatusEl.textContent = `Frame ${this.currentFrameIndex + 1} / ${this.history.length}`;
|
|
263
|
+
|
|
264
|
+
this.elements.btnScrubFirstEl.disabled = this.currentFrameIndex === 0;
|
|
265
|
+
this.elements.btnScrubPrev10El.disabled = this.currentFrameIndex === 0;
|
|
266
|
+
this.elements.btnScrubPrevEl.disabled = this.currentFrameIndex === 0;
|
|
267
|
+
this.elements.btnScrubNextEl.disabled = this.currentFrameIndex === this.history.length - 1;
|
|
268
|
+
this.elements.btnScrubNext10El.disabled = this.currentFrameIndex === this.history.length - 1;
|
|
269
|
+
this.elements.btnScrubLatestEl.disabled = this.currentFrameIndex === this.history.length - 1;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
protected async getLoadedChildInfo({
|
|
273
|
+
addr,
|
|
274
|
+
ibGib,
|
|
275
|
+
}: {
|
|
276
|
+
addr: IbGibAddr,
|
|
277
|
+
ibGib?: IbGib_V1,
|
|
278
|
+
}): Promise<ScrubberTabInfo> {
|
|
279
|
+
const lc = `${this.lc}[${this.getLoadedChildInfo.name}]`;
|
|
280
|
+
try {
|
|
281
|
+
if (logalot) { console.log(`${lc} starting... (I: 9eea188f6b55f04b483fbda8a110f826)`); }
|
|
282
|
+
|
|
283
|
+
if (!addr) { throw new Error(`(UNEXPECTED) addr falsy?`); }
|
|
284
|
+
const tjpGib = getGibInfo({ ibGibAddr: addr }).tjpGib ?? getIbAndGib({ ibGibAddr: addr }).gib;
|
|
285
|
+
|
|
286
|
+
const fnCreateAndLoadChildComponent = async () => {
|
|
287
|
+
const componentSvc = await getComponentSvc();
|
|
288
|
+
const detailsComponent = await componentSvc.getComponentInstance({
|
|
289
|
+
path: 'ibgib-keystone-details',
|
|
290
|
+
ibGibAddr: addr,
|
|
291
|
+
useRegExpPrefilter: true,
|
|
292
|
+
});
|
|
293
|
+
if (!detailsComponent) {
|
|
294
|
+
throw new Error(`(UNEXPECTED) detailsComponent falsy?`);
|
|
295
|
+
}
|
|
296
|
+
return detailsComponent;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let tabInfo: ScrubberTabInfo;
|
|
300
|
+
|
|
301
|
+
const filtered = this.childInfos.filter(x => x.addr === addr);
|
|
302
|
+
|
|
303
|
+
if (filtered.length > 0) {
|
|
304
|
+
if (filtered.length !== 1) { throw new Error(`(UNEXPECTED) filtered.length !== 1?`); }
|
|
305
|
+
tabInfo = filtered[0];
|
|
306
|
+
if (!tabInfo.component) {
|
|
307
|
+
tabInfo.component = await fnCreateAndLoadChildComponent();
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
const detailsComponent = await fnCreateAndLoadChildComponent();
|
|
311
|
+
ibGib = detailsComponent.ibGib ?? ibGib;
|
|
312
|
+
const tabBtnEl = await this.addChild({ addr, ibGib: ibGib! });
|
|
313
|
+
tabInfo = {
|
|
314
|
+
addr,
|
|
315
|
+
childBtnEl: tabBtnEl,
|
|
316
|
+
component: detailsComponent,
|
|
317
|
+
active: false,
|
|
318
|
+
};
|
|
319
|
+
this.childInfos.push(tabInfo);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return tabInfo;
|
|
323
|
+
} catch (error) {
|
|
324
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
325
|
+
throw error;
|
|
326
|
+
} finally {
|
|
327
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
protected override async addChild({
|
|
332
|
+
addr,
|
|
333
|
+
ibGib,
|
|
334
|
+
}: {
|
|
335
|
+
ibGib: IbGib_V1,
|
|
336
|
+
addr?: IbGibAddr,
|
|
337
|
+
}): Promise<HTMLElement> {
|
|
338
|
+
const lc = `${this.lc}[${this.addChild.name}]`;
|
|
339
|
+
try {
|
|
340
|
+
if (logalot) { console.log(`${lc} starting... (I: 824f98b6f9a2c922f8b3a9f67ad63e26)`); }
|
|
341
|
+
|
|
342
|
+
// why are we making a dummy???
|
|
343
|
+
|
|
344
|
+
// Return a dummy hidden element since we don't display visual tab buttons in the scrubber
|
|
345
|
+
const dummy = document.createElement('div');
|
|
346
|
+
dummy.style.display = 'none';
|
|
347
|
+
return dummy;
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
350
|
+
throw error;
|
|
351
|
+
} finally {
|
|
352
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.component-container {
|
|
7
|
+
padding: 1.5rem;
|
|
8
|
+
background: var(--ibgib-bg-surface, #1e1e2e);
|
|
9
|
+
color: var(--ibgib-text-primary, #cdd6f4);
|
|
10
|
+
border-radius: 12px;
|
|
11
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.input-group {
|
|
15
|
+
margin-bottom: 1.2rem;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
gap: 0.4rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.input-group label {
|
|
22
|
+
font-size: 0.95rem;
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
color: var(--ibgib-text-secondary, #a6adc8);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.text-input, .secret-input {
|
|
28
|
+
padding: 0.75rem 1rem;
|
|
29
|
+
border-radius: 8px;
|
|
30
|
+
border: 1px solid var(--ibgib-border-color, #45475a);
|
|
31
|
+
background: var(--ibgib-bg-input, #11111b);
|
|
32
|
+
color: var(--ibgib-text-primary, #cdd6f4);
|
|
33
|
+
font-size: 1rem;
|
|
34
|
+
outline: none;
|
|
35
|
+
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.text-input:focus, .secret-input:focus {
|
|
39
|
+
border-color: var(--ibgib-accent-color, #89b4fa);
|
|
40
|
+
box-shadow: 0 0 0 2px rgba(137, 180, 250, 0.2);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.text-input.invalid, .secret-input.invalid {
|
|
44
|
+
border-color: #f38ba8;
|
|
45
|
+
box-shadow: 0 0 0 2px rgba(243, 139, 168, 0.2);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.action-row {
|
|
49
|
+
margin-top: 1.5rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.action-btn {
|
|
53
|
+
width: 100%;
|
|
54
|
+
padding: 0.85rem 1.5rem;
|
|
55
|
+
border: none;
|
|
56
|
+
border-radius: 8px;
|
|
57
|
+
background: linear-gradient(135deg, #f38ba8, #f5e0dc);
|
|
58
|
+
color: #11111b;
|
|
59
|
+
font-size: 1rem;
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
cursor: pointer;
|
|
62
|
+
transition: transform 0.15s ease, opacity 0.15s ease;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.action-btn:hover {
|
|
66
|
+
transform: translateY(-1px);
|
|
67
|
+
opacity: 0.95;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.action-btn:active {
|
|
71
|
+
transform: translateY(0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.status-area {
|
|
75
|
+
margin-top: 1.2rem;
|
|
76
|
+
padding: 1rem;
|
|
77
|
+
border-radius: 8px;
|
|
78
|
+
font-size: 0.95rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.status-area.info {
|
|
82
|
+
background: rgba(137, 180, 250, 0.15);
|
|
83
|
+
border: 1px solid #89b4fa;
|
|
84
|
+
color: #89b4fa;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.status-area.error {
|
|
88
|
+
background: rgba(243, 139, 168, 0.15);
|
|
89
|
+
border: 1px solid #f38ba8;
|
|
90
|
+
color: #f38ba8;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.status-area.success {
|
|
94
|
+
background: rgba(166, 227, 161, 0.15);
|
|
95
|
+
border: 1px solid #a6e3a1;
|
|
96
|
+
color: #a6e3a1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.hidden {
|
|
100
|
+
display: none !important;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.collapsed {
|
|
104
|
+
display: none !important;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.result-area {
|
|
108
|
+
margin-top: 1.5rem;
|
|
109
|
+
padding: 1.2rem;
|
|
110
|
+
border-radius: 8px;
|
|
111
|
+
background: rgba(243, 139, 168, 0.1);
|
|
112
|
+
border: 1px solid #f38ba8;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.result-area h3 {
|
|
116
|
+
margin-top: 0;
|
|
117
|
+
color: #f38ba8;
|
|
118
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<div id="container" class="component-container">
|
|
2
|
+
<h2 id="title">Remove / Unlink Device</h2>
|
|
3
|
+
<div class="content">
|
|
4
|
+
<p>Unlink an authorized delegate device from your primary identity timeline.</p>
|
|
5
|
+
|
|
6
|
+
<div class="input-group">
|
|
7
|
+
<label for="select-delegate">Select Device / Delegate</label>
|
|
8
|
+
<select id="select-delegate" class="text-input">
|
|
9
|
+
<option value="">-- Loading registered devices... --</option>
|
|
10
|
+
</select>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="input-group">
|
|
14
|
+
<label for="input-passphrase">Master Passphrase</label>
|
|
15
|
+
<input type="password" id="input-passphrase" placeholder="Enter your master passphrase..." class="secret-input">
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="action-row">
|
|
19
|
+
<button id="btn-remove-device" class="action-btn">Unlink & Revoke Device</button>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div id="status-area" class="status-area hidden">
|
|
23
|
+
<p id="status-text" class="status-msg"></p>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div id="result-area" class="result-area collapsed">
|
|
27
|
+
<h3>Device Unlinked Successfully!</h3>
|
|
28
|
+
<p class="warning">🔒 The selected device delegate has been unlinked from your primary identity.</p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|