UNPKG

tns-core-modules

Version:

Telerik NativeScript Core Modules

688 lines (687 loc) • 28.8 kB
var frameCommon = require("./frame-common"); var pages = require("ui/page"); var transitionModule = require("ui/transition"); var trace = require("trace"); var observable_1 = require("data/observable"); var application = require("application"); var types = require("utils/types"); var utils = require("utils/utils"); global.moduleMerge(frameCommon, exports); var TAG = "_fragmentTag"; var HIDDEN = "_hidden"; var INTENT_EXTRA = "com.tns.activity"; var BACKSTACK_TAG = "_backstackTag"; var IS_BACK = "_isBack"; var NAV_DEPTH = "_navDepth"; var CLEARING_HISTORY = "_clearingHistory"; var FRAMEID = "_frameId"; var navDepth = -1; var activityInitialized = false; function onFragmentShown(fragment) { trace.write("SHOWN " + fragment.getTag(), trace.categories.NativeLifecycle); if (fragment[CLEARING_HISTORY]) { trace.write(fragment.getTag() + " has been shown, but we are currently clearing history. Returning.", trace.categories.NativeLifecycle); return null; } var frame = fragment.frame; var entry = fragment.entry; var page = entry.resolvedPage; var currentNavigationContext; var navigationQueue = frame._navigationQueue; for (var i = 0; i < navigationQueue.length; i++) { if (navigationQueue[i].entry === entry) { currentNavigationContext = navigationQueue[i]; break; } } var isBack = currentNavigationContext ? currentNavigationContext.isBackNavigation : false; frame._addView(page); if (!frame.isLoaded) { frame._currentEntry = entry; frame.onLoaded(); } transitionModule._onFragmentShown(fragment, isBack); } function onFragmentHidden(fragment) { trace.write("HIDDEN " + fragment.getTag(), trace.categories.NativeLifecycle); if (fragment[CLEARING_HISTORY]) { trace.write(fragment.getTag() + " has been hidden, but we are currently clearing history. Returning.", trace.categories.NativeLifecycle); return null; } var isBack = fragment.entry[IS_BACK]; fragment.entry[IS_BACK] = undefined; transitionModule._onFragmentHidden(fragment, isBack); } var Frame = (function (_super) { __extends(Frame, _super); function Frame() { _super.call(this); this._containerViewId = -1; this._android = new AndroidFrame(this); this._listener = new android.view.View.OnAttachStateChangeListener({ onViewAttachedToWindow: this.onNativeViewAttachedToWindow.bind(this), onViewDetachedFromWindow: this.onNativeViewDetachedToWindow.bind(this) }); } Object.defineProperty(Frame, "defaultAnimatedNavigation", { get: function () { return frameCommon.Frame.defaultAnimatedNavigation; }, set: function (value) { frameCommon.Frame.defaultAnimatedNavigation = value; }, enumerable: true, configurable: true }); Object.defineProperty(Frame, "defaultTransition", { get: function () { return frameCommon.Frame.defaultTransition; }, set: function (value) { frameCommon.Frame.defaultTransition = value; }, enumerable: true, configurable: true }); Object.defineProperty(Frame.prototype, "containerViewId", { get: function () { return this._containerViewId; }, enumerable: true, configurable: true }); Object.defineProperty(Frame.prototype, "android", { get: function () { return this._android; }, enumerable: true, configurable: true }); Object.defineProperty(Frame.prototype, "_nativeView", { get: function () { return this._android.rootViewGroup; }, enumerable: true, configurable: true }); Frame.prototype._navigateCore = function (backstackEntry) { trace.write(this + "._navigateCore(page: " + backstackEntry.resolvedPage + ", backstackVisible: " + this._isEntryBackstackVisible(backstackEntry) + ", clearHistory: " + backstackEntry.entry.clearHistory + "), navDepth: " + navDepth, trace.categories.Navigation); var activity = this._android.activity; if (!activity) { var currentActivity = this._android.currentActivity; if (currentActivity) { startActivity(currentActivity, this._android.frameId); } this._delayedNavigationEntry = backstackEntry; return; } var manager = activity.getFragmentManager(); var isFirstNavigation = types.isNullOrUndefined(this._currentEntry); if (backstackEntry.entry.clearHistory) { var backStackEntryCount = manager.getBackStackEntryCount(); var i = backStackEntryCount - 1; var fragment = void 0; while (i >= 0) { fragment = manager.findFragmentByTag(manager.getBackStackEntryAt(i--).getName()); trace.write(fragment.getTag() + "[CLEARING_HISTORY] = true;", trace.categories.NativeLifecycle); fragment[CLEARING_HISTORY] = true; } if (this.currentPage) { fragment = manager.findFragmentByTag(this.currentPage[TAG]); if (fragment) { fragment[CLEARING_HISTORY] = true; trace.write(fragment.getTag() + "[CLEARING_HISTORY] = true;", trace.categories.NativeLifecycle); } } if (backStackEntryCount) { 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++; var fragmentTransaction = manager.beginTransaction(); var currentFragmentTag; var currentFragment; if (this.currentPage) { currentFragmentTag = this.currentPage[TAG]; currentFragment = manager.findFragmentByTag(currentFragmentTag); } var newFragmentTag = "fragment" + navDepth; var newFragment = new FragmentClass(); var args = new android.os.Bundle(); args.putInt(FRAMEID, this._android.frameId); newFragment.setArguments(args); var animated = this._getIsAnimatedNavigation(backstackEntry.entry); var navigationTransition = this._getNavigationTransition(backstackEntry.entry); if (currentFragment) { transitionModule._clearForwardTransitions(currentFragment); } if (animated && navigationTransition) { transitionModule._setAndroidFragmentTransitions(navigationTransition, currentFragment, newFragment, fragmentTransaction); } newFragment.frame = this; newFragment.entry = backstackEntry; backstackEntry[BACKSTACK_TAG] = newFragmentTag; backstackEntry[NAV_DEPTH] = navDepth; backstackEntry.resolvedPage[TAG] = newFragmentTag; if (isFirstNavigation) { fragmentTransaction.add(this.containerViewId, newFragment, newFragmentTag); trace.write("fragmentTransaction.add(" + newFragmentTag + ");", trace.categories.NativeLifecycle); } else { if (this.android.cachePagesOnNavigate && !backstackEntry.entry.clearHistory) { if (currentFragment) { fragmentTransaction.hide(currentFragment); trace.write("fragmentTransaction.hide(" + currentFragmentTag + ");", trace.categories.NativeLifecycle); } else { trace.write("Could not find " + currentFragmentTag + " to hide.", trace.categories.NativeLifecycle); } fragmentTransaction.add(this.containerViewId, newFragment, newFragmentTag); trace.write("fragmentTransaction.add(" + newFragmentTag + ");", trace.categories.NativeLifecycle); } else { fragmentTransaction.replace(this.containerViewId, newFragment, newFragmentTag); trace.write("fragmentTransaction.replace(" + newFragmentTag + ");", trace.categories.NativeLifecycle); } if (this.backStack.length > 0 && this._currentEntry) { var backstackTag = this._currentEntry[BACKSTACK_TAG]; fragmentTransaction.addToBackStack(backstackTag); trace.write("fragmentTransaction.addToBackStack(" + backstackTag + ");", trace.categories.NativeLifecycle); } } if (!isFirstNavigation) { ensureAnimationFixed(); if (this.android.cachePagesOnNavigate && animationFixed < 0) { fragmentTransaction.setTransition(android.app.FragmentTransaction.TRANSIT_NONE); } else { var transit = animated ? android.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN : android.app.FragmentTransaction.TRANSIT_NONE; fragmentTransaction.setTransition(transit); } } fragmentTransaction.commit(); trace.write("fragmentTransaction.commit();", trace.categories.NativeLifecycle); }; Frame.prototype._goBackCore = function (backstackEntry) { navDepth = backstackEntry[NAV_DEPTH]; if (this._currentEntry) { this._currentEntry[IS_BACK] = true; } trace.write(this + "._goBackCore(pageId: " + backstackEntry.resolvedPage.id + ", backstackVisible: " + this._isEntryBackstackVisible(backstackEntry) + ", clearHistory: " + backstackEntry.entry.clearHistory + "), navDepth: " + navDepth, trace.categories.Navigation); var manager = this._android.activity.getFragmentManager(); if (manager.getBackStackEntryCount() > 0) { manager.popBackStack(backstackEntry[BACKSTACK_TAG], android.app.FragmentManager.POP_BACK_STACK_INCLUSIVE); } }; Frame.prototype._createUI = function () { var root = new org.nativescript.widgets.ContentLayout(this._context); if (this._containerViewId < 0) { this._containerViewId = android.view.View.generateViewId(); } this._android.rootViewGroup = root; this._android.rootViewGroup.setId(this._containerViewId); this._android.rootViewGroup.addOnAttachStateChangeListener(this._listener); }; Frame.prototype.onNativeViewAttachedToWindow = function (view) { if (this._delayedNavigationEntry) { this._navigateCore(this._delayedNavigationEntry); this._delayedNavigationEntry = undefined; } }; Frame.prototype.onNativeViewDetachedToWindow = function (view) { }; Frame.prototype._popFromFrameStack = function () { if (!this._isInFrameStack) { return; } _super.prototype._popFromFrameStack.call(this); if (this._android.hasOwnActivity) { this._android.activity.finish(); } }; Frame.prototype._clearAndroidReference = function () { this._android.rootViewGroup.removeOnAttachStateChangeListener(this._listener); this._android.rootViewGroup = null; }; Frame.prototype._printNativeBackStack = function () { 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 = manager.findFragmentByTag(manager.getBackStackEntryAt(i--).getName()); console.log("[ " + fragment.getTag() + " ]"); } }; Frame.prototype._printFrameBackStack = function () { var length = this.backStack.length; var i = length - 1; console.log("---------------------------"); console.log("Frame Back Stack (" + length + ")"); while (i >= 0) { var backstackEntry = this.backStack[i--]; console.log("[ " + backstackEntry.resolvedPage.id + " ]"); } }; Frame.prototype._getNavBarVisible = function (page) { if (types.isDefined(page.actionBarHidden)) { return !page.actionBarHidden; } if (this._android && types.isDefined(this._android.showActionBar)) { return this._android.showActionBar; } return true; }; Frame.prototype._processNavigationContext = function (navigationContext) { var _this = this; var activity = this._android.activity; if (activity) { var isForegroundActivity = activity === application.android.foregroundActivity; var isPaused = application.android.paused; if (activity && !isForegroundActivity || (isForegroundActivity && isPaused)) { var weakActivity_1 = new WeakRef(activity); var resume_1 = function (args) { var weakActivityInstance = weakActivity_1.get(); var isCurrent = args.activity === weakActivityInstance; if (!weakActivityInstance) { trace.write("Frame _processNavigationContext: Drop For Activity GC-ed", trace.categories.Navigation); unsubscribe_1(); return; } if (isCurrent) { trace.write("Frame _processNavigationContext: Activity.Resumed, Continue", trace.categories.Navigation); _super.prototype._processNavigationContext.call(_this, navigationContext); unsubscribe_1(); } }; var unsubscribe_1 = function () { trace.write("Frame _processNavigationContext: Unsubscribe from Activity.Resumed", trace.categories.Navigation); application.android.off(application.AndroidApplication.activityResumedEvent, resume_1); application.android.off(application.AndroidApplication.activityStoppedEvent, unsubscribe_1); application.android.off(application.AndroidApplication.activityDestroyedEvent, unsubscribe_1); }; trace.write("Frame._processNavigationContext: Subscribe for Activity.Resumed", trace.categories.Navigation); application.android.on(application.AndroidApplication.activityResumedEvent, resume_1); application.android.on(application.AndroidApplication.activityStoppedEvent, unsubscribe_1); application.android.on(application.AndroidApplication.activityDestroyedEvent, unsubscribe_1); return; } } _super.prototype._processNavigationContext.call(this, navigationContext); }; return Frame; }(frameCommon.Frame)); exports.Frame = Frame; var framesCounter = 0; var framesCache = new Array(); var AndroidFrame = (function (_super) { __extends(AndroidFrame, _super); function AndroidFrame(owner) { _super.call(this); this.hasOwnActivity = false; this._showActionBar = true; this._owner = owner; this.frameId = framesCounter++; framesCache.push(new WeakRef(this)); } Object.defineProperty(AndroidFrame.prototype, "showActionBar", { get: function () { return this._showActionBar; }, set: function (value) { if (this._showActionBar !== value) { this._showActionBar = value; if (this.owner.currentPage) { this.owner.currentPage.actionBar.update(); } } }, enumerable: true, configurable: true }); Object.defineProperty(AndroidFrame.prototype, "activity", { get: function () { var activity = this.owner._context; if (activity) { return activity; } var currView = this._owner.parent; while (currView) { if (currView instanceof Frame) { return currView.android.activity; } currView = currView.parent; } return undefined; }, enumerable: true, configurable: true }); Object.defineProperty(AndroidFrame.prototype, "actionBar", { get: function () { var activity = this.currentActivity; if (!activity) { return undefined; } var bar = activity.getActionBar(); if (!bar) { return undefined; } return bar; }, enumerable: true, configurable: true }); Object.defineProperty(AndroidFrame.prototype, "currentActivity", { get: function () { var activity = this.activity; if (activity) { return activity; } var stack = frameCommon.stack(), length = stack.length, i = length - 1, frame; for (i; i >= 0; i--) { frame = stack[i]; activity = frame.android.activity; if (activity) { return activity; } } return undefined; }, enumerable: true, configurable: true }); Object.defineProperty(AndroidFrame.prototype, "owner", { get: function () { return this._owner; }, enumerable: true, configurable: true }); Object.defineProperty(AndroidFrame.prototype, "cachePagesOnNavigate", { get: function () { return this._cachePagesOnNavigate; }, set: function (value) { if (this._cachePagesOnNavigate !== value) { if (this._owner.backStack.length > 0) { throw new Error("Cannot set cachePagesOnNavigate if there are items in the back stack."); } this._cachePagesOnNavigate = value; } }, enumerable: true, configurable: true }); AndroidFrame.prototype.canGoBack = function () { if (!this.activity) { return false; } return this.activity.getIntent().getAction() !== android.content.Intent.ACTION_MAIN; }; return AndroidFrame; }(observable_1.Observable)); function findPageForFragment(fragment, frame) { var fragmentTag = fragment.getTag(); var page; var entry; trace.write("Finding page for " + fragmentTag + ".", trace.categories.NativeLifecycle); if (fragmentTag === pages.DIALOG_FRAGMENT_TAG) { trace.write("No need to find page for dialog fragment.", trace.categories.NativeLifecycle); return; } if (frame.currentPage && frame.currentPage[TAG] === fragmentTag) { page = frame.currentPage; entry = frame._currentEntry; trace.write("Current page matches fragment " + fragmentTag + ".", trace.categories.NativeLifecycle); } else { var backStack = frame.backStack; for (var i = 0; i < backStack.length; i++) { if (backStack[i].resolvedPage[TAG] === fragmentTag) { entry = backStack[i]; break; } } if (entry) { page = entry.resolvedPage; trace.write("Found " + page + " for " + fragmentTag, trace.categories.NativeLifecycle); } } if (page) { fragment.frame = frame; fragment.entry = entry; page[TAG] = fragmentTag; } else { } } function startActivity(activity, frameId) { var intent = new android.content.Intent(activity, com.tns.NativeScriptActivity.class); intent.setAction(android.content.Intent.ACTION_DEFAULT); intent.putExtra(INTENT_EXTRA, frameId); activity.startActivity(intent); } function getFrameById(frameId) { for (var i = 0; i < framesCache.length; i++) { var aliveFrame = framesCache[i].get(); if (aliveFrame && aliveFrame.frameId === frameId) { return aliveFrame.owner; } } return null; } var animationFixed; function ensureAnimationFixed() { if (!animationFixed) { animationFixed = android.os.Build.VERSION.SDK_INT >= 19 ? 1 : -1; } } var FragmentClass = (function (_super) { __extends(FragmentClass, _super); function FragmentClass() { _super.call(this); return global.__native(this); } FragmentClass.prototype.onHiddenChanged = function (hidden) { trace.write(this.getTag() + ".onHiddenChanged(" + hidden + ")", trace.categories.NativeLifecycle); _super.prototype.onHiddenChanged.call(this, hidden); if (hidden) { onFragmentHidden(this); } else { onFragmentShown(this); } }; FragmentClass.prototype.onCreateAnimator = function (transit, enter, nextAnim) { var animator = transitionModule._onFragmentCreateAnimator(this, nextAnim); if (!animator) { animator = _super.prototype.onCreateAnimator.call(this, transit, enter, nextAnim); } trace.write(this.getTag() + ".onCreateAnimator(" + transit + ", " + enter + ", " + nextAnim + "): " + animator, trace.categories.NativeLifecycle); return animator; }; FragmentClass.prototype.onCreate = function (savedInstanceState) { trace.write(this.getTag() + ".onCreate(" + savedInstanceState + ")", trace.categories.NativeLifecycle); _super.prototype.onCreate.call(this, savedInstanceState); _super.prototype.setHasOptionsMenu.call(this, true); if (!this.entry) { var frameId = this.getArguments().getInt(FRAMEID); var frame = getFrameById(frameId); if (frame) { this.frame = frame; } else { throw new Error("Cannot find Frame for " + this); } findPageForFragment(this, this.frame); } }; FragmentClass.prototype.onCreateView = function (inflater, container, savedInstanceState) { trace.write(this.getTag() + ".onCreateView(inflater, container, " + savedInstanceState + ")", trace.categories.NativeLifecycle); var entry = this.entry; var page = entry.resolvedPage; if (savedInstanceState && savedInstanceState.getBoolean(HIDDEN, false)) { this.getFragmentManager().beginTransaction().hide(this).commit(); page._onAttached(this.getActivity()); } else { onFragmentShown(this); } return page._nativeView; }; FragmentClass.prototype.onSaveInstanceState = function (outState) { trace.write(this.getTag() + ".onSaveInstanceState(" + outState + ")", trace.categories.NativeLifecycle); _super.prototype.onSaveInstanceState.call(this, outState); if (this.isHidden()) { outState.putBoolean(HIDDEN, true); } }; FragmentClass.prototype.onDestroyView = function () { trace.write(this.getTag() + ".onDestroyView()", trace.categories.NativeLifecycle); _super.prototype.onDestroyView.call(this); onFragmentHidden(this); var entry = this.entry; var page = entry.resolvedPage; if (page._context) { page._onDetached(true); } }; FragmentClass.prototype.onDestroy = function () { trace.write(this.getTag() + ".onDestroy()", trace.categories.NativeLifecycle); _super.prototype.onDestroy.call(this); utils.GC(); }; FragmentClass = __decorate([ JavaProxy("com.tns.FragmentClass") ], FragmentClass); return FragmentClass; }(android.app.Fragment)); var NativeScriptActivity = (function (_super) { __extends(NativeScriptActivity, _super); function NativeScriptActivity() { _super.call(this); return global.__native(this); } NativeScriptActivity.prototype.onCreate = function (savedInstanceState) { trace.write("NativeScriptActivity.onCreate(" + savedInstanceState + ")", trace.categories.NativeLifecycle); var app = application.android; var intent = this.getIntent(); if (application.onLaunch) { application.onLaunch(intent); } var args = { eventName: application.launchEvent, object: app, android: intent }; application.notify(args); var frameId = -1; var rootView = args.root; var extras = intent.getExtras(); if (extras) { frameId = extras.getInt(INTENT_EXTRA, -1); } else if (savedInstanceState) { frameId = savedInstanceState.getInt(INTENT_EXTRA, -1); } var frame; var navParam; if (frameId >= 0) { rootView = getFrameById(frameId); } else if (!rootView) { navParam = application.mainEntry; if (!navParam) { navParam = application.mainModule; } if (navParam) { frame = new Frame(); } else { throw new Error("A Frame must be used to navigate to a Page."); } rootView = frame; } var isRestart = !!savedInstanceState && activityInitialized; _super.prototype.onCreate.call(this, isRestart ? savedInstanceState : null); this.rootView = rootView; rootView._onAttached(this); this.setContentView(rootView._nativeView, new org.nativescript.widgets.CommonLayoutParams()); if (frame) { frame.navigate(navParam); } activityInitialized = true; }; NativeScriptActivity.prototype.onSaveInstanceState = function (outState) { _super.prototype.onSaveInstanceState.call(this, outState); var view = this.rootView; if (view instanceof Frame) { outState.putInt(INTENT_EXTRA, view.android.frameId); } }; NativeScriptActivity.prototype.onStart = function () { _super.prototype.onStart.call(this); trace.write("NativeScriptActivity.onStart();", trace.categories.NativeLifecycle); var rootView = this.rootView; if (rootView && !rootView.isLoaded) { rootView.onLoaded(); } }; NativeScriptActivity.prototype.onStop = function () { _super.prototype.onStop.call(this); trace.write("NativeScriptActivity.onStop();", trace.categories.NativeLifecycle); var rootView = this.rootView; if (rootView && rootView.isLoaded) { rootView.onUnloaded(); } }; NativeScriptActivity.prototype.onDestroy = function () { var rootView = this.rootView; if (rootView && rootView._context) { rootView._onDetached(true); } _super.prototype.onDestroy.call(this); trace.write("NativeScriptActivity.onDestroy();", trace.categories.NativeLifecycle); }; NativeScriptActivity.prototype.onBackPressed = function () { trace.write("NativeScriptActivity.onBackPressed;", trace.categories.NativeLifecycle); var args = { eventName: "activityBackPressed", object: application.android, activity: this, cancel: false, }; application.android.notify(args); if (args.cancel) { return; } if (!frameCommon.goBack()) { _super.prototype.onBackPressed.call(this); } }; NativeScriptActivity.prototype.onActivityResult = function (requestCode, resultCode, data) { _super.prototype.onActivityResult.call(this, requestCode, resultCode, data); trace.write("NativeScriptActivity.onActivityResult(" + requestCode + ", " + resultCode + ", " + data + ")", trace.categories.NativeLifecycle); var result = application.android.onActivityResult; if (result) { result(requestCode, resultCode, data); } application.android.notify({ eventName: "activityResult", object: application.android, activity: this, requestCode: requestCode, resultCode: resultCode, intent: data }); }; NativeScriptActivity = __decorate([ JavaProxy("com.tns.NativeScriptActivity") ], NativeScriptActivity); return NativeScriptActivity; }(android.app.Activity));