@nativescript/core 9.1.0-alpha.9 → 9.1.0-next.0
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/accessibility/accessibility-common.d.ts +8 -0
- package/accessibility/accessibility-common.js +28 -0
- package/accessibility/accessibility-common.js.map +1 -1
- package/application/application-common.d.ts +187 -4
- package/application/application-common.js +402 -94
- package/application/application-common.js.map +1 -1
- package/application/application-interfaces.d.ts +59 -1
- package/application/application.android.d.ts +22 -1
- package/application/application.android.js +193 -15
- package/application/application.android.js.map +1 -1
- package/application/application.d.ts +121 -66
- package/application/application.ios.d.ts +104 -27
- package/application/application.ios.js +549 -352
- package/application/application.ios.js.map +1 -1
- package/application/helpers-common.d.ts +5 -0
- package/application/helpers-common.js +23 -1
- package/application/helpers-common.js.map +1 -1
- package/application/scene-delegate-bridge.d.ts +55 -0
- package/application/scene-delegate-bridge.js +122 -0
- package/application/scene-delegate-bridge.js.map +1 -0
- package/config/config.interface.d.ts +44 -2
- package/core-types/index.d.ts +9 -2
- package/core-types/index.js +7 -0
- package/core-types/index.js.map +1 -1
- package/css/CSS3Parser.js +3 -2
- package/css/CSS3Parser.js.map +1 -1
- package/css/system-classes.d.ts +9 -0
- package/css/system-classes.js +23 -0
- package/css/system-classes.js.map +1 -1
- package/data/observable/index.d.ts +5 -0
- package/data/observable/index.js +46 -9
- package/data/observable/index.js.map +1 -1
- package/debugger/dom-types.js +31 -1
- package/debugger/dom-types.js.map +1 -1
- package/fetch/index.mjs +2 -2
- package/file-system/file-system-access.ios.js +18 -10
- package/file-system/file-system-access.ios.js.map +1 -1
- package/file-system/index.d.ts +3 -3
- package/global-types.d.ts +39 -33
- package/globals/global-utils.d.ts +6 -1
- package/globals/global-utils.js +10 -5
- package/globals/global-utils.js.map +1 -1
- package/globals/index.js +14 -4
- package/globals/index.js.map +1 -1
- package/globals/polyfills/utils.js +2 -0
- package/globals/polyfills/utils.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/inspector_modules.js +1 -1
- package/inspector_modules.js.map +1 -1
- package/native-window/index.d.ts +426 -0
- package/native-window/index.js +4 -0
- package/native-window/index.js.map +1 -0
- package/native-window/native-window-common.d.ts +153 -0
- package/native-window/native-window-common.js +340 -0
- package/native-window/native-window-common.js.map +1 -0
- package/native-window/native-window-interfaces.d.ts +186 -0
- package/native-window/native-window-interfaces.js +90 -0
- package/native-window/native-window-interfaces.js.map +1 -0
- package/native-window/native-window.android.d.ts +59 -0
- package/native-window/native-window.android.js +175 -0
- package/native-window/native-window.android.js.map +1 -0
- package/native-window/native-window.ios.d.ts +57 -0
- package/native-window/native-window.ios.js +208 -0
- package/native-window/native-window.ios.js.map +1 -0
- package/native-window/window-base.d.ts +103 -0
- package/native-window/window-base.js +78 -0
- package/native-window/window-base.js.map +1 -0
- package/package.json +1 -1
- package/platforms/android/widgets-release.aar +0 -0
- package/platforms/ios/TNSWidgets.xcframework/Info.plist +14 -14
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Resources/Info.plist +7 -7
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/Resources/Info.plist +7 -7
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/A/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/Resources/Info.plist +7 -7
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/TNSWidgets.framework/Versions/Current/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-maccatalyst/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/TNSWidgets.framework/_CodeSignature/CodeResources +1 -1
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/ios-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/Info.plist +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/TNSWidgets.framework/_CodeSignature/CodeResources +1 -1
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/DWARF/TNSWidgets +0 -0
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/aarch64/TNSWidgets.yml +78 -78
- package/platforms/ios/TNSWidgets.xcframework/xros-arm64_x86_64-simulator/dSYMs/TNSWidgets.framework.dSYM/Contents/Resources/Relocations/x86_64/TNSWidgets.yml +78 -78
- package/platforms/ios/src/NativeScriptMainWindow.swift +72 -39
- package/trace/index.d.ts +2 -2
- package/ui/action-bar/action-bar-common.js +0 -1
- package/ui/action-bar/action-bar-common.js.map +1 -1
- package/ui/animation/keyframe-animation.d.ts +1 -1
- package/ui/builder/index.js +9 -1
- package/ui/builder/index.js.map +1 -1
- package/ui/core/properties/index.d.ts +24 -1
- package/ui/core/properties/index.js +96 -10
- package/ui/core/properties/index.js.map +1 -1
- package/ui/core/properties/property-shared.js +11 -2
- package/ui/core/properties/property-shared.js.map +1 -1
- package/ui/core/view/index.android.js +29 -7
- package/ui/core/view/index.android.js.map +1 -1
- package/ui/core/view/index.d.ts +58 -1
- package/ui/core/view/index.ios.js +11 -2
- package/ui/core/view/index.ios.js.map +1 -1
- package/ui/core/view/view-common.d.ts +37 -0
- package/ui/core/view/view-common.js +81 -0
- package/ui/core/view/view-common.js.map +1 -1
- package/ui/core/view/view-helper/index.ios.d.ts +6 -20
- package/ui/core/view/view-helper/index.ios.js +10 -31
- package/ui/core/view/view-helper/index.ios.js.map +1 -1
- package/ui/core/view/view-helper/view-helper-common.js +21 -3
- package/ui/core/view/view-helper/view-helper-common.js.map +1 -1
- package/ui/core/view-base/index.d.ts +13 -8
- package/ui/core/view-base/index.js +54 -33
- package/ui/core/view-base/index.js.map +1 -1
- package/ui/frame/frame-common.d.ts +14 -2
- package/ui/frame/frame-common.js +19 -17
- package/ui/frame/frame-common.js.map +1 -1
- package/ui/frame/frame-constants.d.ts +9 -0
- package/ui/frame/frame-constants.js +10 -0
- package/ui/frame/frame-constants.js.map +1 -0
- package/ui/frame/frame-helper-for-android.d.ts +2 -2
- package/ui/frame/frame-helper-for-android.js +14 -5
- package/ui/frame/frame-helper-for-android.js.map +1 -1
- package/ui/frame/frame-interfaces.d.ts +1 -1
- package/ui/frame/frame-stack.d.ts +17 -1
- package/ui/frame/frame-stack.js +32 -5
- package/ui/frame/frame-stack.js.map +1 -1
- package/ui/frame/index.android.d.ts +1 -1
- package/ui/frame/index.android.js +139 -38
- package/ui/frame/index.android.js.map +1 -1
- package/ui/frame/index.d.ts +15 -5
- package/ui/image/image-common.js +1 -1
- package/ui/image/image-common.js.map +1 -1
- package/ui/image/index.android.js +13 -1
- package/ui/image/index.android.js.map +1 -1
- package/ui/layouts/absolute-layout/index.ios.js +4 -5
- package/ui/layouts/absolute-layout/index.ios.js.map +1 -1
- package/ui/layouts/dock-layout/index.ios.js +4 -5
- package/ui/layouts/dock-layout/index.ios.js.map +1 -1
- package/ui/layouts/flexbox-layout/flexbox-layout-common.d.ts +7 -0
- package/ui/layouts/flexbox-layout/flexbox-layout-common.js +18 -0
- package/ui/layouts/flexbox-layout/flexbox-layout-common.js.map +1 -1
- package/ui/layouts/flexbox-layout/index.android.d.ts +5 -0
- package/ui/layouts/flexbox-layout/index.android.js +15 -0
- package/ui/layouts/flexbox-layout/index.android.js.map +1 -1
- package/ui/layouts/flexbox-layout/index.d.ts +19 -1
- package/ui/layouts/flexbox-layout/index.ios.d.ts +2 -0
- package/ui/layouts/flexbox-layout/index.ios.js +245 -198
- package/ui/layouts/flexbox-layout/index.ios.js.map +1 -1
- package/ui/layouts/grid-layout/index.ios.js +4 -5
- package/ui/layouts/grid-layout/index.ios.js.map +1 -1
- package/ui/layouts/layout-base-common.d.ts +1 -0
- package/ui/layouts/layout-base-common.js +21 -0
- package/ui/layouts/layout-base-common.js.map +1 -1
- package/ui/layouts/stack-layout/index.ios.js +4 -5
- package/ui/layouts/stack-layout/index.ios.js.map +1 -1
- package/ui/layouts/wrap-layout/index.ios.js +4 -5
- package/ui/layouts/wrap-layout/index.ios.js.map +1 -1
- package/ui/list-view/index.android.js +3 -2
- package/ui/list-view/index.android.js.map +1 -1
- package/ui/list-view/index.ios.d.ts +2 -2
- package/ui/list-view/index.ios.js +15 -17
- package/ui/list-view/index.ios.js.map +1 -1
- package/ui/list-view/list-view-common.d.ts +1 -0
- package/ui/list-view/list-view-common.js +15 -0
- package/ui/list-view/list-view-common.js.map +1 -1
- package/ui/page/index.android.d.ts +1 -0
- package/ui/page/index.android.js +4 -0
- package/ui/page/index.android.js.map +1 -1
- package/ui/page/index.ios.d.ts +2 -1
- package/ui/page/index.ios.js +8 -5
- package/ui/page/index.ios.js.map +1 -1
- package/ui/scroll-view/index.d.ts +3 -5
- package/ui/scroll-view/index.ios.d.ts +3 -1
- package/ui/scroll-view/index.ios.js +26 -20
- package/ui/scroll-view/index.ios.js.map +1 -1
- package/ui/scroll-view/scroll-view-common.js +1 -1
- package/ui/scroll-view/scroll-view-common.js.map +1 -1
- package/ui/segmented-bar/segmented-bar-common.js +6 -1
- package/ui/segmented-bar/segmented-bar-common.js.map +1 -1
- package/ui/styling/background-common.d.ts +2 -0
- package/ui/styling/background-common.js +9 -0
- package/ui/styling/background-common.js.map +1 -1
- package/ui/styling/background.ios.js +2 -0
- package/ui/styling/background.ios.js.map +1 -1
- package/ui/styling/css-selector.d.ts +57 -13
- package/ui/styling/css-selector.js +280 -51
- package/ui/styling/css-selector.js.map +1 -1
- package/ui/styling/css-utils.d.ts +16 -0
- package/ui/styling/css-utils.js +121 -7
- package/ui/styling/css-utils.js.map +1 -1
- package/ui/styling/style/index.d.ts +11 -0
- package/ui/styling/style/index.js.map +1 -1
- package/ui/styling/style-properties.d.ts +5 -0
- package/ui/styling/style-properties.js +134 -74
- package/ui/styling/style-properties.js.map +1 -1
- package/ui/styling/style-scope.d.ts +15 -3
- package/ui/styling/style-scope.js +299 -56
- package/ui/styling/style-scope.js.map +1 -1
- package/ui/switch/index.ios.js +2 -1
- package/ui/switch/index.ios.js.map +1 -1
- package/ui/tab-view/index.android.d.ts +3 -1
- package/ui/tab-view/index.android.js +56 -46
- package/ui/tab-view/index.android.js.map +1 -1
- package/ui/tab-view/index.ios.js +1 -0
- package/ui/tab-view/index.ios.js.map +1 -1
- package/ui/tab-view/tab-view-common.d.ts +1 -0
- package/ui/tab-view/tab-view-common.js +16 -3
- package/ui/tab-view/tab-view-common.js.map +1 -1
- package/ui/text-base/index.android.d.ts +1 -1
- package/ui/text-base/index.android.js +8 -8
- package/ui/text-base/index.android.js.map +1 -1
- package/ui/text-base/index.ios.js +5 -3
- package/ui/text-base/index.ios.js.map +1 -1
- package/ui/transition/shared-transition.d.ts +1 -0
- package/ui/transition/shared-transition.js +13 -8
- package/ui/transition/shared-transition.js.map +1 -1
- package/utils/layout-helper/index.ios.js +11 -3
- package/utils/layout-helper/index.ios.js.map +1 -1
- package/utils/native-helper.d.ts +2 -2
|
@@ -3,10 +3,14 @@ import { isEmbedded } from '../ui/embedding';
|
|
|
3
3
|
import { IOSHelper } from '../ui/core/view/view-helper';
|
|
4
4
|
import { getWindow } from '../utils/native-helper';
|
|
5
5
|
import { SDK_VERSION } from '../utils/constants';
|
|
6
|
-
import { ios as iosUtils, dataSerialize } from '../utils/native-helper';
|
|
7
|
-
import { ApplicationCommon
|
|
6
|
+
import { ios as iosUtils, dataSerialize, dataDeserialize } from '../utils/native-helper';
|
|
7
|
+
import { ApplicationCommon } from './application-common';
|
|
8
|
+
import { deliverShortcutItem, forwardContinueUserActivity, forwardOpenURLContexts, oneShotCompletion } from './scene-delegate-bridge';
|
|
8
9
|
import { Observable } from '../data/observable';
|
|
9
10
|
import { Trace } from '../trace';
|
|
11
|
+
import { IOSNativeWindow } from '../native-window/native-window.ios';
|
|
12
|
+
import { NativeWindow } from '../native-window/native-window-common';
|
|
13
|
+
import { NativeWindowEvents } from '../native-window/native-window-interfaces';
|
|
10
14
|
import { AccessibilityServiceEnabledPropName, CommonA11YServiceEnabledObservable, SharedA11YObservable, a11yServiceClasses, a11yServiceDisabledClass, a11yServiceEnabledClass, fontScaleCategoryClasses, fontScaleExtraLargeCategoryClass, fontScaleExtraSmallCategoryClass, fontScaleMediumCategoryClass, getCurrentA11YServiceClass, getCurrentFontScaleCategory, getCurrentFontScaleClass, getFontScaleCssClasses, setCurrentA11YServiceClass, setCurrentFontScaleCategory, setCurrentFontScaleClass, setFontScaleCssClasses, FontScaleCategory, getClosestValidFontScale, VALID_FONT_SCALES, setFontScale, getFontScale, setInitFontScale, getFontScaleCategory, setInitAccessibilityCssHelper, notifyAccessibilityFocusState, AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait, isA11yEnabled, setA11yEnabled, enforceArray, } from '../accessibility/accessibility-common';
|
|
11
15
|
import { CoreTypes } from '../core-types';
|
|
12
16
|
import { getiOSWindow, setA11yUpdatePropertiesCallback, setApplicationPropertiesCallback, setAppMainEntry, setiOSWindow, setRootView, setToggleApplicationEventListenersCallback } from './helpers-common';
|
|
@@ -39,6 +43,7 @@ var CADisplayLinkTarget = (function (_super) {
|
|
|
39
43
|
return target;
|
|
40
44
|
};
|
|
41
45
|
CADisplayLinkTarget.prototype.onDisplayed = function (link) {
|
|
46
|
+
var _a;
|
|
42
47
|
link.invalidate();
|
|
43
48
|
var owner = this._owner.deref();
|
|
44
49
|
if (!owner) {
|
|
@@ -50,6 +55,7 @@ var CADisplayLinkTarget = (function (_super) {
|
|
|
50
55
|
object: owner,
|
|
51
56
|
ios: UIApplication.sharedApplication,
|
|
52
57
|
});
|
|
58
|
+
(_a = owner.primaryWindow) === null || _a === void 0 ? void 0 : _a._notifyEvent(NativeWindowEvents.displayed);
|
|
53
59
|
owner.displayedLinkTarget = null;
|
|
54
60
|
owner.displayedLink = null;
|
|
55
61
|
};
|
|
@@ -80,6 +86,15 @@ function supportsMultipleScenes() {
|
|
|
80
86
|
}
|
|
81
87
|
return UIApplication.sharedApplication?.supportsMultipleScenes;
|
|
82
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Number of times the JS runtime has been soft-rebooted in this process via
|
|
91
|
+
* NativeScriptRuntime.reloadApplication / restartWithConfig. 0 on first boot.
|
|
92
|
+
* Provided as a global by the iOS runtime (v9+); older runtimes report 0.
|
|
93
|
+
*/
|
|
94
|
+
function getRuntimeReloadCount() {
|
|
95
|
+
const runtime = globalThis.NativeScriptRuntime;
|
|
96
|
+
return runtime && typeof runtime.reloadCount === 'number' ? runtime.reloadCount : 0;
|
|
97
|
+
}
|
|
83
98
|
var Responder = (function (_super) {
|
|
84
99
|
__extends(Responder, _super);
|
|
85
100
|
function Responder() {
|
|
@@ -104,8 +119,28 @@ if (supportsScenes()) {
|
|
|
104
119
|
* Detected by the Info.plist existence 'UIApplicationSceneManifest'.
|
|
105
120
|
* If this method is implemented when there is no manifest defined,
|
|
106
121
|
* the app will boot to a white screen.
|
|
122
|
+
*
|
|
123
|
+
* Since we configure the delegate dynamically here, UISceneConfigurations
|
|
124
|
+
* does NOT need to be present in Info.plist — only UIApplicationSceneManifest is required.
|
|
125
|
+
*
|
|
126
|
+
* NativeScript only handles UIWindowSceneSessionRoleApplication by default.
|
|
127
|
+
* Other scene types (CarPlay, external displays, etc.) are ignored unless
|
|
128
|
+
* the user provides an `onSceneConfiguration` callback.
|
|
107
129
|
*/
|
|
108
130
|
Responder.prototype.applicationConfigurationForConnectingSceneSessionOptions = function (application, connectingSceneSession, options) {
|
|
131
|
+
// Let the user intercept scene configuration for any/all scenes
|
|
132
|
+
const userHandler = Application.ios._onSceneConfiguration;
|
|
133
|
+
if (userHandler) {
|
|
134
|
+
const userConfig = userHandler(application, connectingSceneSession, options);
|
|
135
|
+
if (userConfig) {
|
|
136
|
+
return userConfig;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Only handle the standard window scene role — skip CarPlay, external displays, etc.
|
|
140
|
+
if (connectingSceneSession.role !== UIWindowSceneSessionRoleApplication) {
|
|
141
|
+
// Return a bare configuration so iOS doesn't crash, but NativeScript won't manage it
|
|
142
|
+
return UISceneConfiguration.configurationWithNameSessionRole('Unmanaged', connectingSceneSession.role);
|
|
143
|
+
}
|
|
109
144
|
const config = UISceneConfiguration.configurationWithNameSessionRole('Default Configuration', connectingSceneSession.role);
|
|
110
145
|
config.sceneClass = UIWindowScene;
|
|
111
146
|
config.delegateClass = SceneDelegate;
|
|
@@ -113,10 +148,20 @@ if (supportsScenes()) {
|
|
|
113
148
|
};
|
|
114
149
|
// scene session destruction handling
|
|
115
150
|
Responder.prototype.applicationDidDiscardSceneSessions = function (application, sceneSessions) {
|
|
116
|
-
|
|
117
|
-
// console.log('Scene sessions discarded:', sceneSessions.count);
|
|
151
|
+
Application.ios._onSceneSessionsDiscarded(sceneSessions);
|
|
118
152
|
};
|
|
119
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Reads the payload `openWindow()` put on the activating NSUserActivity.
|
|
156
|
+
*/
|
|
157
|
+
function getSceneConnectionData(connectionOptions) {
|
|
158
|
+
const activities = connectionOptions?.userActivities;
|
|
159
|
+
if (!activities || activities.count === 0) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
const activity = activities.allObjects.objectAtIndex(0);
|
|
163
|
+
return activity?.userInfo ? dataDeserialize(activity.userInfo) : undefined;
|
|
164
|
+
}
|
|
120
165
|
var SceneDelegate = (function (_super) {
|
|
121
166
|
__extends(SceneDelegate, _super);
|
|
122
167
|
function SceneDelegate() {
|
|
@@ -139,48 +184,234 @@ var SceneDelegate = (function (_super) {
|
|
|
139
184
|
if (!(scene instanceof UIWindowScene)) {
|
|
140
185
|
return;
|
|
141
186
|
}
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
this.
|
|
145
|
-
|
|
146
|
-
|
|
187
|
+
var windowScene = scene;
|
|
188
|
+
var isFirstScene = Application.ios._getWindows().length === 0;
|
|
189
|
+
this._scene = windowScene;
|
|
190
|
+
this._window = UIWindow.alloc().initWithWindowScene(windowScene);
|
|
191
|
+
if (!__VISIONOS__) {
|
|
192
|
+
this._window.backgroundColor = SDK_VERSION <= 12 || !UIColor.systemBackgroundColor ? UIColor.whiteColor : UIColor.systemBackgroundColor;
|
|
193
|
+
}
|
|
194
|
+
var nativeWindowId = IOSNativeWindow.getSceneId(windowScene);
|
|
195
|
+
var knownWindow = nativeWindowId ? Application.ios.getWindowById(nativeWindowId) : undefined;
|
|
196
|
+
var nativeWindow;
|
|
197
|
+
if ((knownWindow === null || knownWindow === void 0 ? void 0 : knownWindow.state) === "detached") {
|
|
198
|
+
nativeWindow = knownWindow;
|
|
199
|
+
nativeWindow._reattach(windowScene, this._window);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
var isPrimary_1 = isFirstScene || !Application.ios.primaryWindow;
|
|
203
|
+
nativeWindow = new IOSNativeWindow(windowScene, this._window, nativeWindowId, isPrimary_1);
|
|
204
|
+
Application.ios._registerWindow(nativeWindow);
|
|
205
|
+
}
|
|
206
|
+
var isPrimary = nativeWindow.isPrimary;
|
|
207
|
+
nativeWindow._notifyEvent(NativeWindowEvents.attached);
|
|
208
|
+
if (isPrimary) {
|
|
209
|
+
setiOSWindow(this._window);
|
|
210
|
+
}
|
|
211
|
+
nativeWindow.notify({
|
|
212
|
+
eventName: NativeWindowEvents.sceneWillConnect,
|
|
213
|
+
object: nativeWindow,
|
|
214
|
+
window: nativeWindow,
|
|
215
|
+
scene: windowScene,
|
|
216
|
+
uiWindow: this._window,
|
|
217
|
+
connectionOptions: connectionOptions,
|
|
218
|
+
});
|
|
147
219
|
Application.ios.notify({
|
|
148
|
-
eventName:
|
|
220
|
+
eventName: NativeWindowEvents.sceneWillConnect,
|
|
149
221
|
object: Application.ios,
|
|
150
|
-
|
|
151
|
-
|
|
222
|
+
window: nativeWindow,
|
|
223
|
+
scene: windowScene,
|
|
224
|
+
uiWindow: this._window,
|
|
152
225
|
connectionOptions: connectionOptions,
|
|
153
226
|
});
|
|
154
|
-
if (
|
|
227
|
+
if (isPrimary) {
|
|
155
228
|
this._window.makeKeyAndVisible();
|
|
156
229
|
}
|
|
157
|
-
|
|
158
|
-
Application.ios.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
connectionOptions: connectionOptions,
|
|
230
|
+
if (nativeWindow.role === "application") {
|
|
231
|
+
Application.ios._resolveWindowContent(nativeWindow, {
|
|
232
|
+
window: nativeWindow,
|
|
233
|
+
isPrimary: isPrimary,
|
|
234
|
+
data: getSceneConnectionData(connectionOptions),
|
|
235
|
+
ios: { connectionOptions: connectionOptions },
|
|
164
236
|
});
|
|
165
237
|
}
|
|
166
|
-
if (isFirstScene) {
|
|
167
|
-
Application.ios._notifySceneAppStarted();
|
|
168
|
-
}
|
|
169
238
|
};
|
|
170
239
|
SceneDelegate.prototype.sceneDidBecomeActive = function (scene) {
|
|
240
|
+
var windowScene = scene;
|
|
241
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
242
|
+
if (nativeWindow) {
|
|
243
|
+
nativeWindow._notifyEvent(NativeWindowEvents.activate);
|
|
244
|
+
nativeWindow.notify({
|
|
245
|
+
eventName: NativeWindowEvents.sceneDidActivate,
|
|
246
|
+
object: nativeWindow,
|
|
247
|
+
window: nativeWindow,
|
|
248
|
+
scene: windowScene,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
Application.ios.notify({
|
|
252
|
+
eventName: NativeWindowEvents.sceneDidActivate,
|
|
253
|
+
object: Application.ios,
|
|
254
|
+
window: nativeWindow,
|
|
255
|
+
scene: windowScene,
|
|
256
|
+
});
|
|
257
|
+
var rootView = nativeWindow === null || nativeWindow === void 0 ? void 0 : nativeWindow.rootView;
|
|
258
|
+
if (rootView && !rootView.isLoaded) {
|
|
259
|
+
rootView.callLoaded();
|
|
260
|
+
}
|
|
171
261
|
};
|
|
172
262
|
SceneDelegate.prototype.sceneWillResignActive = function (scene) {
|
|
263
|
+
var windowScene = scene;
|
|
264
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
265
|
+
if (nativeWindow) {
|
|
266
|
+
nativeWindow._notifyEvent(NativeWindowEvents.deactivate);
|
|
267
|
+
nativeWindow.notify({
|
|
268
|
+
eventName: NativeWindowEvents.sceneWillResignActive,
|
|
269
|
+
object: nativeWindow,
|
|
270
|
+
window: nativeWindow,
|
|
271
|
+
scene: windowScene,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
173
274
|
Application.ios.notify({
|
|
174
|
-
eventName:
|
|
275
|
+
eventName: NativeWindowEvents.sceneWillResignActive,
|
|
175
276
|
object: Application.ios,
|
|
176
|
-
|
|
277
|
+
window: nativeWindow,
|
|
278
|
+
scene: windowScene,
|
|
177
279
|
});
|
|
178
280
|
};
|
|
179
281
|
SceneDelegate.prototype.sceneWillEnterForeground = function (scene) {
|
|
282
|
+
var windowScene = scene;
|
|
283
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
284
|
+
if (nativeWindow) {
|
|
285
|
+
nativeWindow._notifyEvent(NativeWindowEvents.foreground);
|
|
286
|
+
nativeWindow.notify({
|
|
287
|
+
eventName: NativeWindowEvents.sceneWillEnterForeground,
|
|
288
|
+
object: nativeWindow,
|
|
289
|
+
window: nativeWindow,
|
|
290
|
+
scene: windowScene,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
Application.ios.notify({
|
|
294
|
+
eventName: NativeWindowEvents.sceneWillEnterForeground,
|
|
295
|
+
object: Application.ios,
|
|
296
|
+
window: nativeWindow,
|
|
297
|
+
scene: windowScene,
|
|
298
|
+
});
|
|
180
299
|
};
|
|
181
300
|
SceneDelegate.prototype.sceneDidEnterBackground = function (scene) {
|
|
301
|
+
var windowScene = scene;
|
|
302
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
303
|
+
if (nativeWindow) {
|
|
304
|
+
nativeWindow._notifyEvent(NativeWindowEvents.background);
|
|
305
|
+
nativeWindow.notify({
|
|
306
|
+
eventName: NativeWindowEvents.sceneDidEnterBackground,
|
|
307
|
+
object: nativeWindow,
|
|
308
|
+
window: nativeWindow,
|
|
309
|
+
scene: windowScene,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
Application.ios.notify({
|
|
313
|
+
eventName: NativeWindowEvents.sceneDidEnterBackground,
|
|
314
|
+
object: Application.ios,
|
|
315
|
+
window: nativeWindow,
|
|
316
|
+
scene: windowScene,
|
|
317
|
+
});
|
|
318
|
+
var rootView = nativeWindow === null || nativeWindow === void 0 ? void 0 : nativeWindow.rootView;
|
|
319
|
+
if (rootView && rootView.isLoaded) {
|
|
320
|
+
rootView.callUnloaded();
|
|
321
|
+
}
|
|
182
322
|
};
|
|
183
323
|
SceneDelegate.prototype.sceneDidDisconnect = function (scene) {
|
|
324
|
+
var windowScene = scene;
|
|
325
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
326
|
+
if (nativeWindow) {
|
|
327
|
+
var isClosing = nativeWindow._closeRequested || !nativeWindow._hasSessionIdentity;
|
|
328
|
+
if (isClosing) {
|
|
329
|
+
nativeWindow._notifyEvent(NativeWindowEvents.close);
|
|
330
|
+
}
|
|
331
|
+
nativeWindow.notify({
|
|
332
|
+
eventName: NativeWindowEvents.sceneDidDisconnect,
|
|
333
|
+
object: nativeWindow,
|
|
334
|
+
window: nativeWindow,
|
|
335
|
+
scene: windowScene,
|
|
336
|
+
});
|
|
337
|
+
if (isClosing) {
|
|
338
|
+
Application.ios._unregisterWindow(nativeWindow);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
nativeWindow._detach();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
Application.ios.notify({
|
|
345
|
+
eventName: NativeWindowEvents.sceneDidDisconnect,
|
|
346
|
+
object: Application.ios,
|
|
347
|
+
window: nativeWindow,
|
|
348
|
+
scene: windowScene,
|
|
349
|
+
});
|
|
350
|
+
};
|
|
351
|
+
SceneDelegate.prototype.sceneOpenURLContexts = function (scene, URLContexts) {
|
|
352
|
+
var windowScene = scene;
|
|
353
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
354
|
+
if (nativeWindow) {
|
|
355
|
+
nativeWindow.notify({
|
|
356
|
+
eventName: NativeWindowEvents.sceneOpenURLContexts,
|
|
357
|
+
object: nativeWindow,
|
|
358
|
+
window: nativeWindow,
|
|
359
|
+
scene: windowScene,
|
|
360
|
+
urlContexts: URLContexts,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
Application.ios.notify({
|
|
364
|
+
eventName: NativeWindowEvents.sceneOpenURLContexts,
|
|
365
|
+
object: Application.ios,
|
|
366
|
+
window: nativeWindow,
|
|
367
|
+
scene: windowScene,
|
|
368
|
+
urlContexts: URLContexts,
|
|
369
|
+
});
|
|
370
|
+
forwardOpenURLContexts(Application.ios.delegate, UIApplication.sharedApplication, URLContexts);
|
|
371
|
+
};
|
|
372
|
+
SceneDelegate.prototype.sceneContinueUserActivity = function (scene, userActivity) {
|
|
373
|
+
var windowScene = scene;
|
|
374
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
375
|
+
if (nativeWindow) {
|
|
376
|
+
nativeWindow.notify({
|
|
377
|
+
eventName: NativeWindowEvents.sceneContinueUserActivity,
|
|
378
|
+
object: nativeWindow,
|
|
379
|
+
window: nativeWindow,
|
|
380
|
+
scene: windowScene,
|
|
381
|
+
userActivity: userActivity,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
Application.ios.notify({
|
|
385
|
+
eventName: NativeWindowEvents.sceneContinueUserActivity,
|
|
386
|
+
object: Application.ios,
|
|
387
|
+
window: nativeWindow,
|
|
388
|
+
scene: windowScene,
|
|
389
|
+
userActivity: userActivity,
|
|
390
|
+
});
|
|
391
|
+
forwardContinueUserActivity(Application.ios.delegate, UIApplication.sharedApplication, userActivity);
|
|
392
|
+
};
|
|
393
|
+
SceneDelegate.prototype.windowScenePerformActionForShortcutItemCompletionHandler = function (windowScene, shortcutItem, completionHandler) {
|
|
394
|
+
var nativeWindow = Application.ios._getWindowForScene(windowScene);
|
|
395
|
+
var deliver = oneShotCompletion(completionHandler);
|
|
396
|
+
if (nativeWindow) {
|
|
397
|
+
nativeWindow.notify({
|
|
398
|
+
eventName: NativeWindowEvents.scenePerformActionForShortcutItem,
|
|
399
|
+
object: nativeWindow,
|
|
400
|
+
window: nativeWindow,
|
|
401
|
+
scene: windowScene,
|
|
402
|
+
shortcutItem: shortcutItem,
|
|
403
|
+
completionHandler: deliver,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
Application.ios.notify({
|
|
407
|
+
eventName: NativeWindowEvents.scenePerformActionForShortcutItem,
|
|
408
|
+
object: Application.ios,
|
|
409
|
+
window: nativeWindow,
|
|
410
|
+
scene: windowScene,
|
|
411
|
+
shortcutItem: shortcutItem,
|
|
412
|
+
completionHandler: deliver,
|
|
413
|
+
});
|
|
414
|
+
deliverShortcutItem(Application.ios.delegate, UIApplication.sharedApplication, shortcutItem, deliver);
|
|
184
415
|
};
|
|
185
416
|
SceneDelegate.ObjCProtocols = [UIWindowSceneDelegate];
|
|
186
417
|
return SceneDelegate;
|
|
@@ -194,12 +425,12 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
194
425
|
constructor() {
|
|
195
426
|
super();
|
|
196
427
|
this._delegateHandlers = new Map();
|
|
197
|
-
this.launchEventCalled = false;
|
|
198
|
-
this._windowSceneMap = new Map();
|
|
199
|
-
this._primaryScene = null;
|
|
200
|
-
this._openedScenesById = new Map();
|
|
201
428
|
this._notificationObservers = [];
|
|
429
|
+
this._softRebootSceneDelegates = new Map();
|
|
202
430
|
this.displayedOnce = false;
|
|
431
|
+
/**
|
|
432
|
+
* @deprecated Has no effect. Application initialization is signalled by the 'ready' event, which is never deferred.
|
|
433
|
+
*/
|
|
203
434
|
this.shouldDelayLaunchEvent = false;
|
|
204
435
|
this.addNotificationObserver(UIApplicationDidFinishLaunchingNotification, this.didFinishLaunchingWithOptions.bind(this));
|
|
205
436
|
this.addNotificationObserver(UIApplicationDidBecomeActiveNotification, this.didBecomeActive.bind(this));
|
|
@@ -207,14 +438,6 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
207
438
|
this.addNotificationObserver(UIApplicationWillTerminateNotification, this.willTerminate.bind(this));
|
|
208
439
|
this.addNotificationObserver(UIApplicationDidReceiveMemoryWarningNotification, this.didReceiveMemoryWarning.bind(this));
|
|
209
440
|
this.addNotificationObserver(UIApplicationDidChangeStatusBarOrientationNotification, this.didChangeStatusBarOrientation.bind(this));
|
|
210
|
-
// Add scene lifecycle notification observers only if scenes are supported
|
|
211
|
-
if (this.supportsScenes()) {
|
|
212
|
-
this.addNotificationObserver('UISceneWillConnectNotification', this.sceneWillConnect.bind(this));
|
|
213
|
-
this.addNotificationObserver('UISceneDidActivateNotification', this.sceneDidActivate.bind(this));
|
|
214
|
-
this.addNotificationObserver('UISceneWillEnterForegroundNotification', this.sceneWillEnterForeground.bind(this));
|
|
215
|
-
this.addNotificationObserver('UISceneDidEnterBackgroundNotification', this.sceneDidEnterBackground.bind(this));
|
|
216
|
-
this.addNotificationObserver('UISceneDidDisconnectNotification', this.sceneDidDisconnect.bind(this));
|
|
217
|
-
}
|
|
218
441
|
}
|
|
219
442
|
getRootView() {
|
|
220
443
|
return this._rootView;
|
|
@@ -277,6 +500,8 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
277
500
|
UIApplicationMain(0, null, null, this.delegate ? NSStringFromClass(this.delegate) : NSStringFromClass(Responder));
|
|
278
501
|
}
|
|
279
502
|
runAsEmbeddedApp() {
|
|
503
|
+
this.notifyReady();
|
|
504
|
+
this._reattachNativeDelegatesAfterSoftReboot();
|
|
280
505
|
// TODO: this rootView should be held alive until rootController dismissViewController is called.
|
|
281
506
|
const rootView = this.createRootView(this._rootView, true);
|
|
282
507
|
if (!rootView) {
|
|
@@ -308,8 +533,23 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
308
533
|
}
|
|
309
534
|
if (targetScene) {
|
|
310
535
|
window = UIWindow.alloc().initWithWindowScene(targetScene);
|
|
311
|
-
|
|
312
|
-
|
|
536
|
+
if (!__VISIONOS__) {
|
|
537
|
+
window.backgroundColor = SDK_VERSION <= 12 || !UIColor.systemBackgroundColor ? UIColor.whiteColor : UIColor.systemBackgroundColor;
|
|
538
|
+
}
|
|
539
|
+
// The registry lives in JS and was lost with the previous isolate, so
|
|
540
|
+
// the still-connected scene needs a fresh NativeWindow to be reachable.
|
|
541
|
+
const isPrimary = !this.primaryWindow;
|
|
542
|
+
const nativeWindow = new IOSNativeWindow(targetScene, window, IOSNativeWindow.getSceneId(targetScene), isPrimary);
|
|
543
|
+
this._registerWindow(nativeWindow);
|
|
544
|
+
if (isPrimary) {
|
|
545
|
+
setiOSWindow(window);
|
|
546
|
+
}
|
|
547
|
+
// If the scene's delegate was recreated after a soft reboot, point it
|
|
548
|
+
// at the new window so `scene.delegate.window` queries resolve.
|
|
549
|
+
const freshSceneDelegate = this._softRebootSceneDelegates.get(targetScene);
|
|
550
|
+
if (freshSceneDelegate) {
|
|
551
|
+
freshSceneDelegate.window = window;
|
|
552
|
+
}
|
|
313
553
|
}
|
|
314
554
|
}
|
|
315
555
|
if (!window) {
|
|
@@ -318,37 +558,78 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
318
558
|
// May be null on a freshly recreated window — expected; the replace-root
|
|
319
559
|
// path below sets it. Only the embedder path needs an existing controller.
|
|
320
560
|
const rootController = window.rootViewController;
|
|
321
|
-
const controller = this.getViewController(rootView);
|
|
322
561
|
const embedderDelegate = NativeScriptEmbedder.sharedInstance().delegate;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const newSystemAppearance = this.getSystemAppearanceValue(userInterfaceStyle);
|
|
327
|
-
this.setSystemAppearance(newSystemAppearance);
|
|
328
|
-
});
|
|
329
|
-
rootView.on(IOSHelper.traitCollectionLayoutDirectionChangedEvent, () => {
|
|
330
|
-
const layoutDirection = controller.traitCollection.layoutDirection;
|
|
331
|
-
const newLayoutDirection = this.getLayoutDirectionValue(layoutDirection);
|
|
332
|
-
this.setLayoutDirection(newLayoutDirection);
|
|
333
|
-
});
|
|
334
|
-
if (embedderDelegate) {
|
|
335
|
-
// Embed into host app.
|
|
336
|
-
// present over the host's existing root view controller.
|
|
337
|
-
if (!rootController) {
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
this.setViewControllerView(rootView);
|
|
341
|
-
embedderDelegate.presentNativeScriptApp(controller);
|
|
562
|
+
// Embed into host app requires an existing root view controller
|
|
563
|
+
if (embedderDelegate && !rootController) {
|
|
564
|
+
return;
|
|
342
565
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
//
|
|
346
|
-
|
|
347
|
-
|
|
566
|
+
let hostWindow = this.primaryWindow;
|
|
567
|
+
if (!hostWindow) {
|
|
568
|
+
// Only an embedder delegate makes this window a guest: without one NativeScript
|
|
569
|
+
// owns the UIApplication and the window has to attach its own content.
|
|
570
|
+
const role = embedderDelegate ? 'embedded' : 'application';
|
|
571
|
+
hostWindow = new IOSNativeWindow(window.windowScene ?? undefined, window, 'embedded-main', true, role);
|
|
572
|
+
this._registerWindow(hostWindow);
|
|
573
|
+
hostWindow._notifyEvent(NativeWindowEvents.attached);
|
|
348
574
|
}
|
|
349
|
-
|
|
575
|
+
hostWindow.setContent(rootView);
|
|
350
576
|
this.notifyAppStarted();
|
|
351
577
|
}
|
|
578
|
+
/**
|
|
579
|
+
* After an in-process soft reboot (NativeScriptRuntime.reloadApplication /
|
|
580
|
+
* restartWithConfig), the Objective-C delegate classes created by the
|
|
581
|
+
* previous JS isolate still exist and UIKit keeps dispatching to their
|
|
582
|
+
* now-inert instances: their method callbacks bail out because the isolate
|
|
583
|
+
* that implemented them is gone. Notification-center observers are
|
|
584
|
+
* re-registered by the new isolate, but delegate-based dispatch (custom
|
|
585
|
+
* UIApplicationDelegate methods like push-token/openURL callbacks, and the
|
|
586
|
+
* UIScene delegates used by scene-lifecycle apps) stays pinned to the old
|
|
587
|
+
* bundle. Recreate those delegates from this bundle's classes and re-point
|
|
588
|
+
* UIKit at them.
|
|
589
|
+
*/
|
|
590
|
+
_reattachNativeDelegatesAfterSoftReboot() {
|
|
591
|
+
if (getRuntimeReloadCount() <= 0) {
|
|
592
|
+
// First boot: UIApplicationMain (or the host app) set up delegates.
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (isEmbedded()) {
|
|
596
|
+
// The host app owns the UIApplication delegate; never touch it.
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const app = UIApplication.sharedApplication;
|
|
600
|
+
if (!app) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
// Fresh application delegate from the new bundle. Assigning `delegate`
|
|
604
|
+
// does not retain (unlike the UIApplicationMain launch path), so keep a
|
|
605
|
+
// strong reference ourselves.
|
|
606
|
+
this.delegate ?? (this.delegate = Responder);
|
|
607
|
+
const freshDelegate = this.delegate.new();
|
|
608
|
+
this._softRebootAppDelegate = freshDelegate;
|
|
609
|
+
app.delegate = freshDelegate;
|
|
610
|
+
// Re-point already-connected scenes at fresh scene delegates so scene
|
|
611
|
+
// lifecycle and user-implemented scene delegate methods (shortcuts,
|
|
612
|
+
// openURLContexts, userActivity continuation, etc.) reach this isolate.
|
|
613
|
+
// Newly connecting scenes are covered by the fresh application delegate's
|
|
614
|
+
// applicationConfigurationForConnectingSceneSessionOptions, which returns
|
|
615
|
+
// this bundle's SceneDelegate class.
|
|
616
|
+
if (this.supportsScenes()) {
|
|
617
|
+
this._softRebootSceneDelegates.clear();
|
|
618
|
+
const scenes = app.connectedScenes?.allObjects;
|
|
619
|
+
for (let i = 0; scenes && i < scenes.count; i++) {
|
|
620
|
+
const scene = scenes.objectAtIndex(i);
|
|
621
|
+
if (!(scene instanceof UIWindowScene)) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
const freshSceneDelegate = SceneDelegate.new();
|
|
625
|
+
scene.delegate = freshSceneDelegate;
|
|
626
|
+
this._softRebootSceneDelegates.set(scene, freshSceneDelegate);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
if (Trace.isEnabled()) {
|
|
630
|
+
Trace.write(`Reattached application delegate${this._softRebootSceneDelegates.size ? ` and ${this._softRebootSceneDelegates.size} scene delegate(s)` : ''} after soft reboot (reloadCount: ${getRuntimeReloadCount()})`, Trace.categories.NativeLifecycle);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
352
633
|
getViewController(rootView) {
|
|
353
634
|
let viewController = rootView.viewController || rootView.ios;
|
|
354
635
|
if (!(viewController instanceof UIViewController)) {
|
|
@@ -533,7 +814,6 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
533
814
|
}
|
|
534
815
|
}
|
|
535
816
|
notifyAppStarted(notification) {
|
|
536
|
-
this.launchEventCalled = true;
|
|
537
817
|
const root = this.notifyLaunch({
|
|
538
818
|
ios: notification?.userInfo?.objectForKey('UIApplicationLaunchOptionsLocalNotificationKey') ?? null,
|
|
539
819
|
});
|
|
@@ -546,10 +826,6 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
546
826
|
setiOSWindow(this.window);
|
|
547
827
|
}
|
|
548
828
|
}
|
|
549
|
-
// Public method for scene-based app startup
|
|
550
|
-
_notifySceneAppStarted() {
|
|
551
|
-
this.notifyAppStarted();
|
|
552
|
-
}
|
|
553
829
|
_onLivesync(context) {
|
|
554
830
|
// Handle application root module
|
|
555
831
|
const isAppRootModuleChanged = context && context.path && context.path.includes(this.getMainEntry().moduleName) && context.type !== 'style';
|
|
@@ -564,14 +840,23 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
564
840
|
}
|
|
565
841
|
}
|
|
566
842
|
setWindowContent(view) {
|
|
843
|
+
const rootView = this.createRootView(view);
|
|
844
|
+
const primaryWindow = this.primaryWindow;
|
|
845
|
+
if (primaryWindow) {
|
|
846
|
+
primaryWindow.setContent(rootView);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
this.setWindowContentFallback(rootView);
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Attaches content to the raw `UIWindow`. Every launch path registers a primary
|
|
853
|
+
* NativeWindow, so this only runs when no window is left to own the content.
|
|
854
|
+
*/
|
|
855
|
+
setWindowContentFallback(rootView) {
|
|
567
856
|
if (this._rootView) {
|
|
568
|
-
// if we already have a root view, we reset it.
|
|
569
857
|
this._rootView._onRootViewReset();
|
|
570
858
|
}
|
|
571
|
-
const rootView = this.createRootView(view);
|
|
572
859
|
const controller = this.getViewController(rootView);
|
|
573
|
-
this._rootView = rootView;
|
|
574
|
-
setRootView(rootView);
|
|
575
860
|
// setup view as styleScopeHost
|
|
576
861
|
rootView._setupAsRootView({});
|
|
577
862
|
this.setViewControllerView(rootView);
|
|
@@ -581,17 +866,7 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
581
866
|
if (!haveController) {
|
|
582
867
|
win.makeKeyAndVisible();
|
|
583
868
|
}
|
|
584
|
-
this.
|
|
585
|
-
rootView.on(IOSHelper.traitCollectionColorAppearanceChangedEvent, () => {
|
|
586
|
-
const userInterfaceStyle = controller.traitCollection.userInterfaceStyle;
|
|
587
|
-
const newSystemAppearance = this.getSystemAppearanceValue(userInterfaceStyle);
|
|
588
|
-
this.setSystemAppearance(newSystemAppearance);
|
|
589
|
-
});
|
|
590
|
-
rootView.on(IOSHelper.traitCollectionLayoutDirectionChangedEvent, () => {
|
|
591
|
-
const layoutDirection = controller.traitCollection.layoutDirection;
|
|
592
|
-
const newLayoutDirection = this.getLayoutDirectionValue(layoutDirection);
|
|
593
|
-
this.setLayoutDirection(newLayoutDirection);
|
|
594
|
-
});
|
|
869
|
+
this.adoptRootView(rootView);
|
|
595
870
|
}
|
|
596
871
|
// Observers
|
|
597
872
|
didFinishLaunchingWithOptions(notification) {
|
|
@@ -609,6 +884,8 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
609
884
|
}
|
|
610
885
|
}
|
|
611
886
|
}
|
|
887
|
+
// Must precede every window registration below and every scene connect that follows.
|
|
888
|
+
this.notifyReady();
|
|
612
889
|
this.setMaxRefreshRate();
|
|
613
890
|
// Only set up window if NOT using scene-based lifecycle
|
|
614
891
|
if (!this.supportsScenes()) {
|
|
@@ -622,9 +899,26 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
622
899
|
if (!__VISIONOS__) {
|
|
623
900
|
this.window.backgroundColor = SDK_VERSION <= 12 || !UIColor.systemBackgroundColor ? UIColor.whiteColor : UIColor.systemBackgroundColor;
|
|
624
901
|
}
|
|
625
|
-
this.
|
|
626
|
-
|
|
627
|
-
this.
|
|
902
|
+
if (!this.primaryWindow) {
|
|
903
|
+
const nativeWindow = new IOSNativeWindow(undefined, this.window, 'main', true, 'application');
|
|
904
|
+
this._registerWindow(nativeWindow);
|
|
905
|
+
nativeWindow._notifyEvent(NativeWindowEvents.attached);
|
|
906
|
+
}
|
|
907
|
+
const primaryWindow = this.primaryWindow;
|
|
908
|
+
const resolveContent = () => this._resolveWindowContent(primaryWindow, {
|
|
909
|
+
window: primaryWindow,
|
|
910
|
+
isPrimary: true,
|
|
911
|
+
}, {
|
|
912
|
+
launchData: {
|
|
913
|
+
ios: notification?.userInfo?.objectForKey('UIApplicationLaunchOptionsLocalNotificationKey') ?? null,
|
|
914
|
+
},
|
|
915
|
+
});
|
|
916
|
+
if (UIApplication.sharedApplication.applicationState === 2 /* UIApplicationState.Background */) {
|
|
917
|
+
// A background launch has no UI to build yet, so content waits for the first activation.
|
|
918
|
+
this._pendingWindowContentResolve = resolveContent;
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
resolveContent();
|
|
628
922
|
}
|
|
629
923
|
}
|
|
630
924
|
else {
|
|
@@ -632,17 +926,22 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
632
926
|
}
|
|
633
927
|
}
|
|
634
928
|
didBecomeActive(notification) {
|
|
635
|
-
|
|
636
|
-
|
|
929
|
+
const pendingWindowContentResolve = this._pendingWindowContentResolve;
|
|
930
|
+
if (pendingWindowContentResolve) {
|
|
931
|
+
this._pendingWindowContentResolve = null;
|
|
932
|
+
pendingWindowContentResolve();
|
|
637
933
|
}
|
|
638
934
|
const additionalData = {
|
|
639
935
|
ios: UIApplication.sharedApplication,
|
|
640
936
|
};
|
|
641
937
|
this.setInBackground(false, additionalData);
|
|
642
938
|
this.setSuspended(false, additionalData);
|
|
643
|
-
|
|
644
|
-
if (
|
|
645
|
-
rootView.
|
|
939
|
+
// In scene mode the root view belongs to a window, so the scene delegate loads it.
|
|
940
|
+
if (!this.supportsScenes()) {
|
|
941
|
+
const rootView = this._rootView;
|
|
942
|
+
if (rootView && !rootView.isLoaded) {
|
|
943
|
+
rootView.callLoaded();
|
|
944
|
+
}
|
|
646
945
|
}
|
|
647
946
|
}
|
|
648
947
|
didEnterBackground(notification) {
|
|
@@ -651,9 +950,11 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
651
950
|
};
|
|
652
951
|
this.setInBackground(true, additionalData);
|
|
653
952
|
this.setSuspended(true, additionalData);
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
rootView.
|
|
953
|
+
if (!this.supportsScenes()) {
|
|
954
|
+
const rootView = this._rootView;
|
|
955
|
+
if (rootView && rootView.isLoaded) {
|
|
956
|
+
rootView.callUnloaded();
|
|
957
|
+
}
|
|
657
958
|
}
|
|
658
959
|
}
|
|
659
960
|
willTerminate(notification) {
|
|
@@ -675,157 +976,111 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
675
976
|
});
|
|
676
977
|
}
|
|
677
978
|
didChangeStatusBarOrientation(notification) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
this.
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
return;
|
|
687
|
-
}
|
|
688
|
-
// Store as primary scene if it's the first one
|
|
689
|
-
if (!this._primaryScene) {
|
|
690
|
-
this._primaryScene = scene;
|
|
979
|
+
// The notification is app-wide, but scenes rotate independently, so every attached
|
|
980
|
+
// window is refreshed from its own scene.
|
|
981
|
+
for (const nativeWindow of this._windows) {
|
|
982
|
+
if (nativeWindow.state !== 'attached') {
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
const orientation = nativeWindow.ios?.scene?.interfaceOrientation ?? UIApplication.sharedApplication.statusBarOrientation;
|
|
986
|
+
nativeWindow._setOrientation(this.getOrientationValue(orientation));
|
|
691
987
|
}
|
|
692
|
-
this.notify({
|
|
693
|
-
eventName: SceneEvents.sceneWillConnect,
|
|
694
|
-
object: this,
|
|
695
|
-
scene: scene,
|
|
696
|
-
userInfo: notification.userInfo,
|
|
697
|
-
});
|
|
698
988
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
this.
|
|
713
|
-
this.setSuspended(false, additionalData);
|
|
714
|
-
if (this._rootView && !this._rootView.isLoaded) {
|
|
715
|
-
this._rootView.callLoaded();
|
|
716
|
-
}
|
|
989
|
+
// --- App-level root view mirror ---
|
|
990
|
+
/**
|
|
991
|
+
* Keeps the app-level root view state (`getRootView()`, the global root view and the
|
|
992
|
+
* `initRootView` event) following whatever the primary window shows.
|
|
993
|
+
*/
|
|
994
|
+
mirrorPrimaryWindow(nativeWindow) {
|
|
995
|
+
if (this._mirroredWindow === nativeWindow) {
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
this._mirroredWindow?.off(NativeWindowEvents.contentLoaded, this.onPrimaryWindowContentLoaded, this);
|
|
999
|
+
this._mirroredWindow = nativeWindow;
|
|
1000
|
+
nativeWindow.on(NativeWindowEvents.contentLoaded, this.onPrimaryWindowContentLoaded, this);
|
|
1001
|
+
if (nativeWindow.rootView && nativeWindow.rootView !== this._rootView) {
|
|
1002
|
+
this.adoptRootView(nativeWindow.rootView);
|
|
717
1003
|
}
|
|
718
1004
|
}
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
this.notify({
|
|
722
|
-
eventName: SceneEvents.sceneWillEnterForeground,
|
|
723
|
-
object: this,
|
|
724
|
-
scene: scene,
|
|
725
|
-
});
|
|
1005
|
+
onPrimaryWindowContentLoaded(data) {
|
|
1006
|
+
this.adoptRootView(data.window.rootView);
|
|
726
1007
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
eventName: SceneEvents.sceneDidEnterBackground,
|
|
731
|
-
object: this,
|
|
732
|
-
scene: scene,
|
|
733
|
-
});
|
|
734
|
-
// If this is the primary scene, trigger traditional app lifecycle
|
|
735
|
-
if (scene === this._primaryScene) {
|
|
736
|
-
const additionalData = {
|
|
737
|
-
ios: UIApplication.sharedApplication,
|
|
738
|
-
scene: scene,
|
|
739
|
-
};
|
|
740
|
-
this.setInBackground(true, additionalData);
|
|
741
|
-
this.setSuspended(true, additionalData);
|
|
742
|
-
if (this._rootView && this._rootView.isLoaded) {
|
|
743
|
-
this._rootView.callUnloaded();
|
|
744
|
-
}
|
|
1008
|
+
adoptRootView(rootView) {
|
|
1009
|
+
if (!rootView) {
|
|
1010
|
+
return;
|
|
745
1011
|
}
|
|
1012
|
+
this._rootView = rootView;
|
|
1013
|
+
setRootView(rootView);
|
|
1014
|
+
this.initRootView(rootView, this._mirroredWindow);
|
|
746
1015
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
1016
|
+
// --- NativeWindow registry ---
|
|
1017
|
+
/**
|
|
1018
|
+
* @internal - iOS reports discarded sessions for windows this JS context may never
|
|
1019
|
+
* have seen (they can arrive on a later launch), so unknown ids are ignored.
|
|
1020
|
+
*/
|
|
1021
|
+
_onSceneSessionsDiscarded(sessions) {
|
|
1022
|
+
const all = sessions?.allObjects;
|
|
1023
|
+
if (!all) {
|
|
1024
|
+
return;
|
|
753
1025
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
console.log('Failed to activate primary scene:', err.localizedDescription);
|
|
760
|
-
}
|
|
761
|
-
});
|
|
762
|
-
}
|
|
763
|
-
else {
|
|
764
|
-
UIApplication.sharedApplication.requestSceneSessionActivationUserActivityOptionsErrorHandler(this._primaryScene.session, null, null, (err) => {
|
|
765
|
-
if (err) {
|
|
766
|
-
console.log('Failed to activate primary scene (legacy):', err.localizedDescription);
|
|
767
|
-
}
|
|
768
|
-
});
|
|
1026
|
+
for (let i = 0; i < all.count; i++) {
|
|
1027
|
+
const persistentIdentifier = all.objectAtIndex(i)?.persistentIdentifier;
|
|
1028
|
+
const nativeWindow = persistentIdentifier ? this.getWindowById(`${persistentIdentifier}`) : undefined;
|
|
1029
|
+
if (!nativeWindow) {
|
|
1030
|
+
continue;
|
|
769
1031
|
}
|
|
1032
|
+
nativeWindow._notifyEvent(NativeWindowEvents.close);
|
|
1033
|
+
this._unregisterWindow(nativeWindow);
|
|
770
1034
|
}
|
|
771
|
-
this.notify({
|
|
772
|
-
eventName: SceneEvents.sceneDidDisconnect,
|
|
773
|
-
object: this,
|
|
774
|
-
scene: scene,
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
// Scene management helper methods
|
|
778
|
-
_setWindowForScene(window, scene) {
|
|
779
|
-
this._windowSceneMap.set(scene, window);
|
|
780
|
-
}
|
|
781
|
-
_removeWindowForScene(scene) {
|
|
782
|
-
this._windowSceneMap.delete(scene);
|
|
783
|
-
// also untrack opened scene id
|
|
784
|
-
try {
|
|
785
|
-
const s = scene;
|
|
786
|
-
if (s && s.session) {
|
|
787
|
-
const id = this._getSceneId(s);
|
|
788
|
-
this._openedScenesById.delete(id);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
catch { }
|
|
792
1035
|
}
|
|
1036
|
+
/**
|
|
1037
|
+
* @internal - Get a NativeWindow by its scene.
|
|
1038
|
+
*/
|
|
793
1039
|
_getWindowForScene(scene) {
|
|
794
|
-
return this.
|
|
1040
|
+
return this._windows.find((nw) => nw.ios?.scene === scene);
|
|
795
1041
|
}
|
|
796
|
-
|
|
797
|
-
if (
|
|
798
|
-
|
|
799
|
-
}
|
|
800
|
-
// track opened scene
|
|
801
|
-
try {
|
|
802
|
-
const id = this._getSceneId(scene);
|
|
803
|
-
this._openedScenesById.set(id, scene);
|
|
1042
|
+
_onWindowRegistered(nativeWindow) {
|
|
1043
|
+
if (nativeWindow.isPrimary) {
|
|
1044
|
+
this.mirrorPrimaryWindow(nativeWindow);
|
|
804
1045
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
// If this is the primary scene, set up the main application content
|
|
811
|
-
if (scene === this._primaryScene || !this._primaryScene) {
|
|
812
|
-
this._primaryScene = scene;
|
|
813
|
-
if (!getiOSWindow()) {
|
|
814
|
-
setiOSWindow(window);
|
|
815
|
-
}
|
|
816
|
-
// During initial scene startup we must wait for launch to be notified first.
|
|
817
|
-
// Some frameworks provide root content from launch handlers.
|
|
818
|
-
// Guard: skip setWindowContent when no main entry is configured yet.
|
|
819
|
-
// During Vite HMR dev boot, the placeholder calls Application.run() with
|
|
820
|
-
// no entry; the real entry is set later when the HTTP-loaded main module
|
|
821
|
-
// calls Application.run({ moduleName: ... }). Without this guard the
|
|
822
|
-
// scene handler would throw "Main entry is missing" and leave the window
|
|
823
|
-
// in a broken state (root view reset but no replacement created).
|
|
824
|
-
if (this.hasLaunched() && this.getMainEntry()) {
|
|
825
|
-
this.setWindowContent();
|
|
826
|
-
}
|
|
1046
|
+
}
|
|
1047
|
+
_onPrimaryWindowPromoted(nativeWindow) {
|
|
1048
|
+
const promotedWindow = nativeWindow.ios?.uiWindow;
|
|
1049
|
+
if (promotedWindow) {
|
|
1050
|
+
setiOSWindow(promotedWindow);
|
|
827
1051
|
}
|
|
1052
|
+
this.mirrorPrimaryWindow(nativeWindow);
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Register a callback to intercept scene configuration.
|
|
1056
|
+
*
|
|
1057
|
+
* Called for every new scene session. Return a `UISceneConfiguration` to handle
|
|
1058
|
+
* the scene yourself (e.g. CarPlay, external display), or return `null`/`undefined`
|
|
1059
|
+
* to let NativeScript handle it with the default SceneDelegate.
|
|
1060
|
+
*
|
|
1061
|
+
* NativeScript only auto-manages `UIWindowSceneSessionRoleApplication` scenes.
|
|
1062
|
+
* All other scene roles are ignored unless you provide a configuration here.
|
|
1063
|
+
*
|
|
1064
|
+
* @example
|
|
1065
|
+
* ```ts
|
|
1066
|
+
* Application.ios.onSceneConfiguration = (app, session, options) => {
|
|
1067
|
+
* if (session.role === CPTemplateApplicationSceneSessionRoleApplication) {
|
|
1068
|
+
* const config = UISceneConfiguration.configurationWithNameSessionRole('CarPlay', session.role);
|
|
1069
|
+
* config.delegateClass = MyCarPlaySceneDelegate;
|
|
1070
|
+
* return config;
|
|
1071
|
+
* }
|
|
1072
|
+
* // Return null to let NativeScript handle the default window scene
|
|
1073
|
+
* return null;
|
|
1074
|
+
* };
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
1077
|
+
set onSceneConfiguration(handler) {
|
|
1078
|
+
this._onSceneConfiguration = handler;
|
|
1079
|
+
}
|
|
1080
|
+
get onSceneConfiguration() {
|
|
1081
|
+
return this._onSceneConfiguration;
|
|
828
1082
|
}
|
|
1083
|
+
// Scene management helper methods (kept for backward compat)
|
|
829
1084
|
get sceneDelegate() {
|
|
830
1085
|
if (!this._sceneDelegate) {
|
|
831
1086
|
this._sceneDelegate = SceneDelegate.new();
|
|
@@ -839,10 +1094,12 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
839
1094
|
* Multi-window support
|
|
840
1095
|
*/
|
|
841
1096
|
/**
|
|
842
|
-
* Opens a new window
|
|
843
|
-
*
|
|
1097
|
+
* Opens a new window (scene).
|
|
1098
|
+
*
|
|
1099
|
+
* @param options Options for the new window. `options.data` is serialized into the
|
|
1100
|
+
* activating scene's `NSUserActivity.userInfo`.
|
|
844
1101
|
*/
|
|
845
|
-
openWindow(
|
|
1102
|
+
openWindow(options) {
|
|
846
1103
|
if (!supportsMultipleScenes()) {
|
|
847
1104
|
console.log('Cannot create a new scene - not supported on this device.');
|
|
848
1105
|
return;
|
|
@@ -851,34 +1108,18 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
851
1108
|
const app = UIApplication.sharedApplication;
|
|
852
1109
|
// iOS 17+
|
|
853
1110
|
if (SDK_VERSION >= 17) {
|
|
854
|
-
// Create a new scene activation request with proper role
|
|
855
1111
|
let request;
|
|
856
1112
|
try {
|
|
857
|
-
// Use the correct factory method to create request with role
|
|
858
|
-
// Based on the type definitions, this is the proper way
|
|
859
1113
|
request = UISceneSessionActivationRequest.requestWithRole(UIWindowSceneSessionRoleApplication);
|
|
860
|
-
// Note: may be useful to allow user defined activity type through optional string typed data in future
|
|
861
1114
|
const activity = NSUserActivity.alloc().initWithActivityType(`${NSBundle.mainBundle.bundleIdentifier}.scene`);
|
|
862
|
-
activity.userInfo = dataSerialize(data);
|
|
1115
|
+
activity.userInfo = dataSerialize(options?.data ?? {});
|
|
863
1116
|
request.userActivity = activity;
|
|
864
|
-
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
options
|
|
870
|
-
/**
|
|
871
|
-
* Note: This does not work in testing but worth exploring further sometime
|
|
872
|
-
* regarding the size/dimensions of opened secondary windows.
|
|
873
|
-
* The initial size is ultimately determined by the system
|
|
874
|
-
* based on available space and user context.
|
|
875
|
-
*/
|
|
876
|
-
// Get the size restrictions from the window scene
|
|
877
|
-
// const sizeRestrictions = (options.requestingScene as UIWindowScene).sizeRestrictions;
|
|
878
|
-
// // Set your minimum and maximum dimensions
|
|
879
|
-
// sizeRestrictions.minimumSize = CGSizeMake(320, 400);
|
|
880
|
-
// sizeRestrictions.maximumSize = CGSizeMake(600, 800);
|
|
881
|
-
request.options = options;
|
|
1117
|
+
const activationOptions = UISceneActivationRequestOptions.new();
|
|
1118
|
+
const primary = this.primaryWindow;
|
|
1119
|
+
if (primary?.ios?.scene) {
|
|
1120
|
+
activationOptions.requestingScene = primary.ios.scene;
|
|
1121
|
+
}
|
|
1122
|
+
request.options = activationOptions;
|
|
882
1123
|
}
|
|
883
1124
|
catch (roleError) {
|
|
884
1125
|
console.log('Error creating request:', roleError);
|
|
@@ -887,32 +1128,25 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
887
1128
|
app.activateSceneSessionForRequestErrorHandler(request, (error) => {
|
|
888
1129
|
if (error) {
|
|
889
1130
|
console.log('Error creating new scene (iOS 17+):', error);
|
|
890
|
-
// Log additional debugging info
|
|
891
1131
|
if (error.userInfo) {
|
|
892
1132
|
console.error(`Error userInfo: ${error.userInfo.description}`);
|
|
893
1133
|
}
|
|
894
|
-
// Handle specific error types
|
|
895
1134
|
if (error.localizedDescription.includes('role') && error.localizedDescription.includes('nil')) {
|
|
896
|
-
this.createSceneWithLegacyAPI(data);
|
|
1135
|
+
this.createSceneWithLegacyAPI(options?.data);
|
|
897
1136
|
}
|
|
898
1137
|
else if (error.domain === 'FBSWorkspaceErrorDomain' && error.code === 2) {
|
|
899
|
-
this.createSceneWithLegacyAPI(data);
|
|
1138
|
+
this.createSceneWithLegacyAPI(options?.data);
|
|
900
1139
|
}
|
|
901
1140
|
}
|
|
902
1141
|
});
|
|
903
1142
|
}
|
|
904
|
-
// iOS 13-16 - Use the legacy requestSceneSessionActivationUserActivityOptionsErrorHandler method
|
|
905
1143
|
else if (SDK_VERSION >= 13 && SDK_VERSION < 17) {
|
|
906
|
-
app.requestSceneSessionActivationUserActivityOptionsErrorHandler(null,
|
|
907
|
-
null, // userActivity
|
|
908
|
-
null, // options
|
|
909
|
-
(error) => {
|
|
1144
|
+
app.requestSceneSessionActivationUserActivityOptionsErrorHandler(null, null, null, (error) => {
|
|
910
1145
|
if (error) {
|
|
911
1146
|
console.log('Error creating new scene (legacy):', error);
|
|
912
1147
|
}
|
|
913
1148
|
});
|
|
914
1149
|
}
|
|
915
|
-
// Fallback for older iOS versions or unsupported configurations
|
|
916
1150
|
else {
|
|
917
1151
|
console.log('Neither new nor legacy scene activation methods are available');
|
|
918
1152
|
}
|
|
@@ -923,71 +1157,66 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
923
1157
|
}
|
|
924
1158
|
/**
|
|
925
1159
|
* Closes a secondary window/scene.
|
|
926
|
-
*
|
|
927
|
-
* - Application.ios.closeWindow() // best-effort close of a non-primary scene
|
|
928
|
-
* - Application.ios.closeWindow(button) // from a tap handler within the scene
|
|
929
|
-
* - Application.ios.closeWindow(window)
|
|
930
|
-
* - Application.ios.closeWindow(scene)
|
|
931
|
-
* - Application.ios.closeWindow('scene-id')
|
|
1160
|
+
* Accepts a NativeWindow, View, UIWindow, UIWindowScene, or string id.
|
|
932
1161
|
*/
|
|
933
1162
|
closeWindow(target) {
|
|
934
1163
|
if (!__APPLE__) {
|
|
935
1164
|
return;
|
|
936
1165
|
}
|
|
937
1166
|
try {
|
|
938
|
-
|
|
939
|
-
if (
|
|
940
|
-
|
|
941
|
-
return;
|
|
1167
|
+
let nativeWindow;
|
|
1168
|
+
if (target instanceof NativeWindow) {
|
|
1169
|
+
nativeWindow = target;
|
|
942
1170
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1171
|
+
else {
|
|
1172
|
+
const scene = this._resolveScene(target);
|
|
1173
|
+
if (scene) {
|
|
1174
|
+
nativeWindow = this._getWindowForScene(scene);
|
|
1175
|
+
}
|
|
947
1176
|
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
console.log('closeWindow: Scene has no session to destroy');
|
|
1177
|
+
if (!nativeWindow) {
|
|
1178
|
+
console.log('closeWindow: No window resolved for target');
|
|
951
1179
|
return;
|
|
952
1180
|
}
|
|
953
|
-
|
|
954
|
-
if (app.requestSceneSessionDestructionOptionsErrorHandler) {
|
|
955
|
-
app.requestSceneSessionDestructionOptionsErrorHandler(session, null, (error) => {
|
|
956
|
-
if (error) {
|
|
957
|
-
console.log('closeWindow: destruction error', error);
|
|
958
|
-
}
|
|
959
|
-
else {
|
|
960
|
-
// clean up tracked id
|
|
961
|
-
const id = this._getSceneId(scene);
|
|
962
|
-
this._openedScenesById.delete(id);
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
|
-
else {
|
|
967
|
-
console.info('closeWindow: Scene destruction API not available on this iOS version');
|
|
968
|
-
}
|
|
1181
|
+
nativeWindow.close();
|
|
969
1182
|
}
|
|
970
1183
|
catch (err) {
|
|
971
1184
|
console.log('closeWindow: Unexpected error', err);
|
|
972
1185
|
}
|
|
973
1186
|
}
|
|
1187
|
+
/**
|
|
1188
|
+
* @deprecated Use `getWindows()` instead.
|
|
1189
|
+
*/
|
|
974
1190
|
getAllWindows() {
|
|
975
|
-
return
|
|
1191
|
+
return this._windows.map((nw) => nw.ios?.uiWindow).filter(Boolean);
|
|
976
1192
|
}
|
|
1193
|
+
/**
|
|
1194
|
+
* @deprecated Use `getWindows()` instead.
|
|
1195
|
+
*/
|
|
977
1196
|
getAllScenes() {
|
|
978
|
-
return
|
|
1197
|
+
return this._windows.map((nw) => nw.ios?.scene).filter(Boolean);
|
|
979
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* @deprecated Use `getWindows()` instead.
|
|
1201
|
+
*/
|
|
980
1202
|
getWindowScenes() {
|
|
981
1203
|
return this.getAllScenes().filter((scene) => scene instanceof UIWindowScene);
|
|
982
1204
|
}
|
|
1205
|
+
/**
|
|
1206
|
+
* @deprecated Use `primaryWindow?.ios?.uiWindow` instead.
|
|
1207
|
+
*/
|
|
983
1208
|
getPrimaryWindow() {
|
|
984
|
-
|
|
985
|
-
|
|
1209
|
+
const primary = this.primaryWindow;
|
|
1210
|
+
if (primary?.ios?.uiWindow) {
|
|
1211
|
+
return primary.ios.uiWindow;
|
|
986
1212
|
}
|
|
987
1213
|
return getiOSWindow();
|
|
988
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* @deprecated Use `primaryWindow?.ios?.scene` instead.
|
|
1217
|
+
*/
|
|
989
1218
|
getPrimaryScene() {
|
|
990
|
-
return this.
|
|
1219
|
+
return this.primaryWindow?.ios?.scene || null;
|
|
991
1220
|
}
|
|
992
1221
|
// Scene lifecycle management
|
|
993
1222
|
supportsScenes() {
|
|
@@ -997,7 +1226,7 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
997
1226
|
return supportsMultipleScenes();
|
|
998
1227
|
}
|
|
999
1228
|
isUsingSceneLifecycle() {
|
|
1000
|
-
return this.supportsScenes() && this.
|
|
1229
|
+
return this.supportsScenes() && this._windows.length > 0;
|
|
1001
1230
|
}
|
|
1002
1231
|
// Call this to set up scene-based configuration
|
|
1003
1232
|
configureForScenes() {
|
|
@@ -1005,34 +1234,6 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
1005
1234
|
console.warn('Scene-based lifecycle is only supported on iOS 13+ iPad or visionOS with multi-scene enabled apps.');
|
|
1006
1235
|
return;
|
|
1007
1236
|
}
|
|
1008
|
-
// Additional scene configuration can be added here
|
|
1009
|
-
// For now, the notification observers are already set up in the constructor
|
|
1010
|
-
}
|
|
1011
|
-
// Stable scene id for lookups
|
|
1012
|
-
_getSceneId(scene) {
|
|
1013
|
-
try {
|
|
1014
|
-
if (!scene) {
|
|
1015
|
-
return 'Unknown';
|
|
1016
|
-
}
|
|
1017
|
-
// Prefer session persistentIdentifier when available (stable across lifetime)
|
|
1018
|
-
const session = scene.session;
|
|
1019
|
-
const persistentId = session && session.persistentIdentifier;
|
|
1020
|
-
if (persistentId) {
|
|
1021
|
-
return `${persistentId}`;
|
|
1022
|
-
}
|
|
1023
|
-
// Fallbacks
|
|
1024
|
-
if (scene.hash != null) {
|
|
1025
|
-
return `${scene.hash}`;
|
|
1026
|
-
}
|
|
1027
|
-
const desc = scene.description;
|
|
1028
|
-
if (desc) {
|
|
1029
|
-
return `${desc}`;
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
catch (err) {
|
|
1033
|
-
// ignore
|
|
1034
|
-
}
|
|
1035
|
-
return 'Unknown';
|
|
1036
1237
|
}
|
|
1037
1238
|
// Resolve a UIWindowScene from various input types
|
|
1038
1239
|
_resolveScene(target) {
|
|
@@ -1040,12 +1241,10 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
1040
1241
|
return null;
|
|
1041
1242
|
}
|
|
1042
1243
|
if (!target) {
|
|
1043
|
-
// Try to pick a non-primary
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
return nonPrimary[0] || scenes[0] || null;
|
|
1244
|
+
// Try to pick a non-primary window's scene
|
|
1245
|
+
const nonPrimary = this._windows.filter((nw) => !nw.isPrimary);
|
|
1246
|
+
return nonPrimary[0]?.ios?.scene || this.primaryWindow?.ios?.scene || null;
|
|
1047
1247
|
}
|
|
1048
|
-
// If a View was passed, derive its window.scene
|
|
1049
1248
|
if (target && typeof target === 'object') {
|
|
1050
1249
|
// UIWindowScene
|
|
1051
1250
|
if (target.session && target.activationState !== undefined) {
|
|
@@ -1064,15 +1263,15 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
1064
1263
|
}
|
|
1065
1264
|
// String id lookup
|
|
1066
1265
|
if (typeof target === 'string') {
|
|
1067
|
-
|
|
1068
|
-
|
|
1266
|
+
const found = this.getWindowById(target);
|
|
1267
|
+
if (found) {
|
|
1268
|
+
return found.ios?.scene || null;
|
|
1069
1269
|
}
|
|
1070
|
-
// Try matching
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
return s;
|
|
1270
|
+
// Try matching among known scenes
|
|
1271
|
+
for (const nw of this._windows) {
|
|
1272
|
+
const scene = nw.ios?.scene;
|
|
1273
|
+
if (scene && IOSNativeWindow.getSceneId(scene) === target) {
|
|
1274
|
+
return scene;
|
|
1076
1275
|
}
|
|
1077
1276
|
}
|
|
1078
1277
|
}
|
|
@@ -1085,7 +1284,7 @@ export class iOSApplication extends ApplicationCommon {
|
|
|
1085
1284
|
}
|
|
1086
1285
|
// Create user activity for the new scene
|
|
1087
1286
|
const userActivity = NSUserActivity.alloc().initWithActivityType(`${NSBundle.mainBundle.bundleIdentifier}.scene`);
|
|
1088
|
-
userActivity.userInfo = dataSerialize(data);
|
|
1287
|
+
userActivity.userInfo = dataSerialize(data ?? {});
|
|
1089
1288
|
// Use the legacy API
|
|
1090
1289
|
const options = UISceneActivationRequestOptions.new();
|
|
1091
1290
|
options.requestingScene = windowScene;
|
|
@@ -1466,14 +1665,12 @@ export class AccessibilityServiceEnabledObservable extends CommonA11YServiceEnab
|
|
|
1466
1665
|
}
|
|
1467
1666
|
}
|
|
1468
1667
|
let accessibilityServiceObservable;
|
|
1469
|
-
export function
|
|
1668
|
+
export function ensureA11yClasses() {
|
|
1470
1669
|
if (accessibilityServiceObservable) {
|
|
1471
1670
|
return;
|
|
1472
1671
|
}
|
|
1473
1672
|
setFontScaleCssClasses(new Map(VALID_FONT_SCALES.map((fs) => [fs, `a11y-fontscale-${Number(fs * 100).toFixed(0)}`])));
|
|
1474
1673
|
accessibilityServiceObservable = new AccessibilityServiceEnabledObservable();
|
|
1475
|
-
// Initialize SDK version CSS class once
|
|
1476
|
-
initializeSdkVersionClass(Application.getRootView());
|
|
1477
1674
|
}
|
|
1478
1675
|
export function updateCurrentHelperClasses(applyRootCssClass) {
|
|
1479
1676
|
const fontScale = getFontScale();
|
|
@@ -1542,7 +1739,7 @@ function applyFontScaleToRootViews() {
|
|
|
1542
1739
|
rootModalViews.forEach((rootModalView) => (rootModalView.style.fontScaleInternal = fontScale));
|
|
1543
1740
|
}
|
|
1544
1741
|
export function initAccessibilityCssHelper() {
|
|
1545
|
-
|
|
1742
|
+
ensureA11yClasses();
|
|
1546
1743
|
updateCurrentHelperClasses(applyRootCssClass);
|
|
1547
1744
|
applyFontScaleToRootViews();
|
|
1548
1745
|
Application.on(Application.fontScaleChangedEvent, () => {
|