@apexnative/navigation 1.0.0-alpha.8 → 1.0.0-alpha.9
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 +13 -0
- package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +36 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +35 -3
- package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
- package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +34 -4
- package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +6 -3
- package/docs-md/containers/side-menu.md +15 -0
- package/docs-md/containers/tabs.md +1 -1
- package/docs-md/index.json +4 -0
- package/ios/CLAUDE.md +4 -1
- package/ios/CORE.md +2 -2
- package/ios/Core/ANNLayoutProtocol.h +5 -5
- package/ios/Core/ANNParking.h +5 -4
- package/ios/Core/ANNReloadCoordinator.mm +1 -4
- package/ios/Core/ANNRenderWait.h +5 -5
- package/ios/Core/ANNRenderWait.mm +24 -39
- package/ios/Core/ApexNavigation.mm +1 -4
- package/ios/Layouts/Modal/ANNModalCoordinator.mm +1 -1
- package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +1 -1
- package/ios/Layouts/Root/ANNRootCoordinator.mm +1 -1
- package/ios/Layouts/Screen/ANNComponentViewController.h +9 -15
- package/ios/Layouts/Screen/ANNComponentViewController.mm +6 -42
- package/ios/Layouts/Screen/ANNScreenPlace.h +12 -0
- package/ios/Layouts/Screen/ANNScreenPlace.mm +46 -16
- package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
- package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
- package/ios/Layouts/Stack/ANNStackController.mm +5 -2
- package/ios/Layouts/Stack/ANNStackQueue.h +2 -1
- package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +222 -51
- package/ios/Options/ANNSideMenuOptions.h +2 -0
- package/ios/Options/ANNSideMenuOptions.mm +2 -0
- package/ios/React/ANNSafeAreaViewComponentView.mm +2 -2
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +2 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/sideMenu.d.ts +16 -0
- package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/interfaces/options/bottomTabs.ts +2 -1
- package/src/interfaces/options/sideMenu.ts +17 -0
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -53
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#import "ANNAppDirection.h"
|
|
4
4
|
#import "ANNAppearanceDispatcher.h"
|
|
5
5
|
#import "ANNAssert.h"
|
|
6
|
+
#import "ANNBottomTabsController.h"
|
|
6
7
|
#import "ANNComponentViewController.h"
|
|
7
8
|
#import "ANNElementFinder.h"
|
|
8
9
|
#import "ANNErrorTexts.h"
|
|
@@ -1175,10 +1176,12 @@ static const CGFloat ANNOwnSwipeEdgeWidth = 20;
|
|
|
1175
1176
|
return self;
|
|
1176
1177
|
}
|
|
1177
1178
|
|
|
1178
|
-
// In More the More navigation is what shows the screens.
|
|
1179
|
+
// In More the More navigation is what shows the screens. A tab rendered before it shows is in a window while its
|
|
1180
|
+
// screens render there, and not on screen.
|
|
1179
1181
|
- (BOOL)stackIsOnScreen {
|
|
1180
1182
|
return self.shownNavigationController.viewIfLoaded.window != nil &&
|
|
1181
|
-
![ANNPendingLayers isWaitingToShow:self]
|
|
1183
|
+
![ANNPendingLayers isWaitingToShow:self] &&
|
|
1184
|
+
![ANNBottomTabsController isInUnseenTab:self];
|
|
1182
1185
|
}
|
|
1183
1186
|
|
|
1184
1187
|
// Only the stack's own transitions (a push, a pop, a replace of its view controllers, the interactive pop): a
|
|
@@ -60,7 +60,8 @@ typedef NS_ENUM(NSInteger, ANNStackChange) {
|
|
|
60
60
|
/// The stack's own view controller: the layout parent of the nodes it took and doesn't show yet.
|
|
61
61
|
- (UIViewController *)stackViewController;
|
|
62
62
|
|
|
63
|
-
/// The stack is seen: its view is in a window, and it isn't inside a layer that waits to show (`ANNPendingLayers`)
|
|
63
|
+
/// The stack is seen: its view is in a window, and it isn't inside a layer that waits to show (`ANNPendingLayers`) nor
|
|
64
|
+
/// in a tab that renders before it shows (`isInUnseenTab:` of the tabs).
|
|
64
65
|
- (BOOL)stackIsOnScreen;
|
|
65
66
|
|
|
66
67
|
/// A transition UIKit runs on the stack now (one the queue didn't start); nil when none runs.
|
|
@@ -45,6 +45,9 @@ typedef NS_ENUM(NSInteger, ANNTabPressSource) {
|
|
|
45
45
|
/// The nearest tabs among the layout parents of `node` (not `node` itself); nil out of tabs.
|
|
46
46
|
+ (nullable ANNBottomTabsController *)tabsOf:(UIViewController *)node;
|
|
47
47
|
|
|
48
|
+
/// `node` is in a tab rendered before it shows, which renders its content in its tabs' view: in a window, not shown.
|
|
49
|
+
+ (BOOL)isInUnseenTab:(UIViewController *)node;
|
|
50
|
+
|
|
48
51
|
/// The tabs in layout order.
|
|
49
52
|
@property(nonatomic, copy, readonly) NSArray<UIViewController *> *layoutTabs;
|
|
50
53
|
|
|
@@ -7,15 +7,17 @@
|
|
|
7
7
|
#import "ANNMoreNavigationDelegate.h"
|
|
8
8
|
#import "ANNNavigationState.h"
|
|
9
9
|
#import "ANNNodeRegistry.h"
|
|
10
|
+
#import "ANNParking.h"
|
|
10
11
|
#import "ANNPendingLayers.h"
|
|
11
12
|
#import "ANNScreenBars.h"
|
|
13
|
+
#import "ANNScreenPlace.h"
|
|
12
14
|
#import "ANNScrollToTop.h"
|
|
13
15
|
#import "ANNShownScreens.h"
|
|
14
16
|
#import "ANNStackController.h"
|
|
17
|
+
#import "ANNStackQueue.h"
|
|
15
18
|
#import "ANNSystemUI.h"
|
|
16
19
|
#import "ANNTabLongPress.h"
|
|
17
20
|
#import "ANNTabsDesign.h"
|
|
18
|
-
#import "ANNTabsPreloadWindow.h"
|
|
19
21
|
#import "InteractivePopGestureDelegate.h"
|
|
20
22
|
#import <React/RCTLog.h>
|
|
21
23
|
|
|
@@ -23,13 +25,17 @@
|
|
|
23
25
|
// waits for it; the drive only must not stay).
|
|
24
26
|
static const NSTimeInterval ANNSwitchDriveLimit = 2;
|
|
25
27
|
|
|
26
|
-
// How long a step of `afterInitialTab` waits for its tab's root to mount before the next one starts
|
|
27
|
-
// lent React view stays in the preload window at most without mounting.
|
|
28
|
+
// How long a step of `afterInitialTab` waits for its tab's root to mount before the next one starts.
|
|
28
29
|
static const NSTimeInterval ANNTabMountLimit = 0.5;
|
|
29
30
|
|
|
30
31
|
// The key of the tabs' ready handlers on the screens of their selected tab (`afterInitialTab`).
|
|
31
32
|
static NSString *const ANNTabsReadyKey = @"ApexNavigation.tabs";
|
|
32
33
|
|
|
34
|
+
// The key of the tabs' ready handlers on the screens of a parked tab, and the longest such a tab waits for them in the
|
|
35
|
+
// parking: past it, its screens render their content where the tab shows.
|
|
36
|
+
static NSString *const ANNTabsUnseenKey = @"ApexNavigation.tabs.unseen";
|
|
37
|
+
static const NSTimeInterval ANNUnseenRenderLimit = 5;
|
|
38
|
+
|
|
33
39
|
// Whether UIKit pops the stack of a tab tapped again itself: the core answers "select" and lets it. NO would make the
|
|
34
40
|
// core pop it for every source and answer "don't" (the simulator decides).
|
|
35
41
|
static const BOOL ANNUIKitPopsOnRepeatPress = YES;
|
|
@@ -81,8 +87,12 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
81
87
|
// The `UITab` of each tab, in layout order (iOS 18 and later).
|
|
82
88
|
NSArray *_uiTabs;
|
|
83
89
|
NSHashTable<UIViewController *> *_renderedTabs;
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
// The tabs rendered before they show (`together`, the chain of `afterInitialTab`) wait unseen and hidden in the
|
|
91
|
+
// tabs' view until their screens rendered their content, as on Android: a screen's safe area view lays out only in
|
|
92
|
+
// a window. They leave it then, since the core takes a view in a window for one that shows, and their screens keep
|
|
93
|
+
// the place they rendered at until they appear. Those not parked yet wait for the tabs' view in a window.
|
|
94
|
+
ANNParking *_unseenParking;
|
|
95
|
+
NSHashTable<UIViewController *> *_tabsToPark;
|
|
86
96
|
// The chain of `afterInitialTab`: started once; a destroy ends it by its number.
|
|
87
97
|
BOOL _chainStarted;
|
|
88
98
|
NSUInteger _chainNumber;
|
|
@@ -137,7 +147,8 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
137
147
|
if (self) {
|
|
138
148
|
_tabs = [childViewControllers copy] ?: @[];
|
|
139
149
|
_renderedTabs = [NSHashTable weakObjectsHashTable];
|
|
140
|
-
|
|
150
|
+
_unseenParking = [ANNParking new];
|
|
151
|
+
_tabsToPark = [NSHashTable weakObjectsHashTable];
|
|
141
152
|
_staleTabs = [NSHashTable weakObjectsHashTable];
|
|
142
153
|
_pressedIndex = NSNotFound;
|
|
143
154
|
_codeChoiceIndex = NSNotFound;
|
|
@@ -444,7 +455,7 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
444
455
|
}
|
|
445
456
|
|
|
446
457
|
// The selected tab's waited screens by the command's rule; with `together` the top screen of every other tab too, by
|
|
447
|
-
//
|
|
458
|
+
// its content rendered unseen (More's tabs too).
|
|
448
459
|
- (NSArray<UIViewController *> *)waitedComponentViewControllers {
|
|
449
460
|
NSMutableArray<UIViewController *> *screens =
|
|
450
461
|
[[[self selectedTabNode] waitedComponentViewControllers] mutableCopy]
|
|
@@ -464,7 +475,7 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
464
475
|
|
|
465
476
|
- (ANNWaitedReadiness)waitedReadinessOfScreen:(UIViewController *)screen {
|
|
466
477
|
NSUInteger index = [self indexOfTabHolding:screen];
|
|
467
|
-
return index != NSNotFound && index != _selectedTabIndex ?
|
|
478
|
+
return index != NSNotFound && index != _selectedTabIndex ? ANNWaitedReadinessUnseen
|
|
468
479
|
: ANNWaitedReadinessContent;
|
|
469
480
|
}
|
|
470
481
|
|
|
@@ -474,12 +485,12 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
474
485
|
if (self.nodeHelper.destroyed) {
|
|
475
486
|
return;
|
|
476
487
|
}
|
|
477
|
-
[self renderTabAtIndex:_selectedTabIndex
|
|
488
|
+
[self renderTabAtIndex:_selectedTabIndex unseen:NO];
|
|
478
489
|
switch (_attachMode) {
|
|
479
490
|
case ANNTabsAttachModeTogether:
|
|
480
491
|
for (NSUInteger index = 0; index < _tabs.count; index++) {
|
|
481
492
|
if (index != _selectedTabIndex) {
|
|
482
|
-
[self renderTabAtIndex:index
|
|
493
|
+
[self renderTabAtIndex:index unseen:YES];
|
|
483
494
|
}
|
|
484
495
|
}
|
|
485
496
|
break;
|
|
@@ -561,6 +572,10 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
561
572
|
}
|
|
562
573
|
[_longPress detach];
|
|
563
574
|
[self.nodeHelper unregisterNode];
|
|
575
|
+
[_tabsToPark removeAllObjects];
|
|
576
|
+
for (UIViewController *tab in _unseenParking.parkedNodes) {
|
|
577
|
+
[self unparkTab:tab showing:NO];
|
|
578
|
+
}
|
|
564
579
|
for (UIViewController *tab in _tabs) {
|
|
565
580
|
@try {
|
|
566
581
|
[tab destroy];
|
|
@@ -569,7 +584,6 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
569
584
|
tab.layoutInfo.componentId ?: @"", exception.reason ?: exception.name);
|
|
570
585
|
}
|
|
571
586
|
}
|
|
572
|
-
[self closePreloadWindow];
|
|
573
587
|
[[self tabsPresenter] tabsWillGo];
|
|
574
588
|
[_components stopAll];
|
|
575
589
|
}
|
|
@@ -591,6 +605,13 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
591
605
|
[[self tabsPresenter] barDidLayOutInWindow];
|
|
592
606
|
}
|
|
593
607
|
[[self tabsPresenter] tabsDidLayOut];
|
|
608
|
+
// A tab UIKit shows by a way of its own leaves the parking too.
|
|
609
|
+
UIViewController *shown = self.selectedViewController;
|
|
610
|
+
if (shown && [_unseenParking isParked:shown]) {
|
|
611
|
+
[self unparkTab:shown showing:YES];
|
|
612
|
+
}
|
|
613
|
+
[self layOutParkedTabs];
|
|
614
|
+
[self parkUnseenTabs];
|
|
594
615
|
}
|
|
595
616
|
|
|
596
617
|
- (void)viewWillAppear:(BOOL)animated {
|
|
@@ -605,9 +626,10 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
605
626
|
[[self tabsPresenter] tabsDidAppear];
|
|
606
627
|
}
|
|
607
628
|
|
|
608
|
-
#pragma mark - Rendering
|
|
629
|
+
#pragma mark - Rendering
|
|
609
630
|
|
|
610
|
-
|
|
631
|
+
// A tab renders once. `unseen`: it renders before it shows, and waits in the parking until then.
|
|
632
|
+
- (void)renderTabAtIndex:(NSUInteger)index unseen:(BOOL)unseen {
|
|
611
633
|
if (index >= _tabs.count) {
|
|
612
634
|
return;
|
|
613
635
|
}
|
|
@@ -617,62 +639,202 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
617
639
|
}
|
|
618
640
|
[_renderedTabs addObject:tab];
|
|
619
641
|
[tab render];
|
|
620
|
-
if (
|
|
621
|
-
[
|
|
642
|
+
if (unseen) {
|
|
643
|
+
[_tabsToPark addObject:tab];
|
|
644
|
+
[self parkUnseenTabs];
|
|
622
645
|
}
|
|
623
646
|
}
|
|
624
647
|
|
|
625
|
-
// The
|
|
626
|
-
//
|
|
627
|
-
- (void)
|
|
628
|
-
|
|
629
|
-
if (![node isKindOfClass:ANNComponentViewController.class]) {
|
|
648
|
+
// The tabs rendered unseen go into the parking once the tabs' view is in a window, at the back of it and hidden, so
|
|
649
|
+
// that a switch's transition never shows them; the shown tab never, nor a tab with nothing to render (native screens).
|
|
650
|
+
- (void)parkUnseenTabs {
|
|
651
|
+
if (_tabsToPark.count == 0 || !self.viewIfLoaded.window || self.nodeHelper.destroyed) {
|
|
630
652
|
return;
|
|
631
653
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
654
|
+
UIViewController *shown = self.selectedViewController;
|
|
655
|
+
UIViewController *selected = [self selectedTabNode];
|
|
656
|
+
for (UIViewController *tab in _tabsToPark.allObjects) {
|
|
657
|
+
[_tabsToPark removeObject:tab];
|
|
658
|
+
if (tab == shown || tab == selected || tab.viewIfLoaded.window ||
|
|
659
|
+
[_unseenParking isParked:tab]) {
|
|
660
|
+
continue;
|
|
661
|
+
}
|
|
662
|
+
NSArray<ANNComponentViewController *> *screens = [self unrenderedScreensOfTab:tab];
|
|
663
|
+
if (screens.count == 0) {
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
[_unseenParking park:tab inView:self.view];
|
|
667
|
+
tab.view.hidden = YES;
|
|
668
|
+
[self layOutParkedTabs];
|
|
669
|
+
[self placeScreensOfParkedTab:tab shownFirst:screens];
|
|
670
|
+
[self unparkTab:tab whenScreensRender:screens];
|
|
636
671
|
}
|
|
637
|
-
|
|
638
|
-
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// The screens the tab shows first whose content didn't render yet.
|
|
675
|
+
- (NSArray<ANNComponentViewController *> *)unrenderedScreensOfTab:(UIViewController *)tab {
|
|
676
|
+
NSMutableArray<ANNComponentViewController *> *screens = [NSMutableArray new];
|
|
677
|
+
for (UIViewController *node in [tab waitedComponentViewControllers]) {
|
|
678
|
+
if (![node isKindOfClass:ANNComponentViewController.class]) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
ANNComponentViewController *screen = (ANNComponentViewController *)node;
|
|
682
|
+
if (screen.reactView && !screen.reactView.isReady) {
|
|
683
|
+
[screens addObject:screen];
|
|
684
|
+
}
|
|
639
685
|
}
|
|
640
|
-
|
|
686
|
+
return screens;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// A parked tab lays out where the shown tab is: beside the sidebar on iPad too.
|
|
690
|
+
- (void)layOutParkedTabs {
|
|
691
|
+
UIView *shownView = self.selectedViewController.viewIfLoaded;
|
|
692
|
+
if (!shownView.window) {
|
|
641
693
|
return;
|
|
642
694
|
}
|
|
643
|
-
[
|
|
695
|
+
CGRect frame = [self.view convertRect:shownView.bounds fromView:shownView];
|
|
696
|
+
for (UIViewController *tab in _unseenParking.parkedNodes) {
|
|
697
|
+
UIView *view = tab.viewIfLoaded;
|
|
698
|
+
if (view && !CGRectEqualToRect(view.frame, frame)) {
|
|
699
|
+
view.frame = frame;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// UIKit gives the views of a tab not shown no safe area: the screens on top of its stacks lay out with their place
|
|
705
|
+
// there, measured in the view of what the tabs show (`ANNScreenPlace`), the safe area and bars they get as the tab
|
|
706
|
+
// shows. A screen the tab shows first keeps the place it rendered at until it appears: as the tab shows, UIKit first
|
|
707
|
+
// gives it a part of its safe area (the bar without the status bar). The others (a closed side menu's) keep it until
|
|
708
|
+
// UIKit gives them a safe area of their own.
|
|
709
|
+
- (void)placeScreensOfParkedTab:(UIViewController *)tab
|
|
710
|
+
shownFirst:(NSArray<ANNComponentViewController *> *)shownFirst {
|
|
711
|
+
NSHashTable<ANNComponentViewController *> *placed = [NSHashTable weakObjectsHashTable];
|
|
712
|
+
NSMutableArray<ANNStackController *> *stacks = [NSMutableArray new];
|
|
713
|
+
ANNStacksOfNode(tab, stacks);
|
|
714
|
+
for (ANNStackController *stack in stacks) {
|
|
715
|
+
UIViewController *top = stack.topViewController;
|
|
716
|
+
for (ANNComponentViewController *screen in top ? ANNStackScreensOfEntry(top) : @[]) {
|
|
717
|
+
[self placeScreen:screen
|
|
718
|
+
onTop:top
|
|
719
|
+
ofStack:stack
|
|
720
|
+
ofParkedTab:tab
|
|
721
|
+
kept:[shownFirst containsObject:screen]];
|
|
722
|
+
[placed addObject:screen];
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
for (ANNComponentViewController *screen in shownFirst) {
|
|
726
|
+
if (![placed containsObject:screen]) {
|
|
727
|
+
[self placeScreen:screen onTop:nil ofStack:nil ofParkedTab:tab kept:YES];
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// The place of one screen of a parked tab: on top of its stack, or a screen of its own. A screen covered since it
|
|
733
|
+
// rendered (a push onto its stack before the tab showed) lays out with its own safe area.
|
|
734
|
+
- (void)placeScreen:(ANNComponentViewController *)screen
|
|
735
|
+
onTop:(nullable UIViewController *)top
|
|
736
|
+
ofStack:(nullable UINavigationController *)stack
|
|
737
|
+
ofParkedTab:(UIViewController *)tab
|
|
738
|
+
kept:(BOOL)kept {
|
|
644
739
|
__weak ANNBottomTabsController *weakSelf = self;
|
|
740
|
+
__weak UIViewController *weakTab = tab;
|
|
645
741
|
__weak ANNComponentViewController *weakScreen = screen;
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
742
|
+
__weak UINavigationController *weakStack = stack;
|
|
743
|
+
__weak UIViewController *weakTop = top;
|
|
744
|
+
BOOL inStack = stack != nil;
|
|
745
|
+
__block ANNScreenPlace *last = nil;
|
|
746
|
+
screen.placeWhileParked = ^ANNScreenPlace * {
|
|
747
|
+
ANNComponentViewController *placed = weakScreen;
|
|
748
|
+
UINavigationController *placedStack = weakStack;
|
|
749
|
+
UIViewController *entry = weakTop;
|
|
750
|
+
if (inStack && (!placedStack || !entry || placedStack.topViewController != entry)) {
|
|
751
|
+
return nil;
|
|
752
|
+
}
|
|
753
|
+
UIView *host = [weakSelf placeHostForTab:weakTab];
|
|
754
|
+
if (!placed || !host) {
|
|
755
|
+
return last;
|
|
756
|
+
}
|
|
757
|
+
ANNScreenPlace *measured =
|
|
758
|
+
inStack ? [ANNScreenPlace placeOfEntry:entry
|
|
759
|
+
inStack:placedStack
|
|
760
|
+
measuredIn:host
|
|
761
|
+
options:[ANNStackOptionsScreen(entry)
|
|
762
|
+
resolveOptionsWithDefault]]
|
|
763
|
+
: [ANNScreenPlace placeOfScreen:placed measuredIn:host];
|
|
764
|
+
if (measured) {
|
|
765
|
+
last = measured;
|
|
766
|
+
}
|
|
767
|
+
return last;
|
|
768
|
+
};
|
|
769
|
+
screen.placeKeptUntilAppearance = kept;
|
|
770
|
+
[screen updateRootLayout];
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Where the screens of a tab rendered unseen measure their place: the view of what the tabs show now (UIKit's More
|
|
774
|
+
// navigation too). Nil once the tab itself shows.
|
|
775
|
+
- (nullable UIView *)placeHostForTab:(UIViewController *)tab {
|
|
776
|
+
UIViewController *shown = self.selectedViewController;
|
|
777
|
+
UIView *host = shown.viewIfLoaded;
|
|
778
|
+
UIView *tabView = tab.viewIfLoaded;
|
|
779
|
+
if (!tab || !host.window || shown == tab || [self selectedTabNode] == tab ||
|
|
780
|
+
(tabView && [host isDescendantOfView:tabView])) {
|
|
781
|
+
return nil;
|
|
782
|
+
}
|
|
783
|
+
return host;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// The parked tab leaves the parking once every screen it waits for rendered its content, or at the limit.
|
|
787
|
+
- (void)unparkTab:(UIViewController *)tab
|
|
788
|
+
whenScreensRender:(NSArray<ANNComponentViewController *> *)screens {
|
|
789
|
+
__weak ANNBottomTabsController *weakSelf = self;
|
|
790
|
+
__weak UIViewController *weakTab = tab;
|
|
791
|
+
NSHashTable<ANNComponentViewController *> *waited = [NSHashTable weakObjectsHashTable];
|
|
792
|
+
for (ANNComponentViewController *screen in screens) {
|
|
793
|
+
[waited addObject:screen];
|
|
794
|
+
}
|
|
795
|
+
for (ANNComponentViewController *screen in screens) {
|
|
796
|
+
[screen
|
|
797
|
+
setReadyHandler:^{
|
|
798
|
+
for (ANNComponentViewController *other in waited.allObjects) {
|
|
799
|
+
if (other.reactView && !other.reactView.isReady) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
[weakSelf unparkTab:weakTab showing:NO];
|
|
804
|
+
}
|
|
805
|
+
forKey:ANNTabsUnseenKey];
|
|
806
|
+
}
|
|
807
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(ANNUnseenRenderLimit * NSEC_PER_SEC)),
|
|
651
808
|
dispatch_get_main_queue(), ^{
|
|
652
|
-
[weakSelf
|
|
809
|
+
[weakSelf unparkTab:weakTab showing:NO];
|
|
653
810
|
});
|
|
654
811
|
}
|
|
655
812
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
813
|
+
// The tab rendered, is about to show, or the tabs go: it leaves the parking, and UIKit places its view as it shows it.
|
|
814
|
+
// `showing`: it shows in this turn, so UIKit's departure of a tab without a parent (More's, with the tab API) ends
|
|
815
|
+
// here.
|
|
816
|
+
- (void)unparkTab:(UIViewController *)tab showing:(BOOL)showing {
|
|
817
|
+
if (!tab) {
|
|
818
|
+
return;
|
|
660
819
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
}
|
|
820
|
+
[_tabsToPark removeObject:tab];
|
|
821
|
+
if (![_unseenParking isParked:tab]) {
|
|
822
|
+
return;
|
|
665
823
|
}
|
|
666
|
-
|
|
824
|
+
tab.viewIfLoaded.hidden = NO;
|
|
825
|
+
[_unseenParking unpark:tab endingDeparture:showing && !tab.parentViewController];
|
|
667
826
|
}
|
|
668
827
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
828
|
+
+ (BOOL)isInUnseenTab:(UIViewController *)node {
|
|
829
|
+
UIViewController *child = node;
|
|
830
|
+
for (UIViewController *parent = node.layoutParent; parent;
|
|
831
|
+
child = parent, parent = parent.layoutParent) {
|
|
832
|
+
if ([parent isKindOfClass:ANNBottomTabsController.class] &&
|
|
833
|
+
[((ANNBottomTabsController *)parent)->_unseenParking isParked:child]) {
|
|
834
|
+
return YES;
|
|
835
|
+
}
|
|
672
836
|
}
|
|
673
|
-
|
|
674
|
-
[_preloadWindow close];
|
|
675
|
-
_preloadWindow = nil;
|
|
837
|
+
return NO;
|
|
676
838
|
}
|
|
677
839
|
|
|
678
840
|
// `afterInitialTab`: the selected tab's shown screens ready (by their content), then the others one by one.
|
|
@@ -739,7 +901,7 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
739
901
|
if (next == NSNotFound) {
|
|
740
902
|
return;
|
|
741
903
|
}
|
|
742
|
-
[self renderTabAtIndex:next
|
|
904
|
+
[self renderTabAtIndex:next unseen:YES];
|
|
743
905
|
__block BOOL stepped = NO;
|
|
744
906
|
__weak ANNBottomTabsController *weakSelf = self;
|
|
745
907
|
dispatch_block_t step = ^{
|
|
@@ -769,8 +931,17 @@ static void ANNStacksOfNode(UIViewController *node, NSMutableArray<ANNStackContr
|
|
|
769
931
|
if (index >= _tabs.count) {
|
|
770
932
|
return;
|
|
771
933
|
}
|
|
772
|
-
[self renderTabAtIndex:index
|
|
934
|
+
[self renderTabAtIndex:index unseen:NO];
|
|
773
935
|
UIViewController *tab = _tabs[index];
|
|
936
|
+
// Its screens rendered unseen measure their place once more while the tab that shows now is still the host: the
|
|
937
|
+
// device may have turned since, or the shown tab laid out again.
|
|
938
|
+
for (UIViewController *node in [tab waitedComponentViewControllers]) {
|
|
939
|
+
if ([node isKindOfClass:ANNComponentViewController.class] &&
|
|
940
|
+
((ANNComponentViewController *)node).placeKeptUntilAppearance) {
|
|
941
|
+
[(ANNComponentViewController *)node updateRootLayout];
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
[self unparkTab:tab showing:YES];
|
|
774
945
|
if ([_staleTabs containsObject:tab]) {
|
|
775
946
|
[_staleTabs removeObject:tab];
|
|
776
947
|
[ANNBottomTabsPresenter repaintNode:tab];
|
|
@@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
12
12
|
@property(nonatomic, strong) Text *openGestureMode;
|
|
13
13
|
/// `'parallax'`, `'slide'`, `'slide-and-scale'` or `'door'`.
|
|
14
14
|
@property(nonatomic, strong) Text *animationType;
|
|
15
|
+
/// `'together'`, `'afterCenter'` or `'onOpen'`.
|
|
16
|
+
@property(nonatomic, strong) Text *menusAttachMode;
|
|
15
17
|
@property(nonatomic, strong) Text *testID;
|
|
16
18
|
|
|
17
19
|
@end
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
[ANNOptionField enumField:@"openGestureMode" values:@[ @"bezel", @"entireScreen" ]],
|
|
10
10
|
[ANNOptionField enumField:@"animationType"
|
|
11
11
|
values:@[ @"parallax", @"slide", @"slide-and-scale", @"door" ]],
|
|
12
|
+
[ANNOptionField enumField:@"menusAttachMode"
|
|
13
|
+
values:@[ @"together", @"afterCenter", @"onOpen" ]],
|
|
12
14
|
[ANNOptionField textField:@"testID"],
|
|
13
15
|
];
|
|
14
16
|
}
|
|
@@ -128,8 +128,8 @@ using namespace facebook::react;
|
|
|
128
128
|
|
|
129
129
|
// The screen renders its content once this view is laid out in its place with a size, as
|
|
130
130
|
// react-native-safe-area-context does: a list that is there before the first layout of the top bar
|
|
131
|
-
// makes UIKit start the large title collapsed.
|
|
132
|
-
//
|
|
131
|
+
// makes UIKit start the large title collapsed. A tab rendered before it shows lays out in the
|
|
132
|
+
// tabs' view, unseen, and renders its content there.
|
|
133
133
|
- (void)sendReadyIfLaidOut {
|
|
134
134
|
if (_readySent || _eventEmitter == nullptr || self.superview == nil) {
|
|
135
135
|
return;
|
|
@@ -204,7 +204,8 @@ export interface OptionsBottomTabs {
|
|
|
204
204
|
* When the screens of the tabs are created: `'together'` creates and draws every tab at the start, and the tabs are
|
|
205
205
|
* ready when all of them are; `'afterInitialTab'` creates the selected tab first and the others right after it;
|
|
206
206
|
* `'onSwitchToTab'` creates a tab the first time it is selected. The screens of tabs not yet selected get no appear
|
|
207
|
-
* events in any mode.
|
|
207
|
+
* events in any mode. On iOS a text input's `autoFocus` in a tab drawn before it is selected does nothing: focus it in
|
|
208
|
+
* `useScreenAppear`. It applies when the tabs are created; `mergeOptions` does not change it.
|
|
208
209
|
* @default 'together'
|
|
209
210
|
*/
|
|
210
211
|
tabsAttachMode?: 'together' | 'afterInitialTab' | 'onSwitchToTab';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottomTabs.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/options/bottomTabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAU,CAAC;AAExF;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,oHAAoH;IACpH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,mCAAmC;IAClD,qGAAqG;IACrG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,SAAS,CAAC,EAAE,mCAAmC,CAAC;IAChD;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,eAAe,CAAC,EAAE,KAAK,CAAC;IACxB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7C;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACtC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,KAAK,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"bottomTabs.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/options/bottomTabs.ts"],"names":[],"mappings":"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"}
|
|
@@ -92,6 +92,8 @@ export type SideMenuOpenGestureMode = 'bezel' | 'entireScreen';
|
|
|
92
92
|
* the center.
|
|
93
93
|
*/
|
|
94
94
|
export type SideMenuAnimationType = 'parallax' | 'slide' | 'slide-and-scale' | 'door';
|
|
95
|
+
/** When the screens of the menus of a side menu are created: see `sideMenu.menusAttachMode`. */
|
|
96
|
+
export type SideMenuAttachMode = 'together' | 'afterCenter' | 'onOpen';
|
|
95
97
|
/**
|
|
96
98
|
* The options of a side menu: a center with a menu on the left, on the right or on both sides. They are set in the
|
|
97
99
|
* options of the side menu, in the options of the screens inside it (through `mergeOptions` or the screen definition)
|
|
@@ -119,6 +121,20 @@ export interface OptionsSideMenu {
|
|
|
119
121
|
* the center moves. It does nothing in `'aboveContent'` mode. A change applies at once. Android doesn't read it.
|
|
120
122
|
*/
|
|
121
123
|
animationType?: SideMenuAnimationType;
|
|
124
|
+
/**
|
|
125
|
+
* When the screens of the menus are created, together with their React content: `'together'` creates them with the
|
|
126
|
+
* center; `'afterCenter'` creates them right after the center first appears, so they don't compete with its first
|
|
127
|
+
* render and still show at once on the first open; `'onOpen'` creates a menu the first time it starts to open — from
|
|
128
|
+
* a swipe, from `visible: true` or from `visible` in the layout — and until React draws its screen the menu shows its
|
|
129
|
+
* background. A command to a screen of a menu not created yet works: a push into its stack and `mergeOptions` wait
|
|
130
|
+
* for the menu like a tab not yet selected. The screens of a menu get appear events only when it opens, in every
|
|
131
|
+
* mode. With `appProvider` the screens render in the app's React tree at once in every mode, and the mode delays only
|
|
132
|
+
* their native containers. On iOS a menu's test identifier (`<testID>.left`, `<testID>.right`) is there once the menu
|
|
133
|
+
* is created; on Android from the start. It applies when the side menu is created, from its own options or the default options;
|
|
134
|
+
* `mergeOptions` does not change it.
|
|
135
|
+
* @default 'together'
|
|
136
|
+
*/
|
|
137
|
+
menusAttachMode?: SideMenuAttachMode;
|
|
122
138
|
/**
|
|
123
139
|
* The test identifier of the side menu's container (on iOS its view, on Android the drawer). The parts derive from
|
|
124
140
|
* it: `<testID>.center`, `<testID>.left`, `<testID>.right`, and on iOS `<testID>.scrim` for the dimming over the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sideMenu.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/options/sideMenu.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,CAAC;IAC1C;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,cAAc,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,OAAO,GAAG,iBAAiB,GAAG,MAAM,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,sBAAsB;IACtB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C;;;OAGG;IACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
1
|
+
{"version":3,"file":"sideMenu.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/options/sideMenu.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,CAAC;IAC1C;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,cAAc,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,UAAU,GAAG,OAAO,GAAG,iBAAiB,GAAG,MAAM,CAAC;AAEtF,gGAAgG;AAChG,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,sBAAsB;IACtB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C;;;OAGG;IACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
package/package.json
CHANGED
|
@@ -211,7 +211,8 @@ export interface OptionsBottomTabs {
|
|
|
211
211
|
* When the screens of the tabs are created: `'together'` creates and draws every tab at the start, and the tabs are
|
|
212
212
|
* ready when all of them are; `'afterInitialTab'` creates the selected tab first and the others right after it;
|
|
213
213
|
* `'onSwitchToTab'` creates a tab the first time it is selected. The screens of tabs not yet selected get no appear
|
|
214
|
-
* events in any mode.
|
|
214
|
+
* events in any mode. On iOS a text input's `autoFocus` in a tab drawn before it is selected does nothing: focus it in
|
|
215
|
+
* `useScreenAppear`. It applies when the tabs are created; `mergeOptions` does not change it.
|
|
215
216
|
* @default 'together'
|
|
216
217
|
*/
|
|
217
218
|
tabsAttachMode?: 'together' | 'afterInitialTab' | 'onSwitchToTab';
|
|
@@ -95,6 +95,9 @@ export type SideMenuOpenGestureMode = 'bezel' | 'entireScreen';
|
|
|
95
95
|
*/
|
|
96
96
|
export type SideMenuAnimationType = 'parallax' | 'slide' | 'slide-and-scale' | 'door';
|
|
97
97
|
|
|
98
|
+
/** When the screens of the menus of a side menu are created: see `sideMenu.menusAttachMode`. */
|
|
99
|
+
export type SideMenuAttachMode = 'together' | 'afterCenter' | 'onOpen';
|
|
100
|
+
|
|
98
101
|
/**
|
|
99
102
|
* The options of a side menu: a center with a menu on the left, on the right or on both sides. They are set in the
|
|
100
103
|
* options of the side menu, in the options of the screens inside it (through `mergeOptions` or the screen definition)
|
|
@@ -122,6 +125,20 @@ export interface OptionsSideMenu {
|
|
|
122
125
|
* the center moves. It does nothing in `'aboveContent'` mode. A change applies at once. Android doesn't read it.
|
|
123
126
|
*/
|
|
124
127
|
animationType?: SideMenuAnimationType;
|
|
128
|
+
/**
|
|
129
|
+
* When the screens of the menus are created, together with their React content: `'together'` creates them with the
|
|
130
|
+
* center; `'afterCenter'` creates them right after the center first appears, so they don't compete with its first
|
|
131
|
+
* render and still show at once on the first open; `'onOpen'` creates a menu the first time it starts to open — from
|
|
132
|
+
* a swipe, from `visible: true` or from `visible` in the layout — and until React draws its screen the menu shows its
|
|
133
|
+
* background. A command to a screen of a menu not created yet works: a push into its stack and `mergeOptions` wait
|
|
134
|
+
* for the menu like a tab not yet selected. The screens of a menu get appear events only when it opens, in every
|
|
135
|
+
* mode. With `appProvider` the screens render in the app's React tree at once in every mode, and the mode delays only
|
|
136
|
+
* their native containers. On iOS a menu's test identifier (`<testID>.left`, `<testID>.right`) is there once the menu
|
|
137
|
+
* is created; on Android from the start. It applies when the side menu is created, from its own options or the default options;
|
|
138
|
+
* `mergeOptions` does not change it.
|
|
139
|
+
* @default 'together'
|
|
140
|
+
*/
|
|
141
|
+
menusAttachMode?: SideMenuAttachMode;
|
|
125
142
|
/**
|
|
126
143
|
* The test identifier of the side menu's container (on iOS its view, on Android the drawer). The parts derive from
|
|
127
144
|
* it: `<testID>.center`, `<testID>.left`, `<testID>.right`, and on iOS `<testID>.scrim` for the dimming over the
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#import <UIKit/UIKit.h>
|
|
2
|
-
|
|
3
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
-
|
|
5
|
-
/// Where the React views of unselected tabs mount while the tabs render: a window of zero size that clips what it
|
|
6
|
-
/// holds, hidden from accessibility, in the scene of the navigation's main window. Nothing in it is seen and its safe
|
|
7
|
-
/// area views never lay out there: a tab renders its content where it shows. One per tabs node; it goes when it holds
|
|
8
|
-
/// nothing more or with its tabs. Main queue.
|
|
9
|
-
@interface ANNTabsPreloadWindow : UIWindow
|
|
10
|
-
|
|
11
|
-
/// A new window in the scene of the main window; when the main window has no scene yet, it joins the scene as the main
|
|
12
|
-
/// window connects (`mainWindowSceneDidConnect:`), before it holds anything that could be seen.
|
|
13
|
-
+ (instancetype)preloadWindow;
|
|
14
|
-
|
|
15
|
-
/// The main window connected to its scene: every live preload window joins it.
|
|
16
|
-
+ (void)mainWindowSceneDidConnect:(UIWindowScene *)windowScene;
|
|
17
|
-
|
|
18
|
-
/// A reload of the JavaScript: every live preload window hides at once; its views go with their old tabs after the
|
|
19
|
-
/// reload's hold.
|
|
20
|
-
+ (void)hideAllAfterReload;
|
|
21
|
-
|
|
22
|
-
/// The window goes: it hides and leaves its scene. Its views are the tabs' to take back first.
|
|
23
|
-
- (void)close;
|
|
24
|
-
|
|
25
|
-
@end
|
|
26
|
-
|
|
27
|
-
NS_ASSUME_NONNULL_END
|