mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Resolved: Cross platform way to clear history #283
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import application = require("application");
|
import application = require("application");
|
||||||
import frameModule = require("ui/frame");
|
|
||||||
import navPageModule = require("../nav-page");
|
import navPageModule = require("../nav-page");
|
||||||
|
|
||||||
import trace = require("trace");
|
import trace = require("trace");
|
||||||
@@ -7,14 +6,13 @@ trace.enable();
|
|||||||
trace.setCategories(trace.categories.concat(
|
trace.setCategories(trace.categories.concat(
|
||||||
trace.categories.NativeLifecycle
|
trace.categories.NativeLifecycle
|
||||||
, trace.categories.Navigation
|
, trace.categories.Navigation
|
||||||
, trace.categories.ViewHierarchy
|
|
||||||
, trace.categories.VisualTreeEvents
|
|
||||||
));
|
));
|
||||||
|
|
||||||
application.onLaunch = function (context) {
|
application.mainEntry = {
|
||||||
var frame = new frameModule.Frame();
|
create: function () {
|
||||||
var pageFactory = function () {
|
|
||||||
return new navPageModule.NavPage(0);
|
return new navPageModule.NavPage(0);
|
||||||
};
|
|
||||||
frame.navigate(pageFactory);
|
|
||||||
}
|
}
|
||||||
|
//backstackVisible: false,
|
||||||
|
//clearHistory: true
|
||||||
|
};
|
||||||
|
application.start();
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ import labelModule = require("ui/label");
|
|||||||
import buttonModule = require("ui/button");
|
import buttonModule = require("ui/button");
|
||||||
import textFieldModule = require("ui/text-field");
|
import textFieldModule = require("ui/text-field");
|
||||||
import enums = require("ui/enums");
|
import enums = require("ui/enums");
|
||||||
|
import switchModule = require("ui/switch");
|
||||||
|
|
||||||
export class NavPage extends pagesModule.Page implements definition.ControlsPage {
|
export class NavPage extends pagesModule.Page implements definition.ControlsPage {
|
||||||
constructor(id: number) {
|
constructor(id: number) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.id = "NavPage " + id;
|
||||||
|
|
||||||
var stackLayout = new stackLayoutModule.StackLayout();
|
var stackLayout = new stackLayoutModule.StackLayout();
|
||||||
stackLayout.orientation = enums.Orientation.vertical;
|
stackLayout.orientation = enums.Orientation.vertical;
|
||||||
|
|
||||||
@@ -21,6 +24,11 @@ export class NavPage extends pagesModule.Page implements definition.ControlsPage
|
|||||||
});
|
});
|
||||||
stackLayout.addChild(goBackButton);
|
stackLayout.addChild(goBackButton);
|
||||||
|
|
||||||
|
this.on(pagesModule.Page.navigatedToEvent, function () {
|
||||||
|
//console.log("Navigated to NavPage " + id + "; backStack.length: " + frameModule.topmost().backStack.length);
|
||||||
|
goBackButton.isEnabled = frameModule.topmost().canGoBack();
|
||||||
|
});
|
||||||
|
|
||||||
var stateLabel = new labelModule.Label();
|
var stateLabel = new labelModule.Label();
|
||||||
stateLabel.text = "NavPage " + id;
|
stateLabel.text = "NavPage " + id;
|
||||||
stackLayout.addChild(stateLabel);
|
stackLayout.addChild(stateLabel);
|
||||||
@@ -39,13 +47,37 @@ export class NavPage extends pagesModule.Page implements definition.ControlsPage
|
|||||||
});
|
});
|
||||||
stackLayout.addChild(changeStateButton);
|
stackLayout.addChild(changeStateButton);
|
||||||
|
|
||||||
|
var optionsLayout = new stackLayoutModule.StackLayout();
|
||||||
|
|
||||||
|
var addToBackStackLabel = new labelModule.Label();
|
||||||
|
addToBackStackLabel.text = "backStackVisible";
|
||||||
|
optionsLayout.addChild(addToBackStackLabel);
|
||||||
|
|
||||||
|
var addToBackStackSwitch = new switchModule.Switch();
|
||||||
|
addToBackStackSwitch.checked = true;
|
||||||
|
optionsLayout.addChild(addToBackStackSwitch);
|
||||||
|
|
||||||
|
var clearHistoryLabel = new labelModule.Label();
|
||||||
|
clearHistoryLabel.text = "clearHistory";
|
||||||
|
optionsLayout.addChild(clearHistoryLabel);
|
||||||
|
|
||||||
|
var clearHistorySwitch = new switchModule.Switch();
|
||||||
|
clearHistorySwitch.checked = false;
|
||||||
|
optionsLayout.addChild(clearHistorySwitch);
|
||||||
|
|
||||||
|
stackLayout.addChild(optionsLayout);
|
||||||
|
|
||||||
var forwardButton = new buttonModule.Button();
|
var forwardButton = new buttonModule.Button();
|
||||||
forwardButton.text = "->";
|
forwardButton.text = "->";
|
||||||
forwardButton.on(buttonModule.Button.tapEvent, function () {
|
forwardButton.on(buttonModule.Button.tapEvent, function () {
|
||||||
var pageFactory = function () {
|
var pageFactory = function () {
|
||||||
return new NavPage(id + 1);
|
return new NavPage(id + 1);
|
||||||
};
|
};
|
||||||
frameModule.topmost().navigate(pageFactory);
|
frameModule.topmost().navigate({
|
||||||
|
create: pageFactory,
|
||||||
|
backstackVisible: addToBackStackSwitch.checked,
|
||||||
|
clearHistory: clearHistorySwitch.checked
|
||||||
|
});
|
||||||
});
|
});
|
||||||
stackLayout.addChild(forwardButton);
|
stackLayout.addChild(forwardButton);
|
||||||
|
|
||||||
|
|||||||
@@ -30,3 +30,36 @@ export var test_backstackVisible = function() {
|
|||||||
frame.topmost().goBack();
|
frame.topmost().goBack();
|
||||||
TKUnit.waitUntilReady(() => { return frame.topmost().currentPage === mainTestPage; });
|
TKUnit.waitUntilReady(() => { return frame.topmost().currentPage === mainTestPage; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clearing the history messes up the tests app.
|
||||||
|
//export var test_ClearHistory = function () {
|
||||||
|
// var pageFactory = function (): pageModule.Page {
|
||||||
|
// return new pageModule.Page();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// var mainTestPage = frame.topmost().currentPage;
|
||||||
|
// var currentPage: pageModule.Page;
|
||||||
|
|
||||||
|
// currentPage = frame.topmost().currentPage;
|
||||||
|
// frame.topmost().navigate({ create: pageFactory });
|
||||||
|
// TKUnit.waitUntilReady(() => { return frame.topmost().currentPage !== currentPage; });
|
||||||
|
|
||||||
|
// currentPage = frame.topmost().currentPage;
|
||||||
|
// frame.topmost().navigate({ create: pageFactory });
|
||||||
|
// TKUnit.waitUntilReady(() => { return frame.topmost().currentPage !== currentPage; });
|
||||||
|
|
||||||
|
// currentPage = frame.topmost().currentPage;
|
||||||
|
// frame.topmost().navigate({ create: pageFactory });
|
||||||
|
// TKUnit.waitUntilReady(() => { return frame.topmost().currentPage !== currentPage; });
|
||||||
|
|
||||||
|
// TKUnit.assert(frame.topmost().canGoBack(), "Frame should be able to go back.");
|
||||||
|
// TKUnit.assert(frame.topmost().backStack.length === 3, "Back stack should have 3 entries.");
|
||||||
|
|
||||||
|
// // Navigate with clear history.
|
||||||
|
// currentPage = frame.topmost().currentPage;
|
||||||
|
// frame.topmost().navigate({ create: pageFactory, clearHistory: true });
|
||||||
|
// TKUnit.waitUntilReady(() => { return frame.topmost().currentPage !== currentPage; });
|
||||||
|
|
||||||
|
// TKUnit.assert(!frame.topmost().canGoBack(), "Frame should NOT be able to go back.");
|
||||||
|
// TKUnit.assert(frame.topmost().backStack.length === 0, "Back stack should have 0 entries.");
|
||||||
|
//}
|
||||||
@@ -184,7 +184,8 @@ export class Frame extends view.CustomLayoutView implements definition.Frame {
|
|||||||
var entry = this._navigationQueue[0].entry;
|
var entry = this._navigationQueue[0].entry;
|
||||||
var currentNavigationPage = entry.resolvedPage;
|
var currentNavigationPage = entry.resolvedPage;
|
||||||
if (page !== currentNavigationPage) {
|
if (page !== currentNavigationPage) {
|
||||||
throw new Error("Corrupted navigation stack.");
|
console.trace();
|
||||||
|
throw new Error(`Corrupted navigation stack; page: ${page.id}; currentNavigationPage: ${currentNavigationPage.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove completed operation.
|
// remove completed operation.
|
||||||
@@ -224,7 +225,10 @@ export class Frame extends view.CustomLayoutView implements definition.Frame {
|
|||||||
var navContext = navigationContext.entry;
|
var navContext = navigationContext.entry;
|
||||||
this._onNavigatingTo(navContext);
|
this._onNavigatingTo(navContext);
|
||||||
|
|
||||||
if (this._isEntryBackstackVisible(this._currentEntry)) {
|
if (navigationContext.entry.entry.clearHistory) {
|
||||||
|
this._backStack.length = 0;
|
||||||
|
}
|
||||||
|
else if (this._isEntryBackstackVisible(this._currentEntry)) {
|
||||||
this._backStack.push(this._currentEntry);
|
this._backStack.push(this._currentEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ var INTENT_EXTRA = "com.tns.activity";
|
|||||||
var ANDROID_FRAME = "android_frame";
|
var ANDROID_FRAME = "android_frame";
|
||||||
var BACKSTACK_TAG = "_backstackTag";
|
var BACKSTACK_TAG = "_backstackTag";
|
||||||
var NAV_DEPTH = "_navDepth";
|
var NAV_DEPTH = "_navDepth";
|
||||||
|
var CLEARING_HISTORY = "_clearingHistory";
|
||||||
|
|
||||||
var navDepth = -1;
|
var navDepth = -1;
|
||||||
|
|
||||||
@@ -32,17 +33,23 @@ class PageFragmentBody extends android.app.Fragment {
|
|||||||
|
|
||||||
onAttach(activity: android.app.Activity) {
|
onAttach(activity: android.app.Activity) {
|
||||||
super.onAttach(activity);
|
super.onAttach(activity);
|
||||||
trace.write(this.getTag() + ".onAttach();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onAttach();", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreate(savedInstanceState: android.os.Bundle) {
|
onCreate(savedInstanceState: android.os.Bundle) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
trace.write(this.getTag() + ".onCreate(); savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onCreate(); savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
||||||
super.setHasOptionsMenu(true);
|
super.setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
|
onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View {
|
||||||
trace.write(this.getTag() + ".onCreateView(); container: " + container + "; savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onCreateView(); container: " + container + "; savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
||||||
|
|
||||||
|
if (this[CLEARING_HISTORY]) {
|
||||||
|
trace.write(`${this.toString() } wants to create a view, but we are currently clearing history. Returning null.`, trace.categories.NativeLifecycle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var entry: definition.BackstackEntry = this.entry;
|
var entry: definition.BackstackEntry = this.entry;
|
||||||
var page: pages.Page = entry.resolvedPage;
|
var page: pages.Page = entry.resolvedPage;
|
||||||
|
|
||||||
@@ -58,13 +65,13 @@ class PageFragmentBody extends android.app.Fragment {
|
|||||||
onFragmentShown(this);
|
onFragmentShown(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.write(this.getTag() + ".onCreateView(); nativeView: " + page._nativeView, trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onCreateView(); nativeView: " + page._nativeView, trace.categories.NativeLifecycle);
|
||||||
return page._nativeView;
|
return page._nativeView;
|
||||||
}
|
}
|
||||||
|
|
||||||
onHiddenChanged(hidden: boolean) {
|
onHiddenChanged(hidden: boolean) {
|
||||||
super.onHiddenChanged(hidden);
|
super.onHiddenChanged(hidden);
|
||||||
trace.write(this.getTag() + ".onHiddenChanged(); hidden: " + hidden, trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onHiddenChanged(); hidden: " + hidden, trace.categories.NativeLifecycle);
|
||||||
|
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
onFragmentHidden(this);
|
onFragmentHidden(this);
|
||||||
@@ -76,12 +83,12 @@ class PageFragmentBody extends android.app.Fragment {
|
|||||||
|
|
||||||
onActivityCreated(savedInstanceState: android.os.Bundle) {
|
onActivityCreated(savedInstanceState: android.os.Bundle) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
trace.write(this.getTag() + ".onActivityCreated(); savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onActivityCreated(); savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSaveInstanceState(outState: android.os.Bundle) {
|
onSaveInstanceState(outState: android.os.Bundle) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
trace.write(this.getTag() + ".onSaveInstanceState();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onSaveInstanceState();", trace.categories.NativeLifecycle);
|
||||||
|
|
||||||
if (this.isHidden()) {
|
if (this.isHidden()) {
|
||||||
outState.putBoolean(HIDDEN, true);
|
outState.putBoolean(HIDDEN, true);
|
||||||
@@ -90,39 +97,39 @@ class PageFragmentBody extends android.app.Fragment {
|
|||||||
|
|
||||||
onViewStateRestored(savedInstanceState: android.os.Bundle) {
|
onViewStateRestored(savedInstanceState: android.os.Bundle) {
|
||||||
super.onViewStateRestored(savedInstanceState);
|
super.onViewStateRestored(savedInstanceState);
|
||||||
trace.write(this.getTag() + ".onViewStateRestored(); savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onViewStateRestored(); savedInstanceState: " + savedInstanceState, trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onStart() {
|
onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
trace.write(this.getTag() + ".onStart();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onStart();", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onResume() {
|
onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
trace.write(this.getTag() + ".onResume();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onResume();", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPause() {
|
onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
trace.write(this.getTag() + ".onPause();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onPause();", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onStop() {
|
onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
trace.write(this.getTag() + ".onStop();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onStop();", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroyView() {
|
onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
trace.write(this.getTag() + ".onDestroyView();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onDestroyView();", trace.categories.NativeLifecycle);
|
||||||
|
|
||||||
onFragmentHidden(this);
|
onFragmentHidden(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy() {
|
onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
trace.write(this.getTag() + ".onDestroy();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onDestroy();", trace.categories.NativeLifecycle);
|
||||||
|
|
||||||
// Explicitly free resources to allow Java Garbage collector to release resources associated with JavaScript implementations - e.g. large image files.
|
// Explicitly free resources to allow Java Garbage collector to release resources associated with JavaScript implementations - e.g. large image files.
|
||||||
// Although we hint the V8 with the externally allocated memory, synchronization between the two GCs is not deterministic without an explicit call.
|
// Although we hint the V8 with the externally allocated memory, synchronization between the two GCs is not deterministic without an explicit call.
|
||||||
@@ -132,11 +139,20 @@ class PageFragmentBody extends android.app.Fragment {
|
|||||||
|
|
||||||
onDetach() {
|
onDetach() {
|
||||||
super.onDetach();
|
super.onDetach();
|
||||||
trace.write(this.getTag() + ".onDetach();", trace.categories.NativeLifecycle);
|
trace.write(this.toString() + ".onDetach();", trace.categories.NativeLifecycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toString() {
|
||||||
|
return `${this.getTag() }[${this.entry.resolvedPage.id}]`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFragmentShown(fragment: PageFragmentBody) {
|
function onFragmentShown(fragment: PageFragmentBody) {
|
||||||
|
if (fragment[CLEARING_HISTORY]) {
|
||||||
|
trace.write(`${fragment.toString() } has been shown, but we are currently clearing history. Returning.`, trace.categories.NativeLifecycle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: consider putting entry and page in queue so we can safely extract them here. Pass the index of current navigation and extract it from here.
|
// TODO: consider putting entry and page in queue so we can safely extract them here. Pass the index of current navigation and extract it from here.
|
||||||
// After extracting navigation info - remove this index from navigation stack.
|
// After extracting navigation info - remove this index from navigation stack.
|
||||||
var frame = fragment.frame;
|
var frame = fragment.frame;
|
||||||
@@ -152,6 +168,11 @@ function onFragmentShown(fragment: PageFragmentBody) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onFragmentHidden(fragment: PageFragmentBody) {
|
function onFragmentHidden(fragment: PageFragmentBody) {
|
||||||
|
if (fragment[CLEARING_HISTORY]) {
|
||||||
|
trace.write(`${fragment.toString() } has been hidden, but we are currently clearing history. Returning.`, trace.categories.NativeLifecycle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var entry: definition.BackstackEntry = fragment.entry;
|
var entry: definition.BackstackEntry = fragment.entry;
|
||||||
var page: pages.Page = entry.resolvedPage;
|
var page: pages.Page = entry.resolvedPage;
|
||||||
// This might be a second call if the fragment is hidden and then destroyed.
|
// This might be a second call if the fragment is hidden and then destroyed.
|
||||||
@@ -193,6 +214,11 @@ export class Frame extends frameCommon.Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public _navigateCore(backstackEntry: definition.BackstackEntry) {
|
public _navigateCore(backstackEntry: definition.BackstackEntry) {
|
||||||
|
trace.write(`_navigateCore; id: ${backstackEntry.resolvedPage.id}; backstackVisible: ${this._isEntryBackstackVisible(backstackEntry)}; clearHistory: ${backstackEntry.entry.clearHistory};`, trace.categories.Navigation);
|
||||||
|
|
||||||
|
//this._printFrameBackStack();
|
||||||
|
//this._printNativeBackStack();
|
||||||
|
|
||||||
var activity = this._android.activity;
|
var activity = this._android.activity;
|
||||||
if (!activity) {
|
if (!activity) {
|
||||||
// We do not have an Activity yet associated. In this case we have two execution paths:
|
// We do not have an Activity yet associated. In this case we have two execution paths:
|
||||||
@@ -207,9 +233,36 @@ export class Frame extends frameCommon.Frame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var manager = activity.getFragmentManager();
|
||||||
|
|
||||||
|
// Clear history
|
||||||
|
if (backstackEntry.entry.clearHistory && !this._isFirstNavigation) {
|
||||||
|
var i = manager.getBackStackEntryCount() - 1;
|
||||||
|
var fragment: android.app.Fragment;
|
||||||
|
while (i >= 0) {
|
||||||
|
fragment = manager.findFragmentByTag(manager.getBackStackEntryAt(i--).getName());
|
||||||
|
trace.write(`${fragment.toString()}[CLEARING_HISTORY] = true;`, trace.categories.NativeLifecycle);
|
||||||
|
fragment[CLEARING_HISTORY] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember that the current fragment has never been added to the backStack, so mark it as well.
|
||||||
|
if (this.currentPage) {
|
||||||
|
fragment = manager.findFragmentByTag(this.currentPage[TAG]);
|
||||||
|
if (fragment) {
|
||||||
|
fragment[CLEARING_HISTORY] = true;
|
||||||
|
trace.write(`${fragment.toString() }[CLEARING_HISTORY] = true;`, trace.categories.NativeLifecycle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstEntryName = manager.getBackStackEntryAt(0).getName();
|
||||||
|
trace.write(`manager.popBackStack(${firstEntryName}, android.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);`, trace.categories.NativeLifecycle);
|
||||||
|
manager.popBackStack(firstEntryName, android.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||||
|
this._currentEntry = null;
|
||||||
|
navDepth = -1;
|
||||||
|
}
|
||||||
|
|
||||||
navDepth++;
|
navDepth++;
|
||||||
|
|
||||||
var manager = activity.getFragmentManager();
|
|
||||||
var fragmentTransaction = manager.beginTransaction();
|
var fragmentTransaction = manager.beginTransaction();
|
||||||
|
|
||||||
var newFragmentTag = "fragment" + navDepth;
|
var newFragmentTag = "fragment" + navDepth;
|
||||||
@@ -227,7 +280,7 @@ export class Frame extends frameCommon.Frame {
|
|||||||
trace.write("fragmentTransaction.add(" + this.containerViewId + ", " + newFragment + ", " + newFragmentTag + ");", trace.categories.NativeLifecycle);
|
trace.write("fragmentTransaction.add(" + this.containerViewId + ", " + newFragment + ", " + newFragmentTag + ");", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (this.android.cachePagesOnNavigate) {
|
if (this.android.cachePagesOnNavigate && !backstackEntry.entry.clearHistory) {
|
||||||
var currentFragmentTag = this.currentPage[TAG];
|
var currentFragmentTag = this.currentPage[TAG];
|
||||||
var currentFragment = manager.findFragmentByTag(currentFragmentTag);
|
var currentFragment = manager.findFragmentByTag(currentFragmentTag);
|
||||||
if (currentFragment) {
|
if (currentFragment) {
|
||||||
@@ -246,7 +299,10 @@ export class Frame extends frameCommon.Frame {
|
|||||||
trace.write("fragmentTransaction.replace(" + this.containerViewId + ", " + newFragment + ", " + newFragmentTag + ");", trace.categories.NativeLifecycle);
|
trace.write("fragmentTransaction.replace(" + this.containerViewId + ", " + newFragment + ", " + newFragmentTag + ");", trace.categories.NativeLifecycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.backStack.length > 0) {
|
// Add to backStack if needed.
|
||||||
|
if (this.backStack.length > 0 &&
|
||||||
|
this._currentEntry &&
|
||||||
|
this._isEntryBackstackVisible(this._currentEntry)) {
|
||||||
// We add each entry in the backstack to avoid the "Stack corrupted" mismatch
|
// We add each entry in the backstack to avoid the "Stack corrupted" mismatch
|
||||||
var backstackTag = this._currentEntry[BACKSTACK_TAG];
|
var backstackTag = this._currentEntry[BACKSTACK_TAG];
|
||||||
fragmentTransaction.addToBackStack(backstackTag);
|
fragmentTransaction.addToBackStack(backstackTag);
|
||||||
@@ -271,6 +327,11 @@ export class Frame extends frameCommon.Frame {
|
|||||||
|
|
||||||
fragmentTransaction.commit();
|
fragmentTransaction.commit();
|
||||||
trace.write("fragmentTransaction.commit();", trace.categories.NativeLifecycle);
|
trace.write("fragmentTransaction.commit();", trace.categories.NativeLifecycle);
|
||||||
|
|
||||||
|
//setTimeout(() => {
|
||||||
|
// this._printFrameBackStack();
|
||||||
|
// this._printNativeBackStack();
|
||||||
|
//}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public _goBackCore(backstackEntry: definition.BackstackEntry) {
|
public _goBackCore(backstackEntry: definition.BackstackEntry) {
|
||||||
@@ -323,6 +384,32 @@ export class Frame extends frameCommon.Frame {
|
|||||||
public _clearAndroidReference() {
|
public _clearAndroidReference() {
|
||||||
// we should keep the reference to underlying native object, since frame can contain many pages.
|
// we should keep the reference to underlying native object, since frame can contain many pages.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public _printNativeBackStack() {
|
||||||
|
if (!this._android.activity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var manager = this._android.activity.getFragmentManager();
|
||||||
|
var length = manager.getBackStackEntryCount();
|
||||||
|
var i = length - 1;
|
||||||
|
console.log("---------------------------");
|
||||||
|
console.log("Fragment Manager Back Stack (" + length + ")");
|
||||||
|
while (i >= 0) {
|
||||||
|
var fragment = <PageFragmentBody>manager.findFragmentByTag(manager.getBackStackEntryAt(i--).getName());
|
||||||
|
console.log("[ " + fragment.toString() + " ]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public _printFrameBackStack() {
|
||||||
|
var length = this.backStack.length;
|
||||||
|
var i = length - 1;
|
||||||
|
console.log("---------------------------");
|
||||||
|
console.log("Frame Back Stack (" + length + ")");
|
||||||
|
while (i >= 0) {
|
||||||
|
var backstackEntry = <definition.BackstackEntry>this.backStack[i--];
|
||||||
|
console.log("[ " + backstackEntry.resolvedPage.id + " ]");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var NativeActivity = {
|
var NativeActivity = {
|
||||||
|
|||||||
5
ui/frame/frame.d.ts
vendored
5
ui/frame/frame.d.ts
vendored
@@ -151,6 +151,11 @@ declare module "ui/frame" {
|
|||||||
* If the parameter is set to false then the Page will be displayed but once navigated from it will not be able to be navigated back to.
|
* If the parameter is set to false then the Page will be displayed but once navigated from it will not be able to be navigated back to.
|
||||||
*/
|
*/
|
||||||
backstackVisible?: boolean;
|
backstackVisible?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True to clear the navigation history, false otherwise. Very useful when navigating away from login pages.
|
||||||
|
*/
|
||||||
|
clearHistory?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export class Frame extends frameCommon.Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public _navigateCore(backstackEntry: definition.BackstackEntry) {
|
public _navigateCore(backstackEntry: definition.BackstackEntry) {
|
||||||
var viewController = backstackEntry.resolvedPage.ios;
|
var viewController: UIViewController = backstackEntry.resolvedPage.ios;
|
||||||
if (!viewController) {
|
if (!viewController) {
|
||||||
throw new Error("Required page does have an viewController created.");
|
throw new Error("Required page does have an viewController created.");
|
||||||
}
|
}
|
||||||
@@ -63,30 +63,48 @@ export class Frame extends frameCommon.Frame {
|
|||||||
|
|
||||||
this._updateActionBar(backstackEntry.resolvedPage);
|
this._updateActionBar(backstackEntry.resolvedPage);
|
||||||
|
|
||||||
if (this._currentEntry && !this._isEntryBackstackVisible(this._currentEntry)) {
|
// First navigation.
|
||||||
|
if (!this._currentEntry) {
|
||||||
|
this._ios.controller.pushViewControllerAnimated(viewController, animated);
|
||||||
|
trace.write("Frame<" + this._domId + ">.pushViewControllerAnimated(newController) depth = " + navDepth, trace.categories.Navigation);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should clear the entire history.
|
||||||
|
if (backstackEntry.entry.clearHistory) {
|
||||||
|
viewController.navigationItem.hidesBackButton = true;
|
||||||
|
var newControllers = NSMutableArray.alloc().initWithCapacity(1);
|
||||||
|
newControllers.addObject(viewController);
|
||||||
|
this._ios.controller.setViewControllersAnimated(newControllers, animated);
|
||||||
|
trace.write("Frame<" + this._domId + ">.setViewControllersAnimated([newController]) depth = " + navDepth, trace.categories.Navigation);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should hide the current entry from the back stack.
|
||||||
|
if (!this._isEntryBackstackVisible(this._currentEntry)) {
|
||||||
var newControllers = NSMutableArray.alloc().initWithArray(this._ios.controller.viewControllers);
|
var newControllers = NSMutableArray.alloc().initWithArray(this._ios.controller.viewControllers);
|
||||||
if (newControllers.count === 0) {
|
if (newControllers.count === 0) {
|
||||||
throw new Error("Wrong controllers count.");
|
throw new Error("Wrong controllers count.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var newController: UIViewController = backstackEntry.resolvedPage.ios;
|
|
||||||
|
|
||||||
// the code below fixes a phantom animation that appears on the Back button in this case
|
// the code below fixes a phantom animation that appears on the Back button in this case
|
||||||
// TODO: investigate why the animation happens at first place before working around it
|
// TODO: investigate why the animation happens at first place before working around it
|
||||||
newController.navigationItem.hidesBackButton = this.backStack.length === 0;
|
viewController.navigationItem.hidesBackButton = this.backStack.length === 0;
|
||||||
|
|
||||||
// swap the top entry with the new one
|
// swap the top entry with the new one
|
||||||
newControllers.removeLastObject();
|
newControllers.removeLastObject();
|
||||||
newControllers.addObject(newController);
|
newControllers.addObject(viewController);
|
||||||
|
|
||||||
// replace the controllers instead of pushing directly
|
// replace the controllers instead of pushing directly
|
||||||
this._ios.controller.setViewControllersAnimated(newControllers, animated);
|
this._ios.controller.setViewControllersAnimated(newControllers, animated);
|
||||||
}
|
trace.write("Frame<" + this._domId + ">.setViewControllersAnimated([originalControllers - lastController + newController]) depth = " + navDepth, trace.categories.Navigation);
|
||||||
else {
|
return;
|
||||||
this._ios.controller.pushViewControllerAnimated(viewController, animated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.write("Frame<" + this._domId + ">.pushViewControllerAnimated depth = " + navDepth, trace.categories.Navigation);
|
// General case.
|
||||||
|
this._ios.controller.pushViewControllerAnimated(viewController, animated);
|
||||||
|
trace.write("Frame<" + this._domId + ">.pushViewControllerAnimated(newController) depth = " + navDepth, trace.categories.Navigation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public _goBackCore(backstackEntry: definition.BackstackEntry) {
|
public _goBackCore(backstackEntry: definition.BackstackEntry) {
|
||||||
|
|||||||
Reference in New Issue
Block a user