@flighthq/statusbar 0.3.1-next.975.01aea94 → 0.4.0-edge.1908.751021c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/statusbar.d.ts +6 -2
- package/dist/statusbar.d.ts.map +1 -1
- package/dist/statusbar.js +64 -75
- package/dist/statusbar.js.map +1 -1
- package/package.json +3 -3
- package/src/statusbar.test.ts +132 -70
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { attachStatusBar, clearStatusBarStyleStack, createStatusBar, detachStatusBar, disposeStatusBar, getStatusBarHeight, getStatusBarInfo, hasStatusBarStyleEntry, popStatusBarStyleEntry, pushStatusBarStyleEntry, setStatusBarColor, setStatusBarOverlaysContent, setStatusBarStyle, setStatusBarVisible, } from './contract';
|
|
1
|
+
export { attachStatusBar, clearStatusBarStyleStack, createStatusBar, detachStatusBar, disposeStatusBar, explainStatusBarBackend, getStatusBarHeight, getStatusBarInfo, hasStatusBarStyleEntry, popStatusBarStyleEntry, pushStatusBarStyleEntry, setStatusBarColor, setStatusBarOverlaysContent, setStatusBarStyle, setStatusBarVisible, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { attachStatusBar, clearStatusBarStyleStack, createStatusBar, detachStatusBar, disposeStatusBar, getStatusBarHeight, getStatusBarInfo, hasStatusBarStyleEntry, popStatusBarStyleEntry, pushStatusBarStyleEntry, setStatusBarColor, setStatusBarOverlaysContent, setStatusBarStyle, setStatusBarVisible, } from './contract';
|
|
1
|
+
export { attachStatusBar, clearStatusBarStyleStack, createStatusBar, detachStatusBar, disposeStatusBar, explainStatusBarBackend, getStatusBarHeight, getStatusBarInfo, hasStatusBarStyleEntry, popStatusBarStyleEntry, pushStatusBarStyleEntry, setStatusBarColor, setStatusBarOverlaysContent, setStatusBarStyle, setStatusBarVisible, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/statusbar.d.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import type { StatusBar, StatusBarAnimation, StatusBarBackend, StatusBarInfo, StatusBarStyle, StatusBarStyleEntry, StatusBarStyleEntryHandle } from '@flighthq/types/contract';
|
|
1
|
+
import type { BackendExplanation, StatusBar, StatusBarAnimation, StatusBarBackend, StatusBarInfo, StatusBarStyle, StatusBarStyleEntry, StatusBarStyleEntryHandle } from '@flighthq/types/contract';
|
|
2
2
|
export declare function attachStatusBar(bar: StatusBar): void;
|
|
3
3
|
export declare function clearStatusBarStyleStack(): void;
|
|
4
4
|
export declare function createStatusBar(): StatusBar;
|
|
5
5
|
export declare function createStatusBarInfo(): StatusBarInfo;
|
|
6
|
-
export declare function createWebStatusBarBackend(): StatusBarBackend;
|
|
7
6
|
export declare function detachStatusBar(bar: StatusBar): void;
|
|
8
7
|
export declare function disposeStatusBar(bar: StatusBar): void;
|
|
8
|
+
export declare function explainStatusBarBackend(): BackendExplanation;
|
|
9
9
|
export declare function getStatusBarBackend(): StatusBarBackend;
|
|
10
10
|
export declare function getStatusBarHeight(): number;
|
|
11
11
|
export declare function getStatusBarInfo(out: StatusBarInfo): StatusBarInfo;
|
|
12
12
|
export declare function hasStatusBarStyleEntry(handle: StatusBarStyleEntryHandle): boolean;
|
|
13
|
+
export declare function installStatusBarHostBackend(backend: StatusBarBackend): void;
|
|
14
|
+
export declare function observeStatusBarHostResult(operation: string, succeeded: boolean): void;
|
|
15
|
+
export declare function packedRgbaToHexColor(color: number): string;
|
|
13
16
|
export declare function popStatusBarStyleEntry(handle: StatusBarStyleEntryHandle): void;
|
|
14
17
|
export declare function pushStatusBarStyleEntry(entry: Readonly<StatusBarStyleEntry>): StatusBarStyleEntryHandle;
|
|
18
|
+
export declare function resetStatusBarBackendForTest(): void;
|
|
15
19
|
export declare function setStatusBarBackend(backend: StatusBarBackend | null): void;
|
|
16
20
|
export declare function setStatusBarColor(color: number, animated?: boolean): void;
|
|
17
21
|
export declare function setStatusBarOverlaysContent(overlay: boolean): void;
|
package/dist/statusbar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statusbar.d.ts","sourceRoot":"","sources":["../src/statusbar.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAalC,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAOpD;AAKD,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAGD,wBAAgB,eAAe,IAAI,SAAS,CAI3C;AAID,wBAAgB,mBAAmB,IAAI,aAAa,CAQnD;
|
|
1
|
+
{"version":3,"file":"statusbar.d.ts","sourceRoot":"","sources":["../src/statusbar.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAalC,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAOpD;AAKD,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAGD,wBAAgB,eAAe,IAAI,SAAS,CAI3C;AAID,wBAAgB,mBAAmB,IAAI,aAAa,CAQnD;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAMpD;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAErD;AAED,wBAAgB,uBAAuB,IAAI,kBAAkB,CAa5D;AAGD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAOD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CAElE;AAKD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAGjF;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAM3E;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAKtF;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG1D;AAMD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAM9E;AAUD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,CAAC,mBAAmB,CAAC,GAAG,yBAAyB,CAWvG;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAKnD;AAGD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE1E;AAKD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAEzE;AAGD,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAElE;AAGD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAE7D;AAGD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAE1F"}
|
package/dist/statusbar.js
CHANGED
|
@@ -44,51 +44,6 @@ export function createStatusBarInfo() {
|
|
|
44
44
|
visible: true,
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
// Builds the default web backend. Web pages have no true status bar, so only setBackgroundColor does
|
|
48
|
-
// anything observable: it upserts a <meta name="theme-color"> hint (alpha dropped). The rest no-op
|
|
49
|
-
// until a native host registers a backend. getInfo reads from the current theme-color meta where
|
|
50
|
-
// present and returns safe defaults for fields the web cannot know (height = -1, visible = true).
|
|
51
|
-
export function createWebStatusBarBackend() {
|
|
52
|
-
return {
|
|
53
|
-
getInfo(out) {
|
|
54
|
-
// Read back the theme-color meta if present; otherwise 0 (no hint set).
|
|
55
|
-
out.color = _webReadThemeColor();
|
|
56
|
-
out.height = -1;
|
|
57
|
-
out.overlaysContent = false;
|
|
58
|
-
out.style = 'default';
|
|
59
|
-
out.visible = true;
|
|
60
|
-
return out;
|
|
61
|
-
},
|
|
62
|
-
setBackgroundColor(color, _animated) {
|
|
63
|
-
// Derive #rrggbb from the top 24 bits of the packed RGBA integer; alpha is dropped.
|
|
64
|
-
if (typeof document === 'undefined')
|
|
65
|
-
return;
|
|
66
|
-
const head = document.head;
|
|
67
|
-
if (head === null || head === undefined)
|
|
68
|
-
return;
|
|
69
|
-
let meta = head.querySelector('meta[name="theme-color"]');
|
|
70
|
-
if (meta === null) {
|
|
71
|
-
meta = document.createElement('meta');
|
|
72
|
-
meta.setAttribute('name', 'theme-color');
|
|
73
|
-
head.appendChild(meta);
|
|
74
|
-
}
|
|
75
|
-
meta.setAttribute('content', packedRgbaToHexColor(color));
|
|
76
|
-
},
|
|
77
|
-
setOverlaysContent(_overlay) {
|
|
78
|
-
// No web status bar; a native host is required to control content overlay.
|
|
79
|
-
},
|
|
80
|
-
setStyle(_style) {
|
|
81
|
-
// No web status bar; a native host (Capacitor/native shell) is required to honor style.
|
|
82
|
-
},
|
|
83
|
-
setVisible(_visible, _animation) {
|
|
84
|
-
// No web status bar; a native host is required to show/hide it.
|
|
85
|
-
},
|
|
86
|
-
subscribe(_listener) {
|
|
87
|
-
// No OS-driven status bar events on web; return a no-op unsubscribe.
|
|
88
|
-
return () => { };
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
47
|
// Stops delivery to `bar` and forgets its subscription. Safe to call when not attached.
|
|
93
48
|
export function detachStatusBar(bar) {
|
|
94
49
|
const unsubscribe = _subscriptions.get(bar);
|
|
@@ -102,11 +57,23 @@ export function detachStatusBar(bar) {
|
|
|
102
57
|
export function disposeStatusBar(bar) {
|
|
103
58
|
detachStatusBar(bar);
|
|
104
59
|
}
|
|
105
|
-
|
|
60
|
+
export function explainStatusBarBackend() {
|
|
61
|
+
if (_custom !== null) {
|
|
62
|
+
return { conflict: _hostConflict, layer: 'custom', operation: null, viability: 'unobserved' };
|
|
63
|
+
}
|
|
64
|
+
if (_host !== null) {
|
|
65
|
+
return {
|
|
66
|
+
conflict: _hostConflict,
|
|
67
|
+
layer: 'host',
|
|
68
|
+
operation: _hostObservation !== null ? _hostObservation.operation : null,
|
|
69
|
+
viability: _hostObservation !== null ? _hostObservation.viability : 'unobserved',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return { conflict: false, layer: 'host-not-enabled', operation: null, viability: 'unobserved' };
|
|
73
|
+
}
|
|
74
|
+
// The active status bar backend. Precedence: custom > host > sentinel.
|
|
106
75
|
export function getStatusBarBackend() {
|
|
107
|
-
|
|
108
|
-
_backend = createWebStatusBarBackend();
|
|
109
|
-
return _backend;
|
|
76
|
+
return _custom ?? _host ?? _sentinel;
|
|
110
77
|
}
|
|
111
78
|
// Returns the status bar height in CSS pixels, or -1 when the host does not report it (web,
|
|
112
79
|
// desktops). Convenience over getStatusBarInfo.
|
|
@@ -129,6 +96,25 @@ export function hasStatusBarStyleEntry(handle) {
|
|
|
129
96
|
return false;
|
|
130
97
|
return _styleStack.some((e) => e.handle === handle);
|
|
131
98
|
}
|
|
99
|
+
export function installStatusBarHostBackend(backend) {
|
|
100
|
+
if (_host !== null) {
|
|
101
|
+
if (_host !== backend)
|
|
102
|
+
_hostConflict = true;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
_host = backend;
|
|
106
|
+
}
|
|
107
|
+
export function observeStatusBarHostResult(operation, succeeded) {
|
|
108
|
+
_hostObservation = {
|
|
109
|
+
operation,
|
|
110
|
+
viability: succeeded ? 'available' : 'runtime-api-unavailable',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// Converts a packed RGBA integer (0xRRGGBBAA) to a #rrggbb hex string, dropping alpha.
|
|
114
|
+
export function packedRgbaToHexColor(color) {
|
|
115
|
+
const rgb = (color >>> 8) & 0xffffff;
|
|
116
|
+
return '#' + rgb.toString(16).padStart(6, '0');
|
|
117
|
+
}
|
|
132
118
|
// Removes the style stack entry identified by `handle`. If the handle is unknown or invalid,
|
|
133
119
|
// this is a no-op. The remaining stack — falling back to the baseline captured before the first
|
|
134
120
|
// push — is re-applied after removal, so a field the popped entry was the last to set returns to
|
|
@@ -162,9 +148,15 @@ export function pushStatusBarStyleEntry(entry) {
|
|
|
162
148
|
_applyTopStyleEntry();
|
|
163
149
|
return handle;
|
|
164
150
|
}
|
|
165
|
-
|
|
151
|
+
export function resetStatusBarBackendForTest() {
|
|
152
|
+
_custom = null;
|
|
153
|
+
_host = null;
|
|
154
|
+
_hostConflict = false;
|
|
155
|
+
_hostObservation = null;
|
|
156
|
+
}
|
|
157
|
+
// Installs a custom status bar backend; pass null to clear the custom override.
|
|
166
158
|
export function setStatusBarBackend(backend) {
|
|
167
|
-
|
|
159
|
+
_custom = backend;
|
|
168
160
|
}
|
|
169
161
|
// Sets the status bar background color from a packed RGBA integer (0xRRGGBBAA). On web this
|
|
170
162
|
// updates the theme-color hint; alpha is ignored. Set animated to true for a smooth transition
|
|
@@ -184,7 +176,27 @@ export function setStatusBarStyle(style) {
|
|
|
184
176
|
export function setStatusBarVisible(visible, animation) {
|
|
185
177
|
getStatusBarBackend().setVisible(visible, animation);
|
|
186
178
|
}
|
|
187
|
-
|
|
179
|
+
const _sentinel = {
|
|
180
|
+
getInfo(out) {
|
|
181
|
+
out.color = 0;
|
|
182
|
+
out.height = -1;
|
|
183
|
+
out.overlaysContent = false;
|
|
184
|
+
out.style = 'default';
|
|
185
|
+
out.visible = true;
|
|
186
|
+
return out;
|
|
187
|
+
},
|
|
188
|
+
setBackgroundColor() { },
|
|
189
|
+
setOverlaysContent() { },
|
|
190
|
+
setStyle() { },
|
|
191
|
+
setVisible() { },
|
|
192
|
+
subscribe() {
|
|
193
|
+
return () => { };
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
let _custom = null;
|
|
197
|
+
let _host = null;
|
|
198
|
+
let _hostConflict = false;
|
|
199
|
+
let _hostObservation = null;
|
|
188
200
|
let _nextHandle = 1;
|
|
189
201
|
const _scratchInfo = createStatusBarInfo();
|
|
190
202
|
const _styleStack = [];
|
|
@@ -264,27 +276,4 @@ function _applyTopStyleEntry() {
|
|
|
264
276
|
next.overlaysContent = overlaysContent;
|
|
265
277
|
_applied = next;
|
|
266
278
|
}
|
|
267
|
-
function packedRgbaToHexColor(color) {
|
|
268
|
-
const rgb = (color >>> 8) & 0xffffff;
|
|
269
|
-
return '#' + rgb.toString(16).padStart(6, '0');
|
|
270
|
-
}
|
|
271
|
-
// Reads the current theme-color meta content and parses it back to a packed RGBA integer.
|
|
272
|
-
// Returns 0 if no meta is present or the value cannot be parsed.
|
|
273
|
-
function _webReadThemeColor() {
|
|
274
|
-
if (typeof document === 'undefined')
|
|
275
|
-
return 0;
|
|
276
|
-
const meta = document.head?.querySelector('meta[name="theme-color"]');
|
|
277
|
-
if (meta === null || meta === undefined)
|
|
278
|
-
return 0;
|
|
279
|
-
const content = meta.getAttribute('content');
|
|
280
|
-
if (content === null || !content.startsWith('#'))
|
|
281
|
-
return 0;
|
|
282
|
-
const hex = content.slice(1);
|
|
283
|
-
if (!/^(?:[\da-f]{3}|[\da-f]{6})$/i.test(hex))
|
|
284
|
-
return 0;
|
|
285
|
-
const expandedHex = hex.length === 3 ? [...hex].map((digit) => digit + digit).join('') : hex;
|
|
286
|
-
const rgb = parseInt(expandedHex, 16);
|
|
287
|
-
// Reconstruct as 0xRRGGBBFF (alpha fully opaque since web drops alpha).
|
|
288
|
-
return ((rgb << 8) | 0xff) >>> 0;
|
|
289
|
-
}
|
|
290
279
|
//# sourceMappingURL=statusbar.js.map
|
package/dist/statusbar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statusbar.js","sourceRoot":"","sources":["../src/statusbar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"statusbar.js","sourceRoot":"","sources":["../src/statusbar.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/statusbar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-edge.1908.751021c",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/signals": "0.
|
|
42
|
-
"@flighthq/types": "0.
|
|
41
|
+
"@flighthq/signals": "0.4.0-edge.1908.751021c",
|
|
42
|
+
"@flighthq/types": "0.4.0-edge.1908.751021c"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.3.0"
|
package/src/statusbar.test.ts
CHANGED
|
@@ -6,15 +6,19 @@ import {
|
|
|
6
6
|
clearStatusBarStyleStack,
|
|
7
7
|
createStatusBar,
|
|
8
8
|
createStatusBarInfo,
|
|
9
|
-
createWebStatusBarBackend,
|
|
10
9
|
detachStatusBar,
|
|
11
10
|
disposeStatusBar,
|
|
11
|
+
explainStatusBarBackend,
|
|
12
12
|
getStatusBarBackend,
|
|
13
13
|
getStatusBarHeight,
|
|
14
14
|
getStatusBarInfo,
|
|
15
15
|
hasStatusBarStyleEntry,
|
|
16
|
+
installStatusBarHostBackend,
|
|
17
|
+
observeStatusBarHostResult,
|
|
18
|
+
packedRgbaToHexColor,
|
|
16
19
|
popStatusBarStyleEntry,
|
|
17
20
|
pushStatusBarStyleEntry,
|
|
21
|
+
resetStatusBarBackendForTest,
|
|
18
22
|
setStatusBarBackend,
|
|
19
23
|
setStatusBarColor,
|
|
20
24
|
setStatusBarOverlaysContent,
|
|
@@ -80,10 +84,8 @@ function fakeBackend(): StatusBarBackend & {
|
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
afterEach(() => {
|
|
83
|
-
// Empty the stack before dropping the backend, so the restore lands on the fake rather than on the
|
|
84
|
-
// web default that setStatusBarBackend(null) falls back to.
|
|
85
87
|
clearStatusBarStyleStack();
|
|
86
|
-
|
|
88
|
+
resetStatusBarBackendForTest();
|
|
87
89
|
});
|
|
88
90
|
|
|
89
91
|
describe('attachStatusBar', () => {
|
|
@@ -208,72 +210,6 @@ describe('createStatusBarInfo', () => {
|
|
|
208
210
|
});
|
|
209
211
|
});
|
|
210
212
|
|
|
211
|
-
describe('createWebStatusBarBackend', () => {
|
|
212
|
-
it('upserts a single theme-color meta with #rrggbb from the top 24 bits', () => {
|
|
213
|
-
document.head.querySelectorAll('meta[name="theme-color"]').forEach((m) => m.remove());
|
|
214
|
-
const backend = createWebStatusBarBackend();
|
|
215
|
-
backend.setBackgroundColor(0x11223344);
|
|
216
|
-
backend.setBackgroundColor(0xaabbccff);
|
|
217
|
-
const metas = document.head.querySelectorAll('meta[name="theme-color"]');
|
|
218
|
-
expect(metas.length).toBe(1);
|
|
219
|
-
expect(metas[0].getAttribute('content')).toBe('#aabbcc');
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('no-ops style/visible/overlay/subscribe without throwing', () => {
|
|
223
|
-
const backend = createWebStatusBarBackend();
|
|
224
|
-
expect(() => {
|
|
225
|
-
backend.setStyle('light');
|
|
226
|
-
backend.setVisible(false, 'slide');
|
|
227
|
-
backend.setOverlaysContent(true);
|
|
228
|
-
const unsub = backend.subscribe(() => {});
|
|
229
|
-
unsub();
|
|
230
|
-
}).not.toThrow();
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
it('getInfo returns -1 height and defaults when no theme-color meta', () => {
|
|
234
|
-
document.head.querySelectorAll('meta[name="theme-color"]').forEach((m) => m.remove());
|
|
235
|
-
const backend = createWebStatusBarBackend();
|
|
236
|
-
const info = createStatusBarInfo();
|
|
237
|
-
backend.getInfo(info);
|
|
238
|
-
expect(info.height).toBe(-1);
|
|
239
|
-
expect(info.visible).toBe(true);
|
|
240
|
-
expect(info.color).toBe(0);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('getInfo reads back a previously set theme-color meta', () => {
|
|
244
|
-
document.head.querySelectorAll('meta[name="theme-color"]').forEach((m) => m.remove());
|
|
245
|
-
const backend = createWebStatusBarBackend();
|
|
246
|
-
backend.setBackgroundColor(0xff000000); // red, no alpha
|
|
247
|
-
const info = createStatusBarInfo();
|
|
248
|
-
backend.getInfo(info);
|
|
249
|
-
// Color should be reconstructed as 0xff0000ff (alpha forced to 0xff on web read-back)
|
|
250
|
-
expect(info.color).toBe(0xff0000ff);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it('getInfo expands a short #rgb theme-color and rejects malformed hex', () => {
|
|
254
|
-
document.head.querySelectorAll('meta[name="theme-color"]').forEach((m) => m.remove());
|
|
255
|
-
const meta = document.createElement('meta');
|
|
256
|
-
meta.setAttribute('name', 'theme-color');
|
|
257
|
-
document.head.appendChild(meta);
|
|
258
|
-
const backend = createWebStatusBarBackend();
|
|
259
|
-
const info = createStatusBarInfo();
|
|
260
|
-
|
|
261
|
-
meta.setAttribute('content', '#aBc');
|
|
262
|
-
backend.getInfo(info);
|
|
263
|
-
expect(info.color).toBe(0xaabbccff);
|
|
264
|
-
|
|
265
|
-
meta.setAttribute('content', '#12xz56');
|
|
266
|
-
backend.getInfo(info);
|
|
267
|
-
expect(info.color).toBe(0);
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it('subscribe returns a no-op unsubscribe function', () => {
|
|
271
|
-
const backend = createWebStatusBarBackend();
|
|
272
|
-
const unsub = backend.subscribe(() => {});
|
|
273
|
-
expect(() => unsub()).not.toThrow();
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
|
|
277
213
|
describe('detachStatusBar', () => {
|
|
278
214
|
it('stops subscription and is safe to call when not attached', () => {
|
|
279
215
|
const backend = fakeBackend();
|
|
@@ -307,6 +243,34 @@ describe('disposeStatusBar', () => {
|
|
|
307
243
|
});
|
|
308
244
|
});
|
|
309
245
|
|
|
246
|
+
describe('explainStatusBarBackend', () => {
|
|
247
|
+
afterEach(() => resetStatusBarBackendForTest());
|
|
248
|
+
|
|
249
|
+
it('reports host-not-enabled when no backend is installed', () => {
|
|
250
|
+
resetStatusBarBackendForTest();
|
|
251
|
+
const explanation = explainStatusBarBackend();
|
|
252
|
+
expect(explanation.layer).toBe('host-not-enabled');
|
|
253
|
+
expect(explanation.conflict).toBe(false);
|
|
254
|
+
expect(explanation.viability).toBe('unobserved');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('reports custom layer when a custom backend is set', () => {
|
|
258
|
+
setStatusBarBackend(fakeBackend());
|
|
259
|
+
expect(explainStatusBarBackend().layer).toBe('custom');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('reports host layer when a host backend is installed', () => {
|
|
263
|
+
installStatusBarHostBackend(fakeBackend());
|
|
264
|
+
expect(explainStatusBarBackend().layer).toBe('host');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('reports conflict when two different host backends are installed', () => {
|
|
268
|
+
installStatusBarHostBackend(fakeBackend());
|
|
269
|
+
installStatusBarHostBackend(fakeBackend());
|
|
270
|
+
expect(explainStatusBarBackend().conflict).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
310
274
|
describe('getStatusBarBackend', () => {
|
|
311
275
|
it('falls back to a web backend', () => {
|
|
312
276
|
expect(getStatusBarBackend()).not.toBeNull();
|
|
@@ -319,6 +283,39 @@ describe('getStatusBarBackend', () => {
|
|
|
319
283
|
});
|
|
320
284
|
});
|
|
321
285
|
|
|
286
|
+
describe('getStatusBarBackend (sentinel)', () => {
|
|
287
|
+
it('no-ops style/visible/overlay/subscribe without throwing', () => {
|
|
288
|
+
const backend = getStatusBarBackend();
|
|
289
|
+
expect(() => {
|
|
290
|
+
backend.setStyle('light');
|
|
291
|
+
backend.setVisible(false, 'slide');
|
|
292
|
+
backend.setOverlaysContent(true);
|
|
293
|
+
const unsub = backend.subscribe(() => {});
|
|
294
|
+
unsub();
|
|
295
|
+
}).not.toThrow();
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('getInfo returns -1 height and defaults', () => {
|
|
299
|
+
const backend = getStatusBarBackend();
|
|
300
|
+
const info = createStatusBarInfo();
|
|
301
|
+
backend.getInfo(info);
|
|
302
|
+
expect(info.height).toBe(-1);
|
|
303
|
+
expect(info.visible).toBe(true);
|
|
304
|
+
expect(info.color).toBe(0);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('setBackgroundColor is a no-op', () => {
|
|
308
|
+
const backend = getStatusBarBackend();
|
|
309
|
+
expect(() => backend.setBackgroundColor(0xff0000ff)).not.toThrow();
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('subscribe returns a no-op unsubscribe function', () => {
|
|
313
|
+
const backend = getStatusBarBackend();
|
|
314
|
+
const unsub = backend.subscribe(() => {});
|
|
315
|
+
expect(() => unsub()).not.toThrow();
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
322
319
|
describe('getStatusBarHeight', () => {
|
|
323
320
|
it('returns the height from the active backend', () => {
|
|
324
321
|
const backend = fakeBackend();
|
|
@@ -387,6 +384,57 @@ describe('hasStatusBarStyleEntry', () => {
|
|
|
387
384
|
});
|
|
388
385
|
});
|
|
389
386
|
|
|
387
|
+
describe('installStatusBarHostBackend', () => {
|
|
388
|
+
afterEach(() => resetStatusBarBackendForTest());
|
|
389
|
+
|
|
390
|
+
it('installs a host backend that getStatusBarBackend returns', () => {
|
|
391
|
+
const backend = fakeBackend();
|
|
392
|
+
installStatusBarHostBackend(backend);
|
|
393
|
+
expect(getStatusBarBackend()).toBe(backend);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('is first-host-wins: a second different backend sets conflict', () => {
|
|
397
|
+
const first = fakeBackend();
|
|
398
|
+
const second = fakeBackend();
|
|
399
|
+
installStatusBarHostBackend(first);
|
|
400
|
+
installStatusBarHostBackend(second);
|
|
401
|
+
expect(getStatusBarBackend()).toBe(first);
|
|
402
|
+
expect(explainStatusBarBackend().conflict).toBe(true);
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
describe('observeStatusBarHostResult', () => {
|
|
407
|
+
afterEach(() => resetStatusBarBackendForTest());
|
|
408
|
+
|
|
409
|
+
it('records a successful observation', () => {
|
|
410
|
+
installStatusBarHostBackend(fakeBackend());
|
|
411
|
+
observeStatusBarHostResult('setBackgroundColor', true);
|
|
412
|
+
const explanation = explainStatusBarBackend();
|
|
413
|
+
expect(explanation.operation).toBe('setBackgroundColor');
|
|
414
|
+
expect(explanation.viability).toBe('available');
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('records a failed observation', () => {
|
|
418
|
+
installStatusBarHostBackend(fakeBackend());
|
|
419
|
+
observeStatusBarHostResult('setBackgroundColor', false);
|
|
420
|
+
expect(explainStatusBarBackend().viability).toBe('runtime-api-unavailable');
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
describe('packedRgbaToHexColor', () => {
|
|
425
|
+
it('converts a packed RGBA to a hex color string', () => {
|
|
426
|
+
expect(packedRgbaToHexColor(0xff0000ff)).toBe('#ff0000');
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('converts black', () => {
|
|
430
|
+
expect(packedRgbaToHexColor(0x000000ff)).toBe('#000000');
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('converts white', () => {
|
|
434
|
+
expect(packedRgbaToHexColor(0xffffffff)).toBe('#ffffff');
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
390
438
|
describe('popStatusBarStyleEntry', () => {
|
|
391
439
|
it('no-ops for unknown or invalid handles', () => {
|
|
392
440
|
expect(() => popStatusBarStyleEntry(-1)).not.toThrow();
|
|
@@ -500,6 +548,20 @@ describe('pushStatusBarStyleEntry', () => {
|
|
|
500
548
|
});
|
|
501
549
|
});
|
|
502
550
|
|
|
551
|
+
describe('resetStatusBarBackendForTest', () => {
|
|
552
|
+
it('clears all backend slots', () => {
|
|
553
|
+
const backend = fakeBackend();
|
|
554
|
+
setStatusBarBackend(backend);
|
|
555
|
+
installStatusBarHostBackend(fakeBackend());
|
|
556
|
+
observeStatusBarHostResult('setBackgroundColor', true);
|
|
557
|
+
resetStatusBarBackendForTest();
|
|
558
|
+
expect(getStatusBarBackend()).not.toBe(backend);
|
|
559
|
+
expect(explainStatusBarBackend().layer).toBe('host-not-enabled');
|
|
560
|
+
expect(explainStatusBarBackend().conflict).toBe(false);
|
|
561
|
+
expect(explainStatusBarBackend().viability).toBe('unobserved');
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
|
|
503
565
|
describe('setStatusBarBackend', () => {
|
|
504
566
|
it('clears back to the web fallback when passed null', () => {
|
|
505
567
|
setStatusBarBackend(fakeBackend());
|