mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(hmr): preserve navigation history on applying changes (#7146)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user