mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00
fix(hmr): quick fade upon replace navigation (#7251)
This commit is contained in:
@ -146,9 +146,5 @@ function _test_onLiveSync_ModuleContext_TypeStyle(context: { type, path }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function waitUntilLivesyncComplete(frame: Frame) {
|
function waitUntilLivesyncComplete(frame: Frame) {
|
||||||
if (isAndroid) {
|
TKUnit.waitUntilReady(() => frame._executingEntry === null);
|
||||||
TKUnit.waitUntilReady(() => frame._executingEntry === null);
|
|
||||||
} else {
|
|
||||||
TKUnit.waitUntilReady(() => frame.currentPage.isLoaded);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from ".";
|
} from ".";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ViewBase, Property, booleanConverter, eachDescendant, EventData, layout,
|
ViewBase, Property, booleanConverter, EventData, layout,
|
||||||
getEventOrGestureName, traceEnabled, traceWrite, traceCategories,
|
getEventOrGestureName, traceEnabled, traceWrite, traceCategories,
|
||||||
InheritedProperty, ShowModalOptions
|
InheritedProperty, ShowModalOptions
|
||||||
} from "../view-base";
|
} from "../view-base";
|
||||||
|
@ -169,8 +169,11 @@ export function _setAndroidFragmentTransitions(
|
|||||||
|
|
||||||
// Having transition means we have custom animation
|
// Having transition means we have custom animation
|
||||||
if (transition) {
|
if (transition) {
|
||||||
// we do not use Android backstack so setting popEnter / popExit is meaningless (3rd and 4th optional args)
|
if (fragmentTransaction) {
|
||||||
fragmentTransaction.setCustomAnimations(AnimationType.enterFakeResourceId, AnimationType.exitFakeResourceId);
|
// we do not use Android backstack so setting popEnter / popExit is meaningless (3rd and 4th optional args)
|
||||||
|
fragmentTransaction.setCustomAnimations(AnimationType.enterFakeResourceId, AnimationType.exitFakeResourceId);
|
||||||
|
}
|
||||||
|
|
||||||
setupAllAnimation(newEntry, transition);
|
setupAllAnimation(newEntry, transition);
|
||||||
if (currentFragmentNeedsDifferentAnimation) {
|
if (currentFragmentNeedsDifferentAnimation) {
|
||||||
setupExitAndPopEnterAnimation(currentEntry, transition);
|
setupExitAndPopEnterAnimation(currentEntry, transition);
|
||||||
@ -502,6 +505,8 @@ function clearEntry(entry: ExpandedEntry, removeListener: boolean): void {
|
|||||||
clearAnimationListener(entry.exitAnimator, listener);
|
clearAnimationListener(entry.exitAnimator, listener);
|
||||||
clearAnimationListener(entry.popEnterAnimator, listener);
|
clearAnimationListener(entry.popEnterAnimator, listener);
|
||||||
clearAnimationListener(entry.popExitAnimator, listener);
|
clearAnimationListener(entry.popExitAnimator, listener);
|
||||||
|
clearAnimationListener(entry.defaultEnterAnimator, listener);
|
||||||
|
clearAnimationListener(entry.defaultExitAnimator, listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// Definitions.
|
// Definitions.
|
||||||
import {
|
import {
|
||||||
AndroidFrame as AndroidFrameDefinition, AndroidActivityCallbacks,
|
AndroidFrame as AndroidFrameDefinition, AndroidActivityCallbacks,
|
||||||
AndroidFragmentCallbacks, BackstackEntry, NavigationTransition
|
AndroidFragmentCallbacks, BackstackEntry, NavigationTransition, NavigationEntry
|
||||||
} from ".";
|
} from ".";
|
||||||
import { Page } from "../page";
|
import { Page } from "../page";
|
||||||
|
|
||||||
// Types.
|
// Types.
|
||||||
import * as application from "../../application";
|
import * as application from "../../application";
|
||||||
import {
|
import {
|
||||||
FrameBase, goBack, stack, NavigationContext, NavigationType,
|
FrameBase, goBack, stack, NavigationType,
|
||||||
Observable, View, traceCategories, traceEnabled, traceError, traceWrite
|
Observable, View, traceCategories, traceEnabled, traceError, traceWrite
|
||||||
} from "./frame-common";
|
} from "./frame-common";
|
||||||
|
|
||||||
@ -21,7 +21,6 @@ import { profile } from "../../profiling";
|
|||||||
|
|
||||||
// TODO: Remove this and get it from global to decouple builder for angular
|
// TODO: Remove this and get it from global to decouple builder for angular
|
||||||
import { createViewFromEntry } from "../builder";
|
import { createViewFromEntry } from "../builder";
|
||||||
import { getModuleName } from "../../utils/utils";
|
|
||||||
|
|
||||||
export * from "./frame-common";
|
export * from "./frame-common";
|
||||||
|
|
||||||
@ -37,6 +36,7 @@ const INTENT_EXTRA = "com.tns.activity";
|
|||||||
const ROOT_VIEW_ID_EXTRA = "com.tns.activity.rootViewId";
|
const ROOT_VIEW_ID_EXTRA = "com.tns.activity.rootViewId";
|
||||||
const FRAMEID = "_frameId";
|
const FRAMEID = "_frameId";
|
||||||
const CALLBACKS = "_callbacks";
|
const CALLBACKS = "_callbacks";
|
||||||
|
const HMR_REPLACE_TRANSITION = "fade";
|
||||||
|
|
||||||
const ownerSymbol = Symbol("_owner");
|
const ownerSymbol = Symbol("_owner");
|
||||||
const activityRootViewsMap = new Map<number, WeakRef<View>>();
|
const activityRootViewsMap = new Map<number, WeakRef<View>>();
|
||||||
@ -319,6 +319,18 @@ export class Frame extends FrameBase {
|
|||||||
restoreAnimatorState(this._currentEntry, this._cachedAnimatorState);
|
restoreAnimatorState(this._currentEntry, this._cachedAnimatorState);
|
||||||
this._cachedAnimatorState = null;
|
this._cachedAnimatorState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore original fragment transitions if we just completed replace navigation (hmr)
|
||||||
|
if (navigationType === NavigationType.replace) {
|
||||||
|
_clearEntry(entry);
|
||||||
|
|
||||||
|
const animated = entry.entry.animated;
|
||||||
|
const navigationTransition = this._getNavigationTransition(entry.entry);
|
||||||
|
const currentEntry = null;
|
||||||
|
const newEntry = entry;
|
||||||
|
const transaction = null;
|
||||||
|
_setAndroidFragmentTransitions(animated, navigationTransition, currentEntry, newEntry, transaction, this._android.frameId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public onBackPressed(): boolean {
|
public onBackPressed(): boolean {
|
||||||
@ -381,12 +393,20 @@ export class Frame extends FrameBase {
|
|||||||
const newFragmentTag = `fragment${fragmentId}[${navDepth}]`;
|
const newFragmentTag = `fragment${fragmentId}[${navDepth}]`;
|
||||||
const newFragment = this.createFragment(newEntry, newFragmentTag);
|
const newFragment = this.createFragment(newEntry, newFragmentTag);
|
||||||
const transaction = manager.beginTransaction();
|
const transaction = manager.beginTransaction();
|
||||||
const animated = currentEntry ? this._getIsAnimatedNavigation(newEntry.entry) : false;
|
let animated = currentEntry ? this._getIsAnimatedNavigation(newEntry.entry) : false;
|
||||||
// NOTE: Don't use transition for the initial navigation (same as on iOS)
|
// NOTE: Don't use transition for the initial navigation (same as on iOS)
|
||||||
// On API 21+ transition won't be triggered unless there was at least one
|
// On API 21+ transition won't be triggered unless there was at least one
|
||||||
// layout pass so we will wait forever for transitionCompleted handler...
|
// layout pass so we will wait forever for transitionCompleted handler...
|
||||||
// https://github.com/NativeScript/NativeScript/issues/4895
|
// https://github.com/NativeScript/NativeScript/issues/4895
|
||||||
const navigationTransition = this._currentEntry ? this._getNavigationTransition(newEntry.entry) : null;
|
let navigationTransition: NavigationTransition;
|
||||||
|
if (isReplace) {
|
||||||
|
animated = true;
|
||||||
|
navigationTransition = { name: HMR_REPLACE_TRANSITION, duration: 100 };
|
||||||
|
} else if (this._currentEntry) {
|
||||||
|
navigationTransition = this._getNavigationTransition(newEntry.entry);
|
||||||
|
} else {
|
||||||
|
navigationTransition = null;
|
||||||
|
}
|
||||||
|
|
||||||
_setAndroidFragmentTransitions(animated, navigationTransition, currentEntry, newEntry, transaction, this._android.frameId);
|
_setAndroidFragmentTransitions(animated, navigationTransition, currentEntry, newEntry, transaction, this._android.frameId);
|
||||||
|
|
||||||
|
@ -7,12 +7,11 @@ import { profile } from "../../profiling";
|
|||||||
|
|
||||||
//Types.
|
//Types.
|
||||||
import {
|
import {
|
||||||
FrameBase, View, isCategorySet, layout, NavigationContext,
|
FrameBase, View, isCategorySet, layout,
|
||||||
NavigationType, traceCategories, traceEnabled, traceWrite
|
NavigationType, traceCategories, traceEnabled, traceWrite
|
||||||
} from "./frame-common";
|
} from "./frame-common";
|
||||||
import { _createIOSAnimatedTransitioning } from "./fragment.transitions";
|
import { _createIOSAnimatedTransitioning } from "./fragment.transitions";
|
||||||
|
|
||||||
import { createViewFromEntry } from "../builder";
|
|
||||||
import * as utils from "../../utils/utils";
|
import * as utils from "../../utils/utils";
|
||||||
|
|
||||||
export * from "./frame-common";
|
export * from "./frame-common";
|
||||||
@ -24,6 +23,7 @@ const DELEGATE = "_delegate";
|
|||||||
const NAV_DEPTH = "_navDepth";
|
const NAV_DEPTH = "_navDepth";
|
||||||
const TRANSITION = "_transition";
|
const TRANSITION = "_transition";
|
||||||
const NON_ANIMATED_TRANSITION = "non-animated";
|
const NON_ANIMATED_TRANSITION = "non-animated";
|
||||||
|
const HMR_REPLACE_TRANSITION = "fade";
|
||||||
|
|
||||||
let navDepth = -1;
|
let navDepth = -1;
|
||||||
|
|
||||||
@ -88,13 +88,16 @@ export class Frame extends FrameBase {
|
|||||||
|
|
||||||
let navigationTransition: NavigationTransition;
|
let navigationTransition: NavigationTransition;
|
||||||
let animated = this.currentPage ? this._getIsAnimatedNavigation(backstackEntry.entry) : false;
|
let animated = this.currentPage ? this._getIsAnimatedNavigation(backstackEntry.entry) : false;
|
||||||
if (animated) {
|
if (isReplace) {
|
||||||
|
animated = true;
|
||||||
|
navigationTransition = { name: HMR_REPLACE_TRANSITION, duration: 100 }
|
||||||
|
viewController[TRANSITION] = navigationTransition;
|
||||||
|
} else if (animated) {
|
||||||
navigationTransition = this._getNavigationTransition(backstackEntry.entry);
|
navigationTransition = this._getNavigationTransition(backstackEntry.entry);
|
||||||
if (navigationTransition) {
|
if (navigationTransition) {
|
||||||
viewController[TRANSITION] = navigationTransition;
|
viewController[TRANSITION] = navigationTransition;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
//https://github.com/NativeScript/NativeScript/issues/1787
|
//https://github.com/NativeScript/NativeScript/issues/1787
|
||||||
viewController[TRANSITION] = { name: NON_ANIMATED_TRANSITION };
|
viewController[TRANSITION] = { name: NON_ANIMATED_TRANSITION };
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Definitions.
|
// Definitions.
|
||||||
import { Frame } from "../frame";
|
import { Frame, BackstackEntry } from "../frame";
|
||||||
import { NavigationType } from "../frame/frame-common";
|
import { NavigationType } from "../frame/frame-common";
|
||||||
|
|
||||||
// Types.
|
// Types.
|
||||||
@ -15,6 +15,8 @@ export * from "./page-common";
|
|||||||
|
|
||||||
const ENTRY = "_entry";
|
const ENTRY = "_entry";
|
||||||
const DELEGATE = "_delegate";
|
const DELEGATE = "_delegate";
|
||||||
|
const TRANSITION = "_transition";
|
||||||
|
const NON_ANIMATED_TRANSITION = "non-animated";
|
||||||
|
|
||||||
const majorVersion = iosUtils.MajorVersion;
|
const majorVersion = iosUtils.MajorVersion;
|
||||||
|
|
||||||
@ -130,7 +132,7 @@ class UIViewControllerImpl extends UIViewController {
|
|||||||
const frame = navigationController ? (<any>navigationController).owner : null;
|
const frame = navigationController ? (<any>navigationController).owner : null;
|
||||||
// Skip navigation events if modal page is shown.
|
// Skip navigation events if modal page is shown.
|
||||||
if (!owner._presentedViewController && frame) {
|
if (!owner._presentedViewController && frame) {
|
||||||
const newEntry = this[ENTRY];
|
const newEntry: BackstackEntry = this[ENTRY];
|
||||||
|
|
||||||
let isBack: boolean;
|
let isBack: boolean;
|
||||||
let navType = frame.navigationType;
|
let navType = frame.navigationType;
|
||||||
@ -146,6 +148,18 @@ class UIViewControllerImpl extends UIViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame.setCurrent(newEntry, navType);
|
frame.setCurrent(newEntry, navType);
|
||||||
|
|
||||||
|
if (frame.navigationType === NavigationType.replace) {
|
||||||
|
let controller = newEntry.resolvedPage.ios;
|
||||||
|
if (controller) {
|
||||||
|
if (newEntry.entry.animated) {
|
||||||
|
controller[TRANSITION] = frame._getNavigationTransition(newEntry.entry);
|
||||||
|
} else {
|
||||||
|
controller[TRANSITION] = { name: NON_ANIMATED_TRANSITION };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
frame.navigationType = isBack ? NavigationType.back : NavigationType.forward;
|
frame.navigationType = isBack ? NavigationType.back : NavigationType.forward;
|
||||||
|
|
||||||
// If page was shown with custom animation - we need to set the navigationController.delegate to the animatedDelegate.
|
// If page was shown with custom animation - we need to set the navigationController.delegate to the animatedDelegate.
|
||||||
|
Reference in New Issue
Block a user