@apexnative/navigation 1.0.0-alpha.6 → 1.0.0-alpha.7
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/ApexNavigation.podspec +2 -1
- package/CHANGELOG.md +7 -0
- package/android/CLAUDE.md +19 -10
- package/android/CORE.md +3 -2
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
- package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +4 -0
- package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +41 -3
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +16 -1
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +12 -1
- package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
- package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +329 -55
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +26 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +60 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +32 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +46 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +15 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +215 -43
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +25 -26
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +36 -38
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +124 -181
- package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +8 -1
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +56 -3
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +170 -153
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +55 -45
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/{TextChangeAnimator.kt → TextMorph.kt} +79 -129
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -24
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +51 -34
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +121 -175
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
- package/android/src/main/jni/ANNContentHeights.cpp +82 -0
- package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
- package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
- package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
- package/android/src/main/res/values/styles.xml +1 -1
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/cli/doctor/checks/app.js +16 -1
- package/cli/project.js +4 -0
- package/cli/setup/index.js +5 -0
- package/cli/setup/steps/metro.js +46 -0
- package/docs-md/architecture/native-screens.md +4 -0
- package/docs-md/architecture/theme-and-context.md +131 -12
- package/docs-md/architecture/transitions.md +43 -4
- package/docs-md/flows/bottom-sheets.md +4 -2
- package/docs-md/fundamentals/screens-and-props.md +9 -1
- package/docs-md/guides/cli.md +3 -1
- package/docs-md/help/troubleshooting.md +1 -1
- package/docs-md/index.json +29 -1
- package/docs-md/screen-ui/back-and-gestures.md +3 -1
- package/docs-md/screen-ui/bar-buttons.md +1 -1
- package/docs-md/screen-ui/toolbar-and-fab.md +2 -0
- package/docs-md/start/installation.md +16 -1
- package/ios/Animations/ANNFrameDriver.h +55 -15
- package/ios/Animations/ANNFrameDriver.mm +214 -60
- package/ios/Animations/ANNTransitionAnimator.h +26 -5
- package/ios/Animations/ANNTransitionAnimator.mm +49 -3
- package/ios/Animations/ANNTransitionPlan.h +2 -2
- package/ios/Animations/ANNTransitionPlan.mm +10 -0
- package/ios/Animations/Elements/ANNElementFinder.h +2 -2
- package/ios/Animations/Elements/ANNElementFinder.mm +2 -2
- package/ios/Animations/Elements/ANNElementTransition.h +3 -3
- package/ios/Animations/Elements/ANNElementTransition.mm +2 -2
- package/ios/Animations/Elements/ANNSharedElementFlight.h +3 -3
- package/ios/Animations/Elements/ANNSharedElementFlight.mm +181 -43
- package/ios/Animations/Interpolators/ANNViewTracks.h +6 -5
- package/ios/Animations/Interpolators/ANNViewTracks.mm +51 -21
- package/ios/CLAUDE.md +15 -7
- package/ios/CORE.md +1 -1
- package/ios/Core/ANNAppDelegate.mm +0 -2
- package/ios/Core/ANNDeepLinkQueue.h +6 -5
- package/ios/Core/ANNDeepLinkQueue.mm +22 -10
- package/ios/Core/ANNSceneDelegate.mm +2 -2
- package/ios/Core/ApexNavigation.mm +6 -2
- package/ios/Layouts/Root/ANNRootCoordinator.mm +45 -15
- package/ios/Layouts/Screen/ANNComponentViewController.mm +4 -1
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
- package/ios/Layouts/Stack/ANNStackController.h +8 -0
- package/ios/Layouts/Stack/ANNStackController.mm +153 -11
- package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
- package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
- package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
- package/ios/Options/ANNAnimationOptions.h +2 -1
- package/ios/Options/ANNAnimationOptions.mm +1 -1
- package/ios/Options/ANNOptions.h +7 -0
- package/ios/Options/ANNOptions.mm +45 -0
- package/ios/Options/ANNOptionsReader.mm +2 -4
- package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
- package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
- package/ios/Options/Params/ColorParser.h +4 -3
- package/ios/Options/Params/ColorParser.mm +22 -4
- package/ios/React/ANNSurfaceHostingView.h +8 -0
- package/ios/React/ANNSurfaceHostingView.mm +28 -1
- package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
- package/ios/TurboModules/ANNTurboModule.mm +46 -0
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
- package/lib/module/ARCHITECTURE.md +9 -3
- package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
- package/lib/module/api/app/AppRegistry.js +14 -2
- package/lib/module/api/app/AppRegistry.js.map +1 -1
- package/lib/module/api/app/createNavigation.js +188 -66
- package/lib/module/api/app/createNavigation.js.map +1 -1
- package/lib/module/api/events/navigationEvents.js +6 -2
- package/lib/module/api/events/navigationEvents.js.map +1 -1
- package/lib/module/api/linking/linking.js +11 -0
- package/lib/module/api/linking/linking.js.map +1 -1
- package/lib/module/api/screens/defineScreen.js +45 -3
- package/lib/module/api/screens/defineScreen.js.map +1 -1
- package/lib/module/api/screens/nativeScreens.js +31 -6
- package/lib/module/api/screens/nativeScreens.js.map +1 -1
- package/lib/module/api/screens/registerScreens.js +172 -35
- package/lib/module/api/screens/registerScreens.js.map +1 -1
- package/lib/module/api/theme/theme.js +5 -0
- package/lib/module/api/theme/theme.js.map +1 -1
- package/lib/module/engine/commands.js +21 -1
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +7 -2
- package/lib/module/engine/layout.js.map +1 -1
- package/lib/module/engine/nativeScreens.js +9 -0
- package/lib/module/engine/nativeScreens.js.map +1 -1
- package/lib/module/engine/options.js +5 -4
- package/lib/module/engine/options.js.map +1 -1
- package/lib/module/engine/optionsChange.js +102 -0
- package/lib/module/engine/optionsChange.js.map +1 -0
- package/lib/module/engine/refresh.js +85 -0
- package/lib/module/engine/refresh.js.map +1 -0
- package/lib/module/engine/rememberedOptions.js +60 -0
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +26 -0
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +7 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
- package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
- package/lib/typescript/api/app/createNavigation.d.ts +5 -0
- package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +2 -2
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/index.d.ts +1 -1
- package/lib/typescript/api/index.d.ts.map +1 -1
- package/lib/typescript/api/linking/linking.d.ts +8 -0
- package/lib/typescript/api/linking/linking.d.ts.map +1 -1
- package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
- package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
- package/lib/typescript/api/theme/theme.d.ts +2 -0
- package/lib/typescript/api/theme/theme.d.ts.map +1 -1
- package/lib/typescript/engine/commands.d.ts +5 -0
- package/lib/typescript/engine/commands.d.ts.map +1 -1
- package/lib/typescript/engine/layout.d.ts.map +1 -1
- package/lib/typescript/engine/nativeScreens.d.ts +5 -0
- package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/engine/optionsChange.d.ts +28 -0
- package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
- package/lib/typescript/engine/refresh.d.ts +35 -0
- package/lib/typescript/engine/refresh.d.ts.map +1 -0
- package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
- package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
- package/lib/typescript/engine/screens.d.ts +7 -0
- package/lib/typescript/engine/screens.d.ts.map +1 -1
- package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
- package/lib/typescript/interfaces/options/animations.d.ts +40 -15
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +2 -2
- package/lib/typescript/interfaces/options/buttons.d.ts +2 -2
- package/lib/typescript/interfaces/options/modals.d.ts +6 -7
- package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +8 -3
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/topBar.d.ts +14 -0
- package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
- package/metro/acceptPlugin.js +57 -0
- package/metro/babelTransformer.js +45 -0
- package/metro/index.js +36 -0
- package/package.json +3 -1
- package/src/ARCHITECTURE.md +9 -3
- package/src/adapters/NativeANNTurboModule.ts +7 -0
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +198 -66
- package/src/api/events/navigationEvents.ts +9 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/screens/defineScreen.ts +49 -5
- package/src/api/screens/nativeScreens.ts +40 -4
- package/src/api/screens/registerScreens.tsx +170 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +21 -0
- package/src/engine/layout.ts +11 -2
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +6 -8
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +70 -0
- package/src/engine/screens.tsx +24 -0
- package/src/interfaces/ComponentEvents.ts +2 -2
- package/src/interfaces/options/animations.ts +40 -15
- package/src/interfaces/options/bottomTabs.ts +2 -2
- package/src/interfaces/options/buttons.ts +2 -2
- package/src/interfaces/options/modals.ts +6 -7
- package/src/interfaces/options/stack.ts +8 -3
- package/src/interfaces/options/topBar.ts +14 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -134
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -78
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -57
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -146
|
@@ -2,39 +2,84 @@
|
|
|
2
2
|
#import "ANNAssert.h"
|
|
3
3
|
#import "ANNCurve.h"
|
|
4
4
|
#import "ANNTransformParts.h"
|
|
5
|
-
#
|
|
5
|
+
#include <cmath>
|
|
6
6
|
|
|
7
|
-
// The
|
|
8
|
-
|
|
9
|
-
@interface ANNFrameTarget : NSObject
|
|
10
|
-
@property(nonatomic, weak) id owner;
|
|
11
|
-
@end
|
|
7
|
+
// The samples per second of a client's values: a frame of a 120 Hz display each.
|
|
8
|
+
static const double ANNSamplesPerSecond = 120;
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@end
|
|
10
|
+
// At most this many samples per client: a longer transition samples less often.
|
|
11
|
+
static const NSUInteger ANNMaxSamples = 2400;
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
NSArray<NSNumber *> *ANNSampleTimes(NSTimeInterval end, NSTimeInterval length,
|
|
14
|
+
NSArray<NSNumber *> *marks) {
|
|
15
|
+
end = MIN(MAX(end, 0), length);
|
|
16
|
+
NSMutableArray<NSNumber *> *candidates = [NSMutableArray arrayWithObject:@0];
|
|
17
|
+
double step = MAX(1 / ANNSamplesPerSecond, end / ANNMaxSamples);
|
|
18
|
+
NSUInteger count = (NSUInteger)std::floor(end / step);
|
|
19
|
+
for (NSUInteger index = 1; index <= count; index++) {
|
|
20
|
+
[candidates addObject:@(index * step)];
|
|
21
|
+
}
|
|
22
|
+
for (NSNumber *mark in marks) {
|
|
23
|
+
double time = mark.doubleValue;
|
|
24
|
+
if (std::isfinite(time) && time > 0 && time < end) {
|
|
25
|
+
[candidates addObject:mark];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
[candidates addObject:@(end)];
|
|
29
|
+
[candidates addObject:@(length)];
|
|
30
|
+
[candidates sortUsingSelector:@selector(compare:)];
|
|
31
|
+
NSMutableArray<NSNumber *> *times = [NSMutableArray arrayWithCapacity:candidates.count];
|
|
32
|
+
for (NSNumber *time in candidates) {
|
|
33
|
+
// Samples closer than a microsecond are one.
|
|
34
|
+
if (times.count == 0 || time.doubleValue - times.lastObject.doubleValue > 1e-6) {
|
|
35
|
+
[times addObject:time];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return times;
|
|
39
|
+
}
|
|
18
40
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
CAKeyframeAnimation *ANNKeyframes(NSString *keyPath, NSArray *values, NSArray<NSNumber *> *times,
|
|
42
|
+
NSTimeInterval length) {
|
|
43
|
+
if (length <= 0 || values.count == 0 || values.count != times.count) {
|
|
44
|
+
return nil;
|
|
45
|
+
}
|
|
46
|
+
NSMutableArray<NSNumber *> *keyTimes = [NSMutableArray arrayWithCapacity:times.count];
|
|
47
|
+
for (NSNumber *time in times) {
|
|
48
|
+
[keyTimes addObject:@(MIN(MAX(time.doubleValue / length, 0.0), 1.0))];
|
|
24
49
|
}
|
|
25
|
-
[
|
|
50
|
+
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keyPath];
|
|
51
|
+
animation.values = values;
|
|
52
|
+
animation.keyTimes = keyTimes;
|
|
53
|
+
animation.calculationMode = kCAAnimationLinear;
|
|
54
|
+
animation.duration = length;
|
|
55
|
+
animation.fillMode = kCAFillModeBoth;
|
|
56
|
+
animation.removedOnCompletion = NO;
|
|
57
|
+
return animation;
|
|
26
58
|
}
|
|
27
59
|
|
|
28
|
-
|
|
60
|
+
NSString *ANNAnimationKey(NSString *keyPath) {
|
|
61
|
+
return [@"ApexNavigation." stringByAppendingString:keyPath];
|
|
62
|
+
}
|
|
29
63
|
|
|
30
64
|
@implementation ANNFrameDriver {
|
|
31
65
|
NSArray<id<ANNFrameClient>> *_clients;
|
|
32
66
|
NSTimeInterval _length;
|
|
33
|
-
CADisplayLink *_link;
|
|
34
|
-
CFTimeInterval _start;
|
|
35
67
|
dispatch_block_t _done;
|
|
36
|
-
|
|
37
|
-
|
|
68
|
+
BOOL _running;
|
|
69
|
+
BOOL _starting;
|
|
70
|
+
// When the animations were added; they start at the commit of the current transaction, a moment later.
|
|
71
|
+
CFTimeInterval _start;
|
|
72
|
+
// The driver keeps itself while its animations run: the transition that started it needn't.
|
|
73
|
+
ANNFrameDriver *_keep;
|
|
74
|
+
// A transition that follows a gesture: the layer whose time stops, its timing before, the clock's time the
|
|
75
|
+
// animations started at, the `done` that tells how it ended, and whether its end plays.
|
|
76
|
+
CALayer *_clock;
|
|
77
|
+
float _clockSpeed;
|
|
78
|
+
CFTimeInterval _clockBegin;
|
|
79
|
+
CFTimeInterval _clockOffset;
|
|
80
|
+
CFTimeInterval _base;
|
|
81
|
+
void (^_pausedDone)(BOOL finished);
|
|
82
|
+
BOOL _ending;
|
|
38
83
|
}
|
|
39
84
|
|
|
40
85
|
- (instancetype)initWithClients:(NSArray<id<ANNFrameClient>> *)clients
|
|
@@ -51,7 +96,11 @@
|
|
|
51
96
|
}
|
|
52
97
|
|
|
53
98
|
- (BOOL)isRunning {
|
|
54
|
-
return
|
|
99
|
+
return _running;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
- (NSTimeInterval)length {
|
|
103
|
+
return _length;
|
|
55
104
|
}
|
|
56
105
|
|
|
57
106
|
- (void)startWithDone:(dispatch_block_t)done {
|
|
@@ -60,69 +109,174 @@
|
|
|
60
109
|
ANNCurveSelfCheck();
|
|
61
110
|
ANNTransformPartsSelfCheck();
|
|
62
111
|
#endif
|
|
63
|
-
if (
|
|
112
|
+
if (_running || _done || _pausedDone) {
|
|
64
113
|
return;
|
|
65
114
|
}
|
|
66
115
|
_done = [done copy];
|
|
67
|
-
_running =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
target.owner = self;
|
|
71
|
-
_link = [CADisplayLink displayLinkWithTarget:target selector:@selector(frame:)];
|
|
72
|
-
[_link addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
|
|
116
|
+
_running = YES;
|
|
117
|
+
_keep = self;
|
|
118
|
+
_starting = YES;
|
|
73
119
|
_start = CACurrentMediaTime();
|
|
120
|
+
__weak ANNFrameDriver *weakSelf = self;
|
|
121
|
+
[CATransaction begin];
|
|
122
|
+
[CATransaction setDisableActions:YES];
|
|
123
|
+
// Called once every animation added in this transaction ended or was removed (with its layer too), and at once
|
|
124
|
+
// without any.
|
|
125
|
+
[CATransaction setCompletionBlock:^{
|
|
126
|
+
[weakSelf animationsEnded];
|
|
127
|
+
}];
|
|
128
|
+
@try {
|
|
129
|
+
for (id<ANNFrameClient> client in _clients) {
|
|
130
|
+
[client addAnimationsWithLength:_length];
|
|
131
|
+
}
|
|
132
|
+
} @finally {
|
|
133
|
+
[CATransaction commit];
|
|
134
|
+
_starting = NO;
|
|
135
|
+
}
|
|
74
136
|
}
|
|
75
137
|
|
|
76
|
-
- (void)
|
|
77
|
-
if (
|
|
78
|
-
[link invalidate];
|
|
138
|
+
- (void)animationsEnded {
|
|
139
|
+
if (!_running) {
|
|
79
140
|
return;
|
|
80
141
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
_running = nil;
|
|
91
|
-
if (done) {
|
|
92
|
-
done();
|
|
93
|
-
}
|
|
142
|
+
// `done` never comes inside `startWithDone:`, nor before the length passed: a transition with nothing to play (no
|
|
143
|
+
// client, every element skipped) or whose animations went early still takes its time, as on Android.
|
|
144
|
+
__weak ANNFrameDriver *weakSelf = self;
|
|
145
|
+
NSTimeInterval left = _length - (CACurrentMediaTime() - _start);
|
|
146
|
+
if (_starting || left > 0) {
|
|
147
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MAX(left, 0) * NSEC_PER_SEC)),
|
|
148
|
+
dispatch_get_main_queue(), ^{
|
|
149
|
+
[weakSelf animationsEnded];
|
|
150
|
+
});
|
|
94
151
|
return;
|
|
95
152
|
}
|
|
96
|
-
|
|
153
|
+
_running = NO;
|
|
154
|
+
dispatch_block_t done = _done;
|
|
155
|
+
_done = nil;
|
|
156
|
+
_keep = nil;
|
|
157
|
+
if (done) {
|
|
158
|
+
done();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
- (void)cancel {
|
|
163
|
+
ANNAssertMainQueue();
|
|
164
|
+
if (!_running) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
_running = NO;
|
|
168
|
+
_done = nil;
|
|
169
|
+
_pausedDone = nil;
|
|
170
|
+
_keep = nil;
|
|
171
|
+
[self releaseClock];
|
|
97
172
|
}
|
|
98
173
|
|
|
99
|
-
-
|
|
174
|
+
#pragma mark - Following a gesture
|
|
175
|
+
|
|
176
|
+
- (void)startPausedOn:(CALayer *)clock done:(void (^)(BOOL finished))done {
|
|
177
|
+
ANNAssertMainQueue();
|
|
178
|
+
if (_running || _done || _pausedDone) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
_pausedDone = [done copy];
|
|
182
|
+
_running = YES;
|
|
183
|
+
_keep = self;
|
|
184
|
+
_clock = clock;
|
|
185
|
+
_clockSpeed = clock.speed;
|
|
186
|
+
_clockBegin = clock.beginTime;
|
|
187
|
+
_clockOffset = clock.timeOffset;
|
|
188
|
+
// The clock stops at its time now: what else animates under it holds still, and the animations added now start
|
|
189
|
+
// there (Core Animation gives an animation without a begin time the layer's time at the commit).
|
|
190
|
+
_base = [clock convertTime:CACurrentMediaTime() fromLayer:nil];
|
|
100
191
|
[CATransaction begin];
|
|
101
192
|
[CATransaction setDisableActions:YES];
|
|
102
|
-
|
|
103
|
-
|
|
193
|
+
clock.speed = 0;
|
|
194
|
+
clock.beginTime = 0;
|
|
195
|
+
clock.timeOffset = _base;
|
|
196
|
+
@try {
|
|
197
|
+
for (id<ANNFrameClient> client in _clients) {
|
|
198
|
+
[client addAnimationsWithLength:_length];
|
|
199
|
+
}
|
|
200
|
+
} @finally {
|
|
201
|
+
[CATransaction commit];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
- (void)setProgress:(CGFloat)progress {
|
|
206
|
+
ANNAssertMainQueue();
|
|
207
|
+
if (!_running || !_pausedDone || _ending) {
|
|
208
|
+
return;
|
|
104
209
|
}
|
|
210
|
+
[CATransaction begin];
|
|
211
|
+
[CATransaction setDisableActions:YES];
|
|
212
|
+
_clock.timeOffset = _base + MIN(MAX(progress, 0.0), 1.0) * _length;
|
|
105
213
|
[CATransaction commit];
|
|
106
214
|
}
|
|
107
215
|
|
|
108
|
-
- (void)
|
|
109
|
-
[
|
|
110
|
-
_link = nil;
|
|
216
|
+
- (void)finishWithSpeed:(CGFloat)speed {
|
|
217
|
+
[self playOnForward:YES speed:speed];
|
|
111
218
|
}
|
|
112
219
|
|
|
113
|
-
- (void)
|
|
220
|
+
- (void)rewindWithSpeed:(CGFloat)speed {
|
|
221
|
+
[self playOnForward:NO speed:speed];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// The clock runs again from where it shows, forward or back, and `done` comes once it reached the end or the start.
|
|
225
|
+
- (void)playOnForward:(BOOL)forward speed:(CGFloat)speed {
|
|
114
226
|
ANNAssertMainQueue();
|
|
115
|
-
if (!
|
|
227
|
+
if (!_running || !_pausedDone || _ending) {
|
|
116
228
|
return;
|
|
117
229
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
230
|
+
_ending = YES;
|
|
231
|
+
speed = MAX(speed, 1.0);
|
|
232
|
+
CALayer *clock = _clock;
|
|
233
|
+
CFTimeInterval at = clock.timeOffset - _base;
|
|
234
|
+
CFTimeInterval left = forward ? _length - at : at;
|
|
235
|
+
CALayer *parent = clock.superlayer;
|
|
236
|
+
CFTimeInterval now = parent ? [parent convertTime:CACurrentMediaTime() fromLayer:nil]
|
|
237
|
+
: CACurrentMediaTime();
|
|
238
|
+
[CATransaction begin];
|
|
239
|
+
[CATransaction setDisableActions:YES];
|
|
240
|
+
// The clock's time is (parent's time - beginTime) * speed + timeOffset: it goes on from where it shows.
|
|
241
|
+
clock.beginTime = now;
|
|
242
|
+
clock.speed = (float)(forward ? speed : -speed);
|
|
243
|
+
[CATransaction commit];
|
|
244
|
+
__weak ANNFrameDriver *weakSelf = self;
|
|
245
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MAX(left / speed, 0) * NSEC_PER_SEC)),
|
|
246
|
+
dispatch_get_main_queue(), ^{
|
|
247
|
+
[weakSelf pausedEndedForward:forward];
|
|
248
|
+
});
|
|
122
249
|
}
|
|
123
250
|
|
|
124
|
-
- (void)
|
|
125
|
-
|
|
251
|
+
- (void)pausedEndedForward:(BOOL)forward {
|
|
252
|
+
if (!_running || !_pausedDone) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
_running = NO;
|
|
256
|
+
void (^done)(BOOL) = _pausedDone;
|
|
257
|
+
_pausedDone = nil;
|
|
258
|
+
_keep = nil;
|
|
259
|
+
// The clock's time back and the caller's restore in one commit: between two, the animations would show at the
|
|
260
|
+
// clock's own time for a frame (past their end, or part way).
|
|
261
|
+
[CATransaction begin];
|
|
262
|
+
[self releaseClock];
|
|
263
|
+
done(forward);
|
|
264
|
+
[CATransaction commit];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// The clock gets back the timing it had before the gesture.
|
|
268
|
+
- (void)releaseClock {
|
|
269
|
+
CALayer *clock = _clock;
|
|
270
|
+
_clock = nil;
|
|
271
|
+
if (!clock) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
[CATransaction begin];
|
|
275
|
+
[CATransaction setDisableActions:YES];
|
|
276
|
+
clock.speed = _clockSpeed;
|
|
277
|
+
clock.beginTime = _clockBegin;
|
|
278
|
+
clock.timeOffset = _clockOffset;
|
|
279
|
+
[CATransaction commit];
|
|
126
280
|
}
|
|
127
281
|
|
|
128
282
|
@end
|
|
@@ -12,10 +12,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
12
12
|
/// above the leaving one (push, `setStackRoot`, show) or below it (pop, dismissal), gets its final frame and lays out
|
|
13
13
|
/// (React gets its final size), and hides (alpha 0) until the start; a forward transition starts after its wait
|
|
14
14
|
/// (`ANNTransitionWait`), a backward one at once. Then one frame driver moves the sides that play, the elements in
|
|
15
|
-
/// place and the shared elements' copies; a side that doesn't play doesn't move. At the end, before
|
|
16
|
-
/// `completeTransition:`, the
|
|
17
|
-
///
|
|
18
|
-
/// comes inside `animateTransition:`. Main queue.
|
|
15
|
+
/// place and the shared elements' copies, in Core Animation; a side that doesn't play doesn't move. At the end, before
|
|
16
|
+
/// `completeTransition:`, the animations go, the copies go and the React views show again, and both views get back the
|
|
17
|
+
/// transform and the alpha they had. Only a pop of the swipe back follows a gesture (`animateFollowingGesture:`) and
|
|
18
|
+
/// can end where it began; `completeTransition:` never comes inside `animateTransition:`. Main queue.
|
|
19
19
|
@interface ANNTransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>
|
|
20
20
|
|
|
21
21
|
- (instancetype)initWithPlan:(ANNTransitionPlan *)plan NS_DESIGNATED_INITIALIZER;
|
|
@@ -25,8 +25,29 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
25
25
|
|
|
26
26
|
@property(nonatomic, strong, readonly) ANNTransitionPlan *plan;
|
|
27
27
|
|
|
28
|
+
/// The start of an interactive transition (a pop of the swipe back, which never waits): as `animateTransition:`, with
|
|
29
|
+
/// the frames held at their start until `setProgress:` moves them (`ANNFrameDriver startPausedOn:`); then
|
|
30
|
+
/// `finishWithSpeed:` or `rewindWithSpeed:`, after the context's own finish or cancel, plays the end.
|
|
31
|
+
- (void)animateFollowingGesture:(id<UIViewControllerContextTransitioning>)transitionContext;
|
|
32
|
+
|
|
33
|
+
/// The frames show at `progress` (0 to 1) of the length.
|
|
34
|
+
- (void)setProgress:(CGFloat)progress;
|
|
35
|
+
|
|
36
|
+
/// The rest plays (`speed` times as fast, 1 or more), and the transition completes.
|
|
37
|
+
- (void)finishWithSpeed:(CGFloat)speed;
|
|
38
|
+
|
|
39
|
+
/// The frames play back to the start (`speed` times as fast, 1 or more), and the transition completes cancelled.
|
|
40
|
+
- (void)rewindWithSpeed:(CGFloat)speed;
|
|
41
|
+
|
|
42
|
+
/// The seconds the frames take: the plan's length, or the end of a longer element.
|
|
43
|
+
@property(nonatomic, readonly) NSTimeInterval length;
|
|
44
|
+
|
|
45
|
+
/// The transition completed (or was never started).
|
|
46
|
+
@property(nonatomic, readonly) BOOL isCompleted;
|
|
47
|
+
|
|
28
48
|
/// A destroy or a reload during the transition: the wait or the frames stop at the end state, every value written goes
|
|
29
|
-
/// back, and the transition completes so that UIKit isn't left half way
|
|
49
|
+
/// back, and the transition completes so that UIKit isn't left half way (an interactive one finishes first). Nothing
|
|
50
|
+
/// once it completed.
|
|
30
51
|
- (void)cancel;
|
|
31
52
|
|
|
32
53
|
@end
|
|
@@ -33,6 +33,9 @@ static void ANNUpdateRootLayoutOf(UIViewController *node) {
|
|
|
33
33
|
NSArray<id<ANNFrameClient>> *_clients;
|
|
34
34
|
BOOL _began;
|
|
35
35
|
BOOL _completed;
|
|
36
|
+
// The transition follows a gesture (`animateFollowingGesture:`), and its end was chosen.
|
|
37
|
+
BOOL _followsGesture;
|
|
38
|
+
BOOL _endChosen;
|
|
36
39
|
// The container's views of the transition that got a depth for it, and the depth each had.
|
|
37
40
|
NSArray<UIView *> *_depthViews;
|
|
38
41
|
NSArray<NSNumber *> *_depthsBefore;
|
|
@@ -118,6 +121,33 @@ static void ANNUpdateRootLayoutOf(UIViewController *node) {
|
|
|
118
121
|
[self begin];
|
|
119
122
|
}
|
|
120
123
|
|
|
124
|
+
- (void)animateFollowingGesture:(id<UIViewControllerContextTransitioning>)transitionContext {
|
|
125
|
+
_followsGesture = YES;
|
|
126
|
+
[self animateTransition:transitionContext];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
- (void)setProgress:(CGFloat)progress {
|
|
130
|
+
[_driver setProgress:progress];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
- (void)finishWithSpeed:(CGFloat)speed {
|
|
134
|
+
_endChosen = YES;
|
|
135
|
+
[_driver finishWithSpeed:speed];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
- (void)rewindWithSpeed:(CGFloat)speed {
|
|
139
|
+
_endChosen = YES;
|
|
140
|
+
[_driver rewindWithSpeed:speed];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
- (NSTimeInterval)length {
|
|
144
|
+
return _driver ? _driver.length : _plan.length;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
- (BOOL)isCompleted {
|
|
148
|
+
return _completed || !_context;
|
|
149
|
+
}
|
|
150
|
+
|
|
121
151
|
- (void)animationEnded:(BOOL)transitionCompleted {
|
|
122
152
|
_wait = nil;
|
|
123
153
|
_driver = nil;
|
|
@@ -187,8 +217,9 @@ static void ANNUpdateRootLayoutOf(UIViewController *node) {
|
|
|
187
217
|
duration:_plan.length
|
|
188
218
|
alphaBefore:_leavingAlpha];
|
|
189
219
|
}
|
|
190
|
-
// The arriving view
|
|
191
|
-
|
|
220
|
+
// The arriving view gets its own alpha back: an `opacity` animation of its tracks shows over it from the start, in
|
|
221
|
+
// the same transaction.
|
|
222
|
+
if (_arriving) {
|
|
192
223
|
_arriving.alpha = _arrivingAlpha;
|
|
193
224
|
}
|
|
194
225
|
if (arrivingTracks.hasTracks) {
|
|
@@ -197,7 +228,7 @@ static void ANNUpdateRootLayoutOf(UIViewController *node) {
|
|
|
197
228
|
if (leavingTracks.hasTracks) {
|
|
198
229
|
[clients addObject:leavingTracks];
|
|
199
230
|
}
|
|
200
|
-
// Each element plays on its own: one whose
|
|
231
|
+
// Each element plays on its own: one whose animations fail goes back and stays, the others and the screens go on.
|
|
201
232
|
for (ANNElementTransition *element in elements) {
|
|
202
233
|
[clients addObject:[[ANNIsolatedElement alloc] initWithClient:element name:element.name]];
|
|
203
234
|
}
|
|
@@ -210,6 +241,13 @@ static void ANNUpdateRootLayoutOf(UIViewController *node) {
|
|
|
210
241
|
}
|
|
211
242
|
__weak ANNTransitionAnimator *weakSelf = self;
|
|
212
243
|
_driver = [[ANNFrameDriver alloc] initWithClients:clients length:_plan.length];
|
|
244
|
+
if (_followsGesture) {
|
|
245
|
+
[_driver startPausedOn:container.layer
|
|
246
|
+
done:^(BOOL finished) {
|
|
247
|
+
[weakSelf complete];
|
|
248
|
+
}];
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
213
251
|
[_driver startWithDone:^{
|
|
214
252
|
[weakSelf complete];
|
|
215
253
|
}];
|
|
@@ -288,8 +326,16 @@ static BOOL ANNSideTilts(ANNViewAnimationOptions *side) {
|
|
|
288
326
|
}
|
|
289
327
|
[_wait cancel];
|
|
290
328
|
_wait = nil;
|
|
329
|
+
// An interactive transition ends at its end state too: UIKit completes only one whose end was chosen.
|
|
330
|
+
if (_followsGesture && !_endChosen) {
|
|
331
|
+
_endChosen = YES;
|
|
332
|
+
[_context finishInteractiveTransition];
|
|
333
|
+
}
|
|
334
|
+
// A stopped clock gets its time back in the commit that removes the animations.
|
|
335
|
+
[CATransaction begin];
|
|
291
336
|
[_driver cancel];
|
|
292
337
|
[self complete];
|
|
338
|
+
[CATransaction commit];
|
|
293
339
|
}
|
|
294
340
|
|
|
295
341
|
@end
|
|
@@ -19,8 +19,8 @@ typedef NS_ENUM(NSInteger, ANNTransitionKind) {
|
|
|
19
19
|
ANNTransitionKindDismiss,
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
/// The screen fade of a transition with elements and no screen animation of its own,
|
|
23
|
-
/// nothing to play.
|
|
22
|
+
/// The screen fade of a transition with elements and no screen animation of its own, of a dismissed popover with
|
|
23
|
+
/// nothing to play, or of any transition while the system's Reduce Motion is on (then nothing else plays).
|
|
24
24
|
typedef NS_ENUM(NSInteger, ANNScreenFade) {
|
|
25
25
|
ANNScreenFadeNone,
|
|
26
26
|
/// The arriving screen from 0 to its alpha.
|
|
@@ -43,6 +43,16 @@ static const NSTimeInterval ANNElementsScreenFade = 0.3;
|
|
|
43
43
|
length = MAX(length, [ANNAnimationRules lengthOfElements:_elements shared:_sharedElements]);
|
|
44
44
|
length = MAX(length, _screenFadeDuration);
|
|
45
45
|
_length = length;
|
|
46
|
+
// With the system's Reduce Motion on, nothing moves: the transition is a fade of the same length, the arriving
|
|
47
|
+
// screen in going forward, the leaving one out otherwise.
|
|
48
|
+
if (UIAccessibilityIsReduceMotionEnabled() && length > 0) {
|
|
49
|
+
_enter = nil;
|
|
50
|
+
_exit = nil;
|
|
51
|
+
_elements = @[];
|
|
52
|
+
_sharedElements = @[];
|
|
53
|
+
_screenFade = _isForward ? ANNScreenFadeArrivingIn : ANNScreenFadeLeavingOut;
|
|
54
|
+
_screenFadeDuration = length;
|
|
55
|
+
}
|
|
46
56
|
}
|
|
47
57
|
return self;
|
|
48
58
|
}
|
|
@@ -69,8 +69,8 @@ FOUNDATION_EXPORT BOOL ANNElementStep(NSString *element, NS_NOESCAPE dispatch_bl
|
|
|
69
69
|
/// The line in the log for the element named `element`, skipped for `reason`: it shows and hides with its screen.
|
|
70
70
|
FOUNDATION_EXPORT void ANNElementSkipped(NSString *element, NSString *reason);
|
|
71
71
|
|
|
72
|
-
/// An element's
|
|
73
|
-
/// (`-restore`)
|
|
72
|
+
/// An element's animations, made in `ANNElementStep`: when making them fails, the element's values go back
|
|
73
|
+
/// (`-restore`) and it doesn't move; the rest of the transition plays.
|
|
74
74
|
@interface ANNIsolatedElement : NSObject <ANNFrameClient>
|
|
75
75
|
|
|
76
76
|
- (instancetype)initWithClient:(id<ANNFrameClient>)client
|
|
@@ -182,13 +182,13 @@ BOOL ANNElementStep(NSString *element, NS_NOESCAPE dispatch_block_t work) {
|
|
|
182
182
|
|
|
183
183
|
#pragma mark - ANNFrameClient
|
|
184
184
|
|
|
185
|
-
- (void)
|
|
185
|
+
- (void)addAnimationsWithLength:(NSTimeInterval)length {
|
|
186
186
|
if (_failed) {
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
189
|
id<ANNFrameClient> client = _client;
|
|
190
190
|
if (!ANNElementStep(_name, ^{
|
|
191
|
-
[client
|
|
191
|
+
[client addAnimationsWithLength:length];
|
|
192
192
|
})) {
|
|
193
193
|
_failed = YES;
|
|
194
194
|
[self restore];
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
NS_ASSUME_NONNULL_BEGIN
|
|
8
8
|
|
|
9
|
-
/// One `elementTransitions[]` item on its React view:
|
|
10
|
-
///
|
|
11
|
-
/// the React view
|
|
9
|
+
/// One `elementTransitions[]` item on its React view: its `transform` and `opacity` animate in place, its parents clip
|
|
10
|
+
/// it as usual; at the end, at a cancel and at a destroy the animations go and the view shows its own values. Nothing
|
|
11
|
+
/// of the React view is written (no value, no frame, no subview, never `layer.zPosition`).
|
|
12
12
|
@interface ANNElementTransition : NSObject <ANNFrameClient>
|
|
13
13
|
|
|
14
14
|
/// The items found: each `id` first in the leaving screen's React view, then in the arriving one; an item not found or
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
|
|
59
59
|
#pragma mark - ANNFrameClient
|
|
60
60
|
|
|
61
|
-
- (void)
|
|
62
|
-
[_tracks
|
|
61
|
+
- (void)addAnimationsWithLength:(NSTimeInterval)length {
|
|
62
|
+
[_tracks addAnimationsWithLength:length];
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
- (NSTimeInterval)endTime {
|
|
@@ -9,9 +9,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
9
9
|
/// One shared pair in flight: a plain view of the core, the copy, flies in the transition's container from the `from`
|
|
10
10
|
/// view to the `to` view with two pictures of them (`renderInContext:` at the screen's scale). The React views are
|
|
11
11
|
/// neither moved nor changed: they are only `hidden` while the copy flies and get back what they had before the
|
|
12
|
-
/// transition completes. All geometry is in the container's coordinates.
|
|
13
|
-
///
|
|
14
|
-
///
|
|
12
|
+
/// transition completes. All geometry is in the container's coordinates. The copy's size, center, visible part (a
|
|
13
|
+
/// mask), corner radius and layer transform go from the `from` values to the `to` values on the pair's curve, delay and
|
|
14
|
+
/// duration, in Core Animation's animations of the copy's layers.
|
|
15
15
|
///
|
|
16
16
|
/// A view (not a text): both pictures fill the copy, the copy clips to its corners, the `to` picture fades in over the
|
|
17
17
|
/// flight. A text (React's paragraph): the pictures keep their aspect, as tall as the copy, at the line's start (the
|