@satinhq/kit 0.1.0-beta.3 → 0.1.0-beta.4
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/NOTICE +1 -1
- package/README.md +1 -2
- package/dist/acknowledgements/inventory.json +1 -1
- package/dist/actions/RowActions.d.ts +2 -2
- package/dist/actions/RowActions.js +91 -25
- package/dist/actions/fullSwipeContact.d.ts +73 -0
- package/dist/actions/fullSwipeContact.js +186 -0
- package/dist/actions/rowScrub.d.ts +7 -4
- package/dist/actions/rowScrub.js +39 -37
- package/dist/actions/types.d.ts +13 -7
- package/dist/app/InstallComponents.d.ts +4 -7
- package/dist/app/InstallComponents.js +7 -7
- package/dist/app/InstallationDiagnostics.d.ts +2 -1
- package/dist/app/InstallationDiagnostics.js +2 -1
- package/dist/app/appearance.d.ts +5 -3
- package/dist/app/appearance.js +5 -3
- package/dist/app/appearanceStore.d.ts +3 -2
- package/dist/app/buildInfo.d.ts +4 -4
- package/dist/app/buildInfo.js +2 -2
- package/dist/app/definition.d.ts +11 -3
- package/dist/app/definition.js +2 -0
- package/dist/app/head.d.ts +2 -1
- package/dist/app/head.js +13 -16
- package/dist/app/inlineCSP.d.ts +6 -0
- package/dist/app/inlineCSP.js +25 -0
- package/dist/app/install.d.ts +1 -0
- package/dist/app/install.js +5 -2
- package/dist/app/installCheck.js +32 -86
- package/dist/app/installContext.d.ts +10 -5
- package/dist/app/installContext.js +2 -0
- package/dist/app/installCustom.js +1 -0
- package/dist/app/installExperience.js +0 -60
- package/dist/app/installationFailure.d.ts +3 -2
- package/dist/app/installationFailure.js +1 -1
- package/dist/app/launchScreen.d.ts +6 -2
- package/dist/app/launchScreen.js +104 -1
- package/dist/app/launchScreenRuntime.d.ts +31 -4
- package/dist/app/launchScreenRuntime.js +150 -22
- package/dist/app/launchWatchdog.js +25 -65
- package/dist/app/platformScripts.js +11 -0
- package/dist/app/styles.d.ts +3 -0
- package/dist/app/styles.js +42 -0
- package/dist/app/viewportValue.d.ts +2 -1
- package/dist/app/vite.d.ts +4 -0
- package/dist/app/vite.js +22 -24
- package/dist/content/content.d.ts +35 -30
- package/dist/content/content.js +19 -16
- package/dist/content/layout.d.ts +10 -2
- package/dist/content/layout.js +4 -2
- package/dist/content/scaledMetric.d.ts +2 -1
- package/dist/content/scaledMetric.js +2 -1
- package/dist/controls/ColorPicker.d.ts +2 -4
- package/dist/controls/ColorPicker.js +2 -4
- package/dist/controls/DatePicker.d.ts +4 -4
- package/dist/controls/DatePicker.js +2 -2
- package/dist/controls/ProgressView.d.ts +4 -4
- package/dist/controls/ProgressView.js +1 -2
- package/dist/data/database.d.ts +9 -8
- package/dist/data/database.js +4 -4
- package/dist/docs/reference.md +982 -964
- package/dist/docs/tailwind.md +76 -0
- package/dist/docs/tokens.md +1 -1
- package/dist/gestures/GestureView.d.ts +3 -1
- package/dist/gestures/GestureView.js +2 -1
- package/dist/gestures/gesture.d.ts +22 -2
- package/dist/gestures/gesture.js +7 -2
- package/dist/glass/GlassEffect.d.ts +2 -1
- package/dist/glass/GlassEffect.js +2 -1
- package/dist/glass/GlassPresentation.d.ts +1 -0
- package/dist/glass/GlassPresentation.js +21 -4
- package/dist/glass/TabBar.js +23 -1
- package/dist/glass/errorAlert.js +2 -1
- package/dist/glass/errors.d.ts +3 -1
- package/dist/glass/fallback/runtime.d.ts +1 -0
- package/dist/glass/fallback/runtime.js +8 -1
- package/dist/glass/liquidContext.d.ts +2 -0
- package/dist/glass/menuPresenter.d.ts +2 -0
- package/dist/glass/regions.d.ts +2 -1
- package/dist/glass/renderSpecs.d.ts +1 -0
- package/dist/glass/renderSpecs.js +1 -0
- package/dist/glass/webgpu/controlRim.d.ts +29 -0
- package/dist/glass/webgpu/controlRim.js +68 -0
- package/dist/glass/webgpu/passes.d.ts +2 -2
- package/dist/glass/webgpu/production.d.ts +1 -0
- package/dist/glass/webgpu/production.js +27 -1
- package/dist/glass/webgpu/rasterUniforms.js +9 -0
- package/dist/glass/webgpu/shaders.d.ts +2 -2
- package/dist/glass/webgpu/shaders.js +5 -1
- package/dist/haptics/SensoryButton.d.ts +4 -4
- package/dist/haptics/SensoryButton.js +3 -3
- package/dist/image/Image.d.ts +6 -3
- package/dist/image/Image.js +4 -3
- package/dist/image/asset.d.ts +2 -1
- package/dist/keyboard/adapter.d.ts +3 -4
- package/dist/keyboard/geometry.d.ts +1 -1
- package/dist/list-form/ListForm.d.ts +8 -7
- package/dist/list-form/ListForm.js +2 -2
- package/dist/list-form/editing.d.ts +5 -6
- package/dist/list-form/editing.js +4 -5
- package/dist/list-form/offsets.d.ts +2 -2
- package/dist/list-form/offsets.js +2 -2
- package/dist/media/react.d.ts +2 -1
- package/dist/media/react.js +2 -1
- package/dist/media/types.d.ts +6 -3
- package/dist/motion/TransitionView.d.ts +4 -2
- package/dist/motion/TransitionView.js +3 -2
- package/dist/motion/animationValue.d.ts +1 -1
- package/dist/motion/matchedGeometry.d.ts +6 -5
- package/dist/motion/matchedGeometry.js +2 -1
- package/dist/motion/transition.d.ts +4 -1
- package/dist/motion/transition.js +2 -0
- package/dist/navigation/DetailList.d.ts +1 -1
- package/dist/navigation/DetailList.js +1 -1
- package/dist/navigation/Sidebar.d.ts +3 -1
- package/dist/navigation/Sidebar.js +1 -1
- package/dist/navigation/SidebarSymbol.d.ts +2 -1
- package/dist/navigation/SidebarSymbol.js +2 -1
- package/dist/navigation/navigationContext.d.ts +2 -1
- package/dist/navigation/navigationContext.js +2 -1
- package/dist/navigation/splitContext.d.ts +2 -1
- package/dist/navigation/splitContext.js +2 -1
- package/dist/navigation/toolbarMinimization.d.ts +4 -3
- package/dist/navigation/types.d.ts +7 -5
- package/dist/presentation/Presentation.d.ts +8 -7
- package/dist/presentation/Presentation.js +3 -2
- package/dist/presentation/model.d.ts +2 -1
- package/dist/press/Pressable.d.ts +5 -1
- package/dist/press/Pressable.js +2 -0
- package/dist/press/stateMachine.d.ts +1 -1
- package/dist/public/Label.d.ts +2 -1
- package/dist/public/Label.js +2 -1
- package/dist/public/Screen.d.ts +4 -6
- package/dist/public/actions.d.ts +2 -1
- package/dist/public/actions.js +2 -1
- package/dist/public/buttonBorderShape.d.ts +2 -1
- package/dist/public/colors.d.ts +7 -4
- package/dist/public/colors.js +3 -2
- package/dist/public/controlStyle.d.ts +17 -14
- package/dist/public/controls.d.ts +27 -26
- package/dist/public/controls.js +20 -19
- package/dist/public/deviceActions.d.ts +6 -4
- package/dist/public/deviceActions.js +4 -2
- package/dist/public/environment.d.ts +16 -13
- package/dist/public/environment.js +11 -9
- package/dist/public/filePickers.d.ts +6 -4
- package/dist/public/filePickers.js +3 -2
- package/dist/public/glass.d.ts +6 -3
- package/dist/public/glass.js +2 -1
- package/dist/public/glassValue.d.ts +3 -4
- package/dist/public/glassValue.js +3 -4
- package/dist/public/keyboard.d.ts +4 -1
- package/dist/public/keyboard.js +2 -1
- package/dist/public/navigationTransition.d.ts +5 -5
- package/dist/public/navigationTransition.js +2 -2
- package/dist/public/presentation.d.ts +8 -7
- package/dist/public/presentation.js +5 -5
- package/dist/public/runtime.d.ts +9 -8
- package/dist/public/runtime.js +7 -7
- package/dist/public/scroll.d.ts +6 -3
- package/dist/public/scroll.js +3 -1
- package/dist/public/structure.d.ts +2 -2
- package/dist/public/toolbar.d.ts +15 -11
- package/dist/public/toolbar.js +12 -7
- package/dist/reachability/model.d.ts +4 -3
- package/dist/reachability/react.d.ts +4 -1
- package/dist/reachability/react.js +2 -1
- package/dist/root/SatinRoot.d.ts +3 -3
- package/dist/root/SatinRoot.js +12 -36
- package/dist/root/mountSatin.d.ts +1 -1
- package/dist/root/mountSatin.js +26 -35
- package/dist/root/runtimeContext.d.ts +2 -1
- package/dist/root/runtimeContext.js +2 -1
- package/dist/safe-area/Overlay.d.ts +3 -2
- package/dist/safe-area/Overlay.js +2 -1
- package/dist/safe-area/SafeAreaInset.d.ts +11 -7
- package/dist/safe-area/SafeAreaInset.js +7 -6
- package/dist/safe-area/context.d.ts +3 -3
- package/dist/safe-area/context.js +1 -1
- package/dist/safe-area/displayCorners.d.ts +4 -2
- package/dist/safe-area/displayCorners.js +4 -2
- package/dist/safe-area/modifiers.d.ts +14 -10
- package/dist/safe-area/modifiers.js +8 -4
- package/dist/scroll/ScrollSurface.js +5 -1
- package/dist/scroll/ScrollTarget.d.ts +1 -1
- package/dist/scroll/ScrollTarget.js +1 -1
- package/dist/scroll/edgePolicy.d.ts +2 -2
- package/dist/scroll/position.d.ts +5 -3
- package/dist/scroll/types.d.ts +1 -1
- package/dist/search/PadSearchDrawer.d.ts +7 -0
- package/dist/search/PadSearchDrawer.js +8 -0
- package/dist/search/PadSearchPresentationContext.d.ts +6 -0
- package/dist/search/PadSearchPresentationContext.js +4 -0
- package/dist/search/SearchDrawer.d.ts +1 -1
- package/dist/search/SearchDrawer.js +6 -1
- package/dist/search/SearchSuggestionsPopover.d.ts +6 -0
- package/dist/search/SearchSuggestionsPopover.js +42 -0
- package/dist/search/SearchToolbarField.d.ts +2 -1
- package/dist/search/SearchToolbarField.js +28 -7
- package/dist/search/padSearchBarMotion.d.ts +69 -0
- package/dist/search/padSearchBarMotion.js +73 -0
- package/dist/search/padSearchFieldSamples.json +491 -0
- package/dist/search/searchPlacement.d.ts +3 -0
- package/dist/search/searchPlacement.js +7 -0
- package/dist/search/searchable.d.ts +14 -12
- package/dist/search/usePadSearchFieldMotion.d.ts +4 -0
- package/dist/search/usePadSearchFieldMotion.js +100 -0
- package/dist/search/useSearchPresentation.d.ts +2 -1
- package/dist/search/useSearchPresentation.js +23 -5
- package/dist/server.d.ts +4 -4
- package/dist/server.js +4 -4
- package/dist/shapes/corners.d.ts +3 -3
- package/dist/shapes/corners.js +1 -2
- package/dist/styles.css +8289 -8244
- package/dist/sw/vite.d.ts +4 -0
- package/dist/sw/vite.js +2 -0
- package/dist/symbols/Symbol.d.ts +7 -5
- package/dist/symbols/Symbol.js +5 -3
- package/dist/symbols/catalogue.d.ts +1 -1
- package/dist/symbols/types.d.ts +6 -4
- package/dist/tabs/TabSection.d.ts +3 -2
- package/dist/tabs/TabSection.js +2 -1
- package/dist/tabs/TabView.js +54 -51
- package/dist/tasks/useTask.d.ts +5 -4
- package/dist/tasks/useTask.js +4 -3
- package/dist/testing.d.ts +3 -2
- package/dist/testing.js +3 -2
- package/dist/text-input/focusChain.d.ts +4 -3
- package/dist/text-input/focusChain.js +3 -2
- package/dist/text-input/kinds.d.ts +1 -1
- package/dist/web/WebView.d.ts +10 -3
- package/dist/web/WebView.js +3 -2
- package/dist/web/authentication.d.ts +12 -1
- package/dist/web/authentication.js +2 -1
- package/dist/web/openURL.d.ts +10 -4
- package/dist/web/openURL.js +4 -2
- package/dist/web/useWebAuthentication.d.ts +2 -1
- package/dist/web/useWebAuthentication.js +2 -1
- package/dist/zoom/Zoomable.d.ts +3 -3
- package/dist/zoom/Zoomable.js +2 -2
- package/package.json +1 -1
package/dist/app/installCheck.js
CHANGED
|
@@ -3,6 +3,7 @@ import { checkDeployment, } from './deployment.js';
|
|
|
3
3
|
export async function installPageCheck(expected, check, requestTimeoutMs = 4000,
|
|
4
4
|
// Called once the check passes; a custom install page loads the author's code here.
|
|
5
5
|
onPass) {
|
|
6
|
+
const environment = window.__SATIN_PRELAUNCH__;
|
|
6
7
|
const guide = document.getElementById('satin-install-guide');
|
|
7
8
|
const status = document.getElementById('satin-install-check');
|
|
8
9
|
const standalone = matchMedia('(display-mode: standalone)').matches ||
|
|
@@ -50,100 +51,45 @@ onPass) {
|
|
|
50
51
|
status.hidden = true;
|
|
51
52
|
status.style.display = 'none';
|
|
52
53
|
guide.hidden = false;
|
|
54
|
+
environment.recover();
|
|
53
55
|
onPass?.();
|
|
54
56
|
return;
|
|
55
57
|
}
|
|
56
58
|
guide.hidden = true;
|
|
57
|
-
status.hidden =
|
|
58
|
-
status.style.removeProperty('display');
|
|
59
|
-
status.replaceChildren();
|
|
60
|
-
status.setAttribute('role', 'alert');
|
|
61
|
-
status.dataset.error = 'true';
|
|
62
|
-
const style = document.createElement('style');
|
|
63
|
-
style.textContent = `
|
|
64
|
-
#satin-install-check[data-error] {
|
|
65
|
-
position: fixed;
|
|
66
|
-
inset: 0;
|
|
67
|
-
z-index: 20002;
|
|
68
|
-
display: grid;
|
|
69
|
-
place-items: center;
|
|
70
|
-
overflow: auto;
|
|
71
|
-
padding: 32px;
|
|
72
|
-
box-sizing: border-box;
|
|
73
|
-
background: #f2f2f7;
|
|
74
|
-
color: #1c1c1e;
|
|
75
|
-
color-scheme: light dark;
|
|
76
|
-
font: 17px/1.45 -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
77
|
-
text-align: center;
|
|
78
|
-
}
|
|
79
|
-
#satin-install-check button { font: inherit; border: 0; background: transparent; color: #007aff; min-height: 44px; cursor: pointer; }
|
|
80
|
-
#satin-install-check .install-error-content { width: min(100%, 560px); }
|
|
81
|
-
#satin-install-check h2 { font-size: 24px; margin: 0 0 12px; }
|
|
82
|
-
#satin-install-check p { opacity: 1; margin: 12px 0; }
|
|
83
|
-
#satin-install-check .install-error-detail {
|
|
84
|
-
font-size: 13px;
|
|
85
|
-
color: #6c6c70;
|
|
86
|
-
overflow-wrap: anywhere;
|
|
87
|
-
}
|
|
88
|
-
#satin-install-check ul { list-style: none; padding: 0; margin: 24px 0 0; }
|
|
89
|
-
#satin-install-check li { margin: 8px 0; font-size: 13px; overflow-wrap: anywhere; }
|
|
90
|
-
@media (prefers-color-scheme: dark) {
|
|
91
|
-
#satin-install-check[data-error] { background: #000; color: #fff; }
|
|
92
|
-
#satin-install-check .install-error-detail { color: #aeaeb2; }
|
|
93
|
-
}
|
|
94
|
-
`;
|
|
95
|
-
document.head.append(style);
|
|
96
|
-
const content = document.createElement('div');
|
|
97
|
-
content.className = 'install-error-content';
|
|
98
|
-
const title = document.createElement('h2');
|
|
59
|
+
status.hidden = true;
|
|
99
60
|
const unverified = !wrongBase && failures.length > 0 && failures.every(failure => failure.transient);
|
|
100
|
-
|
|
61
|
+
for (const failure of failures)
|
|
62
|
+
console.error('[Satin deployment]', failure.reason, failure.url, failure.fix);
|
|
63
|
+
const title = standalone
|
|
101
64
|
? 'Wrong Home Screen icon'
|
|
102
65
|
: unverified
|
|
103
66
|
? "Can't reach the app right now"
|
|
104
67
|
: 'This app is misconfigured';
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
68
|
+
const reason = standalone
|
|
69
|
+
? 'This icon opens the install page instead of the app. Reinstall from Safari.'
|
|
70
|
+
: unverified
|
|
71
|
+
? 'Check your connection and try again.'
|
|
72
|
+
: wrongBase
|
|
73
|
+
? `Built for ${expected.base} but served at ${servedBase}. Serve this build at ${expected.base}, or rebuild with Vite base ${servedBase}.`
|
|
74
|
+
: 'Required app files are missing or do not match this build. ' + failures[0].fix;
|
|
75
|
+
const detail = standalone
|
|
76
|
+
? location.href
|
|
77
|
+
: unverified
|
|
78
|
+
? undefined
|
|
79
|
+
: failures
|
|
80
|
+
.map(failure => {
|
|
81
|
+
const url = new URL(failure.url, location.href);
|
|
82
|
+
const address = url.origin === location.origin ? url.pathname + url.search : url.href;
|
|
83
|
+
return `${failure.check ?? 'Configuration'} → ${address} → ${failure.status ?? failure.reason}`;
|
|
84
|
+
})
|
|
85
|
+
.join('\n');
|
|
86
|
+
let retrying = false;
|
|
87
|
+
environment.error(reason, title, () => {
|
|
88
|
+
if (retrying)
|
|
89
|
+
return;
|
|
90
|
+
retrying = true;
|
|
91
|
+
void installPageCheck(expected, check, 30_000, onPass).finally(() => {
|
|
92
|
+
retrying = false;
|
|
129
93
|
});
|
|
130
|
-
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
explanation.textContent = wrongBase
|
|
134
|
-
? `Built for ${expected.base} but served at ${servedBase}.`
|
|
135
|
-
: 'Required app files are missing or do not match this build.';
|
|
136
|
-
action.textContent = wrongBase
|
|
137
|
-
? `Serve this build at ${expected.base}, or rebuild with Vite base ${servedBase}.`
|
|
138
|
-
: failures[0].fix;
|
|
139
|
-
const checks = document.createElement('ul');
|
|
140
|
-
checks.setAttribute('aria-label', 'Failed checks');
|
|
141
|
-
for (const failure of failures) {
|
|
142
|
-
const row = document.createElement('li');
|
|
143
|
-
const url = new URL(failure.url, location.href);
|
|
144
|
-
const address = url.origin === location.origin ? url.pathname + url.search : url.href;
|
|
145
|
-
row.textContent = `${failure.check ?? 'Configuration'} → ${address} → ${failure.status ?? failure.reason}`;
|
|
146
|
-
checks.append(row);
|
|
147
|
-
}
|
|
148
|
-
content.append(checks);
|
|
94
|
+
}, detail);
|
|
149
95
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a custom install page needs to know (public through `@satinhq/kit/install`). Every value is
|
|
3
|
-
* read from the browser as it is; nothing is inferred. In particular "installed" is only the
|
|
4
|
-
* standalone display mode: a Safari tab cannot tell whether the app is on the Home Screen.
|
|
5
|
-
*/
|
|
1
|
+
/** The device the install page is open on: `iphone`, `ipad` or `other`. */
|
|
6
2
|
export type InstallDevice = 'iphone' | 'ipad' | 'other';
|
|
3
|
+
/** The browser the install page is open in. `in-app` is a browser inside another app, which
|
|
4
|
+
* cannot add to the Home Screen. */
|
|
7
5
|
export type InstallBrowser = 'safari' | 'in-app' | 'other';
|
|
6
|
+
/** The app being installed: its name, icon, tint and install page address. */
|
|
8
7
|
export interface InstallApp {
|
|
9
8
|
readonly name: string;
|
|
10
9
|
readonly icon: string;
|
|
@@ -13,6 +12,9 @@ export interface InstallApp {
|
|
|
13
12
|
/** The absolute address of the install page, for a QR code or Copy Link. */
|
|
14
13
|
readonly installUrl: string;
|
|
15
14
|
}
|
|
15
|
+
/** What a custom install page knows about where it is open: device, browser, Safari version,
|
|
16
|
+
* standalone mode and the app. A Safari tab cannot tell whether the app is already on the Home
|
|
17
|
+
* Screen. */
|
|
16
18
|
export interface InstallContext {
|
|
17
19
|
readonly device: InstallDevice;
|
|
18
20
|
readonly browser: InstallBrowser;
|
|
@@ -22,6 +24,7 @@ export interface InstallContext {
|
|
|
22
24
|
readonly standalone: boolean;
|
|
23
25
|
readonly app: InstallApp;
|
|
24
26
|
}
|
|
27
|
+
/** Whether `copyInstallLink` copied the address, and the address itself. */
|
|
25
28
|
export interface CopyLinkResult {
|
|
26
29
|
readonly copied: boolean;
|
|
27
30
|
/** The address, so a failure can show it for the person to select. */
|
|
@@ -30,6 +33,8 @@ export interface CopyLinkResult {
|
|
|
30
33
|
export declare function classifyInstallDevice(userAgent: string, platform: string, maxTouchPoints: number): InstallDevice;
|
|
31
34
|
export declare function classifyInstallBrowser(userAgent: string): InstallBrowser;
|
|
32
35
|
export declare function safariVersion(userAgent: string): number | null;
|
|
36
|
+
/** Reads the install context from the browser. It throws outside the install page that
|
|
37
|
+
* `satinApp` builds. */
|
|
33
38
|
export declare function readInstallContext(): InstallContext;
|
|
34
39
|
/** Copies the install page's address. Never throws: a refusal is reported with the address. */
|
|
35
40
|
export declare function copyInstallLink(): Promise<CopyLinkResult>;
|
|
@@ -20,6 +20,8 @@ function readApp() {
|
|
|
20
20
|
installUrl: new URL(data.installRoute, location.href).href,
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
/** Reads the install context from the browser. It throws outside the install page that
|
|
24
|
+
* `satinApp` builds. */
|
|
23
25
|
export function readInstallContext() {
|
|
24
26
|
const { userAgent, platform, maxTouchPoints } = navigator;
|
|
25
27
|
const signals = classifyInstallSignals(userAgent, platform, maxTouchPoints);
|
|
@@ -18,6 +18,7 @@ export function installCustomMount(entry) {
|
|
|
18
18
|
script.type = 'module';
|
|
19
19
|
script.src = entry;
|
|
20
20
|
script.dataset.satinInstallAuthor = '';
|
|
21
|
+
script.onerror = () => window.__SATIN_PRELAUNCH__?.error('The install page failed to load. Please retry.');
|
|
21
22
|
document.body.append(script);
|
|
22
23
|
}
|
|
23
24
|
export function customInstallPage(input) {
|
|
@@ -217,66 +217,6 @@ html:not([data-ready]) [data-js], html[data-ready] [data-nojs], [data-copy-faile
|
|
|
217
217
|
}
|
|
218
218
|
html[data-env="gate"] .ix { max-width: 440px; margin: 0 auto; }
|
|
219
219
|
|
|
220
|
-
/*
|
|
221
|
-
* The deployment check's failure report keeps its words and gets the page's voice. The
|
|
222
|
-
* check injects its own styles later, so each rule here starts at the body element to outrank them.
|
|
223
|
-
*/
|
|
224
|
-
body:has(#satin-install-check[data-error]) :is(.ix-hero, .ix-pointer) { visibility: hidden; }
|
|
225
|
-
/* Nested, so the long selector is written once. */
|
|
226
|
-
body #satin-install-check {
|
|
227
|
-
&[data-error] {
|
|
228
|
-
padding: 32px 24px;
|
|
229
|
-
background: var(--bg);
|
|
230
|
-
color: var(--label);
|
|
231
|
-
font: inherit;
|
|
232
|
-
}
|
|
233
|
-
& .install-error-content::before {
|
|
234
|
-
content: "!";
|
|
235
|
-
display: grid;
|
|
236
|
-
place-items: center;
|
|
237
|
-
width: 44px;
|
|
238
|
-
height: 44px;
|
|
239
|
-
margin: 0 auto 16px;
|
|
240
|
-
border-radius: 50%;
|
|
241
|
-
background: #ff3b30;
|
|
242
|
-
color: #fff;
|
|
243
|
-
font-size: 26px;
|
|
244
|
-
font-weight: 700;
|
|
245
|
-
line-height: 1;
|
|
246
|
-
}
|
|
247
|
-
& .install-error-content:has(button)::before {
|
|
248
|
-
content: "?";
|
|
249
|
-
background: var(--third);
|
|
250
|
-
}
|
|
251
|
-
& h2 { font-size: 1.294rem; margin: 0 0 8px; }
|
|
252
|
-
& p { margin: 6px 0; color: var(--second); }
|
|
253
|
-
& p:nth-of-type(2) { color: var(--label); }
|
|
254
|
-
& button {
|
|
255
|
-
min-height: 50px;
|
|
256
|
-
margin-top: 20px;
|
|
257
|
-
padding: 0 36px;
|
|
258
|
-
border-radius: 25px;
|
|
259
|
-
background: var(--tint);
|
|
260
|
-
color: var(--on-tint);
|
|
261
|
-
font-weight: 600;
|
|
262
|
-
}
|
|
263
|
-
& ul {
|
|
264
|
-
margin-top: 24px;
|
|
265
|
-
padding: 4px 16px;
|
|
266
|
-
border-radius: 20px;
|
|
267
|
-
background: var(--fill);
|
|
268
|
-
text-align: left;
|
|
269
|
-
}
|
|
270
|
-
& li {
|
|
271
|
-
margin: 0;
|
|
272
|
-
padding: 10px 0;
|
|
273
|
-
color: var(--label);
|
|
274
|
-
font: 0.706rem/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
275
|
-
}
|
|
276
|
-
& li + li { border-top: 1px solid var(--hair); }
|
|
277
|
-
& .install-error-detail { color: var(--second); }
|
|
278
|
-
}
|
|
279
|
-
|
|
280
220
|
@media (prefers-reduced-motion: reduce) {
|
|
281
221
|
*, *::before, *::after { animation: none !important; transition: none !important; }
|
|
282
222
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** An installation failure recorded before the app launched: the build, the URL, the reason and
|
|
2
|
+
* whether the network failed. */
|
|
2
3
|
export interface InstallationFailure {
|
|
3
4
|
buildId: string;
|
|
4
5
|
url: string;
|
|
@@ -6,7 +7,7 @@ export interface InstallationFailure {
|
|
|
6
7
|
networkFailure: boolean;
|
|
7
8
|
recordedAt?: number;
|
|
8
9
|
}
|
|
9
|
-
/** Reads the recorded installation failure for
|
|
10
|
+
/** Reads the last recorded installation failure for an app scope, or null when there is none. */
|
|
10
11
|
export declare function readInstallationFailure(scope: string): InstallationFailure | null;
|
|
11
12
|
export declare function readInstallationSuccess(scope: string): {
|
|
12
13
|
buildId: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Reads the recorded installation failure for
|
|
1
|
+
/** Reads the last recorded installation failure for an app scope, or null when there is none. */
|
|
2
2
|
export function readInstallationFailure(scope) {
|
|
3
3
|
try {
|
|
4
4
|
const value = JSON.parse(localStorage.getItem('satin-install-failure:' + scope) ?? 'null');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AppDefinition } from './definition.js';
|
|
2
|
-
/**
|
|
2
|
+
/** The launch screen's icon and optional label. The inline environment paints it before application JavaScript loads, so
|
|
3
|
+
* both must be plain strings. */
|
|
3
4
|
export interface LaunchScreenSlot {
|
|
4
5
|
readonly icon?: string;
|
|
5
6
|
readonly label?: string;
|
|
@@ -7,10 +8,13 @@ export interface LaunchScreenSlot {
|
|
|
7
8
|
export declare function launchScreenMarkup(app: AppDefinition): string;
|
|
8
9
|
export declare const launchScreenLayer = 20000;
|
|
9
10
|
export declare const launchErrorLayer: number;
|
|
10
|
-
export declare const launchScreenCSS = "#satin-launch-screen{position:fixed
|
|
11
|
+
export declare const launchScreenCSS = "\n#satin-launch-screen {\n position:fixed;\n inset:calc(-1 * var(--satin-launch-excluded-top, 0px)) 0 0;\n z-index:20000;\n display:flex;\n flex-direction:column;\n align-items:center;\n justify-content:center;\n background:var(--satin-launch-background);\n color:var(--satin-launch-ink);\n font:17px system-ui;\n pointer-events:none\n}\n#satin-launch-screen[hidden],#satin-launch-progress[hidden] {\n display:none\n}\n.satin-launch-icon {\n position:relative;\n width:108px;\n height:108px;\n display:grid;\n place-items:center\n}\n#satin-launch-screen>p {\n position:absolute;\n top:calc(50% + 54px);\n margin:16px 0 0\n}\n.satin-launch-icon img {\n border-radius:15px\n}\n#satin-launch-progress {\n position:absolute;\n inset:0;\n width:108px;\n height:108px;\n transform:rotate(-90deg)\n}\n";
|
|
11
12
|
export interface DownloadProgress {
|
|
12
13
|
/** Monotonic response-header progress, independent of downloaded bytes. */
|
|
13
14
|
activity?: number;
|
|
14
15
|
readonly loaded: number;
|
|
15
16
|
readonly total: number;
|
|
16
17
|
}
|
|
18
|
+
/** Closed-shadow styles. Inner !important declarations protect the host itself
|
|
19
|
+
* from author resets; descendants never participate in the app cascade. */
|
|
20
|
+
export declare const prelaunchCSS = "\n:host {\n all:initial !important;\n display:block !important;\n position:fixed !important;\n inset:0 !important;\n z-index:20004 !important;\n opacity:1 !important;\n visibility:visible !important;\n transform:none !important;\n filter:none !important;\n clip-path:none !important;\n overflow:visible !important;\n pointer-events:none !important;\n contain:none !important;\n isolation:isolate !important;\n color-scheme:light dark !important\n}\n* {\n box-sizing:border-box\n}\n [hidden] {\n display:none !important\n}\n\n#satin-launch-screen {\n position:fixed;\n inset:calc(-1 * var(--satin-launch-excluded-top, 0px)) 0 0;\n z-index:20000;\n display:flex;\n flex-direction:column;\n align-items:center;\n justify-content:center;\n background:var(--satin-launch-background);\n color:var(--satin-launch-ink);\n font:17px system-ui;\n pointer-events:none\n}\n#satin-launch-screen[hidden],#satin-launch-progress[hidden] {\n display:none\n}\n.satin-launch-icon {\n position:relative;\n width:108px;\n height:108px;\n display:grid;\n place-items:center\n}\n#satin-launch-screen>p {\n position:absolute;\n top:calc(50% + 54px);\n margin:16px 0 0\n}\n.satin-launch-icon img {\n border-radius:15px\n}\n#satin-launch-progress {\n position:absolute;\n inset:0;\n width:108px;\n height:108px;\n transform:rotate(-90deg)\n}\n#satin-launch-error {\n position:fixed;\n inset:0;\n display:flex;\n flex-direction:column;\n align-items:center;\n justify-content:center;\n padding:32px;\n background:var(--satin-launch-background);\n color:var(--satin-launch-ink);\n font:17px/1.45 system-ui;\n text-align:center;\n pointer-events:auto;\n overflow:auto\n}\n#satin-launch-error h1 {\n font-size:24px;\n margin:0 0 12px\n}\n#satin-launch-error p {\n max-width:420px;\n margin:17px 0;\n white-space:pre-wrap;\n overflow-wrap:anywhere\n}\n#satin-launch-error .detail {\n font-size:13px;\n opacity:.65\n}\n#satin-launch-error button {\n font:600 17px system-ui;\n color:#007aff;\n background:transparent;\n border:0;\n padding:16px 32px;\n min-height:44px\n}\n";
|
package/dist/app/launchScreen.js
CHANGED
|
@@ -11,4 +11,107 @@ export function launchScreenMarkup(app) {
|
|
|
11
11
|
// ordering away from the maximum CSS integer boundary.
|
|
12
12
|
export const launchScreenLayer = 20_000;
|
|
13
13
|
export const launchErrorLayer = launchScreenLayer + 1;
|
|
14
|
-
export const launchScreenCSS =
|
|
14
|
+
export const launchScreenCSS = `
|
|
15
|
+
#satin-launch-screen {
|
|
16
|
+
position:fixed;
|
|
17
|
+
inset:calc(-1 * var(--satin-launch-excluded-top, 0px)) 0 0;
|
|
18
|
+
z-index:${launchScreenLayer};
|
|
19
|
+
display:flex;
|
|
20
|
+
flex-direction:column;
|
|
21
|
+
align-items:center;
|
|
22
|
+
justify-content:center;
|
|
23
|
+
background:var(--satin-launch-background);
|
|
24
|
+
color:var(--satin-launch-ink);
|
|
25
|
+
font:17px system-ui;
|
|
26
|
+
pointer-events:none
|
|
27
|
+
}
|
|
28
|
+
#satin-launch-screen[hidden],#satin-launch-progress[hidden] {
|
|
29
|
+
display:none
|
|
30
|
+
}
|
|
31
|
+
.satin-launch-icon {
|
|
32
|
+
position:relative;
|
|
33
|
+
width:108px;
|
|
34
|
+
height:108px;
|
|
35
|
+
display:grid;
|
|
36
|
+
place-items:center
|
|
37
|
+
}
|
|
38
|
+
#satin-launch-screen>p {
|
|
39
|
+
position:absolute;
|
|
40
|
+
top:calc(50% + 54px);
|
|
41
|
+
margin:16px 0 0
|
|
42
|
+
}
|
|
43
|
+
.satin-launch-icon img {
|
|
44
|
+
border-radius:15px
|
|
45
|
+
}
|
|
46
|
+
#satin-launch-progress {
|
|
47
|
+
position:absolute;
|
|
48
|
+
inset:0;
|
|
49
|
+
width:108px;
|
|
50
|
+
height:108px;
|
|
51
|
+
transform:rotate(-90deg)
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
/** Closed-shadow styles. Inner !important declarations protect the host itself
|
|
55
|
+
* from author resets; descendants never participate in the app cascade. */
|
|
56
|
+
export const prelaunchCSS = `
|
|
57
|
+
:host {
|
|
58
|
+
all:initial !important;
|
|
59
|
+
display:block !important;
|
|
60
|
+
position:fixed !important;
|
|
61
|
+
inset:0 !important;
|
|
62
|
+
z-index:20004 !important;
|
|
63
|
+
opacity:1 !important;
|
|
64
|
+
visibility:visible !important;
|
|
65
|
+
transform:none !important;
|
|
66
|
+
filter:none !important;
|
|
67
|
+
clip-path:none !important;
|
|
68
|
+
overflow:visible !important;
|
|
69
|
+
pointer-events:none !important;
|
|
70
|
+
contain:none !important;
|
|
71
|
+
isolation:isolate !important;
|
|
72
|
+
color-scheme:light dark !important
|
|
73
|
+
}
|
|
74
|
+
* {
|
|
75
|
+
box-sizing:border-box
|
|
76
|
+
}
|
|
77
|
+
[hidden] {
|
|
78
|
+
display:none !important
|
|
79
|
+
}
|
|
80
|
+
${launchScreenCSS}#satin-launch-error {
|
|
81
|
+
position:fixed;
|
|
82
|
+
inset:0;
|
|
83
|
+
display:flex;
|
|
84
|
+
flex-direction:column;
|
|
85
|
+
align-items:center;
|
|
86
|
+
justify-content:center;
|
|
87
|
+
padding:32px;
|
|
88
|
+
background:var(--satin-launch-background);
|
|
89
|
+
color:var(--satin-launch-ink);
|
|
90
|
+
font:17px/1.45 system-ui;
|
|
91
|
+
text-align:center;
|
|
92
|
+
pointer-events:auto;
|
|
93
|
+
overflow:auto
|
|
94
|
+
}
|
|
95
|
+
#satin-launch-error h1 {
|
|
96
|
+
font-size:24px;
|
|
97
|
+
margin:0 0 12px
|
|
98
|
+
}
|
|
99
|
+
#satin-launch-error p {
|
|
100
|
+
max-width:420px;
|
|
101
|
+
margin:17px 0;
|
|
102
|
+
white-space:pre-wrap;
|
|
103
|
+
overflow-wrap:anywhere
|
|
104
|
+
}
|
|
105
|
+
#satin-launch-error .detail {
|
|
106
|
+
font-size:13px;
|
|
107
|
+
opacity:.65
|
|
108
|
+
}
|
|
109
|
+
#satin-launch-error button {
|
|
110
|
+
font:600 17px system-ui;
|
|
111
|
+
color:#007aff;
|
|
112
|
+
background:transparent;
|
|
113
|
+
border:0;
|
|
114
|
+
padding:16px 32px;
|
|
115
|
+
min-height:44px
|
|
116
|
+
}
|
|
117
|
+
`;
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import type { DownloadProgress } from './launchScreen.js';
|
|
2
|
-
interface LaunchScreenController {
|
|
2
|
+
export interface LaunchScreenController {
|
|
3
|
+
readonly version: 1;
|
|
4
|
+
stylesReady(): Promise<void>;
|
|
5
|
+
error(reason: string, title?: string, retry?: () => void, detail?: string): void;
|
|
6
|
+
recover(): void;
|
|
7
|
+
appearance(background: string, ink: string): void;
|
|
8
|
+
snapshot(): {
|
|
9
|
+
version: 1;
|
|
10
|
+
state: string;
|
|
11
|
+
error: string;
|
|
12
|
+
coverVisible: boolean;
|
|
13
|
+
ringVisible: boolean;
|
|
14
|
+
label: string | null;
|
|
15
|
+
offset: string;
|
|
16
|
+
box: number[];
|
|
17
|
+
background: string;
|
|
18
|
+
};
|
|
3
19
|
progress(progress: DownloadProgress | null): void;
|
|
4
20
|
updated(start?: 0 | 100): Promise<boolean>;
|
|
5
21
|
complete(): Promise<boolean>;
|
|
@@ -7,13 +23,24 @@ interface LaunchScreenController {
|
|
|
7
23
|
fail(onRetired: () => void): void;
|
|
8
24
|
restore(): void;
|
|
9
25
|
}
|
|
10
|
-
export
|
|
26
|
+
export interface PrelaunchOptions {
|
|
27
|
+
readonly markup: string;
|
|
28
|
+
readonly css: string;
|
|
29
|
+
readonly scope: string;
|
|
30
|
+
readonly background: string;
|
|
31
|
+
readonly darkBackground: string;
|
|
32
|
+
readonly darkInk: string;
|
|
33
|
+
readonly nonce?: string;
|
|
34
|
+
readonly cover?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare function installLaunchScreenRuntime(options: PrelaunchOptions): LaunchScreenController;
|
|
37
|
+
export declare function prelaunchController(): LaunchScreenController;
|
|
38
|
+
export declare function showLaunchFailure(reason: string, title?: string): void;
|
|
11
39
|
export declare function setLaunchScreen(visible: boolean): void;
|
|
12
40
|
export declare function setLaunchProgress(progress: DownloadProgress | null): void;
|
|
13
41
|
/** Complete a visible arc before a cold-update document replacement. */
|
|
14
42
|
export declare function completeLaunchProgress(): Promise<boolean>;
|
|
15
43
|
/** Confirm an applied update on its successor document before revealing the app. */
|
|
16
44
|
export declare function showAppliedUpdate(): Promise<boolean>;
|
|
17
|
-
/**
|
|
45
|
+
/** Runs immediately after the inline environment, before application modules. */
|
|
18
46
|
export declare function resumeAppliedUpdate(scope: string, buildId?: string): void;
|
|
19
|
-
export {};
|