Skip to content

Commit

Permalink
fix(hmr): quick fade upon replace navigation (#7251)
Browse files Browse the repository at this point in the history
  • Loading branch information
manoldonev committed May 22, 2019
1 parent d60e5da commit 0aca087
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 20 deletions.
6 changes: 1 addition & 5 deletions tests/app/livesync/livesync-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,5 @@ function _test_onLiveSync_ModuleContext_TypeStyle(context: { type, path }) {
}

function waitUntilLivesyncComplete(frame: Frame) {
if (isAndroid) {
TKUnit.waitUntilReady(() => frame._executingEntry === null);
} else {
TKUnit.waitUntilReady(() => frame.currentPage.isLoaded);
}
TKUnit.waitUntilReady(() => frame._executingEntry === null);
}
2 changes: 1 addition & 1 deletion tns-core-modules/ui/core/view/view-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from ".";

import {
ViewBase, Property, booleanConverter, eachDescendant, EventData, layout,
ViewBase, Property, booleanConverter, EventData, layout,
getEventOrGestureName, traceEnabled, traceWrite, traceCategories,
InheritedProperty, ShowModalOptions
} from "../view-base";
Expand Down
9 changes: 7 additions & 2 deletions tns-core-modules/ui/frame/fragment.transitions.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,11 @@ export function _setAndroidFragmentTransitions(

// Having transition means we have custom animation
if (transition) {
// we do not use Android backstack so setting popEnter / popExit is meaningless (3rd and 4th optional args)
fragmentTransaction.setCustomAnimations(AnimationType.enterFakeResourceId, AnimationType.exitFakeResourceId);
if (fragmentTransaction) {
// 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);
if (currentFragmentNeedsDifferentAnimation) {
setupExitAndPopEnterAnimation(currentEntry, transition);
Expand Down Expand Up @@ -502,6 +505,8 @@ function clearEntry(entry: ExpandedEntry, removeListener: boolean): void {
clearAnimationListener(entry.exitAnimator, listener);
clearAnimationListener(entry.popEnterAnimator, listener);
clearAnimationListener(entry.popExitAnimator, listener);
clearAnimationListener(entry.defaultEnterAnimator, listener);
clearAnimationListener(entry.defaultExitAnimator, listener);
}
}

Expand Down
30 changes: 25 additions & 5 deletions tns-core-modules/ui/frame/frame.android.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Definitions.
import {
AndroidFrame as AndroidFrameDefinition, AndroidActivityCallbacks,
AndroidFragmentCallbacks, BackstackEntry, NavigationTransition
AndroidFragmentCallbacks, BackstackEntry, NavigationTransition, NavigationEntry
} from ".";
import { Page } from "../page";

// Types.
import * as application from "../../application";
import {
FrameBase, goBack, stack, NavigationContext, NavigationType,
FrameBase, goBack, stack, NavigationType,
Observable, View, traceCategories, traceEnabled, traceError, traceWrite
} from "./frame-common";

Expand All @@ -21,7 +21,6 @@ import { profile } from "../../profiling";

// TODO: Remove this and get it from global to decouple builder for angular
import { createViewFromEntry } from "../builder";
import { getModuleName } from "../../utils/utils";

export * from "./frame-common";

Expand All @@ -37,6 +36,7 @@ const INTENT_EXTRA = "com.tns.activity";
const ROOT_VIEW_ID_EXTRA = "com.tns.activity.rootViewId";
const FRAMEID = "_frameId";
const CALLBACKS = "_callbacks";
const HMR_REPLACE_TRANSITION = "fade";

const ownerSymbol = Symbol("_owner");
const activityRootViewsMap = new Map<number, WeakRef<View>>();
Expand Down Expand Up @@ -319,6 +319,18 @@ export class Frame extends FrameBase {
restoreAnimatorState(this._currentEntry, this._cachedAnimatorState);
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 {
Expand Down Expand Up @@ -381,12 +393,20 @@ export class Frame extends FrameBase {
const newFragmentTag = `fragment${fragmentId}[${navDepth}]`;
const newFragment = this.createFragment(newEntry, newFragmentTag);
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)
// On API 21+ transition won't be triggered unless there was at least one
// layout pass so we will wait forever for transitionCompleted handler...
// 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);

Expand Down
13 changes: 8 additions & 5 deletions tns-core-modules/ui/frame/frame.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import { profile } from "../../profiling";

//Types.
import {
FrameBase, View, isCategorySet, layout, NavigationContext,
FrameBase, View, isCategorySet, layout,
NavigationType, traceCategories, traceEnabled, traceWrite
} from "./frame-common";
import { _createIOSAnimatedTransitioning } from "./fragment.transitions";

import { createViewFromEntry } from "../builder";
import * as utils from "../../utils/utils";

export * from "./frame-common";
Expand All @@ -24,6 +23,7 @@ const DELEGATE = "_delegate";
const NAV_DEPTH = "_navDepth";
const TRANSITION = "_transition";
const NON_ANIMATED_TRANSITION = "non-animated";
const HMR_REPLACE_TRANSITION = "fade";

let navDepth = -1;

Expand Down Expand Up @@ -88,13 +88,16 @@ export class Frame extends FrameBase {

let navigationTransition: NavigationTransition;
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);
if (navigationTransition) {
viewController[TRANSITION] = navigationTransition;
}
}
else {
} else {
//https://github.com/NativeScript/NativeScript/issues/1787
viewController[TRANSITION] = { name: NON_ANIMATED_TRANSITION };
}
Expand Down
18 changes: 16 additions & 2 deletions tns-core-modules/ui/page/page.ios.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Definitions.
import { Frame } from "../frame";
import { Frame, BackstackEntry } from "../frame";
import { NavigationType } from "../frame/frame-common";

// Types.
Expand All @@ -15,6 +15,8 @@ export * from "./page-common";

const ENTRY = "_entry";
const DELEGATE = "_delegate";
const TRANSITION = "_transition";
const NON_ANIMATED_TRANSITION = "non-animated";

const majorVersion = iosUtils.MajorVersion;

Expand Down Expand Up @@ -130,7 +132,7 @@ class UIViewControllerImpl extends UIViewController {
const frame = navigationController ? (<any>navigationController).owner : null;
// Skip navigation events if modal page is shown.
if (!owner._presentedViewController && frame) {
const newEntry = this[ENTRY];
const newEntry: BackstackEntry = this[ENTRY];

let isBack: boolean;
let navType = frame.navigationType;
Expand All @@ -146,6 +148,18 @@ class UIViewControllerImpl extends UIViewController {
}

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;

// If page was shown with custom animation - we need to set the navigationController.delegate to the animatedDelegate.
Expand Down

0 comments on commit 0aca087

Please sign in to comment.