@franzzemen/brokenstock-shell 0.4.5 → 0.4.6
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.
|
@@ -2777,12 +2777,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
|
|
|
2777
2777
|
args: [{ providedIn: 'root' }]
|
|
2778
2778
|
}], ctorParameters: () => [] });
|
|
2779
2779
|
|
|
2780
|
+
/** Roomy enough for the scanner beside a chart, small enough for a laptop. */
|
|
2781
|
+
const POP_OUT_WIDTH = 1280;
|
|
2782
|
+
const POP_OUT_HEIGHT = 900;
|
|
2780
2783
|
class StatusBar {
|
|
2781
2784
|
constructor() {
|
|
2782
2785
|
this.#authService = inject(AuthenticationService);
|
|
2783
2786
|
this.#focusService = inject(TerminalFocusService);
|
|
2784
2787
|
this.#commandService = inject(CommandService);
|
|
2788
|
+
this.#sharedSession = inject(SHELL_SHARED_SESSION, { optional: true }) ?? false;
|
|
2785
2789
|
this.isAuthenticated = this.#authService.authenticated;
|
|
2790
|
+
/**
|
|
2791
|
+
* Whether a second window is offered at all (multiple-windows PRD D14).
|
|
2792
|
+
*
|
|
2793
|
+
* ⚠ GATED ON SHARED SESSIONS, and this is a correctness gate rather than a
|
|
2794
|
+
* tidiness one. Without a session shared across windows, the new window starts
|
|
2795
|
+
* with no token, goes to the login screen, and signing in there ends the
|
|
2796
|
+
* session THIS window is using. A pop-out button in an app without sharing is
|
|
2797
|
+
* a button that signs you out — the exact failure the multiple-windows work
|
|
2798
|
+
* exists to remove.
|
|
2799
|
+
*/
|
|
2800
|
+
this.canPopOut = computed(() => this.#sharedSession && this.isAuthenticated(), /* @ts-ignore */
|
|
2801
|
+
...(ngDevMode ? [{ debugName: "canPopOut" }] : /* istanbul ignore next */ []));
|
|
2786
2802
|
this.loginStatus = computed(() => this.#authService.authenticating()
|
|
2787
2803
|
? 'Authenticating...'
|
|
2788
2804
|
: this.#authService.authenticated()
|
|
@@ -2793,21 +2809,41 @@ class StatusBar {
|
|
|
2793
2809
|
#authService;
|
|
2794
2810
|
#focusService;
|
|
2795
2811
|
#commandService;
|
|
2812
|
+
#sharedSession;
|
|
2796
2813
|
logout() {
|
|
2797
2814
|
this.#authService.logout();
|
|
2798
2815
|
this.#commandService.echoCommand('logout');
|
|
2799
2816
|
this.#focusService.requestFocus();
|
|
2800
2817
|
}
|
|
2818
|
+
/**
|
|
2819
|
+
* Open the screen you are on in a second, sized window.
|
|
2820
|
+
*
|
|
2821
|
+
* There is no mechanism by which this differs from the browser's own
|
|
2822
|
+
* "Duplicate tab": every window is a separate copy of the app started at some
|
|
2823
|
+
* address. It exists for the sizing and because it is discoverable — Ctrl+T,
|
|
2824
|
+
* a bookmark and dragging a tab out all work equally well once the session is
|
|
2825
|
+
* shared.
|
|
2826
|
+
*
|
|
2827
|
+
* `noopener` is deliberate. The new window needs nothing from this one — it
|
|
2828
|
+
* reads the session from storage — and leaving the opener reachable would give
|
|
2829
|
+
* two windows script access to each other for no purpose.
|
|
2830
|
+
*/
|
|
2831
|
+
popOut() {
|
|
2832
|
+
if (typeof window === 'undefined')
|
|
2833
|
+
return;
|
|
2834
|
+
window.open(window.location.href, '_blank', `noopener,noreferrer,width=${POP_OUT_WIDTH},height=${POP_OUT_HEIGHT}`);
|
|
2835
|
+
this.#focusService.requestFocus();
|
|
2836
|
+
}
|
|
2801
2837
|
openFaq() {
|
|
2802
2838
|
this.#commandService.execute('faq');
|
|
2803
2839
|
this.#focusService.requestFocus();
|
|
2804
2840
|
}
|
|
2805
2841
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: StatusBar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2806
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: StatusBar, isStandalone: true, selector: "shell-status-bar", ngImport: i0, template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2842
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: StatusBar, isStandalone: true, selector: "shell-status-bar", ngImport: i0, template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n @if (canPopOut()) {\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"popOut()\"\n title=\"Open this screen in a second window\"\n aria-label=\"Open this screen in a second window\"\n >\u29C9</button>\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2807
2843
|
}
|
|
2808
2844
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: StatusBar, decorators: [{
|
|
2809
2845
|
type: Component,
|
|
2810
|
-
args: [{ selector: 'shell-status-bar', changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"] }]
|
|
2846
|
+
args: [{ selector: 'shell-status-bar', changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"status-bar\">\n <div class=\"status-item\">\n <span class=\"status-label text-secondary-info\">Status:</span>\n @if (isAuthenticated()) {\n <a class=\"status-value text-interactive logout-link\" (click)=\"logout()\">Log Out</a>\n } @else {\n <span class=\"status-value text-loss\">{{ loginStatus() }}</span>\n }\n </div>\n @if (isAuthenticated()) {\n <ng-content />\n }\n @if (canPopOut()) {\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"popOut()\"\n title=\"Open this screen in a second window\"\n aria-label=\"Open this screen in a second window\"\n >\u29C9</button>\n }\n <button\n type=\"button\"\n class=\"faq-button text-interactive\"\n (click)=\"openFaq()\"\n title=\"Open FAQ (or type `faq`)\"\n aria-label=\"Open FAQ\"\n >?</button>\n</div>\n", styles: [".status-bar{display:flex;align-items:center;gap:24px;padding:0 16px;height:100%;background-color:var(--color-surface);border-bottom:1px solid var(--color-surface-border);font-size:.8rem}.status-item{display:flex;align-items:baseline;gap:6px}.status-label{font-weight:500;text-transform:uppercase;letter-spacing:.05em;font-size:.7rem}.logout-link{cursor:pointer;text-decoration:underline}.logout-link:hover{opacity:.8}.faq-button{margin-left:auto;background:none;border:1px solid var(--color-surface-border);border-radius:50%;width:22px;height:22px;font-size:.85rem;font-weight:600;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0}.faq-button:hover{opacity:.8}\n"] }]
|
|
2811
2847
|
}] });
|
|
2812
2848
|
|
|
2813
2849
|
class SideMenu {
|