@nativescript/vite 8.0.0-alpha.6 → 8.0.0-alpha.61
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/README.md +51 -11
- package/bin/cli.cjs +8 -14
- package/configuration/angular.d.ts +34 -1
- package/configuration/angular.js +390 -165
- package/configuration/angular.js.map +1 -1
- package/configuration/base.js +244 -53
- package/configuration/base.js.map +1 -1
- package/configuration/javascript.js +14 -93
- package/configuration/javascript.js.map +1 -1
- package/configuration/react.js +41 -73
- package/configuration/react.js.map +1 -1
- package/configuration/solid.js +51 -6
- package/configuration/solid.js.map +1 -1
- package/configuration/typescript.js +12 -93
- package/configuration/typescript.js.map +1 -1
- package/helpers/app-components.d.ts +2 -1
- package/helpers/app-components.js.map +1 -1
- package/helpers/app-css-state.d.ts +8 -0
- package/helpers/app-css-state.js +8 -0
- package/helpers/app-css-state.js.map +1 -0
- package/helpers/bundler-context.d.ts +11 -0
- package/helpers/bundler-context.js +71 -0
- package/helpers/bundler-context.js.map +1 -0
- package/helpers/cli-flags.d.ts +12 -0
- package/helpers/cli-flags.js +34 -0
- package/helpers/cli-flags.js.map +1 -1
- package/helpers/css-platform-plugin.d.ts +14 -0
- package/helpers/css-platform-plugin.js +43 -25
- package/helpers/css-platform-plugin.js.map +1 -1
- package/helpers/dev-host.d.ts +360 -0
- package/helpers/dev-host.js +694 -0
- package/helpers/dev-host.js.map +1 -0
- package/helpers/dynamic-import-plugin.js +9 -4
- package/helpers/dynamic-import-plugin.js.map +1 -1
- package/helpers/esbuild-platform-resolver.js +4 -1
- package/helpers/esbuild-platform-resolver.js.map +1 -1
- package/helpers/external-configs.d.ts +10 -12
- package/helpers/external-configs.js +58 -35
- package/helpers/external-configs.js.map +1 -1
- package/helpers/global-defines.d.ts +100 -13
- package/helpers/global-defines.js +165 -28
- package/helpers/global-defines.js.map +1 -1
- package/helpers/hmr-scope.d.ts +26 -0
- package/helpers/hmr-scope.js +67 -0
- package/helpers/hmr-scope.js.map +1 -0
- package/helpers/init.js +0 -18
- package/helpers/init.js.map +1 -1
- package/helpers/logging.js +29 -1
- package/helpers/logging.js.map +1 -1
- package/helpers/main-entry.d.ts +4 -1
- package/helpers/main-entry.js +368 -53
- package/helpers/main-entry.js.map +1 -1
- package/helpers/nativeclass-esbuild-plugin.d.ts +2 -1
- package/helpers/nativeclass-esbuild-plugin.js +6 -1
- package/helpers/nativeclass-esbuild-plugin.js.map +1 -1
- package/helpers/nativeclass-transform.d.ts +13 -0
- package/helpers/nativeclass-transform.js +37 -7
- package/helpers/nativeclass-transform.js.map +1 -1
- package/helpers/nativeclass-transformer-plugin.d.ts +9 -2
- package/helpers/nativeclass-transformer-plugin.js +163 -15
- package/helpers/nativeclass-transformer-plugin.js.map +1 -1
- package/helpers/nativescript-package-resolver.js +10 -62
- package/helpers/nativescript-package-resolver.js.map +1 -1
- package/helpers/normalize-id.d.ts +42 -0
- package/helpers/normalize-id.js +60 -0
- package/helpers/normalize-id.js.map +1 -0
- package/helpers/ns-core-url.d.ts +29 -7
- package/helpers/ns-core-url.js +69 -12
- package/helpers/ns-core-url.js.map +1 -1
- package/helpers/optimize-deps.d.ts +16 -0
- package/helpers/optimize-deps.js +17 -0
- package/helpers/optimize-deps.js.map +1 -0
- package/helpers/package-platform-aliases.js +34 -49
- package/helpers/package-platform-aliases.js.map +1 -1
- package/helpers/platform-types.d.ts +2 -0
- package/helpers/platform-types.js +2 -0
- package/helpers/platform-types.js.map +1 -0
- package/helpers/postcss-platform-config.d.ts +17 -1
- package/helpers/postcss-platform-config.js +20 -37
- package/helpers/postcss-platform-config.js.map +1 -1
- package/helpers/project.d.ts +35 -0
- package/helpers/project.js +120 -2
- package/helpers/project.js.map +1 -1
- package/helpers/resolve-main-field-platform.d.ts +20 -0
- package/helpers/resolve-main-field-platform.js +49 -0
- package/helpers/resolve-main-field-platform.js.map +1 -0
- package/helpers/resolver.js +17 -2
- package/helpers/resolver.js.map +1 -1
- package/helpers/theme-core-plugins.js +1 -1
- package/helpers/theme-core-plugins.js.map +1 -1
- package/helpers/ts-config-paths.d.ts +32 -0
- package/helpers/ts-config-paths.js +156 -27
- package/helpers/ts-config-paths.js.map +1 -1
- package/helpers/typescript-check.d.ts +2 -1
- package/helpers/typescript-check.js +2 -2
- package/helpers/typescript-check.js.map +1 -1
- package/helpers/ui-registration.d.ts +21 -0
- package/helpers/ui-registration.js +156 -0
- package/helpers/ui-registration.js.map +1 -0
- package/helpers/utils.d.ts +9 -0
- package/helpers/utils.js +22 -2
- package/helpers/utils.js.map +1 -1
- package/helpers/vite-package-version.d.ts +7 -0
- package/helpers/vite-package-version.js +44 -0
- package/helpers/vite-package-version.js.map +1 -0
- package/helpers/workers.d.ts +48 -19
- package/helpers/workers.js +662 -13
- package/helpers/workers.js.map +1 -1
- package/hmr/client/css-handler.d.ts +2 -1
- package/hmr/client/css-handler.js +50 -26
- package/hmr/client/css-handler.js.map +1 -1
- package/hmr/client/css-update-overlay.d.ts +18 -0
- package/hmr/client/css-update-overlay.js +27 -0
- package/hmr/client/css-update-overlay.js.map +1 -0
- package/hmr/client/framework-client-strategy.d.ts +79 -0
- package/hmr/client/framework-client-strategy.js +19 -0
- package/hmr/client/framework-client-strategy.js.map +1 -0
- package/hmr/client/hmr-pending-overlay.d.ts +0 -14
- package/hmr/client/hmr-pending-overlay.js +14 -4
- package/hmr/client/hmr-pending-overlay.js.map +1 -1
- package/hmr/client/hot-context.d.ts +67 -0
- package/hmr/client/hot-context.js +284 -0
- package/hmr/client/hot-context.js.map +1 -0
- package/hmr/client/index.js +922 -273
- package/hmr/client/index.js.map +1 -1
- package/hmr/client/utils.d.ts +2 -1
- package/hmr/client/utils.js +111 -99
- package/hmr/client/utils.js.map +1 -1
- package/hmr/entry-runtime.d.ts +2 -1
- package/hmr/entry-runtime.js +279 -71
- package/hmr/entry-runtime.js.map +1 -1
- package/hmr/frameworks/angular/build/angular-linker.d.ts +12 -0
- package/hmr/frameworks/angular/build/angular-linker.js +109 -0
- package/hmr/frameworks/angular/build/angular-linker.js.map +1 -0
- package/hmr/frameworks/angular/build/inject-component-hmr-registration.d.ts +112 -0
- package/hmr/frameworks/angular/build/inject-component-hmr-registration.js +291 -0
- package/hmr/frameworks/angular/build/inject-component-hmr-registration.js.map +1 -0
- package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.d.ts +75 -0
- package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js +221 -0
- package/hmr/frameworks/angular/build/inject-hmr-vite-ignore.js.map +1 -0
- package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.js +1 -170
- package/hmr/frameworks/angular/build/inline-decorator-component-templates.js.map +1 -0
- package/hmr/frameworks/angular/build/js-lexer.d.ts +4 -0
- package/{helpers/angular/synthesize-decorator-ctor-parameters.js → hmr/frameworks/angular/build/js-lexer.js} +22 -96
- package/hmr/frameworks/angular/build/js-lexer.js.map +1 -0
- package/hmr/frameworks/angular/build/shared-linker.d.ts +39 -0
- package/hmr/frameworks/angular/build/shared-linker.js +128 -0
- package/hmr/frameworks/angular/build/shared-linker.js.map +1 -0
- package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js +88 -0
- package/hmr/frameworks/angular/build/synthesize-decorator-ctor-parameters.js.map +1 -0
- package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.js +1 -174
- package/hmr/frameworks/angular/build/synthesize-injectable-factories.js.map +1 -0
- package/{helpers/angular → hmr/frameworks/angular/build}/util.d.ts +1 -0
- package/hmr/frameworks/angular/build/util.js +155 -0
- package/hmr/frameworks/angular/build/util.js.map +1 -0
- package/hmr/frameworks/angular/client/index.js +542 -175
- package/hmr/frameworks/angular/client/index.js.map +1 -1
- package/hmr/frameworks/angular/client/strategy.d.ts +9 -0
- package/hmr/frameworks/angular/client/strategy.js +19 -0
- package/hmr/frameworks/angular/client/strategy.js.map +1 -0
- package/hmr/frameworks/angular/server/angular-root-component.d.ts +79 -0
- package/hmr/frameworks/angular/server/angular-root-component.js +149 -0
- package/hmr/frameworks/angular/server/angular-root-component.js.map +1 -0
- package/hmr/frameworks/angular/server/linker.js +1 -4
- package/hmr/frameworks/angular/server/linker.js.map +1 -1
- package/hmr/frameworks/angular/server/strategy.js +458 -12
- package/hmr/frameworks/angular/server/strategy.js.map +1 -1
- package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.js +2 -2
- package/hmr/frameworks/angular/server/websocket-angular-entry.js.map +1 -0
- package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.d.ts +14 -11
- package/hmr/{server → frameworks/angular/server}/websocket-angular-hot-update.js +108 -111
- package/hmr/frameworks/angular/server/websocket-angular-hot-update.js.map +1 -0
- package/hmr/frameworks/react/server/strategy.d.ts +2 -0
- package/hmr/frameworks/react/server/strategy.js +230 -0
- package/hmr/frameworks/react/server/strategy.js.map +1 -0
- package/hmr/frameworks/solid/build/solid-jsx-deps.d.ts +15 -0
- package/hmr/frameworks/solid/build/solid-jsx-deps.js +178 -0
- package/hmr/frameworks/solid/build/solid-jsx-deps.js.map +1 -0
- package/hmr/frameworks/solid/client/app-runtime.d.ts +68 -0
- package/hmr/frameworks/solid/client/app-runtime.js +246 -0
- package/hmr/frameworks/solid/client/app-runtime.js.map +1 -0
- package/hmr/frameworks/solid/server/strategy.js +291 -16
- package/hmr/frameworks/solid/server/strategy.js.map +1 -1
- package/hmr/frameworks/typescript/server/strategy.js +38 -14
- package/hmr/frameworks/typescript/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/client/dep-propagation.d.ts +44 -0
- package/hmr/frameworks/vue/client/dep-propagation.js +148 -0
- package/hmr/frameworks/vue/client/dep-propagation.js.map +1 -0
- package/hmr/frameworks/vue/client/index.d.ts +9 -0
- package/hmr/frameworks/vue/client/index.js +251 -247
- package/hmr/frameworks/vue/client/index.js.map +1 -1
- package/hmr/frameworks/vue/client/strategy.d.ts +33 -0
- package/hmr/frameworks/vue/client/strategy.js +157 -0
- package/hmr/frameworks/vue/client/strategy.js.map +1 -0
- package/hmr/frameworks/vue/client/vue-sfc-update-overlay.d.ts +49 -0
- package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js +142 -0
- package/hmr/frameworks/vue/client/vue-sfc-update-overlay.js.map +1 -0
- package/hmr/frameworks/vue/server/compiler.d.ts +3 -1
- package/hmr/frameworks/vue/server/compiler.js +3 -1
- package/hmr/frameworks/vue/server/compiler.js.map +1 -1
- package/hmr/frameworks/vue/server/sfc-route-assemble.d.ts +7 -0
- package/hmr/frameworks/vue/server/sfc-route-assemble.js +823 -0
- package/hmr/frameworks/vue/server/sfc-route-assemble.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-meta.d.ts +7 -0
- package/hmr/frameworks/vue/server/sfc-route-meta.js +80 -0
- package/hmr/frameworks/vue/server/sfc-route-meta.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-serve.d.ts +8 -0
- package/hmr/frameworks/vue/server/sfc-route-serve.js +462 -0
- package/hmr/frameworks/vue/server/sfc-route-serve.js.map +1 -0
- package/hmr/frameworks/vue/server/sfc-route-shared.d.ts +45 -0
- package/hmr/frameworks/vue/server/sfc-route-shared.js +105 -0
- package/hmr/frameworks/vue/server/sfc-route-shared.js.map +1 -0
- package/hmr/frameworks/vue/server/strategy.d.ts +35 -0
- package/hmr/frameworks/vue/server/strategy.js +286 -7
- package/hmr/frameworks/vue/server/strategy.js.map +1 -1
- package/hmr/frameworks/vue/server/websocket-sfc.d.ts +15 -0
- package/hmr/frameworks/vue/server/websocket-sfc.js +20 -0
- package/hmr/frameworks/vue/server/websocket-sfc.js.map +1 -0
- package/hmr/helpers/ast-normalizer.d.ts +3 -1
- package/hmr/helpers/ast-normalizer.js +77 -10
- package/hmr/helpers/ast-normalizer.js.map +1 -1
- package/hmr/helpers/cjs-named-exports.d.ts +23 -0
- package/hmr/helpers/cjs-named-exports.js +152 -0
- package/hmr/helpers/cjs-named-exports.js.map +1 -0
- package/hmr/helpers/package-exports.d.ts +16 -0
- package/hmr/helpers/package-exports.js +396 -0
- package/hmr/helpers/package-exports.js.map +1 -0
- package/hmr/helpers/vendor-rewrite.d.ts +1 -1
- package/hmr/helpers/vendor-rewrite.js +5 -3
- package/hmr/helpers/vendor-rewrite.js.map +1 -1
- package/hmr/server/boot-archive-route.d.ts +40 -0
- package/hmr/server/boot-archive-route.js +154 -0
- package/hmr/server/boot-archive-route.js.map +1 -0
- package/hmr/server/boot-closure-route.d.ts +49 -0
- package/hmr/server/boot-closure-route.js +144 -0
- package/hmr/server/boot-closure-route.js.map +1 -0
- package/hmr/server/boot-recording.d.ts +58 -0
- package/hmr/server/boot-recording.js +228 -0
- package/hmr/server/boot-recording.js.map +1 -0
- package/hmr/server/constants.js +20 -5
- package/hmr/server/constants.js.map +1 -1
- package/hmr/server/core-bundle.d.ts +140 -0
- package/hmr/server/core-bundle.js +614 -0
- package/hmr/server/core-bundle.js.map +1 -0
- package/hmr/server/core-sanitize.d.ts +86 -7
- package/hmr/server/core-sanitize.js +170 -45
- package/hmr/server/core-sanitize.js.map +1 -1
- package/hmr/server/css-device-module.d.ts +28 -0
- package/hmr/server/css-device-module.js +44 -0
- package/hmr/server/css-device-module.js.map +1 -0
- package/hmr/server/deps-bundle.d.ts +218 -0
- package/hmr/server/deps-bundle.js +998 -0
- package/hmr/server/deps-bundle.js.map +1 -0
- package/hmr/server/device-transform-helpers.d.ts +24 -0
- package/hmr/server/device-transform-helpers.js +408 -0
- package/hmr/server/device-transform-helpers.js.map +1 -0
- package/hmr/server/framework-strategy.d.ts +113 -11
- package/hmr/server/hmr-module-graph.d.ts +37 -0
- package/hmr/server/hmr-module-graph.js +215 -0
- package/hmr/server/hmr-module-graph.js.map +1 -0
- package/hmr/server/import-map.d.ts +13 -4
- package/hmr/server/import-map.js +94 -47
- package/hmr/server/import-map.js.map +1 -1
- package/hmr/server/index.js +7 -16
- package/hmr/server/index.js.map +1 -1
- package/hmr/server/ns-core-cjs-shape.d.ts +2 -4
- package/hmr/server/ns-core-cjs-shape.js +4 -6
- package/hmr/server/ns-core-cjs-shape.js.map +1 -1
- package/hmr/server/ns-m-response-memo.d.ts +10 -0
- package/hmr/server/ns-m-response-memo.js +33 -0
- package/hmr/server/ns-m-response-memo.js.map +1 -0
- package/hmr/server/ns-rt-bridge.d.ts +51 -0
- package/hmr/server/ns-rt-bridge.js +131 -0
- package/hmr/server/ns-rt-bridge.js.map +1 -0
- package/hmr/server/ns-rt-route.d.ts +5 -0
- package/hmr/server/ns-rt-route.js +39 -0
- package/hmr/server/ns-rt-route.js.map +1 -0
- package/hmr/server/perf-instrumentation.d.ts +6 -10
- package/hmr/server/perf-instrumentation.js +5 -6
- package/hmr/server/perf-instrumentation.js.map +1 -1
- package/hmr/server/process-code-for-device.d.ts +30 -0
- package/hmr/server/process-code-for-device.js +791 -0
- package/hmr/server/process-code-for-device.js.map +1 -0
- package/hmr/server/require-guard.d.ts +1 -0
- package/hmr/server/require-guard.js +12 -0
- package/hmr/server/require-guard.js.map +1 -0
- package/hmr/server/rewrite-imports.d.ts +2 -0
- package/hmr/server/rewrite-imports.js +638 -0
- package/hmr/server/rewrite-imports.js.map +1 -0
- package/hmr/server/route-helpers.d.ts +7 -0
- package/hmr/server/route-helpers.js +13 -0
- package/hmr/server/route-helpers.js.map +1 -0
- package/hmr/server/server-origin.d.ts +2 -0
- package/hmr/server/server-origin.js +83 -0
- package/hmr/server/server-origin.js.map +1 -0
- package/hmr/server/shared-transform-request.js +1 -2
- package/hmr/server/shared-transform-request.js.map +1 -1
- package/hmr/server/transform-cache-invalidation.d.ts +37 -0
- package/hmr/server/transform-cache-invalidation.js +156 -0
- package/hmr/server/transform-cache-invalidation.js.map +1 -0
- package/hmr/server/vendor-bare-module-shims.d.ts +4 -0
- package/hmr/server/vendor-bare-module-shims.js +80 -0
- package/hmr/server/vendor-bare-module-shims.js.map +1 -0
- package/hmr/server/vite-plugin.d.ts +1 -0
- package/hmr/server/vite-plugin.js +180 -54
- package/hmr/server/vite-plugin.js.map +1 -1
- package/hmr/server/websocket-core-bridge.d.ts +51 -4
- package/hmr/server/websocket-core-bridge.js +62 -54
- package/hmr/server/websocket-core-bridge.js.map +1 -1
- package/hmr/server/websocket-css-hot-update.d.ts +33 -0
- package/hmr/server/websocket-css-hot-update.js +65 -0
- package/hmr/server/websocket-css-hot-update.js.map +1 -0
- package/hmr/server/websocket-device-transform.d.ts +3 -0
- package/hmr/server/websocket-device-transform.js +7 -0
- package/hmr/server/websocket-device-transform.js.map +1 -0
- package/hmr/server/websocket-hmr-pending.d.ts +3 -9
- package/hmr/server/websocket-hmr-pending.js +1 -1
- package/hmr/server/websocket-hmr-pending.js.map +1 -1
- package/hmr/server/websocket-hot-update.d.ts +77 -0
- package/hmr/server/websocket-hot-update.js +360 -0
- package/hmr/server/websocket-hot-update.js.map +1 -0
- package/hmr/server/websocket-import-map-route.d.ts +15 -0
- package/hmr/server/websocket-import-map-route.js +50 -0
- package/hmr/server/websocket-import-map-route.js.map +1 -0
- package/hmr/server/websocket-module-bindings.js +3 -3
- package/hmr/server/websocket-module-bindings.js.map +1 -1
- package/hmr/server/websocket-module-specifiers.d.ts +66 -2
- package/hmr/server/websocket-module-specifiers.js +191 -20
- package/hmr/server/websocket-module-specifiers.js.map +1 -1
- package/hmr/server/websocket-ns-core.d.ts +34 -0
- package/hmr/server/websocket-ns-core.js +414 -0
- package/hmr/server/websocket-ns-core.js.map +1 -0
- package/hmr/server/websocket-ns-entry.d.ts +21 -0
- package/hmr/server/websocket-ns-entry.js +164 -0
- package/hmr/server/websocket-ns-entry.js.map +1 -0
- package/hmr/server/websocket-ns-m-paths.d.ts +1 -3
- package/hmr/server/websocket-ns-m-paths.js +25 -82
- package/hmr/server/websocket-ns-m-paths.js.map +1 -1
- package/hmr/server/websocket-ns-m-request.d.ts +11 -1
- package/hmr/server/websocket-ns-m-request.js +17 -9
- package/hmr/server/websocket-ns-m-request.js.map +1 -1
- package/hmr/server/websocket-ns-m.d.ts +52 -0
- package/hmr/server/websocket-ns-m.js +835 -0
- package/hmr/server/websocket-ns-m.js.map +1 -0
- package/hmr/server/websocket-served-module-helpers.d.ts +50 -4
- package/hmr/server/websocket-served-module-helpers.js +384 -86
- package/hmr/server/websocket-served-module-helpers.js.map +1 -1
- package/hmr/server/websocket-txn.js +6 -9
- package/hmr/server/websocket-txn.js.map +1 -1
- package/hmr/server/websocket-vendor-unifier.d.ts +0 -1
- package/hmr/server/websocket-vendor-unifier.js +4 -9
- package/hmr/server/websocket-vendor-unifier.js.map +1 -1
- package/hmr/server/websocket.d.ts +7 -39
- package/hmr/server/websocket.js +643 -6716
- package/hmr/server/websocket.js.map +1 -1
- package/hmr/shared/ns-globals.d.ts +108 -0
- package/hmr/shared/ns-globals.js +28 -0
- package/hmr/shared/ns-globals.js.map +1 -0
- package/hmr/shared/protocol.d.ts +145 -0
- package/hmr/shared/protocol.js +28 -0
- package/hmr/shared/protocol.js.map +1 -0
- package/hmr/shared/runtime/boot-archive-format.d.ts +16 -0
- package/hmr/shared/runtime/boot-archive-format.js +31 -0
- package/hmr/shared/runtime/boot-archive-format.js.map +1 -0
- package/hmr/shared/runtime/boot-complete.d.ts +14 -0
- package/hmr/shared/runtime/boot-complete.js +32 -0
- package/hmr/shared/runtime/boot-complete.js.map +1 -0
- package/hmr/shared/runtime/boot-placeholder-ui.d.ts +69 -0
- package/hmr/shared/runtime/boot-placeholder-ui.js +101 -0
- package/hmr/shared/runtime/boot-placeholder-ui.js.map +1 -0
- package/hmr/shared/runtime/boot-progress.d.ts +44 -0
- package/hmr/shared/runtime/boot-progress.js +134 -0
- package/hmr/shared/runtime/boot-progress.js.map +1 -0
- package/hmr/shared/runtime/boot-timeline.d.ts +2 -1
- package/hmr/shared/runtime/boot-timeline.js +9 -22
- package/hmr/shared/runtime/boot-timeline.js.map +1 -1
- package/hmr/shared/runtime/browser-runtime-contract.d.ts +53 -22
- package/hmr/shared/runtime/browser-runtime-contract.js +6 -9
- package/hmr/shared/runtime/browser-runtime-contract.js.map +1 -1
- package/hmr/shared/runtime/dev-overlay-snapshots.d.ts +31 -0
- package/hmr/shared/runtime/dev-overlay-snapshots.js +324 -0
- package/hmr/shared/runtime/dev-overlay-snapshots.js.map +1 -0
- package/hmr/shared/runtime/dev-overlay.d.ts +76 -30
- package/hmr/shared/runtime/dev-overlay.js +767 -408
- package/hmr/shared/runtime/dev-overlay.js.map +1 -1
- package/hmr/shared/runtime/global-scope.d.ts +18 -0
- package/hmr/shared/runtime/global-scope.js +21 -0
- package/hmr/shared/runtime/global-scope.js.map +1 -0
- package/hmr/shared/runtime/hooks.js +2 -1
- package/hmr/shared/runtime/hooks.js.map +1 -1
- package/hmr/shared/runtime/http-only-boot.js +7 -6
- package/hmr/shared/runtime/http-only-boot.js.map +1 -1
- package/hmr/shared/runtime/module-provenance.js +4 -6
- package/hmr/shared/runtime/module-provenance.js.map +1 -1
- package/hmr/shared/runtime/root-placeholder-view.d.ts +19 -0
- package/hmr/shared/runtime/root-placeholder-view.js +311 -0
- package/hmr/shared/runtime/root-placeholder-view.js.map +1 -0
- package/hmr/shared/runtime/root-placeholder.js +398 -204
- package/hmr/shared/runtime/root-placeholder.js.map +1 -1
- package/hmr/shared/runtime/session-bootstrap.js +274 -55
- package/hmr/shared/runtime/session-bootstrap.js.map +1 -1
- package/hmr/shared/runtime/vendor-bootstrap.js +3 -10
- package/hmr/shared/runtime/vendor-bootstrap.js.map +1 -1
- package/hmr/shared/vendor/manifest-collect.d.ts +4 -0
- package/hmr/shared/vendor/manifest-collect.js +549 -0
- package/hmr/shared/vendor/manifest-collect.js.map +1 -0
- package/hmr/shared/vendor/manifest-loader.d.ts +2 -1
- package/hmr/shared/vendor/manifest-loader.js +5 -3
- package/hmr/shared/vendor/manifest-loader.js.map +1 -1
- package/hmr/shared/vendor/manifest.d.ts +1 -7
- package/hmr/shared/vendor/manifest.js +136 -825
- package/hmr/shared/vendor/manifest.js.map +1 -1
- package/hmr/shared/vendor/registry.d.ts +2 -0
- package/hmr/shared/vendor/registry.js +14 -0
- package/hmr/shared/vendor/registry.js.map +1 -1
- package/hmr/shared/vendor/vendor-device-shim.d.ts +1 -0
- package/hmr/shared/vendor/vendor-device-shim.js +208 -0
- package/hmr/shared/vendor/vendor-device-shim.js.map +1 -0
- package/hmr/shared/vendor/vendor-esbuild-plugins.d.ts +76 -0
- package/hmr/shared/vendor/vendor-esbuild-plugins.js +401 -0
- package/hmr/shared/vendor/vendor-esbuild-plugins.js.map +1 -0
- package/hmr/vendor-bootstrap.d.ts +1 -3
- package/hmr/vendor-bootstrap.js +4 -6
- package/hmr/vendor-bootstrap.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +5 -0
- package/index.js.map +1 -1
- package/package.json +65 -11
- package/runtime/core-aliases-early.js +25 -55
- package/runtime/core-aliases-early.js.map +1 -1
- package/shims/react-jsx-runtime.d.ts +4 -0
- package/shims/react-jsx-runtime.js +61 -0
- package/shims/react-jsx-runtime.js.map +1 -0
- package/helpers/angular/angular-linker.d.ts +0 -13
- package/helpers/angular/angular-linker.js +0 -194
- package/helpers/angular/angular-linker.js.map +0 -1
- package/helpers/angular/inline-decorator-component-templates.js.map +0 -1
- package/helpers/angular/shared-linker.d.ts +0 -11
- package/helpers/angular/shared-linker.js +0 -75
- package/helpers/angular/shared-linker.js.map +0 -1
- package/helpers/angular/synthesize-decorator-ctor-parameters.js.map +0 -1
- package/helpers/angular/synthesize-injectable-factories.js.map +0 -1
- package/helpers/angular/util.js +0 -67
- package/helpers/angular/util.js.map +0 -1
- package/helpers/prelink-angular.d.ts +0 -2
- package/helpers/prelink-angular.js +0 -117
- package/helpers/prelink-angular.js.map +0 -1
- package/hmr/server/websocket-angular-entry.js.map +0 -1
- package/hmr/server/websocket-angular-hot-update.js.map +0 -1
- package/hmr/server/websocket-ns-m-finalize.d.ts +0 -22
- package/hmr/server/websocket-ns-m-finalize.js +0 -88
- package/hmr/server/websocket-ns-m-finalize.js.map +0 -1
- package/hmr/server/websocket-runtime-compat.d.ts +0 -19
- package/hmr/server/websocket-runtime-compat.js +0 -286
- package/hmr/server/websocket-runtime-compat.js.map +0 -1
- package/hmr/server/websocket-vue-sfc.d.ts +0 -27
- package/hmr/server/websocket-vue-sfc.js +0 -1114
- package/hmr/server/websocket-vue-sfc.js.map +0 -1
- package/transformers/NativeClass/index.d.ts +0 -2
- package/transformers/NativeClass/index.js +0 -222
- package/transformers/NativeClass/index.js.map +0 -1
- /package/{helpers/angular → hmr/frameworks/angular/build}/inline-decorator-component-templates.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-decorator-ctor-parameters.d.ts +0 -0
- /package/{helpers/angular → hmr/frameworks/angular/build}/synthesize-injectable-factories.d.ts +0 -0
- /package/hmr/{server → frameworks/angular/server}/websocket-angular-entry.d.ts +0 -0
|
@@ -1,18 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
phase: '',
|
|
8
|
-
detail: '',
|
|
9
|
-
progress: null,
|
|
10
|
-
busy: false,
|
|
11
|
-
blocking: false,
|
|
12
|
-
tone: 'info',
|
|
13
|
-
};
|
|
1
|
+
import { BOOT_PLACEHOLDER_MOTION, computeBootProgressFillScale, formatBootDetailLine, formatBootPrimaryLine } from './boot-placeholder-ui.js';
|
|
2
|
+
import { BOOT_TITLE, DEFAULT_SNAPSHOT, createBootOverlaySnapshot, createConnectionOverlaySnapshot, createUpdateOverlaySnapshot } from './dev-overlay-snapshots.js';
|
|
3
|
+
import { getGlobalScope } from './global-scope.js';
|
|
4
|
+
// Re-export the snapshot model so existing `./dev-overlay.js` importers keep working.
|
|
5
|
+
export { createBootOverlaySnapshot, createConnectionOverlaySnapshot, createUpdateOverlaySnapshot } from './dev-overlay-snapshots.js';
|
|
6
|
+
const DEFAULT_OVERLAY_POSITION = 'top';
|
|
14
7
|
function getOverlayGlobal() {
|
|
15
|
-
return
|
|
8
|
+
return getGlobalScope();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the configured live-overlay position.
|
|
12
|
+
*
|
|
13
|
+
* Reads `globalThis.__NS_HMR_OVERLAY_POSITION__` so a project can
|
|
14
|
+
* override the default at boot time (e.g. inside `app.ts` before the
|
|
15
|
+
* Vite session bootstraps). Falls back to 'top' which gives the
|
|
16
|
+
* toast-style chip with a slide-in animation and safe-area padding.
|
|
17
|
+
*/
|
|
18
|
+
export function getHmrDevOverlayPosition() {
|
|
19
|
+
const g = getOverlayGlobal();
|
|
20
|
+
const stored = g.__NS_HMR_OVERLAY_POSITION__;
|
|
21
|
+
if (stored === 'top' || stored === 'bottom' || stored === 'center') {
|
|
22
|
+
return stored;
|
|
23
|
+
}
|
|
24
|
+
return DEFAULT_OVERLAY_POSITION;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Imperative setter for the live-overlay position. Re-applies the
|
|
28
|
+
* current snapshot so the change is visible without waiting for the
|
|
29
|
+
* next HMR cycle. Useful during dev to A/B between top/bottom/center
|
|
30
|
+
* without restarting the app.
|
|
31
|
+
*/
|
|
32
|
+
export function setHmrDevOverlayPosition(position) {
|
|
33
|
+
if (position !== 'top' && position !== 'bottom' && position !== 'center') {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const g = getOverlayGlobal();
|
|
37
|
+
g.__NS_HMR_OVERLAY_POSITION__ = position;
|
|
38
|
+
const state = getRuntimeState();
|
|
39
|
+
applyRuntimeSnapshot(state.snapshot);
|
|
16
40
|
}
|
|
17
41
|
function getRuntimeState() {
|
|
18
42
|
const g = getOverlayGlobal();
|
|
@@ -41,319 +65,6 @@ function getRuntimeState() {
|
|
|
41
65
|
state.updateCycleStartedAt = 0;
|
|
42
66
|
return state;
|
|
43
67
|
}
|
|
44
|
-
function describeAttempt(info) {
|
|
45
|
-
const attempt = Number(info?.attempt || 0);
|
|
46
|
-
const attempts = Number(info?.attempts || 0);
|
|
47
|
-
if (!attempt || !attempts) {
|
|
48
|
-
return '';
|
|
49
|
-
}
|
|
50
|
-
return `Attempt ${attempt}/${attempts}`;
|
|
51
|
-
}
|
|
52
|
-
export function createBootOverlaySnapshot(stage, info) {
|
|
53
|
-
const attemptText = describeAttempt(info);
|
|
54
|
-
const phaseInfo = {
|
|
55
|
-
placeholder: {
|
|
56
|
-
visible: true,
|
|
57
|
-
mode: 'boot',
|
|
58
|
-
badge: 'BOOT',
|
|
59
|
-
title: BOOT_TITLE,
|
|
60
|
-
phase: 'Preparing the HTTP HMR bootstrap',
|
|
61
|
-
progress: 4,
|
|
62
|
-
busy: true,
|
|
63
|
-
blocking: true,
|
|
64
|
-
tone: 'info',
|
|
65
|
-
},
|
|
66
|
-
'probing-origin': {
|
|
67
|
-
visible: true,
|
|
68
|
-
mode: 'boot',
|
|
69
|
-
badge: 'BOOT',
|
|
70
|
-
title: BOOT_TITLE,
|
|
71
|
-
phase: 'Contacting the Vite dev server',
|
|
72
|
-
progress: 8,
|
|
73
|
-
busy: true,
|
|
74
|
-
blocking: true,
|
|
75
|
-
tone: 'info',
|
|
76
|
-
},
|
|
77
|
-
'loading-entry-runtime': {
|
|
78
|
-
visible: true,
|
|
79
|
-
mode: 'boot',
|
|
80
|
-
badge: 'BOOT',
|
|
81
|
-
title: BOOT_TITLE,
|
|
82
|
-
phase: 'Loading the entry runtime bridge',
|
|
83
|
-
progress: 16,
|
|
84
|
-
busy: true,
|
|
85
|
-
blocking: true,
|
|
86
|
-
tone: 'info',
|
|
87
|
-
},
|
|
88
|
-
'configuring-import-map': {
|
|
89
|
-
visible: true,
|
|
90
|
-
mode: 'boot',
|
|
91
|
-
badge: 'BOOT',
|
|
92
|
-
title: BOOT_TITLE,
|
|
93
|
-
phase: 'Configuring the import map',
|
|
94
|
-
progress: 26,
|
|
95
|
-
busy: true,
|
|
96
|
-
blocking: true,
|
|
97
|
-
tone: 'info',
|
|
98
|
-
},
|
|
99
|
-
'loading-runtime-bridge': {
|
|
100
|
-
visible: true,
|
|
101
|
-
mode: 'boot',
|
|
102
|
-
badge: 'BOOT',
|
|
103
|
-
title: BOOT_TITLE,
|
|
104
|
-
phase: 'Loading the NativeScript runtime bridge',
|
|
105
|
-
progress: 40,
|
|
106
|
-
busy: true,
|
|
107
|
-
blocking: true,
|
|
108
|
-
tone: 'info',
|
|
109
|
-
},
|
|
110
|
-
'loading-core-bridge': {
|
|
111
|
-
visible: true,
|
|
112
|
-
mode: 'boot',
|
|
113
|
-
badge: 'BOOT',
|
|
114
|
-
title: BOOT_TITLE,
|
|
115
|
-
phase: 'Loading the unified core bridge',
|
|
116
|
-
progress: 54,
|
|
117
|
-
busy: true,
|
|
118
|
-
blocking: true,
|
|
119
|
-
tone: 'info',
|
|
120
|
-
},
|
|
121
|
-
'preloading-style-scope': {
|
|
122
|
-
visible: true,
|
|
123
|
-
mode: 'boot',
|
|
124
|
-
badge: 'BOOT',
|
|
125
|
-
title: BOOT_TITLE,
|
|
126
|
-
phase: 'Preparing the shared style scope',
|
|
127
|
-
progress: 62,
|
|
128
|
-
busy: true,
|
|
129
|
-
blocking: true,
|
|
130
|
-
tone: 'info',
|
|
131
|
-
},
|
|
132
|
-
'installing-css': {
|
|
133
|
-
visible: true,
|
|
134
|
-
mode: 'boot',
|
|
135
|
-
badge: 'BOOT',
|
|
136
|
-
title: BOOT_TITLE,
|
|
137
|
-
phase: 'Applying the app stylesheet',
|
|
138
|
-
progress: 70,
|
|
139
|
-
busy: true,
|
|
140
|
-
blocking: true,
|
|
141
|
-
tone: 'info',
|
|
142
|
-
},
|
|
143
|
-
'importing-main': {
|
|
144
|
-
visible: true,
|
|
145
|
-
mode: 'boot',
|
|
146
|
-
badge: 'BOOT',
|
|
147
|
-
title: BOOT_TITLE,
|
|
148
|
-
phase: 'Importing the app entry',
|
|
149
|
-
progress: 82,
|
|
150
|
-
busy: true,
|
|
151
|
-
blocking: true,
|
|
152
|
-
tone: 'info',
|
|
153
|
-
},
|
|
154
|
-
'waiting-for-app': {
|
|
155
|
-
visible: true,
|
|
156
|
-
mode: 'boot',
|
|
157
|
-
badge: 'BOOT',
|
|
158
|
-
title: BOOT_TITLE,
|
|
159
|
-
phase: 'Waiting for the app root view',
|
|
160
|
-
progress: 94,
|
|
161
|
-
busy: true,
|
|
162
|
-
blocking: true,
|
|
163
|
-
tone: 'info',
|
|
164
|
-
},
|
|
165
|
-
'app-root-committed': {
|
|
166
|
-
visible: true,
|
|
167
|
-
mode: 'boot',
|
|
168
|
-
badge: 'READY',
|
|
169
|
-
title: BOOT_TITLE,
|
|
170
|
-
phase: 'Real app root committed',
|
|
171
|
-
progress: 100,
|
|
172
|
-
busy: false,
|
|
173
|
-
blocking: true,
|
|
174
|
-
tone: 'info',
|
|
175
|
-
},
|
|
176
|
-
ready: {
|
|
177
|
-
visible: true,
|
|
178
|
-
mode: 'boot',
|
|
179
|
-
badge: 'READY',
|
|
180
|
-
title: BOOT_TITLE,
|
|
181
|
-
phase: 'Boot complete',
|
|
182
|
-
progress: 100,
|
|
183
|
-
busy: false,
|
|
184
|
-
blocking: true,
|
|
185
|
-
tone: 'info',
|
|
186
|
-
},
|
|
187
|
-
error: {
|
|
188
|
-
visible: true,
|
|
189
|
-
mode: 'boot',
|
|
190
|
-
badge: 'RETRY',
|
|
191
|
-
title: BOOT_TITLE,
|
|
192
|
-
phase: 'Retrying after a boot failure',
|
|
193
|
-
progress: null,
|
|
194
|
-
busy: true,
|
|
195
|
-
blocking: true,
|
|
196
|
-
tone: 'error',
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
const base = phaseInfo[stage];
|
|
200
|
-
let detail = info?.detail || '';
|
|
201
|
-
if (!detail && stage === 'probing-origin' && info?.origin) {
|
|
202
|
-
detail = `Trying ${info.origin}`;
|
|
203
|
-
}
|
|
204
|
-
if (attemptText) {
|
|
205
|
-
detail = detail ? `${detail} ${attemptText}` : attemptText;
|
|
206
|
-
}
|
|
207
|
-
return {
|
|
208
|
-
...base,
|
|
209
|
-
detail,
|
|
210
|
-
progress: typeof info?.progress === 'number' || info?.progress === null ? info.progress : base.progress,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
export function createConnectionOverlaySnapshot(stage, info) {
|
|
214
|
-
if (stage === 'healthy') {
|
|
215
|
-
return { ...DEFAULT_SNAPSHOT };
|
|
216
|
-
}
|
|
217
|
-
const phaseInfo = {
|
|
218
|
-
connecting: {
|
|
219
|
-
visible: true,
|
|
220
|
-
mode: 'connection',
|
|
221
|
-
badge: 'SOCKET',
|
|
222
|
-
title: 'Waiting for Vite dev server',
|
|
223
|
-
phase: 'Opening websocket connection',
|
|
224
|
-
detail: 'Live updates are paused until the connection is healthy.',
|
|
225
|
-
progress: null,
|
|
226
|
-
busy: true,
|
|
227
|
-
blocking: false,
|
|
228
|
-
tone: 'warn',
|
|
229
|
-
},
|
|
230
|
-
reconnecting: {
|
|
231
|
-
visible: true,
|
|
232
|
-
mode: 'connection',
|
|
233
|
-
badge: 'SOCKET',
|
|
234
|
-
title: 'HMR connection lost',
|
|
235
|
-
phase: 'Reconnecting Vite websocket',
|
|
236
|
-
detail: 'The app may be stale until the dev server reconnects.',
|
|
237
|
-
progress: null,
|
|
238
|
-
busy: true,
|
|
239
|
-
blocking: false,
|
|
240
|
-
tone: 'warn',
|
|
241
|
-
},
|
|
242
|
-
synchronizing: {
|
|
243
|
-
visible: true,
|
|
244
|
-
mode: 'connection',
|
|
245
|
-
badge: 'SYNC',
|
|
246
|
-
title: 'HMR connection restored',
|
|
247
|
-
phase: 'Synchronizing live-update state',
|
|
248
|
-
detail: 'Finalizing the module graph before dismissing the overlay.',
|
|
249
|
-
progress: 95,
|
|
250
|
-
busy: true,
|
|
251
|
-
blocking: false,
|
|
252
|
-
tone: 'info',
|
|
253
|
-
},
|
|
254
|
-
offline: {
|
|
255
|
-
visible: true,
|
|
256
|
-
mode: 'connection',
|
|
257
|
-
badge: 'OFFLINE',
|
|
258
|
-
title: 'Vite dev server offline',
|
|
259
|
-
phase: 'Please check your terminal.',
|
|
260
|
-
detail: 'The websocket and HTTP HMR path are both unavailable right now.',
|
|
261
|
-
progress: null,
|
|
262
|
-
busy: true,
|
|
263
|
-
blocking: false,
|
|
264
|
-
tone: 'error',
|
|
265
|
-
},
|
|
266
|
-
};
|
|
267
|
-
const base = phaseInfo[stage];
|
|
268
|
-
return {
|
|
269
|
-
...base,
|
|
270
|
-
detail: info?.detail || base.detail,
|
|
271
|
-
progress: typeof info?.progress === 'number' || info?.progress === null ? info.progress : base.progress,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
// Round-eleven.3 (alpha.62) — Snapshot factory for the HMR-applying
|
|
275
|
-
// overlay. Each stage owns a fixed phase string, badge, and progress
|
|
276
|
-
// %. We pick the percentages so users see continuous forward motion:
|
|
277
|
-
// the cheap stages (mutex acquire, eviction call) advance fast; the
|
|
278
|
-
// long tail (entry re-import + Angular reboot) sits at 60→90 so the
|
|
279
|
-
// bar keeps moving even when the V8 ESM walk dominates wall time.
|
|
280
|
-
//
|
|
281
|
-
// The 'complete' stage holds for a brief moment (the API auto-hides
|
|
282
|
-
// it via setUpdateStage) so the user gets visual closure ("the update
|
|
283
|
-
// landed") without staring at a frozen overlay; tone stays 'success'
|
|
284
|
-
// throughout so the colour scheme never flickers between phases.
|
|
285
|
-
const HMR_UPDATE_TITLE = 'HMR update applying...';
|
|
286
|
-
const HMR_UPDATE_DONE_TITLE = 'HMR update applied';
|
|
287
|
-
export function createUpdateOverlaySnapshot(stage, info) {
|
|
288
|
-
const phaseInfo = {
|
|
289
|
-
received: {
|
|
290
|
-
visible: true,
|
|
291
|
-
mode: 'update',
|
|
292
|
-
badge: 'HMR',
|
|
293
|
-
title: HMR_UPDATE_TITLE,
|
|
294
|
-
phase: 'Preparing update',
|
|
295
|
-
detail: '',
|
|
296
|
-
progress: 5,
|
|
297
|
-
busy: true,
|
|
298
|
-
blocking: false,
|
|
299
|
-
tone: 'success',
|
|
300
|
-
},
|
|
301
|
-
evicting: {
|
|
302
|
-
visible: true,
|
|
303
|
-
mode: 'update',
|
|
304
|
-
badge: 'HMR',
|
|
305
|
-
title: HMR_UPDATE_TITLE,
|
|
306
|
-
phase: 'Invalidating module cache',
|
|
307
|
-
detail: '',
|
|
308
|
-
progress: 30,
|
|
309
|
-
busy: true,
|
|
310
|
-
blocking: false,
|
|
311
|
-
tone: 'success',
|
|
312
|
-
},
|
|
313
|
-
reimporting: {
|
|
314
|
-
visible: true,
|
|
315
|
-
mode: 'update',
|
|
316
|
-
badge: 'HMR',
|
|
317
|
-
title: HMR_UPDATE_TITLE,
|
|
318
|
-
phase: 'Re-importing entry',
|
|
319
|
-
detail: '',
|
|
320
|
-
progress: 60,
|
|
321
|
-
busy: true,
|
|
322
|
-
blocking: false,
|
|
323
|
-
tone: 'success',
|
|
324
|
-
},
|
|
325
|
-
rebooting: {
|
|
326
|
-
visible: true,
|
|
327
|
-
mode: 'update',
|
|
328
|
-
badge: 'HMR',
|
|
329
|
-
title: HMR_UPDATE_TITLE,
|
|
330
|
-
phase: 'Rebooting Angular',
|
|
331
|
-
detail: '',
|
|
332
|
-
progress: 90,
|
|
333
|
-
busy: true,
|
|
334
|
-
blocking: false,
|
|
335
|
-
tone: 'success',
|
|
336
|
-
},
|
|
337
|
-
complete: {
|
|
338
|
-
visible: true,
|
|
339
|
-
mode: 'update',
|
|
340
|
-
badge: 'HMR',
|
|
341
|
-
title: HMR_UPDATE_DONE_TITLE,
|
|
342
|
-
phase: 'Update applied',
|
|
343
|
-
detail: '',
|
|
344
|
-
progress: 100,
|
|
345
|
-
busy: false,
|
|
346
|
-
blocking: false,
|
|
347
|
-
tone: 'success',
|
|
348
|
-
},
|
|
349
|
-
};
|
|
350
|
-
const base = phaseInfo[stage];
|
|
351
|
-
return {
|
|
352
|
-
...base,
|
|
353
|
-
detail: info?.detail || base.detail,
|
|
354
|
-
progress: typeof info?.progress === 'number' || info?.progress === null ? info.progress : base.progress,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
68
|
function resolveCoreExport(name) {
|
|
358
69
|
const g = getOverlayGlobal();
|
|
359
70
|
try {
|
|
@@ -533,10 +244,28 @@ function findBootStatusLabel() {
|
|
|
533
244
|
catch { }
|
|
534
245
|
return null;
|
|
535
246
|
}
|
|
247
|
+
function findBootDetailLabel() {
|
|
248
|
+
const g = getOverlayGlobal();
|
|
249
|
+
return g.__NS_DEV_BOOT_DETAIL_LABEL__ || null;
|
|
250
|
+
}
|
|
251
|
+
function findBootProgressFill() {
|
|
252
|
+
const g = getOverlayGlobal();
|
|
253
|
+
return g.__NS_DEV_BOOT_PROGRESS_FILL__ || null;
|
|
254
|
+
}
|
|
536
255
|
function updateBootStatusLabel(snapshot) {
|
|
537
|
-
const newText = formatStatusText(snapshot) || 'Preparing the HTTP HMR bootstrap (4%)';
|
|
538
256
|
const statusLabel = findBootStatusLabel();
|
|
257
|
+
const detailLabel = findBootDetailLabel();
|
|
258
|
+
const progressFill = findBootProgressFill();
|
|
539
259
|
const activityIndicator = findBootActivityIndicator();
|
|
260
|
+
// New (card) layout: phase line + detail line live in separate
|
|
261
|
+
// labels so the typography can differ. Legacy (single-label)
|
|
262
|
+
// layout: keep the original combined "phase (X%)\ndetail" text so
|
|
263
|
+
// nothing visually regresses for runtimes still attached to the
|
|
264
|
+
// older placeholder shape.
|
|
265
|
+
const hasSplitLabels = !!detailLabel;
|
|
266
|
+
const phaseLine = formatBootPrimaryLine(snapshot);
|
|
267
|
+
const detailLine = formatBootDetailLine(snapshot);
|
|
268
|
+
const combinedText = formatStatusText(snapshot) || 'Preparing the HTTP HMR bootstrap (4%)';
|
|
540
269
|
if (!statusLabel) {
|
|
541
270
|
if (activityIndicator) {
|
|
542
271
|
try {
|
|
@@ -545,11 +274,16 @@ function updateBootStatusLabel(snapshot) {
|
|
|
545
274
|
}
|
|
546
275
|
catch { }
|
|
547
276
|
}
|
|
277
|
+
applyBootProgressFill(progressFill, snapshot);
|
|
548
278
|
return;
|
|
549
279
|
}
|
|
550
280
|
try {
|
|
551
|
-
statusLabel.text =
|
|
552
|
-
|
|
281
|
+
statusLabel.text = hasSplitLabels ? phaseLine || 'Preparing the HTTP HMR bootstrap' : combinedText;
|
|
282
|
+
// Card layout uses the calibrated phase-text colour from the
|
|
283
|
+
// palette; legacy single-label layout keeps the original muted
|
|
284
|
+
// brown so we don't visually regress mid-session.
|
|
285
|
+
const phaseColorHex = snapshot.tone === 'error' ? '#B91C1C' : hasSplitLabels ? '#475569' : '#563e3fb1';
|
|
286
|
+
statusLabel.color = asColor(phaseColorHex);
|
|
553
287
|
if (typeof statusLabel.requestLayout === 'function') {
|
|
554
288
|
statusLabel.requestLayout();
|
|
555
289
|
}
|
|
@@ -559,6 +293,15 @@ function updateBootStatusLabel(snapshot) {
|
|
|
559
293
|
}
|
|
560
294
|
}
|
|
561
295
|
catch { }
|
|
296
|
+
if (detailLabel) {
|
|
297
|
+
try {
|
|
298
|
+
detailLabel.text = detailLine;
|
|
299
|
+
detailLabel.color = asColor(snapshot.tone === 'error' ? '#DC2626' : '#94A3B8');
|
|
300
|
+
detailLabel.visibility = detailLine ? 'visible' : 'collapse';
|
|
301
|
+
}
|
|
302
|
+
catch { }
|
|
303
|
+
}
|
|
304
|
+
applyBootProgressFill(progressFill, snapshot);
|
|
562
305
|
if (activityIndicator) {
|
|
563
306
|
try {
|
|
564
307
|
activityIndicator.busy = !!snapshot.busy;
|
|
@@ -567,6 +310,50 @@ function updateBootStatusLabel(snapshot) {
|
|
|
567
310
|
catch { }
|
|
568
311
|
}
|
|
569
312
|
}
|
|
313
|
+
// Drive the progress fill scaleX from the snapshot. Uses NS's view
|
|
314
|
+
// animate API for a smooth 220 ms easeOut between heartbeat ticks; a
|
|
315
|
+
// monotonic ratchet on `globalThis.__NS_DEV_BOOT_PROGRESS_LAST_SCALE__`
|
|
316
|
+
// guards against the fill snapping backwards if a less-progressed
|
|
317
|
+
// snapshot ever lands between ticks (mirrors the JS-side
|
|
318
|
+
// `applyMonotonicBootProgress` contract).
|
|
319
|
+
function applyBootProgressFill(progressFill, snapshot) {
|
|
320
|
+
if (!progressFill)
|
|
321
|
+
return;
|
|
322
|
+
const g = getOverlayGlobal();
|
|
323
|
+
const isError = snapshot.tone === 'error';
|
|
324
|
+
progressFill.backgroundColor = asColor(isError ? '#B41810' : '#3B6FE5');
|
|
325
|
+
const targetScale = computeBootProgressFillScale(snapshot.progress ?? null);
|
|
326
|
+
const previousRaw = Number(g.__NS_DEV_BOOT_PROGRESS_LAST_SCALE__);
|
|
327
|
+
const previous = Number.isFinite(previousRaw) ? previousRaw : 0;
|
|
328
|
+
const next = Math.max(previous, targetScale);
|
|
329
|
+
g.__NS_DEV_BOOT_PROGRESS_LAST_SCALE__ = next;
|
|
330
|
+
try {
|
|
331
|
+
// NS view.animate scales around `originX`/`originY`; the
|
|
332
|
+
// placeholder builder pins `originX = 0` so the fill grows
|
|
333
|
+
// rightward. animate() may be unavailable in some headless
|
|
334
|
+
// test environments — fall through to a direct property set.
|
|
335
|
+
if (typeof progressFill.animate === 'function') {
|
|
336
|
+
progressFill
|
|
337
|
+
.animate({
|
|
338
|
+
scale: { x: next, y: 1 },
|
|
339
|
+
duration: BOOT_PLACEHOLDER_MOTION.progressDurationMs,
|
|
340
|
+
curve: 'easeOut',
|
|
341
|
+
})
|
|
342
|
+
.catch(() => {
|
|
343
|
+
try {
|
|
344
|
+
progressFill.scaleX = next;
|
|
345
|
+
}
|
|
346
|
+
catch { }
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
progressFill.scaleX = next;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
progressFill.scaleX = next;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
570
357
|
function resolveActivePage() {
|
|
571
358
|
try {
|
|
572
359
|
const Frame = resolveCoreExport('Frame');
|
|
@@ -590,6 +377,87 @@ function resolveActivePage() {
|
|
|
590
377
|
catch { }
|
|
591
378
|
return null;
|
|
592
379
|
}
|
|
380
|
+
function readCachedAndroidSafeAreaInsets() {
|
|
381
|
+
const g = getOverlayGlobal();
|
|
382
|
+
const cached = g.__NS_HMR_ANDROID_SAFE_INSETS__;
|
|
383
|
+
if (cached && typeof cached.top === 'number') {
|
|
384
|
+
return cached;
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Read the Android system-bar safe-area insets (status bar / navigation
|
|
390
|
+
* bar / display cutout) in device-independent pixels.
|
|
391
|
+
*
|
|
392
|
+
* NativeScript runs every Android activity edge-to-edge, so the overlay
|
|
393
|
+
* wrapper fills the whole window — we need these insets to keep the toast
|
|
394
|
+
* chip out from under the system bars (see `computeAndroidToastMargin`).
|
|
395
|
+
*
|
|
396
|
+
* Returns null on non-Android runtimes (iOS / web / vitest) so callers
|
|
397
|
+
* fall back to base margins. The last good reading is cached on the
|
|
398
|
+
* global so a transient null (e.g. insets queried before the decor view
|
|
399
|
+
* is attached) reuses the previous value instead of snapping the chip
|
|
400
|
+
* back under the status bar.
|
|
401
|
+
*/
|
|
402
|
+
function readAndroidSafeAreaInsets() {
|
|
403
|
+
const g = getOverlayGlobal();
|
|
404
|
+
// `android.*` is exposed as a global only on the NativeScript Android
|
|
405
|
+
// runtime; its absence means iOS, web, or a test environment.
|
|
406
|
+
const androidNs = g.android || (typeof globalThis.android !== 'undefined' ? globalThis.android : undefined);
|
|
407
|
+
if (!androidNs) {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
try {
|
|
411
|
+
const Application = resolveCoreExport('Application');
|
|
412
|
+
const activity = Application?.android?.foregroundActivity || Application?.android?.startActivity;
|
|
413
|
+
const decorView = activity?.getWindow?.()?.getDecorView?.();
|
|
414
|
+
const rootInsets = decorView?.getRootWindowInsets?.();
|
|
415
|
+
if (!rootInsets) {
|
|
416
|
+
return readCachedAndroidSafeAreaInsets();
|
|
417
|
+
}
|
|
418
|
+
let density = 1;
|
|
419
|
+
try {
|
|
420
|
+
const metricsDensity = Number(activity?.getResources?.()?.getDisplayMetrics?.()?.density);
|
|
421
|
+
if (Number.isFinite(metricsDensity) && metricsDensity > 0) {
|
|
422
|
+
density = metricsDensity;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch { }
|
|
426
|
+
let px = { top: 0, bottom: 0, left: 0, right: 0 };
|
|
427
|
+
const WindowInsets = androidNs.view?.WindowInsets;
|
|
428
|
+
const Type = WindowInsets?.Type;
|
|
429
|
+
if (typeof rootInsets.getInsets === 'function' && Type && typeof Type.systemBars === 'function') {
|
|
430
|
+
// API 30+: query the system bars + display cutout so notches /
|
|
431
|
+
// camera holes are respected in landscape.
|
|
432
|
+
let mask = Type.systemBars();
|
|
433
|
+
if (typeof Type.displayCutout === 'function') {
|
|
434
|
+
mask = mask | Type.displayCutout();
|
|
435
|
+
}
|
|
436
|
+
const i = rootInsets.getInsets(mask);
|
|
437
|
+
px = { top: Number(i?.top) || 0, bottom: Number(i?.bottom) || 0, left: Number(i?.left) || 0, right: Number(i?.right) || 0 };
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
// API < 30 fallback.
|
|
441
|
+
px = {
|
|
442
|
+
top: Number(rootInsets.getSystemWindowInsetTop?.()) || 0,
|
|
443
|
+
bottom: Number(rootInsets.getSystemWindowInsetBottom?.()) || 0,
|
|
444
|
+
left: Number(rootInsets.getSystemWindowInsetLeft?.()) || 0,
|
|
445
|
+
right: Number(rootInsets.getSystemWindowInsetRight?.()) || 0,
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
const insets = {
|
|
449
|
+
top: px.top / density,
|
|
450
|
+
bottom: px.bottom / density,
|
|
451
|
+
left: px.left / density,
|
|
452
|
+
right: px.right / density,
|
|
453
|
+
};
|
|
454
|
+
g.__NS_HMR_ANDROID_SAFE_INSETS__ = insets;
|
|
455
|
+
return insets;
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
return readCachedAndroidSafeAreaInsets();
|
|
459
|
+
}
|
|
460
|
+
}
|
|
593
461
|
function buildLiveOverlayView(snapshot) {
|
|
594
462
|
const GridLayout = resolveCoreExport('GridLayout');
|
|
595
463
|
const StackLayout = resolveCoreExport('StackLayout');
|
|
@@ -603,8 +471,18 @@ function buildLiveOverlayView(snapshot) {
|
|
|
603
471
|
overlay.height = '100%';
|
|
604
472
|
overlay.horizontalAlignment = 'stretch';
|
|
605
473
|
overlay.verticalAlignment = 'stretch';
|
|
474
|
+
// Toast mode lets touches reach the underlying app. We flip
|
|
475
|
+
// isUserInteractionEnabled in applySnapshotToLiveRefs based on
|
|
476
|
+
// the resolved position, but keep it false here as a safe default
|
|
477
|
+
// (the panel itself is purely informational).
|
|
478
|
+
try {
|
|
479
|
+
overlay.isUserInteractionEnabled = false;
|
|
480
|
+
}
|
|
481
|
+
catch { }
|
|
606
482
|
const panel = new StackLayout();
|
|
607
483
|
panel.horizontalAlignment = 'center';
|
|
484
|
+
// Vertical alignment is overridden in applySnapshotToLiveRefs
|
|
485
|
+
// based on getHmrDevOverlayPosition(); 'middle' is the default
|
|
608
486
|
panel.verticalAlignment = 'middle';
|
|
609
487
|
panel.width = 320;
|
|
610
488
|
panel.margin = 24;
|
|
@@ -626,6 +504,8 @@ function buildLiveOverlayView(snapshot) {
|
|
|
626
504
|
overlay,
|
|
627
505
|
titleLabel,
|
|
628
506
|
statusLabel,
|
|
507
|
+
wasVisible: false,
|
|
508
|
+
currentPosition: getHmrDevOverlayPosition(),
|
|
629
509
|
};
|
|
630
510
|
applySnapshotToLiveRefs(refs, snapshot);
|
|
631
511
|
return refs;
|
|
@@ -682,33 +562,43 @@ function applySnapshotToLiveRefs(refs, snapshot) {
|
|
|
682
562
|
if (!refs) {
|
|
683
563
|
return;
|
|
684
564
|
}
|
|
685
|
-
//
|
|
686
|
-
//
|
|
687
|
-
//
|
|
565
|
+
// 'update' mode shares the live (in-tree) overlay chrome with
|
|
566
|
+
// 'connection'. Both render a small panel inside the page; only
|
|
567
|
+
// the colours, text, and (now) panel position change with the
|
|
568
|
+
// snapshot's tone and the configured overlay position.
|
|
688
569
|
const visible = snapshot.visible && (snapshot.mode === 'connection' || snapshot.mode === 'update');
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
// subtle on light app backgrounds that users couldn't
|
|
694
|
-
// tell the overlay had even fired. 50% alpha keeps the
|
|
695
|
-
// underlying app legible while making the apply event
|
|
696
|
-
// unmistakable during the (often <300ms) cycle.
|
|
697
|
-
// default → warm orange (existing connection-overlay look)
|
|
698
|
-
const overlayBg = snapshot.tone === 'error' ? '#b4181068' : snapshot.tone === 'success' ? '#1f883d80' : '#a1771683';
|
|
699
|
-
refs.overlay.backgroundColor = asColor(overlayBg);
|
|
570
|
+
const wasVisible = !!refs.wasVisible;
|
|
571
|
+
const position = getHmrDevOverlayPosition();
|
|
572
|
+
const previousPosition = refs.currentPosition || position;
|
|
573
|
+
const isToast = position !== 'center';
|
|
700
574
|
refs.titleLabel.text = snapshot.title;
|
|
575
|
+
refs.statusLabel.text = formatStatusText(snapshot);
|
|
701
576
|
const textColor = snapshot.tone === 'error' ? '#b41810e6' : snapshot.tone === 'success' ? '#0e6e2fff' : '#563e3fb1';
|
|
702
577
|
refs.titleLabel.color = asColor(textColor);
|
|
703
|
-
refs.statusLabel.text = formatStatusText(snapshot);
|
|
704
578
|
refs.statusLabel.color = asColor(textColor);
|
|
579
|
+
// Backdrop tints (centered modal only). Toast modes use a fully
|
|
580
|
+
// transparent backdrop so the rest of the app stays visible AND
|
|
581
|
+
// reachable; the panel itself carries enough colour to stand out.
|
|
582
|
+
if (isToast) {
|
|
583
|
+
refs.overlay.backgroundColor = asColor('transparent');
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
// Original wash-by-tone for centered:
|
|
587
|
+
// error → red wash (matches existing UX)
|
|
588
|
+
// success → richer green wash so the apply event is visible
|
|
589
|
+
// on bright app backgrounds
|
|
590
|
+
// default → warm orange (existing connection-overlay look)
|
|
591
|
+
const overlayBg = snapshot.tone === 'error' ? '#b4181068' : snapshot.tone === 'success' ? '#1f883d80' : '#a1771683';
|
|
592
|
+
refs.overlay.backgroundColor = asColor(overlayBg);
|
|
593
|
+
}
|
|
594
|
+
// Panel chrome — toast and centered share the same chip look,
|
|
595
|
+
// just position differs. We keep the slightly richer green tint
|
|
596
|
+
// for the HMR success state so it pops without needing the
|
|
597
|
+
// backdrop wash.
|
|
598
|
+
let panel = null;
|
|
705
599
|
try {
|
|
706
|
-
|
|
600
|
+
panel = refs.titleLabel.parent;
|
|
707
601
|
if (panel) {
|
|
708
|
-
// Slightly richer green-tinted panel for HMR-apply so the
|
|
709
|
-
// title/status text reads at a glance against the brighter
|
|
710
|
-
// backdrop wash. White panel for connection/error keeps
|
|
711
|
-
// existing UX intact.
|
|
712
602
|
const panelBg = snapshot.tone === 'success' ? '#E6F8E9FF' : '#FFFFFFFF';
|
|
713
603
|
panel.backgroundColor = asColor(panelBg);
|
|
714
604
|
panel.opacity = 1;
|
|
@@ -717,9 +607,169 @@ function applySnapshotToLiveRefs(refs, snapshot) {
|
|
|
717
607
|
panel.borderRadius = 12;
|
|
718
608
|
}
|
|
719
609
|
catch { }
|
|
610
|
+
// Position-aware alignment. The wrapper GridLayout fills the
|
|
611
|
+
// page content area. NativeScript runs every Android activity
|
|
612
|
+
// edge-to-edge, so that area extends under the status bar and
|
|
613
|
+
// navigation bar — we fold the system-bar safe-area insets into
|
|
614
|
+
// the chip's margin (via computeAndroidToastMargin) so a top
|
|
615
|
+
// chip clears the status bar and a bottom chip clears the nav
|
|
616
|
+
// bar instead of being clipped behind them. readAndroidSafeAreaInsets
|
|
617
|
+
// returns null off-Android, so the margins collapse to their base
|
|
618
|
+
// values (no behavioural change on iOS's in-tree fallback / tests).
|
|
619
|
+
try {
|
|
620
|
+
if (position === 'top' || position === 'bottom') {
|
|
621
|
+
const m = computeAndroidToastMargin({ position, safeInsets: readAndroidSafeAreaInsets() });
|
|
622
|
+
panel.verticalAlignment = position;
|
|
623
|
+
panel.margin = `${m.top} ${m.right} ${m.bottom} ${m.left}`;
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
panel.verticalAlignment = 'middle';
|
|
627
|
+
panel.margin = 24;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
catch { }
|
|
631
|
+
// Force a tight re-measure so the StackLayout panel hugs the
|
|
632
|
+
// CURRENT title+status text. Connection stages can swap between
|
|
633
|
+
// frames whose text wraps to a different number of lines (e.g. a
|
|
634
|
+
// long 'reconnecting' "Retrying ws://…" detail vs. the short
|
|
635
|
+
// 'offline' message). Without an explicit relayout the panel can
|
|
636
|
+
// retain the tallest height it ever measured, leaving an oversized
|
|
637
|
+
// gap between title and message. Mirrors updateBootStatusLabel.
|
|
638
|
+
try {
|
|
639
|
+
refs.titleLabel.requestLayout?.();
|
|
640
|
+
refs.statusLabel.requestLayout?.();
|
|
641
|
+
panel.requestLayout?.();
|
|
642
|
+
}
|
|
643
|
+
catch { }
|
|
720
644
|
}
|
|
721
645
|
}
|
|
722
646
|
catch { }
|
|
647
|
+
// Touch passthrough for toast; centered mode keeps the
|
|
648
|
+
// blocking modal so the dim backdrop is meaningful.
|
|
649
|
+
try {
|
|
650
|
+
refs.overlay.isUserInteractionEnabled = !isToast;
|
|
651
|
+
}
|
|
652
|
+
catch { }
|
|
653
|
+
const positionChanged = previousPosition !== position;
|
|
654
|
+
const justAppeared = visible && (!wasVisible || positionChanged);
|
|
655
|
+
const justDismissed = !visible && wasVisible;
|
|
656
|
+
if (justAppeared) {
|
|
657
|
+
refs.overlay.visibility = 'visible';
|
|
658
|
+
if (isToast && panel && typeof panel.animate === 'function') {
|
|
659
|
+
animateLivePanelIn(panel, position);
|
|
660
|
+
}
|
|
661
|
+
else if (panel) {
|
|
662
|
+
try {
|
|
663
|
+
panel.translateY = 0;
|
|
664
|
+
panel.opacity = 1;
|
|
665
|
+
}
|
|
666
|
+
catch { }
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
else if (justDismissed) {
|
|
670
|
+
if (isToast && panel && typeof panel.animate === 'function') {
|
|
671
|
+
animateLivePanelOut(panel, previousPosition, () => {
|
|
672
|
+
try {
|
|
673
|
+
refs.overlay.visibility = 'collapse';
|
|
674
|
+
}
|
|
675
|
+
catch { }
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
refs.overlay.visibility = 'collapse';
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
// Steady-state refresh (e.g. offline → reconnecting → offline while
|
|
684
|
+
// already visible): no slide animation fires here, so clear any
|
|
685
|
+
// transform residue a previously-interrupted slide-in/out may have
|
|
686
|
+
// left on the panel. Otherwise the chip can appear shifted or
|
|
687
|
+
// faded across rapid connection-stage swaps.
|
|
688
|
+
if (visible && panel) {
|
|
689
|
+
try {
|
|
690
|
+
panel.translateY = 0;
|
|
691
|
+
panel.opacity = 1;
|
|
692
|
+
}
|
|
693
|
+
catch { }
|
|
694
|
+
}
|
|
695
|
+
refs.overlay.visibility = visible ? 'visible' : 'collapse';
|
|
696
|
+
}
|
|
697
|
+
if (typeof refs.wasVisible !== 'undefined')
|
|
698
|
+
refs.wasVisible = visible;
|
|
699
|
+
if (typeof refs.currentPosition !== 'undefined')
|
|
700
|
+
refs.currentPosition = position;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Slide-in animation for the in-tree toast panel.
|
|
704
|
+
*
|
|
705
|
+
* NativeScript's `View.animate({ translate, opacity, duration, curve })`
|
|
706
|
+
* is widely available across Core versions, so we don't depend on any
|
|
707
|
+
* specific curve enum being importable here. We use a moderate-to-snappy
|
|
708
|
+
* 320ms ease-out which feels close to a UIView spring without needing
|
|
709
|
+
* platform-specific APIs.
|
|
710
|
+
*/
|
|
711
|
+
function animateLivePanelIn(panel, position) {
|
|
712
|
+
if (!panel || typeof panel.animate !== 'function')
|
|
713
|
+
return;
|
|
714
|
+
try {
|
|
715
|
+
const startY = position === 'bottom' ? 80 : -80;
|
|
716
|
+
panel.translateY = startY;
|
|
717
|
+
panel.opacity = 0;
|
|
718
|
+
const result = panel.animate({
|
|
719
|
+
translate: { x: 0, y: 0 },
|
|
720
|
+
opacity: 1,
|
|
721
|
+
duration: 320,
|
|
722
|
+
curve: 'easeOut',
|
|
723
|
+
});
|
|
724
|
+
if (result && typeof result.catch === 'function') {
|
|
725
|
+
result.catch(() => {
|
|
726
|
+
try {
|
|
727
|
+
panel.translateY = 0;
|
|
728
|
+
panel.opacity = 1;
|
|
729
|
+
}
|
|
730
|
+
catch { }
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
catch {
|
|
735
|
+
try {
|
|
736
|
+
panel.translateY = 0;
|
|
737
|
+
panel.opacity = 1;
|
|
738
|
+
}
|
|
739
|
+
catch { }
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
function animateLivePanelOut(panel, position, onComplete) {
|
|
743
|
+
if (!panel || typeof panel.animate !== 'function') {
|
|
744
|
+
onComplete();
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
try {
|
|
748
|
+
const targetY = position === 'bottom' ? 80 : -80;
|
|
749
|
+
const result = panel.animate({
|
|
750
|
+
translate: { x: 0, y: targetY },
|
|
751
|
+
opacity: 0,
|
|
752
|
+
duration: 220,
|
|
753
|
+
curve: 'easeIn',
|
|
754
|
+
});
|
|
755
|
+
const finish = () => {
|
|
756
|
+
try {
|
|
757
|
+
panel.translateY = 0;
|
|
758
|
+
panel.opacity = 1;
|
|
759
|
+
}
|
|
760
|
+
catch { }
|
|
761
|
+
onComplete();
|
|
762
|
+
};
|
|
763
|
+
if (result && typeof result.then === 'function') {
|
|
764
|
+
result.then(finish, finish);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
finish();
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
catch {
|
|
771
|
+
onComplete();
|
|
772
|
+
}
|
|
723
773
|
}
|
|
724
774
|
// pure helpers for iOS window promotion. Factored out so the layout
|
|
725
775
|
// math and window-level selection stay unit-testable without booting a
|
|
@@ -739,8 +789,17 @@ export function computeIosOverlayWindowLevel(baseAlert) {
|
|
|
739
789
|
/**
|
|
740
790
|
* Layout math for the live overlay when it runs inside its own UIWindow.
|
|
741
791
|
* Pure, deterministic and independent of UIKit so we can verify the rules
|
|
742
|
-
* (max panel width,
|
|
743
|
-
* from tests.
|
|
792
|
+
* (max panel width, position-aware placement, safe-area clamping, sane
|
|
793
|
+
* defaults) from tests.
|
|
794
|
+
*
|
|
795
|
+
* `position` controls where the panel sits vertically:
|
|
796
|
+
* - 'top': hugs `safeInsets.top + toastVerticalInset` so the chip
|
|
797
|
+
* sits just below the notch / Dynamic Island.
|
|
798
|
+
* - 'bottom': hugs `viewHeight - safeInsets.bottom - panelHeight -
|
|
799
|
+
* toastVerticalInset` so the chip sits just above the
|
|
800
|
+
* home indicator / nav bar.
|
|
801
|
+
* - 'center': original modal placement (vertically centered, clamped
|
|
802
|
+
* so it never crosses the top safe-area inset).
|
|
744
803
|
*/
|
|
745
804
|
export function computeIosOverlayLayout(input) {
|
|
746
805
|
const viewWidth = Math.max(0, Number(input.viewWidth) || 0);
|
|
@@ -758,15 +817,41 @@ export function computeIosOverlayLayout(input) {
|
|
|
758
817
|
const panelPadding = Math.max(0, Number(input.panelPadding ?? 16));
|
|
759
818
|
const interLabelSpacing = Math.max(0, Number(input.interLabelSpacing ?? 10));
|
|
760
819
|
const minTopInset = Math.max(0, Number(input.minTopInset ?? 20));
|
|
820
|
+
// Default to 'center' on the pure function so the existing
|
|
821
|
+
// snapshot/layout tests remain stable; the runtime call site
|
|
822
|
+
// (layoutIosOverlayRefs) reads the configured position from
|
|
823
|
+
// `getHmrDevOverlayPosition()` and forwards it explicitly.
|
|
824
|
+
const position = input.position ?? 'center';
|
|
825
|
+
// Distance between the panel and the safe-area edge in toast
|
|
826
|
+
// modes. 8pt mirrors the typical iOS notification chip inset and
|
|
827
|
+
// keeps the chip from hugging the notch / home indicator.
|
|
828
|
+
const toastVerticalInset = Math.max(0, Number(input.toastVerticalInset ?? 8));
|
|
761
829
|
const available = Math.max(0, viewWidth - 2 * horizontalMargin - safeInsets.left - safeInsets.right);
|
|
762
830
|
const panelWidth = Math.min(maxPanelWidth, available);
|
|
763
831
|
const innerWidth = Math.max(0, panelWidth - 2 * panelPadding);
|
|
764
832
|
const spacing = titleHeight > 0 && statusHeight > 0 ? interLabelSpacing : 0;
|
|
765
833
|
const panelHeight = panelPadding * 2 + titleHeight + spacing + statusHeight;
|
|
766
834
|
const panelX = Math.max(0, (viewWidth - panelWidth) / 2);
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
835
|
+
let panelY;
|
|
836
|
+
if (position === 'top') {
|
|
837
|
+
// Pin to the top safe-area inset (just below notch / Dynamic
|
|
838
|
+
// Island). Clamp non-negative for fully-NaN input.
|
|
839
|
+
panelY = Math.max(0, safeInsets.top + toastVerticalInset);
|
|
840
|
+
}
|
|
841
|
+
else if (position === 'bottom') {
|
|
842
|
+
// Pin to the bottom safe-area inset (just above home indicator
|
|
843
|
+
// / nav bar). If the panel can't fit between the safe-area
|
|
844
|
+
// insets we fall back to the top safe-area edge so the chip is
|
|
845
|
+
// always visible (rather than getting clipped off-screen).
|
|
846
|
+
const desired = viewHeight - safeInsets.bottom - panelHeight - toastVerticalInset;
|
|
847
|
+
panelY = Math.max(safeInsets.top + minTopInset, desired);
|
|
848
|
+
}
|
|
849
|
+
else {
|
|
850
|
+
// Center vertically, but never cross the top safe-area inset
|
|
851
|
+
// (notch/Dynamic Island). Original modal placement.
|
|
852
|
+
const centered = (viewHeight - panelHeight) / 2;
|
|
853
|
+
panelY = Math.max(safeInsets.top + minTopInset, centered);
|
|
854
|
+
}
|
|
770
855
|
return {
|
|
771
856
|
backdrop: { x: 0, y: 0, width: viewWidth, height: viewHeight },
|
|
772
857
|
panel: { x: panelX, y: panelY, width: panelWidth, height: panelHeight },
|
|
@@ -779,6 +864,59 @@ export function computeIosOverlayLayout(input) {
|
|
|
779
864
|
},
|
|
780
865
|
};
|
|
781
866
|
}
|
|
867
|
+
/**
|
|
868
|
+
* Margin math for the in-tree (Android) live/update toast chip.
|
|
869
|
+
*
|
|
870
|
+
* NativeScript enables edge-to-edge on every Android activity
|
|
871
|
+
* (`@nativescript/core` → `application.android.ts` → `enableEdgeToEdge`),
|
|
872
|
+
* so the page content — and therefore the overlay wrapper we inject into
|
|
873
|
+
* it — extends underneath the status bar and navigation bar. A fixed
|
|
874
|
+
* top/bottom margin leaves the chip tucked behind the system bars, where
|
|
875
|
+
* it gets clipped (Android 15 / API 35 enforces edge-to-edge, so this is
|
|
876
|
+
* now the norm rather than the exception).
|
|
877
|
+
*
|
|
878
|
+
* This pure helper folds the system-bar safe-area insets into the chip's
|
|
879
|
+
* margin so the toast always clears the status bar (top position) /
|
|
880
|
+
* navigation bar (bottom position). It is deterministic and free of
|
|
881
|
+
* native deps so the rules stay unit-testable — the runtime reads the
|
|
882
|
+
* live insets via `readAndroidSafeAreaInsets()` and forwards them here.
|
|
883
|
+
*
|
|
884
|
+
* - 'top': margin.top = baseVerticalInset + safeInsets.top
|
|
885
|
+
* - 'bottom': margin.bottom = baseVerticalInset + safeInsets.bottom
|
|
886
|
+
* - 'center': fixed `centerMargin` all around (vertically centered, so
|
|
887
|
+
* it never approaches the system bars on normal viewports).
|
|
888
|
+
*
|
|
889
|
+
* Horizontal margins always include the relevant safe-area inset so a
|
|
890
|
+
* landscape display cutout / gesture pill doesn't clip the chip edge.
|
|
891
|
+
*/
|
|
892
|
+
export function computeAndroidToastMargin(input) {
|
|
893
|
+
// Clamp to a finite, non-negative number; fall back to `fallback`
|
|
894
|
+
// for missing/NaN input so a glitched measurement can't produce a
|
|
895
|
+
// negative or NaN margin (which NativeScript would silently drop).
|
|
896
|
+
const clamp = (value, fallback) => {
|
|
897
|
+
const n = Number(value);
|
|
898
|
+
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
899
|
+
};
|
|
900
|
+
const safe = {
|
|
901
|
+
top: clamp(input.safeInsets?.top, 0),
|
|
902
|
+
bottom: clamp(input.safeInsets?.bottom, 0),
|
|
903
|
+
left: clamp(input.safeInsets?.left, 0),
|
|
904
|
+
right: clamp(input.safeInsets?.right, 0),
|
|
905
|
+
};
|
|
906
|
+
const baseVerticalInset = clamp(input.baseVerticalInset, 8);
|
|
907
|
+
const baseHorizontalInset = clamp(input.baseHorizontalInset, 16);
|
|
908
|
+
const centerMargin = clamp(input.centerMargin, 24);
|
|
909
|
+
if (input.position === 'center') {
|
|
910
|
+
return { top: centerMargin, right: centerMargin, bottom: centerMargin, left: centerMargin };
|
|
911
|
+
}
|
|
912
|
+
const left = Math.round(baseHorizontalInset + safe.left);
|
|
913
|
+
const right = Math.round(baseHorizontalInset + safe.right);
|
|
914
|
+
if (input.position === 'bottom') {
|
|
915
|
+
return { top: 0, right, bottom: Math.round(baseVerticalInset + safe.bottom), left };
|
|
916
|
+
}
|
|
917
|
+
// 'top' (and any unexpected value) hugs the status-bar safe area.
|
|
918
|
+
return { top: Math.round(baseVerticalInset + safe.top), right, bottom: 0, left };
|
|
919
|
+
}
|
|
782
920
|
/**
|
|
783
921
|
* Returns the iOS UIKit symbols we rely on if we're running on an iOS runtime
|
|
784
922
|
* with the metadata bridge available. Returns null on Android, web, or in
|
|
@@ -833,10 +971,7 @@ function buildIosOverlayRefs(state) {
|
|
|
833
971
|
const scene = findActiveWindowScene(host);
|
|
834
972
|
if (!scene) {
|
|
835
973
|
if (state.verbose) {
|
|
836
|
-
|
|
837
|
-
console.info('[ns-hmr-overlay] no active UIWindowScene; skipping iOS overlay promotion');
|
|
838
|
-
}
|
|
839
|
-
catch { }
|
|
974
|
+
console.info('[ns-hmr-overlay] no active UIWindowScene; skipping iOS overlay promotion');
|
|
840
975
|
}
|
|
841
976
|
return null;
|
|
842
977
|
}
|
|
@@ -883,13 +1018,35 @@ function buildIosOverlayRefs(state) {
|
|
|
883
1018
|
statusLabel.font = UIFont.systemFontOfSize(13);
|
|
884
1019
|
statusLabel.textColor = UIColor.darkGrayColor;
|
|
885
1020
|
panel.addSubview(statusLabel);
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1021
|
+
// Subtle drop-shadow so the toast chip reads against light app
|
|
1022
|
+
// content (white-on-white is invisible). The error / centered
|
|
1023
|
+
// branches still get the dim backdrop, so the shadow is mostly
|
|
1024
|
+
// a no-op for them — but it's a one-time setup.
|
|
889
1025
|
try {
|
|
890
|
-
|
|
1026
|
+
panel.layer.shadowColor = UIColor.blackColor.CGColor;
|
|
1027
|
+
panel.layer.shadowOpacity = 0.18;
|
|
1028
|
+
panel.layer.shadowRadius = 8;
|
|
1029
|
+
panel.layer.shadowOffset = { width: 0, height: 2 };
|
|
1030
|
+
panel.layer.masksToBounds = false;
|
|
891
1031
|
}
|
|
892
1032
|
catch { }
|
|
1033
|
+
// `wasVisible` / `currentPosition` are mutated by
|
|
1034
|
+
// applySnapshotToIosRefs when the snapshot triggers a slide-in
|
|
1035
|
+
// or slide-out. They start in the "hidden" state so the very
|
|
1036
|
+
// first visible snapshot animates in cleanly.
|
|
1037
|
+
return {
|
|
1038
|
+
window,
|
|
1039
|
+
controller,
|
|
1040
|
+
backdrop,
|
|
1041
|
+
panel,
|
|
1042
|
+
titleLabel,
|
|
1043
|
+
statusLabel,
|
|
1044
|
+
wasVisible: false,
|
|
1045
|
+
currentPosition: getHmrDevOverlayPosition(),
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
catch (err) {
|
|
1049
|
+
console.warn('[ns-hmr-overlay] iOS overlay construction failed:', err?.message || err);
|
|
893
1050
|
return null;
|
|
894
1051
|
}
|
|
895
1052
|
}
|
|
@@ -909,7 +1066,7 @@ function ensureIosOverlayRefs(state) {
|
|
|
909
1066
|
}
|
|
910
1067
|
return state.iosRefs;
|
|
911
1068
|
}
|
|
912
|
-
function layoutIosOverlayRefs(refs) {
|
|
1069
|
+
function layoutIosOverlayRefs(refs, position) {
|
|
913
1070
|
try {
|
|
914
1071
|
const bounds = refs.controller.view.bounds;
|
|
915
1072
|
const viewWidth = Number(bounds?.size?.width) || 0;
|
|
@@ -940,6 +1097,7 @@ function layoutIosOverlayRefs(refs) {
|
|
|
940
1097
|
maxPanelWidth,
|
|
941
1098
|
horizontalMargin,
|
|
942
1099
|
panelPadding,
|
|
1100
|
+
position,
|
|
943
1101
|
});
|
|
944
1102
|
const toCgRect = (rect) => ({
|
|
945
1103
|
origin: { x: rect.x, y: rect.y },
|
|
@@ -949,27 +1107,156 @@ function layoutIosOverlayRefs(refs) {
|
|
|
949
1107
|
refs.panel.frame = toCgRect(layout.panel);
|
|
950
1108
|
refs.titleLabel.frame = toCgRect(layout.title);
|
|
951
1109
|
refs.statusLabel.frame = toCgRect(layout.status);
|
|
1110
|
+
return layout;
|
|
952
1111
|
}
|
|
953
1112
|
catch (err) {
|
|
1113
|
+
console.warn('[ns-hmr-overlay] iOS overlay layout failed:', err?.message || err);
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Slide-in animation for the iOS toast panel. Off-screen start frame
|
|
1119
|
+
* lives just above (top) or below (bottom) the visible area; the panel
|
|
1120
|
+
* snaps to its target frame with a spring so the motion feels physical
|
|
1121
|
+
* without the heavy "settle" overshoot of a hard spring (damping 0.85
|
|
1122
|
+
* lands quickly with a small overshoot).
|
|
1123
|
+
*/
|
|
1124
|
+
function animateIosPanelIn(refs, position, layout) {
|
|
1125
|
+
const g = getOverlayGlobal();
|
|
1126
|
+
const UIView = g?.UIView;
|
|
1127
|
+
if (!UIView)
|
|
1128
|
+
return;
|
|
1129
|
+
try {
|
|
1130
|
+
const targetFrame = {
|
|
1131
|
+
origin: { x: layout.panel.x, y: layout.panel.y },
|
|
1132
|
+
size: { width: layout.panel.width, height: layout.panel.height },
|
|
1133
|
+
};
|
|
1134
|
+
// Off-screen start: distance includes a small fudge so the
|
|
1135
|
+
// shadow blur tail isn't visible at t=0.
|
|
1136
|
+
const startY = position === 'bottom' ? layout.backdrop.height + 24 : -(layout.panel.height + 24);
|
|
1137
|
+
refs.panel.frame = {
|
|
1138
|
+
origin: { x: layout.panel.x, y: startY },
|
|
1139
|
+
size: { width: layout.panel.width, height: layout.panel.height },
|
|
1140
|
+
};
|
|
1141
|
+
refs.panel.alpha = 0;
|
|
1142
|
+
try {
|
|
1143
|
+
if (typeof UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion === 'function') {
|
|
1144
|
+
UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion(0.42, 0, 0.85, 0.7, 0, () => {
|
|
1145
|
+
refs.panel.frame = targetFrame;
|
|
1146
|
+
refs.panel.alpha = 1;
|
|
1147
|
+
}, null);
|
|
1148
|
+
}
|
|
1149
|
+
else if (typeof UIView.animateWithDurationAnimations === 'function') {
|
|
1150
|
+
UIView.animateWithDurationAnimations(0.32, () => {
|
|
1151
|
+
refs.panel.frame = targetFrame;
|
|
1152
|
+
refs.panel.alpha = 1;
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
else {
|
|
1156
|
+
refs.panel.frame = targetFrame;
|
|
1157
|
+
refs.panel.alpha = 1;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
catch {
|
|
1161
|
+
refs.panel.frame = targetFrame;
|
|
1162
|
+
refs.panel.alpha = 1;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
catch { }
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Slide-out animation for the iOS toast panel. Mirrors animateIosPanelIn:
|
|
1169
|
+
* the panel travels to the nearest off-screen edge while fading out so
|
|
1170
|
+
* the dismissal still feels intentional even on fast HMR cycles.
|
|
1171
|
+
*/
|
|
1172
|
+
function animateIosPanelOut(refs, position, onComplete) {
|
|
1173
|
+
const g = getOverlayGlobal();
|
|
1174
|
+
const UIView = g?.UIView;
|
|
1175
|
+
const currentFrame = refs.panel?.frame;
|
|
1176
|
+
if (!UIView || !currentFrame) {
|
|
1177
|
+
onComplete();
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
try {
|
|
1181
|
+
const bounds = refs.controller?.view?.bounds;
|
|
1182
|
+
const viewHeight = Number(bounds?.size?.height) || 0;
|
|
1183
|
+
const targetY = position === 'bottom' ? viewHeight + 24 : -(Number(currentFrame.size?.height) + 24);
|
|
1184
|
+
const startFrame = currentFrame;
|
|
1185
|
+
const targetFrame = {
|
|
1186
|
+
origin: { x: Number(startFrame.origin?.x) || 0, y: targetY },
|
|
1187
|
+
size: startFrame.size,
|
|
1188
|
+
};
|
|
954
1189
|
try {
|
|
955
|
-
|
|
1190
|
+
if (typeof UIView.animateWithDurationDelayOptionsAnimationsCompletion === 'function') {
|
|
1191
|
+
// UIViewAnimationOptionCurveEaseIn = 1 << 16 — accelerate
|
|
1192
|
+
// out so the dismissal doesn't drag on screen.
|
|
1193
|
+
UIView.animateWithDurationDelayOptionsAnimationsCompletion(0.22, 0, 1 << 16, () => {
|
|
1194
|
+
refs.panel.frame = targetFrame;
|
|
1195
|
+
refs.panel.alpha = 0;
|
|
1196
|
+
}, () => onComplete());
|
|
1197
|
+
}
|
|
1198
|
+
else if (typeof UIView.animateWithDurationAnimationsCompletion === 'function') {
|
|
1199
|
+
UIView.animateWithDurationAnimationsCompletion(0.22, () => {
|
|
1200
|
+
refs.panel.frame = targetFrame;
|
|
1201
|
+
refs.panel.alpha = 0;
|
|
1202
|
+
}, () => onComplete());
|
|
1203
|
+
}
|
|
1204
|
+
else {
|
|
1205
|
+
refs.panel.alpha = 0;
|
|
1206
|
+
onComplete();
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
catch {
|
|
1210
|
+
refs.panel.alpha = 0;
|
|
1211
|
+
onComplete();
|
|
956
1212
|
}
|
|
957
|
-
|
|
1213
|
+
}
|
|
1214
|
+
catch {
|
|
1215
|
+
onComplete();
|
|
958
1216
|
}
|
|
959
1217
|
}
|
|
960
1218
|
function applySnapshotToIosRefs(refs, snapshot) {
|
|
961
1219
|
if (!refs)
|
|
962
1220
|
return false;
|
|
963
1221
|
try {
|
|
964
|
-
//
|
|
965
|
-
//
|
|
966
|
-
//
|
|
967
|
-
//
|
|
968
|
-
//
|
|
1222
|
+
// 'update' mode rides the same dedicated UIWindow as
|
|
1223
|
+
// 'connection' so the HMR apply overlay always stacks above
|
|
1224
|
+
// modals/sheets/system alerts. The window is constructed
|
|
1225
|
+
// lazily (ensureIosOverlayRefs) and reused for the lifetime of
|
|
1226
|
+
// the dev session.
|
|
969
1227
|
const visible = snapshot.visible && (snapshot.mode === 'connection' || snapshot.mode === 'update');
|
|
970
|
-
|
|
971
|
-
|
|
1228
|
+
const wasVisible = !!refs.wasVisible;
|
|
1229
|
+
const position = getHmrDevOverlayPosition();
|
|
1230
|
+
const previousPosition = refs.currentPosition;
|
|
1231
|
+
const isToast = position !== 'center';
|
|
1232
|
+
// Touches pass through the overlay window in toast mode so
|
|
1233
|
+
// the user can keep tapping the app while the HMR chip is
|
|
1234
|
+
// shown. In centered mode we keep the blocking
|
|
1235
|
+
// behaviour (the dim backdrop is itself a hint to wait).
|
|
1236
|
+
try {
|
|
1237
|
+
refs.window.userInteractionEnabled = !isToast;
|
|
1238
|
+
}
|
|
1239
|
+
catch { }
|
|
1240
|
+
if (!visible) {
|
|
1241
|
+
// Animate out before hiding the window so the dismissal
|
|
1242
|
+
// has a discoverable motion. Only animate when previously
|
|
1243
|
+
// visible and in toast mode — centered modal hides instantly.
|
|
1244
|
+
if (wasVisible && isToast) {
|
|
1245
|
+
animateIosPanelOut(refs, previousPosition, () => {
|
|
1246
|
+
try {
|
|
1247
|
+
refs.window.hidden = true;
|
|
1248
|
+
}
|
|
1249
|
+
catch { }
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
else {
|
|
1253
|
+
refs.window.hidden = true;
|
|
1254
|
+
}
|
|
1255
|
+
refs.wasVisible = false;
|
|
1256
|
+
refs.currentPosition = position;
|
|
972
1257
|
return true;
|
|
1258
|
+
}
|
|
1259
|
+
refs.window.hidden = false;
|
|
973
1260
|
refs.titleLabel.text = snapshot.title || '';
|
|
974
1261
|
refs.statusLabel.text = formatStatusText(snapshot);
|
|
975
1262
|
const host = getIosOverlayHost();
|
|
@@ -983,9 +1270,6 @@ function applySnapshotToIosRefs(refs, snapshot) {
|
|
|
983
1270
|
refs.panel.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(1, 0.96, 0.96, 1);
|
|
984
1271
|
refs.titleLabel.textColor = UIColor.colorWithRedGreenBlueAlpha(0.7, 0.1, 0.06, 1);
|
|
985
1272
|
refs.statusLabel.textColor = UIColor.colorWithRedGreenBlueAlpha(0.7, 0.1, 0.06, 0.9);
|
|
986
|
-
// Slightly stronger dimming on errors; users need to
|
|
987
|
-
// notice these.
|
|
988
|
-
refs.backdrop.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0, 0, 0, 0.35);
|
|
989
1273
|
}
|
|
990
1274
|
else if (isSuccess) {
|
|
991
1275
|
// Slightly more saturated green panel + dark-green
|
|
@@ -997,31 +1281,56 @@ function applySnapshotToIosRefs(refs, snapshot) {
|
|
|
997
1281
|
refs.panel.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0.9, 0.97, 0.91, 1);
|
|
998
1282
|
refs.titleLabel.textColor = UIColor.colorWithRedGreenBlueAlpha(0.05, 0.43, 0.18, 1);
|
|
999
1283
|
refs.statusLabel.textColor = UIColor.colorWithRedGreenBlueAlpha(0.05, 0.43, 0.18, 1);
|
|
1000
|
-
// Bumped from 0.12 to 0.28. The 0.12 wash was so
|
|
1001
|
-
// faint on bright app backgrounds that the overlay
|
|
1002
|
-
// was effectively invisible during a fast cycle.
|
|
1003
|
-
// 0.28 still keeps the app readable underneath but
|
|
1004
|
-
// makes the HMR event visually unmistakable.
|
|
1005
|
-
refs.backdrop.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0, 0.15, 0.05, 0.28);
|
|
1006
1284
|
}
|
|
1007
1285
|
else {
|
|
1008
1286
|
// Default (info / warn) — existing connection look.
|
|
1009
1287
|
refs.panel.backgroundColor = UIColor.whiteColor;
|
|
1010
1288
|
refs.titleLabel.textColor = UIColor.blackColor;
|
|
1011
1289
|
refs.statusLabel.textColor = UIColor.darkGrayColor;
|
|
1290
|
+
}
|
|
1291
|
+
// Backdrop dims only in centered mode; toast mode keeps
|
|
1292
|
+
// the rest of the app fully visible/usable. Errors get
|
|
1293
|
+
// a slightly stronger dim in centered mode because the
|
|
1294
|
+
// user MUST notice them.
|
|
1295
|
+
if (isToast) {
|
|
1296
|
+
refs.backdrop.backgroundColor = UIColor.clearColor;
|
|
1297
|
+
}
|
|
1298
|
+
else if (isError) {
|
|
1012
1299
|
refs.backdrop.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0, 0, 0, 0.35);
|
|
1013
1300
|
}
|
|
1301
|
+
else if (isSuccess) {
|
|
1302
|
+
refs.backdrop.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0, 0.15, 0.05, 0.28);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
refs.backdrop.backgroundColor = UIColor.colorWithRedGreenBlueAlpha(0, 0, 0, 0.35);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
catch { }
|
|
1309
|
+
}
|
|
1310
|
+
const layout = layoutIosOverlayRefs(refs, position);
|
|
1311
|
+
// Slide-in animation only fires on the actual hidden→visible
|
|
1312
|
+
// transition (or on a position swap — e.g. dev toggling top
|
|
1313
|
+
// to bottom mid-cycle). Subsequent updates within the same
|
|
1314
|
+
// visible cycle just refresh text/colours without re-animating.
|
|
1315
|
+
const positionChanged = previousPosition !== position;
|
|
1316
|
+
const justAppeared = !wasVisible || positionChanged;
|
|
1317
|
+
if (justAppeared && isToast && layout) {
|
|
1318
|
+
animateIosPanelIn(refs, position, layout);
|
|
1319
|
+
}
|
|
1320
|
+
else if (justAppeared && !isToast) {
|
|
1321
|
+
// Centered modal: ensure alpha is reset to 1 in case a
|
|
1322
|
+
// previous toast-mode dismissal left it at 0.
|
|
1323
|
+
try {
|
|
1324
|
+
refs.panel.alpha = 1;
|
|
1014
1325
|
}
|
|
1015
1326
|
catch { }
|
|
1016
1327
|
}
|
|
1017
|
-
|
|
1328
|
+
refs.wasVisible = true;
|
|
1329
|
+
refs.currentPosition = position;
|
|
1018
1330
|
return true;
|
|
1019
1331
|
}
|
|
1020
1332
|
catch (err) {
|
|
1021
|
-
|
|
1022
|
-
console.warn('[ns-hmr-overlay] iOS overlay apply failed:', err?.message || err);
|
|
1023
|
-
}
|
|
1024
|
-
catch { }
|
|
1333
|
+
console.warn('[ns-hmr-overlay] iOS overlay apply failed:', err?.message || err);
|
|
1025
1334
|
return false;
|
|
1026
1335
|
}
|
|
1027
1336
|
}
|
|
@@ -1064,21 +1373,19 @@ function applyRuntimeSnapshot(snapshot) {
|
|
|
1064
1373
|
}
|
|
1065
1374
|
return state.snapshot;
|
|
1066
1375
|
}
|
|
1067
|
-
//
|
|
1068
|
-
//
|
|
1069
|
-
//
|
|
1070
|
-
//
|
|
1071
|
-
//
|
|
1072
|
-
//
|
|
1073
|
-
// that something happened.
|
|
1376
|
+
// How long the 'complete' frame stays on screen before we auto-hide.
|
|
1377
|
+
// The original 350ms was too tight: many HMR cycles complete in
|
|
1378
|
+
// 50–250ms, so the *total* overlay lifetime (received → complete +
|
|
1379
|
+
// 350ms) was often under 500ms, which is faster than the human eye
|
|
1380
|
+
// can comfortably register. 600ms gives the user time to read the
|
|
1381
|
+
// "Total Xms" line and confirm visually that something happened.
|
|
1074
1382
|
const UPDATE_AUTO_HIDE_MS = 600;
|
|
1075
|
-
//
|
|
1076
|
-
//
|
|
1077
|
-
//
|
|
1078
|
-
//
|
|
1079
|
-
// the
|
|
1080
|
-
//
|
|
1081
|
-
// MIN_VISIBLE_MS - elapsed-since-received).
|
|
1383
|
+
// Minimum perceptible duration for an entire update overlay cycle
|
|
1384
|
+
// (from 'received' to hide). If the cycle finished in 50ms (e.g., a
|
|
1385
|
+
// tiny HTML edit on a warm cache), we still hold for ~MIN_VISIBLE_MS
|
|
1386
|
+
// total before hiding so the overlay is actually seen. Combined with
|
|
1387
|
+
// UPDATE_AUTO_HIDE_MS, the *effective* hold-after-complete =
|
|
1388
|
+
// max(UPDATE_AUTO_HIDE_MS, MIN_VISIBLE_MS - elapsed-since-received).
|
|
1082
1389
|
const UPDATE_MIN_VISIBLE_MS = 800;
|
|
1083
1390
|
function clearUpdateAutoHideTimer(state) {
|
|
1084
1391
|
if (state.updateAutoHideTimer) {
|
|
@@ -1157,7 +1464,17 @@ function createOverlayApi() {
|
|
|
1157
1464
|
const state = getRuntimeState();
|
|
1158
1465
|
clearUpdateAutoHideTimer(state);
|
|
1159
1466
|
state.updateCycleStartedAt = 0;
|
|
1160
|
-
|
|
1467
|
+
const next = createBootOverlaySnapshot(stage, info);
|
|
1468
|
+
// Monotonic boot-progress ratchet: boot stages can fire out of
|
|
1469
|
+
// order across boot paths (JS session bootstrap vs the
|
|
1470
|
+
// http-bootloader fallback) and individual bases were tuned
|
|
1471
|
+
// independently, so clamp boot→boot transitions to never go
|
|
1472
|
+
// backwards. Non-boot snapshots (error/ready) bypass — they
|
|
1473
|
+
// genuinely want to reset the visual.
|
|
1474
|
+
if (next.mode === 'boot' && state.snapshot.mode === 'boot' && typeof next.progress === 'number' && typeof state.snapshot.progress === 'number' && next.progress < state.snapshot.progress) {
|
|
1475
|
+
next.progress = state.snapshot.progress;
|
|
1476
|
+
}
|
|
1477
|
+
return applyRuntimeSnapshot(next);
|
|
1161
1478
|
},
|
|
1162
1479
|
setConnectionStage(stage, info) {
|
|
1163
1480
|
const state = getRuntimeState();
|
|
@@ -1217,12 +1534,54 @@ function createOverlayApi() {
|
|
|
1217
1534
|
},
|
|
1218
1535
|
};
|
|
1219
1536
|
}
|
|
1537
|
+
// The NS_VITE_PROGRESS_OVERLAY opt-out. Read the build-time define (const-substituted
|
|
1538
|
+
// into served modules) first, then fall back to the globalThis seed, defaulting to
|
|
1539
|
+
// enabled — mirrors the gate used by the per-framework update overlays.
|
|
1540
|
+
function isHmrProgressOverlayEnabled() {
|
|
1541
|
+
try {
|
|
1542
|
+
if (typeof __NS_HMR_PROGRESS_OVERLAY_ENABLED__ === 'boolean')
|
|
1543
|
+
return __NS_HMR_PROGRESS_OVERLAY_ENABLED__;
|
|
1544
|
+
}
|
|
1545
|
+
catch { }
|
|
1546
|
+
try {
|
|
1547
|
+
const seeded = getGlobalScope().__NS_HMR_PROGRESS_OVERLAY_ENABLED__;
|
|
1548
|
+
if (typeof seeded === 'boolean')
|
|
1549
|
+
return seeded;
|
|
1550
|
+
}
|
|
1551
|
+
catch { }
|
|
1552
|
+
return true;
|
|
1553
|
+
}
|
|
1554
|
+
// When the overlay is opted out, every surface (boot / connection / update / pending)
|
|
1555
|
+
// becomes a no-op so nothing is ever drawn. The boot placeholder root and the
|
|
1556
|
+
// `__NS_HMR_BOOT_COMPLETE__` signal are owned by `root-placeholder.ts` and are
|
|
1557
|
+
// unaffected, so boot + HMR keep working — the user just sees no progress UI.
|
|
1558
|
+
function createNoopOverlayApi() {
|
|
1559
|
+
const snapshot = () => getRuntimeState().snapshot;
|
|
1560
|
+
return {
|
|
1561
|
+
ensureBootPage() {
|
|
1562
|
+
return null;
|
|
1563
|
+
},
|
|
1564
|
+
setBootStage() {
|
|
1565
|
+
return snapshot();
|
|
1566
|
+
},
|
|
1567
|
+
setConnectionStage() {
|
|
1568
|
+
return snapshot();
|
|
1569
|
+
},
|
|
1570
|
+
setUpdateStage() {
|
|
1571
|
+
return snapshot();
|
|
1572
|
+
},
|
|
1573
|
+
hide() { },
|
|
1574
|
+
getSnapshot() {
|
|
1575
|
+
return snapshot();
|
|
1576
|
+
},
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1220
1579
|
export function ensureHmrDevOverlayRuntimeInstalled(verbose) {
|
|
1221
1580
|
const g = getOverlayGlobal();
|
|
1222
1581
|
const state = getRuntimeState();
|
|
1223
1582
|
state.verbose = state.verbose || !!verbose;
|
|
1224
1583
|
if (!g.__NS_HMR_DEV_OVERLAY__) {
|
|
1225
|
-
g.__NS_HMR_DEV_OVERLAY__ = createOverlayApi();
|
|
1584
|
+
g.__NS_HMR_DEV_OVERLAY__ = isHmrProgressOverlayEnabled() ? createOverlayApi() : createNoopOverlayApi();
|
|
1226
1585
|
}
|
|
1227
1586
|
return g.__NS_HMR_DEV_OVERLAY__;
|
|
1228
1587
|
}
|
|
@@ -1235,11 +1594,11 @@ export function setHmrBootStage(stage, info) {
|
|
|
1235
1594
|
export function setHmrConnectionStage(stage, info) {
|
|
1236
1595
|
return ensureHmrDevOverlayRuntimeInstalled().setConnectionStage(stage, info);
|
|
1237
1596
|
}
|
|
1238
|
-
//
|
|
1239
|
-
//
|
|
1240
|
-
//
|
|
1241
|
-
//
|
|
1242
|
-
//
|
|
1597
|
+
// Public entry point for driving the HMR-applying overlay. Callers
|
|
1598
|
+
// walk through stages (received → evicting → reimporting → rebooting
|
|
1599
|
+
// → complete); 'complete' auto-hides after a short interval.
|
|
1600
|
+
// Soft-fails (no-op) if the runtime overlay was never installed
|
|
1601
|
+
// (e.g., production builds, test environments).
|
|
1243
1602
|
export function setHmrUpdateStage(stage, info) {
|
|
1244
1603
|
return ensureHmrDevOverlayRuntimeInstalled().setUpdateStage(stage, info);
|
|
1245
1604
|
}
|