feat(hmr): preserve navigation history on applying changes (#7146)

This commit is contained in:
Vasil Chimev
2019-04-23 17:47:29 +03:00
committed by GitHub
parent 4e56c89f7d
commit d35e14ed0f
23 changed files with 414 additions and 168 deletions

View File

@@ -11,6 +11,12 @@ import { profile } from "../../profiling";
import { frameStack, topmost as frameStackTopmost, _pushInFrameStack, _popFromFrameStack, _removeFromFrameStack } from "./frame-stack";
export * from "../core/view";
export enum NavigationType {
back,
forward,
replace
}
function buildEntryFromArgs(arg: any): NavigationEntry {
let entry: NavigationEntry;
if (typeof arg === "string") {
@@ -48,6 +54,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
public _isInFrameStack = false;
public static defaultAnimatedNavigation = true;
public static defaultTransition: NavigationTransition;
public navigationType: NavigationType;
// TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity.
@@ -206,7 +213,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
return this._currentEntry === entry;
}
public setCurrent(entry: BackstackEntry, isBack: boolean): void {
public setCurrent(entry: BackstackEntry, navigationType: NavigationType): void {
const newPage = entry.resolvedPage;
// In case we navigated forward to a page that was in the backstack
// with clearHistory: true
@@ -217,6 +224,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
this._currentEntry = entry;
const isBack = navigationType === NavigationType.back;
if (isBack) {
this._pushInFrameStack();
}
@@ -229,15 +237,18 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
this._executingEntry = null;
}
public _updateBackstack(entry: BackstackEntry, isBack: boolean): void {
public _updateBackstack(entry: BackstackEntry, navigationType: NavigationType): void {
const isBack = navigationType === NavigationType.back;
const isReplace = navigationType === NavigationType.replace;
this.raiseCurrentPageNavigatedEvents(isBack);
const current = this._currentEntry;
// Do nothing for Hot Module Replacement
if (isBack) {
const index = this._backStack.indexOf(entry);
this._backStack.splice(index + 1).forEach(e => this._removeEntry(e));
this._backStack.pop();
} else {
} else if (!isReplace) {
if (entry.entry.clearHistory) {
this._backStack.forEach(e => this._removeEntry(e));
this._backStack.length = 0;
@@ -345,7 +356,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
}
@profile
private performNavigation(navigationContext: NavigationContext) {
public performNavigation(navigationContext: NavigationContext) {
const navContext = navigationContext.entry;
this._executingEntry = navContext;
this._onNavigatingTo(navContext, navigationContext.isBackNavigation);
@@ -563,35 +574,39 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
return result;
}
public _onLivesync(context?: ModuleContext): boolean {
// Execute a navigation if not handled on `View` level
if (!super._onLivesync(context)) {
if (!this._currentEntry || !this._currentEntry.entry) {
public _onLivesync(): boolean {
// Reset activity/window content when:
// + Changes are not handled on View
// + There is no ModuleContext
if (traceEnabled()) {
traceWrite(`${this}._onLivesync()`, traceCategories.Livesync);
}
if (!this._currentEntry || !this._currentEntry.entry) {
return false;
}
const currentEntry = this._currentEntry.entry;
const newEntry: NavigationEntry = {
animated: false,
clearHistory: true,
context: currentEntry.context,
create: currentEntry.create,
moduleName: currentEntry.moduleName,
backstackVisible: currentEntry.backstackVisible
}
// If create returns the same page instance we can't recreate it.
// Instead of navigation set activity content.
// This could happen if current page was set in XML as a Page instance.
if (newEntry.create) {
const page = newEntry.create();
if (page === this.currentPage) {
return false;
}
const currentEntry = this._currentEntry.entry;
const newEntry: NavigationEntry = {
animated: false,
clearHistory: true,
context: currentEntry.context,
create: currentEntry.create,
moduleName: currentEntry.moduleName,
backstackVisible: currentEntry.backstackVisible
}
// If create returns the same page instance we can't recreate it.
// Instead of navigation set activity content.
// This could happen if current page was set in XML as a Page instance.
if (newEntry.create) {
const page = newEntry.create();
if (page === this.currentPage) {
return false;
}
}
this.navigate(newEntry);
}
this.navigate(newEntry);
return true;
}
}