@apexnative/navigation 1.0.0-alpha.3 → 1.0.0-alpha.5
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/CHANGELOG.md +22 -0
- package/android/CLAUDE.md +26 -9
- package/android/CORE.md +32 -17
- package/android/RECIPES.md +9 -3
- package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +25 -9
- package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
- package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
- package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
- package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
- package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
- package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
- package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +33 -22
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +5 -4
- package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +39 -20
- package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +10 -5
- package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +47 -46
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +34 -7
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
- package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +6 -4
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +12 -12
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +4 -3
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +3 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +25 -17
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +6 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +5 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +45 -14
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +25 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +8 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +8 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +61 -15
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +28 -18
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +25 -12
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +2 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +85 -29
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +7 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +5 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +14 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +56 -21
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +4 -2
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
- package/cli/doctor/checks/app.js +61 -13
- package/cli/doctor/checks/splash.js +4 -22
- package/cli/migrate/native.js +18 -0
- package/cli/setup/source.js +2 -1
- package/cli/setup/steps/mainApplication.js +134 -19
- package/cli/splash/index.js +3 -1
- package/docs-md/architecture/transitions.md +6 -7
- package/docs-md/containers/modals.md +2 -2
- package/docs-md/guides/cli.md +1 -2
- package/docs-md/help/glossary.md +1 -1
- package/docs-md/help/troubleshooting.md +22 -5
- package/docs-md/index.json +4 -0
- package/docs-md/migration/from-react-native-navigation.md +8 -2
- package/docs-md/screen-ui/back-and-gestures.md +24 -2
- package/docs-md/start/installation.md +4 -2
- package/ios/CLAUDE.md +17 -5
- package/ios/CORE.md +18 -13
- package/ios/Contract/ANNCommandAnswer.h +9 -2
- package/ios/Contract/ANNCommandAnswer.mm +28 -30
- package/ios/Contract/ANNCommandContract.h +15 -0
- package/ios/Contract/ANNCommandContract.mm +78 -0
- package/ios/Core/ANNAppearanceDispatcher.h +5 -4
- package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
- package/ios/Core/ANNErrorHandler.h +1 -1
- package/ios/Core/ANNErrorHandler.mm +3 -1
- package/ios/Core/ANNEventEmitter.h +1 -1
- package/ios/Core/ANNEventEmitter.mm +2 -2
- package/ios/Core/ANNJavaScriptCalls.h +34 -0
- package/ios/Core/ANNJavaScriptCalls.mm +61 -0
- package/ios/Core/ANNNavigationState.h +7 -5
- package/ios/Core/ANNNavigationState.mm +8 -7
- package/ios/Core/ANNNodeHelper.h +32 -12
- package/ios/Core/ANNNodeHelper.mm +100 -3
- package/ios/Core/ANNRenderWait.h +15 -1
- package/ios/Core/ANNRenderWait.mm +119 -17
- package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
- package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
- package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
- package/ios/Layouts/Modal/ANNModalCoordinator.mm +55 -14
- package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
- package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
- package/ios/Layouts/Screen/ANNComponentViewController.h +8 -0
- package/ios/Layouts/Screen/ANNComponentViewController.mm +32 -5
- package/ios/Layouts/Screen/ANNScreenPlace.h +41 -0
- package/ios/Layouts/Screen/ANNScreenPlace.mm +175 -0
- package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
- package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
- package/ios/Layouts/SplitView/ANNSplitViewController.mm +4 -2
- package/ios/Layouts/Stack/ANNPreviewPush.h +5 -5
- package/ios/Layouts/Stack/ANNPreviewPush.mm +85 -22
- package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
- package/ios/Layouts/Stack/ANNStackController.mm +26 -3
- package/ios/Layouts/Stack/ANNStackQueue.h +3 -1
- package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +13 -5
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +2 -2
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +109 -7
- package/ios/Options/ANNOptionsCache.h +7 -6
- package/ios/Options/ANNSearchBarOptions.h +4 -3
- package/ios/Options/ANNUserChoice.h +57 -0
- package/ios/Options/ANNUserChoice.mm +44 -0
- package/ios/Options/Params/ANNImageSource.h +61 -0
- package/ios/Options/Params/ANNImageSource.mm +101 -0
- package/ios/Options/Params/ANNOptionImages.h +37 -0
- package/ios/Options/Params/ANNOptionImages.mm +284 -0
- package/ios/Options/Params/Image.h +11 -2
- package/ios/Options/Params/Image.mm +15 -2
- package/ios/Options/Params/ImageParser.h +5 -5
- package/ios/Options/Params/ImageParser.mm +28 -46
- package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
- package/ios/RECIPES.md +11 -5
- package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
- package/ios/React/Slots/ANNSlotContainers.h +14 -6
- package/ios/React/Slots/ANNSlotContainers.mm +75 -2
- package/ios/TopBar/ANNBarButtons.h +9 -5
- package/ios/TopBar/ANNBarButtons.mm +211 -63
- package/ios/TopBar/ANNIconButtonImage.h +1 -0
- package/ios/TopBar/ANNIconButtonImage.mm +34 -1
- package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
- package/ios/TopBar/ANNLargeTitlePresenter.mm +26 -3
- package/ios/TopBar/ANNSearchPresenter.mm +170 -19
- package/ios/TopBar/ANNTopBarPresenter.h +5 -0
- package/ios/TopBar/ANNTopBarPresenter.mm +60 -11
- package/ios/TurboModules/ANNTurboModule.mm +39 -21
- package/lib/module/ARCHITECTURE.md +18 -18
- package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
- package/lib/module/api/commands/commands.js +54 -6
- package/lib/module/api/commands/commands.js.map +1 -1
- package/lib/module/api/navigation.js.map +1 -1
- package/lib/module/engine/commands.js +9 -7
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +13 -9
- package/lib/module/engine/layout.js.map +1 -1
- package/lib/module/engine/options.js +44 -11
- package/lib/module/engine/options.js.map +1 -1
- package/lib/module/engine/places.js +52 -7
- package/lib/module/engine/places.js.map +1 -1
- package/lib/module/engine/props.js +30 -1
- package/lib/module/engine/props.js.map +1 -1
- package/lib/module/engine/rememberedOptions.js +1 -1
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +22 -12
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/module/interfaces/contract/commands.json +101 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +5 -2
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
- package/lib/typescript/api/commands/commands.d.ts.map +1 -1
- package/lib/typescript/api/commands/presentation.d.ts +4 -3
- package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
- package/lib/typescript/api/navigation.d.ts +4 -1
- package/lib/typescript/api/navigation.d.ts.map +1 -1
- package/lib/typescript/engine/commands.d.ts.map +1 -1
- package/lib/typescript/engine/options.d.ts +5 -2
- package/lib/typescript/engine/options.d.ts.map +1 -1
- package/lib/typescript/engine/places.d.ts +7 -2
- package/lib/typescript/engine/places.d.ts.map +1 -1
- package/lib/typescript/engine/props.d.ts +8 -1
- package/lib/typescript/engine/props.d.ts.map +1 -1
- package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
- package/lib/typescript/engine/screens.d.ts.map +1 -1
- package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
- package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
- package/lib/typescript/interfaces/Events.d.ts +19 -10
- package/lib/typescript/interfaces/Events.d.ts.map +1 -1
- package/lib/typescript/interfaces/Options.d.ts +1 -1
- package/lib/typescript/interfaces/Options.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/animations.d.ts +23 -4
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/buttons.d.ts +13 -5
- package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +9 -0
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/topBar.d.ts +22 -9
- package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ARCHITECTURE.md +18 -18
- package/src/adapters/NativeANNTurboModule.ts +5 -2
- package/src/api/commands/commands.ts +48 -7
- package/src/api/commands/presentation.ts +4 -3
- package/src/api/events/navigationEvents.ts +1 -1
- package/src/api/hooks/useNavigation.ts +1 -1
- package/src/api/navigation.ts +4 -1
- package/src/engine/commands.ts +19 -7
- package/src/engine/layout.ts +16 -9
- package/src/engine/options.ts +39 -11
- package/src/engine/places.ts +65 -7
- package/src/engine/props.ts +30 -1
- package/src/engine/rememberedOptions.ts +4 -1
- package/src/engine/screens.tsx +23 -13
- package/src/interfaces/ComponentEvents.ts +2 -2
- package/src/interfaces/Events.ts +19 -10
- package/src/interfaces/Options.ts +1 -0
- package/src/interfaces/contract/commands.json +101 -0
- package/src/interfaces/options/animations.ts +24 -4
- package/src/interfaces/options/buttons.ts +13 -5
- package/src/interfaces/options/stack.ts +9 -0
- package/src/interfaces/options/topBar.ts +22 -9
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
package/ios/Core/ANNNodeHelper.h
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#import "ANNLayoutInfo.h"
|
|
4
4
|
#import "ANNNavigationOptions.h"
|
|
5
5
|
#import "ANNNodePresenter.h"
|
|
6
|
+
#import "ANNUserChoice.h"
|
|
6
7
|
#import <UIKit/UIKit.h>
|
|
7
8
|
|
|
8
9
|
NS_ASSUME_NONNULL_BEGIN
|
|
@@ -24,9 +25,11 @@ FOUNDATION_EXPORT NSString *const ANNContainerReadyHandlerKey;
|
|
|
24
25
|
@property(nonatomic, weak, readonly, nullable) UIViewController *node;
|
|
25
26
|
|
|
26
27
|
@property(nonatomic, strong, nullable) ANNLayoutInfo *layoutInfo;
|
|
27
|
-
/// The node's own options: its layout options with every `mergeOptions` into it and the
|
|
28
|
-
///
|
|
29
|
-
///
|
|
28
|
+
/// The node's own options: its layout options with every `mergeOptions` into it and what the core keeps of a merge (the
|
|
29
|
+
/// title component a merged text drops, side colors). The user's choices are not here but in the user layer
|
|
30
|
+
/// (`setUserChoice:forKey:`). The setter stores them without the one-shot options and makes every resolved options miss
|
|
31
|
+
/// its cache; it is the only way to change them. Never change them in place: `mergeOwnOptions:` or
|
|
32
|
+
/// `changeOwnOptions:`.
|
|
30
33
|
@property(nonatomic, strong, nullable) ANNNavigationOptions *options;
|
|
31
34
|
/// The default options of the app (`ANNDefaultOptions.current`); setting it does nothing, the defaults are the app's.
|
|
32
35
|
@property(nonatomic, strong, nullable) ANNNavigationOptions *defaultOptions;
|
|
@@ -57,21 +60,38 @@ FOUNDATION_EXPORT NSString *const ANNContainerReadyHandlerKey;
|
|
|
57
60
|
/// the layout, else the fallback (when there is none, the parent view controller).
|
|
58
61
|
- (nullable UIViewController *)layoutParent;
|
|
59
62
|
|
|
60
|
-
/// `options` merged with `options` given and stored through the setter.
|
|
63
|
+
/// The app's `mergeOptions` into the node: `options` merged with `options` given and stored through the setter. A
|
|
64
|
+
/// choice of the user layer that the merge changes leaves the layer, by Android's rules
|
|
65
|
+
/// (`ANNUserChoice choiceAfterMerge:own:before:after:`): a field given a value other than the app had there (the own
|
|
66
|
+
/// options', else the node's resolution before the merge), or the button, item or scope of the choice gone from the
|
|
67
|
+
/// node's resolution after it; the same value sent again keeps it.
|
|
61
68
|
- (void)mergeOwnOptions:(ANNNavigationOptions *)options;
|
|
62
69
|
|
|
63
|
-
/// A change of the own options by the core
|
|
64
|
-
///
|
|
65
|
-
///
|
|
70
|
+
/// A change of the own options by the core: `change` gets a copy of them, and the copy is stored through the setter.
|
|
71
|
+
/// For what the core keeps of the app's merges (the title component a merged text drops, side colors), never for a
|
|
72
|
+
/// choice of the user, which goes into the user layer.
|
|
66
73
|
- (void)changeOwnOptions:(void (^)(ANNNavigationOptions *options))change;
|
|
67
74
|
|
|
68
|
-
/// The
|
|
69
|
-
///
|
|
75
|
+
/// The user layer: the choices the user made in native UI (a toggled button, the check of a single-selection menu, the
|
|
76
|
+
/// search scope, the tokens and suggestions UIKit removed, a renamed title), one per key, apart from the own options.
|
|
77
|
+
/// The resolution writes them over the own options, by identity (`ANNUserChoice applyTo:`): defaults < parents < own <
|
|
78
|
+
/// user. Setting one (nil removes it) makes every resolved options miss its cache, as a change of own options does.
|
|
79
|
+
/// `setDefaultOptions` never touches the layer; it goes with the node.
|
|
80
|
+
- (void)setUserChoice:(nullable ANNUserChoice *)choice forKey:(NSString *)key;
|
|
81
|
+
|
|
82
|
+
/// The choice under `key`, or nil.
|
|
83
|
+
- (nullable ANNUserChoice *)userChoiceForKey:(NSString *)key;
|
|
84
|
+
|
|
85
|
+
/// The common resolve: a copy of the node's own options with its user layer written over them, then the resolved
|
|
86
|
+
/// options of its current child over that, down the visible chain. A new object each call: a container's override may
|
|
87
|
+
/// change it in place.
|
|
70
88
|
- (ANNNavigationOptions *)resolveOptions;
|
|
71
89
|
|
|
72
|
-
/// What the node shows with: the default options, then the own options of its parents
|
|
73
|
-
/// then the node's `resolveOptions
|
|
74
|
-
///
|
|
90
|
+
/// What the node shows with: the default options, then the own options of its parents (each with its user layer) from
|
|
91
|
+
/// the farthest to the nearest, then the node's `resolveOptions`; a node without a current child (a screen) writes its
|
|
92
|
+
/// user layer once more at the end, so a choice also reaches a list the screen takes from its stack or the defaults.
|
|
93
|
+
/// Cached until any options or user layer change (`ANNOptionsCache`), the node has another parent, or a node of its
|
|
94
|
+
/// visible chain has another current child. Read-only: copy it before changing anything.
|
|
75
95
|
- (ANNNavigationOptions *)resolveOptionsWithDefault;
|
|
76
96
|
|
|
77
97
|
/// `resolveOptionsWithDefault` built now, without the cache: for a reader whose node resolves through more than its
|
|
@@ -29,8 +29,14 @@ static NSPointerArray *ANNWeakNodes(NSArray<UIViewController *> *nodes) {
|
|
|
29
29
|
|
|
30
30
|
NSString *const ANNContainerReadyHandlerKey = @"ApexNavigation.container";
|
|
31
31
|
|
|
32
|
+
// Set while a node works out the app's resolution (`appResolution`): no user layer is written. Main queue.
|
|
33
|
+
static BOOL ANNUserLayersLeftOut = NO;
|
|
34
|
+
|
|
32
35
|
@implementation ANNNodeHelper {
|
|
33
36
|
ANNNavigationOptions *_options;
|
|
37
|
+
// The user layer: the choices by key, and their keys in the order they were set, the order they are written in.
|
|
38
|
+
NSMutableDictionary<NSString *, ANNUserChoice *> *_userChoices;
|
|
39
|
+
NSMutableArray<NSString *> *_userChoiceKeys;
|
|
34
40
|
// The ready handlers by key, and their keys in the order they were first set.
|
|
35
41
|
NSMutableDictionary<NSString *, dispatch_block_t> *_readyHandlers;
|
|
36
42
|
NSMutableArray<NSString *> *_readyKeys;
|
|
@@ -108,10 +114,27 @@ NSString *const ANNContainerReadyHandlerKey = @"ApexNavigation.container";
|
|
|
108
114
|
- (void)setDefaultOptions:(ANNNavigationOptions *)defaultOptions {
|
|
109
115
|
}
|
|
110
116
|
|
|
117
|
+
// With a user layer, the choices meet the merge as on Android: they see the app's resolution before it and after it
|
|
118
|
+
// (the merge in place for that, uncached), and those the merge changes leave; the setter then moves the cache once for
|
|
119
|
+
// both, also when a choice's rule throws: the new own options never stay with a cache of the old ones.
|
|
111
120
|
- (void)mergeOwnOptions:(ANNNavigationOptions *)options {
|
|
112
|
-
|
|
121
|
+
ANNAssertMainQueue();
|
|
122
|
+
ANNNavigationOptions *own = _options ?: [ANNNavigationOptions new];
|
|
123
|
+
ANNNavigationOptions *merged = [own copy];
|
|
113
124
|
[merged mergeOptions:options];
|
|
114
|
-
|
|
125
|
+
if (_userChoiceKeys.count == 0) {
|
|
126
|
+
self.options = merged;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
ANNNavigationOptions *before = [self appResolution];
|
|
130
|
+
ANNNavigationOptions *stored = [merged withoutOneShotOptions];
|
|
131
|
+
_options = stored;
|
|
132
|
+
@try {
|
|
133
|
+
ANNNavigationOptions *after = [self appResolution];
|
|
134
|
+
[self userChoicesMeetMerge:options own:own before:before after:after];
|
|
135
|
+
} @finally {
|
|
136
|
+
self.options = stored;
|
|
137
|
+
}
|
|
115
138
|
}
|
|
116
139
|
|
|
117
140
|
- (void)changeOwnOptions:(void (^)(ANNNavigationOptions *options))change {
|
|
@@ -120,10 +143,78 @@ NSString *const ANNContainerReadyHandlerKey = @"ApexNavigation.container";
|
|
|
120
143
|
self.options = changed;
|
|
121
144
|
}
|
|
122
145
|
|
|
146
|
+
#pragma mark - The user layer
|
|
147
|
+
|
|
148
|
+
- (void)setUserChoice:(ANNUserChoice *)choice forKey:(NSString *)key {
|
|
149
|
+
ANNAssertMainQueue();
|
|
150
|
+
if (!choice && !_userChoices[key]) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (!_userChoices) {
|
|
154
|
+
_userChoices = [NSMutableDictionary new];
|
|
155
|
+
_userChoiceKeys = [NSMutableArray new];
|
|
156
|
+
}
|
|
157
|
+
// A choice set again goes last: it is the newest.
|
|
158
|
+
[_userChoiceKeys removeObject:key];
|
|
159
|
+
if (choice) {
|
|
160
|
+
_userChoices[key] = choice;
|
|
161
|
+
[_userChoiceKeys addObject:key];
|
|
162
|
+
} else {
|
|
163
|
+
[_userChoices removeObjectForKey:key];
|
|
164
|
+
}
|
|
165
|
+
[ANNOptionsCache optionsChanged];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
- (ANNUserChoice *)userChoiceForKey:(NSString *)key {
|
|
169
|
+
return _userChoices[key];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Each choice answers the merge itself: it stays, keeps a part, or goes. The order of the rest stays.
|
|
173
|
+
- (void)userChoicesMeetMerge:(ANNNavigationOptions *)merge
|
|
174
|
+
own:(ANNNavigationOptions *)own
|
|
175
|
+
before:(ANNNavigationOptions *)before
|
|
176
|
+
after:(ANNNavigationOptions *)after {
|
|
177
|
+
for (NSString *key in [_userChoiceKeys copy]) {
|
|
178
|
+
ANNUserChoice *choice = _userChoices[key];
|
|
179
|
+
ANNUserChoice *kept = [choice choiceAfterMerge:merge own:own before:before after:after];
|
|
180
|
+
if (kept == choice) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (kept) {
|
|
184
|
+
_userChoices[key] = kept;
|
|
185
|
+
} else {
|
|
186
|
+
[_userChoices removeObjectForKey:key];
|
|
187
|
+
[_userChoiceKeys removeObject:key];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// The node's resolution with the defaults and without any user layer: what the app's options alone give (Android's
|
|
193
|
+
// `resolveCurrentOptions().withDefaultOptions`). Built now, never cached: the resolution reads no cache on the way.
|
|
194
|
+
- (ANNNavigationOptions *)appResolution {
|
|
195
|
+
BOOL leftOut = ANNUserLayersLeftOut;
|
|
196
|
+
ANNUserLayersLeftOut = YES;
|
|
197
|
+
@try {
|
|
198
|
+
return [self resolveOptionsWithDefaultUncached];
|
|
199
|
+
} @finally {
|
|
200
|
+
ANNUserLayersLeftOut = leftOut;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
- (void)applyUserLayerTo:(ANNNavigationOptions *)options {
|
|
205
|
+
if (ANNUserLayersLeftOut) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
for (NSString *key in _userChoiceKeys) {
|
|
209
|
+
[_userChoices[key] applyTo:options];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
123
213
|
#pragma mark - Resolving
|
|
124
214
|
|
|
125
215
|
- (ANNNavigationOptions *)resolveOptions {
|
|
126
216
|
ANNNavigationOptions *result = _options ? [_options copy] : [ANNNavigationOptions new];
|
|
217
|
+
[self applyUserLayerTo:result];
|
|
127
218
|
UIViewController *child = [_node getCurrentChild];
|
|
128
219
|
if (child) {
|
|
129
220
|
[result mergeOptions:[child resolveOptions]];
|
|
@@ -168,7 +259,9 @@ NSString *const ANNContainerReadyHandlerKey = @"ApexNavigation.container";
|
|
|
168
259
|
return [self resolveOfNode:node parents:parents];
|
|
169
260
|
}
|
|
170
261
|
|
|
171
|
-
// Built on copies: the defaults never go into a node's own options.
|
|
262
|
+
// Built on copies: the defaults never go into a node's own options. Each parent's user layer goes over its own
|
|
263
|
+
// options; a node without a current child writes its own layer once more at the end, for the lists it takes from its
|
|
264
|
+
// parents or the defaults (a toggle of a button of the stack's). Writing a choice twice gives the same result.
|
|
172
265
|
- (ANNNavigationOptions *)resolveOfNode:(UIViewController *)node
|
|
173
266
|
parents:(NSArray<UIViewController *> *)parents {
|
|
174
267
|
ANNNavigationOptions *result = [ANNDefaultOptions.current copy];
|
|
@@ -177,8 +270,12 @@ NSString *const ANNContainerReadyHandlerKey = @"ApexNavigation.container";
|
|
|
177
270
|
if (own) {
|
|
178
271
|
[result mergeOptions:own];
|
|
179
272
|
}
|
|
273
|
+
[parent.nodeHelper applyUserLayerTo:result];
|
|
180
274
|
}
|
|
181
275
|
[result mergeOptions:[node resolveOptions]];
|
|
276
|
+
if (![node getCurrentChild]) {
|
|
277
|
+
[self applyUserLayerTo:result];
|
|
278
|
+
}
|
|
182
279
|
return result;
|
|
183
280
|
}
|
|
184
281
|
|
package/ios/Core/ANNRenderWait.h
CHANGED
|
@@ -5,7 +5,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
5
5
|
|
|
6
6
|
/// What content a render wait waits for.
|
|
7
7
|
typedef NS_ENUM(NSInteger, ANNRenderWaitContent) {
|
|
8
|
-
/// No content: the bar components alone
|
|
8
|
+
/// No content: the bar components alone.
|
|
9
9
|
ANNRenderWaitContentNone,
|
|
10
10
|
/// Each screen of `screens` whose React content isn't ready, by its own ready handler (a root's screens). The limit
|
|
11
11
|
/// marks ready the screens still waited.
|
|
@@ -59,6 +59,20 @@ typedef NS_ENUM(NSInteger, ANNRenderWaitBar) {
|
|
|
59
59
|
/// has none).
|
|
60
60
|
@property(nonatomic) BOOL unknownContentRule;
|
|
61
61
|
|
|
62
|
+
/// The content phase ends only once every call JavaScript made by then is applied on the main queue
|
|
63
|
+
/// (`ANNJavaScriptCalls`): the options a screen merges in the commit that mounted it are there before the owner's next
|
|
64
|
+
/// step. Also when the content is there already as the wait starts or takes its screens again (the commit that mounted
|
|
65
|
+
/// it may have run just now): such a phase ends after `start`, through `protect`, while JavaScript has a call invoker;
|
|
66
|
+
/// without one (no JavaScript running) the calls are applied already and the phase ends inside `start`, as without
|
|
67
|
+
/// this. Screens without React content (a native screen) end the phase at once. The limit still ends the phase
|
|
68
|
+
/// meanwhile. Off by default.
|
|
69
|
+
@property(nonatomic) BOOL settlesThroughJavaScript;
|
|
70
|
+
|
|
71
|
+
/// With `ANNRenderWaitBarAfterContent`, the bar phase that follows the content phase counts its limits from the wait's
|
|
72
|
+
/// start, not from its own: the time the content took comes off each kind's limit, and a kind past it by then waits no
|
|
73
|
+
/// more. A bar phase that starts again (`retakeScreens:`) counts from then, as without it. Off by default.
|
|
74
|
+
@property(nonatomic) BOOL barLimitsFromStart;
|
|
75
|
+
|
|
62
76
|
/// Runs inside `start`, after the ready handlers are set and before the readiness test (the stack parks and renders
|
|
63
77
|
/// its entry there). A ready handler that runs inside it is left to the test after it.
|
|
64
78
|
@property(nonatomic, copy, nullable) dispatch_block_t setUp;
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
#import "ANNRenderWait.h"
|
|
2
2
|
#import "ANNAssert.h"
|
|
3
3
|
#import "ANNComponentViewController.h"
|
|
4
|
+
#import "ANNJavaScriptCalls.h"
|
|
4
5
|
#import "ANNScreenReadiness.h"
|
|
5
6
|
#import "UIViewController+LayoutProtocol.h"
|
|
7
|
+
#import <QuartzCore/QuartzCore.h>
|
|
6
8
|
|
|
7
9
|
// A screen whose rendered state stays unknown counts as ready after this, with `unknownContentRule`.
|
|
8
10
|
static const NSTimeInterval ANNUnknownContentLimit = 1;
|
|
9
11
|
|
|
12
|
+
// What a kind of the bar whose limit passed in the content phase still gets, with `barLimitsFromStart`: a limit of 0
|
|
13
|
+
// would mean none of its own.
|
|
14
|
+
static const NSTimeInterval ANNPassedBarLimit = 0.001;
|
|
15
|
+
|
|
16
|
+
// What is left of a bar kind's `limit` after `spent`; no limit of its own stays none.
|
|
17
|
+
static NSTimeInterval ANNBarLimitLeft(NSTimeInterval limit, NSTimeInterval spent) {
|
|
18
|
+
if (limit <= 0) {
|
|
19
|
+
return limit;
|
|
20
|
+
}
|
|
21
|
+
return MAX(limit - spent, ANNPassedBarLimit);
|
|
22
|
+
}
|
|
23
|
+
|
|
10
24
|
// The number of the last wait made: each wait listens under a key of its own.
|
|
11
25
|
static NSUInteger ANNRenderWaitCount;
|
|
12
26
|
|
|
@@ -18,12 +32,18 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
18
32
|
ANNRenderWaitBar _bar;
|
|
19
33
|
ANNBarWaitLimits _barLimits;
|
|
20
34
|
NSString *_key;
|
|
35
|
+
// When the running wait started (`barLimitsFromStart`).
|
|
36
|
+
CFTimeInterval _startTime;
|
|
21
37
|
// The token: each start, phase and end takes the next one, so that what an earlier one set up does nothing.
|
|
22
38
|
NSUInteger _number;
|
|
23
39
|
// Inside `start`: a step runs as it is, under the caller's protection.
|
|
24
40
|
BOOL _starting;
|
|
25
41
|
// Inside `setUp`: a ready handler leaves the node to the readiness test after it.
|
|
26
42
|
BOOL _settingUp;
|
|
43
|
+
// The content is there and the phase waits for the calls JavaScript made by then (`settlesThroughJavaScript`); the
|
|
44
|
+
// number of that settle, so that one of an earlier take does nothing.
|
|
45
|
+
BOOL _settling;
|
|
46
|
+
NSUInteger _settleNumber;
|
|
27
47
|
// The content nodes still waited, and every node the wait set its ready handler on.
|
|
28
48
|
NSHashTable<UIViewController *> *_waited;
|
|
29
49
|
NSHashTable<UIViewController *> *_listened;
|
|
@@ -70,6 +90,7 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
70
90
|
_isWaiting = YES;
|
|
71
91
|
_isInBarPhase = NO;
|
|
72
92
|
_mountLimitPassed = NO;
|
|
93
|
+
_startTime = CACurrentMediaTime();
|
|
73
94
|
NSUInteger number = ++_number;
|
|
74
95
|
_starting = YES;
|
|
75
96
|
@try {
|
|
@@ -117,11 +138,9 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
117
138
|
if (![self runs:number]) {
|
|
118
139
|
return;
|
|
119
140
|
}
|
|
120
|
-
|
|
121
|
-
[_waited removeObject:_node];
|
|
122
|
-
}
|
|
141
|
+
[self testNode];
|
|
123
142
|
if (_waited.count == 0 && !_barWait) {
|
|
124
|
-
[self
|
|
143
|
+
[self contentOfNumber:number];
|
|
125
144
|
}
|
|
126
145
|
}
|
|
127
146
|
|
|
@@ -206,7 +225,7 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
206
225
|
}
|
|
207
226
|
[_waited removeObject:node];
|
|
208
227
|
if (_waited.count == 0 && !_barWait) {
|
|
209
|
-
[self
|
|
228
|
+
[self contentOfNumber:number];
|
|
210
229
|
}
|
|
211
230
|
}
|
|
212
231
|
|
|
@@ -219,6 +238,36 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
219
238
|
if (_waited.count > 0) {
|
|
220
239
|
return;
|
|
221
240
|
}
|
|
241
|
+
[self contentOfNumber:number];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// What the running phase waited for came by its signals, or was there already. The content phase with
|
|
245
|
+
// `settlesThroughJavaScript` ends once the calls JavaScript made by now are applied: the commit that mounted the content
|
|
246
|
+
// ran its layout effects (`useScreenOptions`) in the same task of the JavaScript thread, so their `mergeOptions` are on
|
|
247
|
+
// their way to the main queue ahead of the settle. Content that was there already (as the wait starts or takes its
|
|
248
|
+
// screens again) may have mounted in a commit that ran just now: it settles too. The bar phase, and screens without
|
|
249
|
+
// React content (a native screen), end at once.
|
|
250
|
+
- (void)contentOfNumber:(NSUInteger)number {
|
|
251
|
+
if (!_settlesThroughJavaScript || _isInBarPhase || ![self hasReactScreen]) {
|
|
252
|
+
[self phaseOfNumber:number endedMarkingReady:NO];
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (_settling) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
_settling = YES;
|
|
259
|
+
NSUInteger settle = ++_settleNumber;
|
|
260
|
+
__weak ANNRenderWait *weakSelf = self;
|
|
261
|
+
[ANNJavaScriptCalls afterCallsMadeSoFar:^{
|
|
262
|
+
[weakSelf settleOfNumber:number settle:settle];
|
|
263
|
+
}];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
- (void)settleOfNumber:(NSUInteger)number settle:(NSUInteger)settle {
|
|
267
|
+
if (![self runs:number] || !_settling || settle != _settleNumber) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
_settling = NO;
|
|
222
271
|
[self phaseOfNumber:number endedMarkingReady:NO];
|
|
223
272
|
}
|
|
224
273
|
|
|
@@ -240,9 +289,18 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
240
289
|
}
|
|
241
290
|
}
|
|
242
291
|
|
|
243
|
-
// The limit: what is still waited counts as rendered from now on, its held events go at once.
|
|
292
|
+
// The limit: what is still waited counts as rendered from now on, its held events go at once. A phase that only waits
|
|
293
|
+
// for the calls of JavaScript (its content is there) ends without marking anything.
|
|
244
294
|
- (void)limitOfNumber:(NSUInteger)number {
|
|
245
|
-
if (![self runs:number]
|
|
295
|
+
if (![self runs:number]) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (_settling) {
|
|
299
|
+
[self stopSettling];
|
|
300
|
+
[self phaseOfNumber:number endedMarkingReady:NO];
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (_waited.count == 0 && !_barWait) {
|
|
246
304
|
return;
|
|
247
305
|
}
|
|
248
306
|
[self phaseOfNumber:number endedMarkingReady:YES];
|
|
@@ -288,7 +346,7 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
288
346
|
[self markContentReady];
|
|
289
347
|
}
|
|
290
348
|
if (self->_bar == ANNRenderWaitBarAfterContent && !self->_isInBarPhase) {
|
|
291
|
-
[self
|
|
349
|
+
[self startBarPhaseWithLimits:[self barLimitsAfterContent]];
|
|
292
350
|
return;
|
|
293
351
|
}
|
|
294
352
|
[self finish];
|
|
@@ -309,9 +367,10 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
309
367
|
|
|
310
368
|
#pragma mark - The bar phase
|
|
311
369
|
|
|
312
|
-
// The content is there: the bar components of the screens now, each kind to its
|
|
313
|
-
// for ends the wait at once.
|
|
314
|
-
- (void)
|
|
370
|
+
// The content is there: the bar components of the screens now, each kind to its limit in `limits` from now. Nothing to
|
|
371
|
+
// wait for ends the wait at once.
|
|
372
|
+
- (void)startBarPhaseWithLimits:(ANNBarWaitLimits)limits {
|
|
373
|
+
[self stopSettling];
|
|
315
374
|
[_barWait cancel];
|
|
316
375
|
_barWait = nil;
|
|
317
376
|
[self releaseContent];
|
|
@@ -321,7 +380,7 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
321
380
|
NSArray<UIViewController *> *barScreens = [self barScreens];
|
|
322
381
|
[self rememberTakenScreens:barScreens states:nil];
|
|
323
382
|
ANNBarComponentsWait *barWait = [ANNBarComponentsWait waitForScreens:barScreens
|
|
324
|
-
limits:
|
|
383
|
+
limits:limits
|
|
325
384
|
done:^{
|
|
326
385
|
[weakSelf barOfNumber:number];
|
|
327
386
|
}];
|
|
@@ -344,23 +403,28 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
344
403
|
}
|
|
345
404
|
if (_isInBarPhase) {
|
|
346
405
|
[self runStep:^{
|
|
347
|
-
[self
|
|
406
|
+
[self startBarPhaseWithLimits:self->_barLimits];
|
|
348
407
|
}];
|
|
349
408
|
return;
|
|
350
409
|
}
|
|
351
410
|
// The same token: the limit set at the start stays.
|
|
352
411
|
NSUInteger number = _number;
|
|
412
|
+
[self stopSettling];
|
|
353
413
|
[self releaseContent];
|
|
354
414
|
[_barWait cancel];
|
|
355
415
|
_barWait = nil;
|
|
356
|
-
if (take) {
|
|
357
|
-
[self takeScreensOfNumber:number];
|
|
358
|
-
} else {
|
|
416
|
+
if (!take) {
|
|
359
417
|
_takenScreens = nil;
|
|
360
418
|
_takenStates = nil;
|
|
419
|
+
[self phaseOfNumber:number endedMarkingReady:NO];
|
|
420
|
+
return;
|
|
361
421
|
}
|
|
422
|
+
// As at the start: a node ready already counts at once (its ready handler waits for the next time), and content
|
|
423
|
+
// that is there settles again, the settle of the last take having stopped.
|
|
424
|
+
[self takeScreensOfNumber:number];
|
|
425
|
+
[self testNode];
|
|
362
426
|
if (_waited.count == 0 && !_barWait) {
|
|
363
|
-
[self
|
|
427
|
+
[self contentOfNumber:number];
|
|
364
428
|
}
|
|
365
429
|
}
|
|
366
430
|
|
|
@@ -382,6 +446,7 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
382
446
|
|
|
383
447
|
// The wait lets go of everything: its handlers, its bar wait; its limits find another token.
|
|
384
448
|
- (void)stop {
|
|
449
|
+
[self stopSettling];
|
|
385
450
|
_isWaiting = NO;
|
|
386
451
|
_isInBarPhase = NO;
|
|
387
452
|
_takenScreens = nil;
|
|
@@ -404,6 +469,12 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
404
469
|
|
|
405
470
|
#pragma mark - Helpers
|
|
406
471
|
|
|
472
|
+
// A settle on its way does nothing from now on.
|
|
473
|
+
- (void)stopSettling {
|
|
474
|
+
_settling = NO;
|
|
475
|
+
_settleNumber++;
|
|
476
|
+
}
|
|
477
|
+
|
|
407
478
|
// What the content phase's take reads of each screen to decide what it waits for: the readiness it needs, whether it
|
|
408
479
|
// has its content yet, whether that content is ready, and whether its root mounted.
|
|
409
480
|
- (NSArray<NSNumber *> *)takeStateOfScreens:(NSArray<UIViewController *> *)screens {
|
|
@@ -470,6 +541,37 @@ static NSUInteger ANNRenderWaitCount;
|
|
|
470
541
|
return screens;
|
|
471
542
|
}
|
|
472
543
|
|
|
544
|
+
// With `ANNRenderWaitContentNode`, the node counts as ready when every screen of it is.
|
|
545
|
+
- (void)testNode {
|
|
546
|
+
if (_content == ANNRenderWaitContentNode && _node && [self screensAreReady]) {
|
|
547
|
+
[_waited removeObject:_node];
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// The limits of the bar phase that follows the content phase: with `barLimitsFromStart`, what is left of each since the
|
|
552
|
+
// wait started.
|
|
553
|
+
- (ANNBarWaitLimits)barLimitsAfterContent {
|
|
554
|
+
ANNBarWaitLimits limits = _barLimits;
|
|
555
|
+
if (!_barLimitsFromStart) {
|
|
556
|
+
return limits;
|
|
557
|
+
}
|
|
558
|
+
NSTimeInterval spent = CACurrentMediaTime() - _startTime;
|
|
559
|
+
limits.titleAndBackground = ANNBarLimitLeft(limits.titleAndBackground, spent);
|
|
560
|
+
limits.buttons = ANNBarLimitLeft(limits.buttons, spent);
|
|
561
|
+
return limits;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// A screen with React content is among the screens: a commit of React mounted it.
|
|
565
|
+
- (BOOL)hasReactScreen {
|
|
566
|
+
for (UIViewController *node in [self screens]) {
|
|
567
|
+
if ([node isKindOfClass:ANNComponentViewController.class] &&
|
|
568
|
+
((ANNComponentViewController *)node).reactView) {
|
|
569
|
+
return YES;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return NO;
|
|
573
|
+
}
|
|
574
|
+
|
|
473
575
|
// Every screen has no content to wait for (a native screen) or its content is ready.
|
|
474
576
|
- (BOOL)screensAreReady {
|
|
475
577
|
for (UIViewController *node in [self screens]) {
|
|
@@ -64,10 +64,17 @@ FOUNDATION_EXPORT ANNWaitedReadiness ANNWaitedReadinessOf(UIViewController *scre
|
|
|
64
64
|
/// The own options merged with `options` (`ANNNodeHelper mergeOwnOptions:`).
|
|
65
65
|
- (void)mergeOwnOptions:(ANNNavigationOptions *)options;
|
|
66
66
|
|
|
67
|
-
/// A change of the own options on a copy (`ANNNodeHelper changeOwnOptions:`): the
|
|
68
|
-
/// choice of the user (a scope, tokens, a checked menu item, a toggled button).
|
|
67
|
+
/// A change of the own options on a copy (`ANNNodeHelper changeOwnOptions:`): what the core keeps of the app's merges.
|
|
69
68
|
- (void)changeOwnOptions:(void (^)(ANNNavigationOptions *options))change;
|
|
70
69
|
|
|
70
|
+
/// A choice of the user in the node's user layer (`ANNNodeHelper setUserChoice:forKey:`): the way a presenter or a
|
|
71
|
+
/// module keeps what the user did (a scope, tokens, a checked menu item, a toggled button, a renamed title). Nil
|
|
72
|
+
/// removes it.
|
|
73
|
+
- (void)setUserChoice:(nullable ANNUserChoice *)choice forKey:(NSString *)key;
|
|
74
|
+
|
|
75
|
+
/// The choice of the user layer under `key`, or nil (`ANNNodeHelper userChoiceForKey:`).
|
|
76
|
+
- (nullable ANNUserChoice *)userChoiceForKey:(NSString *)key;
|
|
77
|
+
|
|
71
78
|
#pragma mark - Readiness
|
|
72
79
|
|
|
73
80
|
/// A ready handler of the node under the waiter's own key (`ANNNodeHelper setReadyHandler:forKey:`): it runs once, the
|
|
@@ -125,6 +125,14 @@ ANNWaitedReadiness ANNWaitedReadinessOf(UIViewController *screen) {
|
|
|
125
125
|
[self.nodeHelper changeOwnOptions:change];
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
- (void)setUserChoice:(ANNUserChoice *)choice forKey:(NSString *)key {
|
|
129
|
+
[self.nodeHelper setUserChoice:choice forKey:key];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
- (ANNUserChoice *)userChoiceForKey:(NSString *)key {
|
|
133
|
+
return [self.nodeHelper userChoiceForKey:key];
|
|
134
|
+
}
|
|
135
|
+
|
|
128
136
|
#pragma mark - Readiness
|
|
129
137
|
|
|
130
138
|
- (void)setReadyHandler:(dispatch_block_t)handler forKey:(NSString *)key {
|
|
@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
25
25
|
|
|
26
26
|
/// `dismissModal`: the record of `componentId` (its root's id or any id inside, also of a modal closed below or by the
|
|
27
27
|
/// user), the options merged into its visible screen, the animation from the command's screen, then its state decides.
|
|
28
|
-
/// Answers with the root's id.
|
|
28
|
+
/// Answers with the root's id. The last modal over no root rejects `[ANNErrorTexts modalWithoutRoot:]`, as on Android.
|
|
29
29
|
+ (void)dismissModal:(NSString *)componentId
|
|
30
30
|
options:(nullable NSDictionary *)options
|
|
31
31
|
answer:(ANNCommandAnswer *)answer;
|