MOBILE-2735 tabs: Ask confirm when going to root of current tab

main
Dani Palou 2019-06-18 11:37:06 +02:00
parent 08322a299d
commit dc5b9875b3
5 changed files with 56 additions and 10 deletions

View File

@ -1260,6 +1260,8 @@
"core.completion-alt-manual-y-override": "completion", "core.completion-alt-manual-y-override": "completion",
"core.confirmcanceledit": "local_moodlemobileapp", "core.confirmcanceledit": "local_moodlemobileapp",
"core.confirmdeletefile": "repository", "core.confirmdeletefile": "repository",
"core.confirmgotabroot": "local_moodlemobileapp",
"core.confirmgotabrootdefault": "local_moodlemobileapp",
"core.confirmloss": "local_moodlemobileapp", "core.confirmloss": "local_moodlemobileapp",
"core.confirmopeninbrowser": "local_moodlemobileapp", "core.confirmopeninbrowser": "local_moodlemobileapp",
"core.considereddigitalminor": "moodle", "core.considereddigitalminor": "moodle",

View File

@ -1260,6 +1260,8 @@
"core.completion-alt-manual-y-override": "Completed: {{$a.modname}} (set by {{$a.overrideuser}}). Select to mark as not complete.", "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.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.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.confirmloss": "Are you sure? All changes will be lost.",
"core.confirmopeninbrowser": "Do you want to open it in a web browser?", "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.", "core.considereddigitalminor": "You are too young to create an account on this site.",

View File

@ -1,5 +1,5 @@
<div class="tabbar" role="tablist" #tabbar [hidden]="hidden"> <div class="tabbar" role="tablist" #tabbar [hidden]="hidden">
<a [hidden]="_loaded === false" *ngFor="let t of _tabs" [tab]="t" class="tab-button" role="tab" href="#" (ionSelect)="select(t)" [attr.aria-hidden]="!t.show" [attr.aria-label]="t.tabTitle || ''" [title]="t.tabTitle || ''"></a> <a [hidden]="_loaded === false" *ngFor="let t of _tabs" [tab]="t" class="tab-button" role="tab" href="#" (ionSelect)="select(t, undefined, undefined, true)" [attr.aria-hidden]="!t.show" [attr.aria-label]="t.tabTitle || ''" [title]="t.tabTitle || ''"></a>
<div class="tab-highlight"></div> <div class="tab-highlight"></div>
<div *ngIf="_loaded === false" class="core-ion-tabs-loading"> <div *ngIf="_loaded === false" class="core-ion-tabs-loading">
<span class="core-ion-tabs-loading-spinner"> <span class="core-ion-tabs-loading-spinner">

View File

@ -20,11 +20,14 @@ import {
import { CoreIonTabComponent } from './ion-tab'; import { CoreIonTabComponent } from './ion-tab';
import { CoreUtilsProvider, PromiseDefer } from '@providers/utils/utils'; import { CoreUtilsProvider, PromiseDefer } from '@providers/utils/utils';
import { CoreAppProvider } from '@providers/app'; 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. * - 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. * - 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({ @Component({
selector: 'core-ion-tabs', 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, constructor(protected utils: CoreUtilsProvider, protected appProvider: CoreAppProvider, @Optional() parent: NavController,
@Optional() viewCtrl: ViewController, _app: App, config: Config, elementRef: ElementRef, _plt: Platform, @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); 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 {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select.
* @param {NavOptions} Nav options. * @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<any>} Promise resolved when selected. * @return {Promise<any>} Promise resolved when selected.
*/ */
select(tabOrIndex: number | Tab, opts: NavOptions = {}, fromUrl: boolean = false): Promise<any> { select(tabOrIndex: number | Tab, opts: NavOptions = {}, fromUrl?: boolean, manualClick?: boolean): Promise<any> {
if (this.initialized) { if (this.initialized) {
// Tabs have been initialized, select the tab. // 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); return super.select(tabOrIndex, opts, fromUrl);
} else { } else {
// Tabs not initialized yet. Mark it as "selectedIndex" input so it's treated when the tabs are initialized. // Tabs not initialized yet. Mark it as "selectedIndex" input so it's treated when the tabs are initialized.
@ -305,12 +321,17 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy {
if (this.initialized) { if (this.initialized) {
const tab = this.getByIndex(index); const tab = this.getByIndex(index);
if (tab) { if (tab) {
return tab.goToRoot({animate: false, updateUrl: true, isNavRoot: true}).then(() => { 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. // Tab not previously selected. Select it after going to root.
if (!tab.isSelected) { if (!tab.isSelected) {
return this.select(tab, {animate: false, updateUrl: true, isNavRoot: true}); return this.select(tab, {animate: false, updateUrl: true, isNavRoot: true});
} }
}); });
}, () => {
// User cancelled.
});
} }
// Not found. // Not found.
@ -349,4 +370,23 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy {
// Unregister the custom back button action for this page // Unregister the custom back button action for this page
this.unregisterBackButtonAction && this.unregisterBackButtonAction(); 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<any>} Promise resolved when confirmed.
*/
confirmGoToRoot(tab: Tab): Promise<any> {
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'));
}
}
}
} }

View File

@ -40,6 +40,8 @@
"completion-alt-manual-y-override": "Completed: {{$a.modname}} (set by {{$a.overrideuser}}). Select to mark as not complete.", "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.", "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?", "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.", "confirmloss": "Are you sure? All changes will be lost.",
"confirmopeninbrowser": "Do you want to open it in a web browser?", "confirmopeninbrowser": "Do you want to open it in a web browser?",
"considereddigitalminor": "You are too young to create an account on this site.", "considereddigitalminor": "You are too young to create an account on this site.",