From dc5b9875b36812ea457e8c1342620fe67b2cf391 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 18 Jun 2019 11:37:06 +0200 Subject: [PATCH] MOBILE-2735 tabs: Ask confirm when going to root of current tab --- scripts/langindex.json | 2 + src/assets/lang/en.json | 2 + src/components/ion-tabs/core-ion-tabs.html | 2 +- src/components/ion-tabs/ion-tabs.ts | 58 ++++++++++++++++++---- src/lang/en.json | 2 + 5 files changed, 56 insertions(+), 10 deletions(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index 7381c6fc8..6f1b7f091 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1260,6 +1260,8 @@ "core.completion-alt-manual-y-override": "completion", "core.confirmcanceledit": "local_moodlemobileapp", "core.confirmdeletefile": "repository", + "core.confirmgotabroot": "local_moodlemobileapp", + "core.confirmgotabrootdefault": "local_moodlemobileapp", "core.confirmloss": "local_moodlemobileapp", "core.confirmopeninbrowser": "local_moodlemobileapp", "core.considereddigitalminor": "moodle", diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 7ed0d4812..6069bde0b 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1260,6 +1260,8 @@ "core.completion-alt-manual-y-override": "Completed: {{$a.modname}} (set by {{$a.overrideuser}}). Select to mark as not complete.", "core.confirmcanceledit": "Are you sure you want to leave this page? All changes will be lost.", "core.confirmdeletefile": "Are you sure you want to delete this file?", + "core.confirmgotabroot": "Are you sure you want to go back to {{name}}?", + "core.confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?", "core.confirmloss": "Are you sure? All changes will be lost.", "core.confirmopeninbrowser": "Do you want to open it in a web browser?", "core.considereddigitalminor": "You are too young to create an account on this site.", diff --git a/src/components/ion-tabs/core-ion-tabs.html b/src/components/ion-tabs/core-ion-tabs.html index 123d340c1..5a4dda4b3 100644 --- a/src/components/ion-tabs/core-ion-tabs.html +++ b/src/components/ion-tabs/core-ion-tabs.html @@ -1,5 +1,5 @@
- +
diff --git a/src/components/ion-tabs/ion-tabs.ts b/src/components/ion-tabs/ion-tabs.ts index deeb76a53..914d97ab6 100644 --- a/src/components/ion-tabs/ion-tabs.ts +++ b/src/components/ion-tabs/ion-tabs.ts @@ -20,11 +20,14 @@ import { import { CoreIonTabComponent } from './ion-tab'; import { CoreUtilsProvider, PromiseDefer } from '@providers/utils/utils'; import { CoreAppProvider } from '@providers/app'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { TranslateService } from '@ngx-translate/core'; /** - * Equivalent to ion-tabs. It has 2 improvements: + * Equivalent to ion-tabs. It has several improvements: * - If a core-ion-tab is added or removed, it will be reflected in the tab bar in the right position. * - It supports a loaded input to tell when are the tabs ready. + * - When the user clicks the tab again to go to root, a confirm modal is shown. */ @Component({ selector: 'core-ion-tabs', @@ -73,7 +76,8 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy { constructor(protected utils: CoreUtilsProvider, protected appProvider: CoreAppProvider, @Optional() parent: NavController, @Optional() viewCtrl: ViewController, _app: App, config: Config, elementRef: ElementRef, _plt: Platform, - renderer: Renderer, _linker: DeepLinker, keyboard?: Keyboard) { + renderer: Renderer, _linker: DeepLinker, protected domUtils: CoreDomUtilsProvider, + protected translate: TranslateService, keyboard?: Keyboard) { super(parent, viewCtrl, _app, config, elementRef, _plt, renderer, _linker, keyboard); } @@ -272,13 +276,25 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy { * * @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select. * @param {NavOptions} Nav options. - * @param {boolean} [fromUrl=true] Whether to load from a URL. + * @param {boolean} [fromUrl] Whether to load from a URL. + * @param {boolean} [manualClick] Whether the user manually clicked the tab. * @return {Promise} Promise resolved when selected. */ - select(tabOrIndex: number | Tab, opts: NavOptions = {}, fromUrl: boolean = false): Promise { + select(tabOrIndex: number | Tab, opts: NavOptions = {}, fromUrl?: boolean, manualClick?: boolean): Promise { if (this.initialized) { // Tabs have been initialized, select the tab. + if (manualClick) { + // If we'll go to the root of the current tab, ask the user to confirm first. + const tab = typeof tabOrIndex == 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex; + + return this.confirmGoToRoot(tab).then(() => { + return super.select(tabOrIndex, opts, fromUrl); + }, () => { + // User cancelled. + }); + } + return super.select(tabOrIndex, opts, fromUrl); } else { // Tabs not initialized yet. Mark it as "selectedIndex" input so it's treated when the tabs are initialized. @@ -305,11 +321,16 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy { if (this.initialized) { const tab = this.getByIndex(index); if (tab) { - return tab.goToRoot({animate: false, updateUrl: true, isNavRoot: true}).then(() => { - // Tab not previously selected. Select it after going to root. - if (!tab.isSelected) { - return this.select(tab, {animate: false, updateUrl: true, isNavRoot: true}); - } + return this.confirmGoToRoot(tab).then(() => { + // User confirmed, go to root. + return tab.goToRoot({animate: tab.isSelected, updateUrl: true, isNavRoot: true}).then(() => { + // Tab not previously selected. Select it after going to root. + if (!tab.isSelected) { + return this.select(tab, {animate: false, updateUrl: true, isNavRoot: true}); + } + }); + }, () => { + // User cancelled. }); } @@ -349,4 +370,23 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy { // Unregister the custom back button action for this page this.unregisterBackButtonAction && this.unregisterBackButtonAction(); } + + /** + * Confirm if the user wants to go to the root of the current tab. + * + * @param {Tab} tab Tab to go to root. + * @return {Promise} Promise resolved when confirmed. + */ + confirmGoToRoot(tab: Tab): Promise { + if (!tab || !tab.isSelected || (tab.getActive() && tab.getActive().isFirst())) { + // Tab not selected or is already at root, no need to confirm. + return Promise.resolve(); + } else { + if (tab.tabTitle) { + return this.domUtils.showConfirm(this.translate.instant('core.confirmgotabroot', {name: tab.tabTitle})); + } else { + return this.domUtils.showConfirm(this.translate.instant('core.confirmgotabrootdefault')); + } + } + } } diff --git a/src/lang/en.json b/src/lang/en.json index bf2f305e5..fe9102832 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -40,6 +40,8 @@ "completion-alt-manual-y-override": "Completed: {{$a.modname}} (set by {{$a.overrideuser}}). Select to mark as not complete.", "confirmcanceledit": "Are you sure you want to leave this page? All changes will be lost.", "confirmdeletefile": "Are you sure you want to delete this file?", + "confirmgotabroot": "Are you sure you want to go back to {{name}}?", + "confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?", "confirmloss": "Are you sure? All changes will be lost.", "confirmopeninbrowser": "Do you want to open it in a web browser?", "considereddigitalminor": "You are too young to create an account on this site.",