From 9d3f4d5a2983ba0579a202b0d81c4a2b96d3e63f Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 23 Feb 2021 12:09:51 +0100 Subject: [PATCH] MOBILE-3708 settings: Add split view in site preferences --- src/addons/messages/messages-lazy.module.ts | 6 - src/addons/messages/messages.module.ts | 10 +- .../messages/services/handlers/settings.ts | 5 +- .../notifications-lazy.module.ts | 5 - .../notifications/notifications.module.ts | 10 +- .../services/handlers/settings.ts | 5 +- .../settings/pages/site/site-routing.ts | 33 +++++ .../features/settings/pages/site/site.html | 126 +++++++++--------- .../settings/pages/site/site.module.ts | 43 ++++-- src/core/features/settings/pages/site/site.ts | 91 ++++++++----- 10 files changed, 208 insertions(+), 126 deletions(-) create mode 100644 src/core/features/settings/pages/site/site-routing.ts diff --git a/src/addons/messages/messages-lazy.module.ts b/src/addons/messages/messages-lazy.module.ts index 35e2a2431..c606a6ae0 100644 --- a/src/addons/messages/messages-lazy.module.ts +++ b/src/addons/messages/messages-lazy.module.ts @@ -16,7 +16,6 @@ import { Injector, NgModule } from '@angular/core'; import { Route, RouterModule, ROUTES, Routes } from '@angular/router'; import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; -import { AddonMessagesSettingsHandlerService } from './services/handlers/settings'; export const AddonMessagesDiscussionRoute: Route = { path: 'discussion', @@ -46,11 +45,6 @@ function buildRoutes(injector: Injector): Routes { loadChildren: () => import('./pages/search/search.module') .then(m => m.AddonMessagesSearchPageModule), }, - { - path: AddonMessagesSettingsHandlerService.PAGE_NAME, - loadChildren: () => import('./pages/settings/settings.module') - .then(m => m.AddonMessagesSettingsPageModule), - }, { path: 'contacts', // 3.6 or greater. loadChildren: () => import('./pages/contacts/contacts.module') diff --git a/src/addons/messages/messages.module.ts b/src/addons/messages/messages.module.ts index 33b1124a0..d097a4363 100644 --- a/src/addons/messages/messages.module.ts +++ b/src/addons/messages/messages.module.ts @@ -22,7 +22,7 @@ import { CoreMainMenuDelegate } from '@features/mainmenu/services/mainmenu-deleg import { AddonMessagesMainMenuHandler, AddonMessagesMainMenuHandlerService } from './services/handlers/mainmenu'; import { CoreCronDelegate } from '@services/cron'; import { CoreSettingsDelegate } from '@features/settings/services/settings-delegate'; -import { AddonMessagesSettingsHandler } from './services/handlers/settings'; +import { AddonMessagesSettingsHandler, AddonMessagesSettingsHandlerService } from './services/handlers/settings'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { AddonMessagesIndexLinkHandler } from './services/handlers/index-link'; @@ -35,6 +35,7 @@ import { AddonMessagesSendMessageUserHandler } from './services/handlers/user-se import { Network, NgZone } from '@singletons'; import { AddonMessagesSync } from './services/messages-sync'; import { AddonMessagesSyncCronHandler } from './services/handlers/sync-cron'; +import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; const mainMenuChildrenRoutes: Routes = [ { @@ -42,11 +43,18 @@ const mainMenuChildrenRoutes: Routes = [ loadChildren: () => import('./messages-lazy.module').then(m => m.AddonMessagesLazyModule), }, ]; +const preferencesRoutes: Routes = [ + { + path: AddonMessagesSettingsHandlerService.PAGE_NAME, + loadChildren: () => import('./pages/settings/settings.module').then(m => m.AddonMessagesSettingsPageModule), + }, +]; @NgModule({ imports: [ CoreMainMenuRoutingModule.forChild({ children: mainMenuChildrenRoutes }), CoreMainMenuTabRoutingModule.forChild( mainMenuChildrenRoutes), + CoreSitePreferencesRoutingModule.forChild(preferencesRoutes), ], providers: [ { diff --git a/src/addons/messages/services/handlers/settings.ts b/src/addons/messages/services/handlers/settings.ts index d6e625767..40f29b1e2 100644 --- a/src/addons/messages/services/handlers/settings.ts +++ b/src/addons/messages/services/handlers/settings.ts @@ -16,7 +16,6 @@ import { Injectable } from '@angular/core'; import { CoreSettingsHandler, CoreSettingsHandlerData } from '@features/settings/services/settings-delegate'; import { makeSingleton } from '@singletons'; import { AddonMessages } from '../messages'; -import { AddonMessagesMainMenuHandlerService } from './mainmenu'; /** * Message settings handler. @@ -24,7 +23,7 @@ import { AddonMessagesMainMenuHandlerService } from './mainmenu'; @Injectable({ providedIn: 'root' }) export class AddonMessagesSettingsHandlerService implements CoreSettingsHandler { - static readonly PAGE_NAME = 'settings'; + static readonly PAGE_NAME = 'messages'; name = 'AddonMessages'; priority = 600; @@ -49,7 +48,7 @@ export class AddonMessagesSettingsHandlerService implements CoreSettingsHandler return { icon: 'fas-comments', title: 'addon.messages.messages', - page: AddonMessagesMainMenuHandlerService.PAGE_NAME + '/' + AddonMessagesSettingsHandlerService.PAGE_NAME, + page: AddonMessagesSettingsHandlerService.PAGE_NAME, class: 'addon-messages-settings-handler', }; } diff --git a/src/addons/notifications/notifications-lazy.module.ts b/src/addons/notifications/notifications-lazy.module.ts index 556467262..890e8df7c 100644 --- a/src/addons/notifications/notifications-lazy.module.ts +++ b/src/addons/notifications/notifications-lazy.module.ts @@ -16,7 +16,6 @@ import { Injector, NgModule } from '@angular/core'; import { RouterModule, ROUTES, Routes } from '@angular/router'; import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; -import { AddonNotificationsSettingsHandlerService } from './services/handlers/settings'; function buildRoutes(injector: Injector): Routes { return [ @@ -24,10 +23,6 @@ function buildRoutes(injector: Injector): Routes { path: 'list', loadChildren: () => import('./pages/list/list.module').then(m => m.AddonNotificationsListPageModule), }, - { - path: AddonNotificationsSettingsHandlerService.PAGE_NAME, - loadChildren: () => import('./pages/settings/settings.module').then(m => m.AddonNotificationsSettingsPageModule), - }, ...buildTabMainRoutes(injector, { redirectTo: 'list', pathMatch: 'full', diff --git a/src/addons/notifications/notifications.module.ts b/src/addons/notifications/notifications.module.ts index 34217e31a..01abc8f39 100644 --- a/src/addons/notifications/notifications.module.ts +++ b/src/addons/notifications/notifications.module.ts @@ -24,7 +24,8 @@ import { CoreSettingsDelegate } from '@features/settings/services/settings-deleg import { AddonNotificationsMainMenuHandler, AddonNotificationsMainMenuHandlerService } from './services/handlers/mainmenu'; import { AddonNotificationsCronHandler } from './services/handlers/cron'; import { AddonNotificationsPushClickHandler } from './services/handlers/push-click'; -import { AddonNotificationsSettingsHandler } from './services/handlers/settings'; +import { AddonNotificationsSettingsHandler, AddonNotificationsSettingsHandlerService } from './services/handlers/settings'; +import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; const routes: Routes = [ { @@ -32,11 +33,18 @@ const routes: Routes = [ loadChildren: () => import('@/addons/notifications/notifications-lazy.module').then(m => m.AddonNotificationsLazyModule), }, ]; +const preferencesRoutes: Routes = [ + { + path: AddonNotificationsSettingsHandlerService.PAGE_NAME, + loadChildren: () => import('./pages/settings/settings.module').then(m => m.AddonNotificationsSettingsPageModule), + }, +]; @NgModule({ imports: [ CoreMainMenuRoutingModule.forChild({ children: routes }), CoreMainMenuTabRoutingModule.forChild(routes), + CoreSitePreferencesRoutingModule.forChild(preferencesRoutes), ], exports: [CoreMainMenuRoutingModule], providers: [ diff --git a/src/addons/notifications/services/handlers/settings.ts b/src/addons/notifications/services/handlers/settings.ts index 6bea1480d..a67c415f4 100644 --- a/src/addons/notifications/services/handlers/settings.ts +++ b/src/addons/notifications/services/handlers/settings.ts @@ -18,7 +18,6 @@ import { CoreLocalNotifications } from '@services/local-notifications'; import { makeSingleton } from '@singletons'; import { CoreSettingsHandler, CoreSettingsHandlerData } from '@features/settings/services/settings-delegate'; import { AddonNotifications } from '../notifications'; -import { AddonNotificationsMainMenuHandlerService } from './mainmenu'; /** * Notifications settings handler. @@ -26,7 +25,7 @@ import { AddonNotificationsMainMenuHandlerService } from './mainmenu'; @Injectable({ providedIn: 'root' }) export class AddonNotificationsSettingsHandlerService implements CoreSettingsHandler { - static readonly PAGE_NAME = 'settings'; + static readonly PAGE_NAME = 'notifications'; name = 'AddonNotifications'; priority = 500; @@ -50,7 +49,7 @@ export class AddonNotificationsSettingsHandlerService implements CoreSettingsHan return { icon: 'fas-bell', title: 'addon.notifications.notifications', - page: AddonNotificationsMainMenuHandlerService.PAGE_NAME + '/' + AddonNotificationsSettingsHandlerService.PAGE_NAME, + page: AddonNotificationsSettingsHandlerService.PAGE_NAME, class: 'addon-notifications-settings-handler', }; } diff --git a/src/core/features/settings/pages/site/site-routing.ts b/src/core/features/settings/pages/site/site-routing.ts new file mode 100644 index 000000000..367a3b92f --- /dev/null +++ b/src/core/features/settings/pages/site/site-routing.ts @@ -0,0 +1,33 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core'; + +import { ModuleRoutesConfig } from '@/app/app-routing.module'; + +export const SITE_PREFERENCES_ROUTES = new InjectionToken('SITE_PREFERENCES_ROUTES'); + +@NgModule() +export class CoreSitePreferencesRoutingModule { + + static forChild(routes: ModuleRoutesConfig): ModuleWithProviders { + return { + ngModule: CoreSitePreferencesRoutingModule, + providers: [ + { provide: SITE_PREFERENCES_ROUTES, multi: true, useValue: routes }, + ], + }; + } + +} diff --git a/src/core/features/settings/pages/site/site.html b/src/core/features/settings/pages/site/site.html index c4d9e4a08..6ee4b674d 100644 --- a/src/core/features/settings/pages/site/site.html +++ b/src/core/features/settings/pages/site/site.html @@ -9,72 +9,74 @@ - - - - - - - -

{{siteInfo!.fullname}}

-

- -

-

{{ siteUrl }}

-
-
- - - - -

{{ 'core.sharedfiles.sharedfiles' | translate }}

-
- {{ iosSharedFiles }} -
- - - - - -

{{ handler.title | translate}}

-
-
- - - + + + + + + + -

{{ 'core.settings.spaceusage' | translate }} -

-

{{ spaceUsage.spaceUsage | coreBytesToSize }}

+

{{siteInfo!.fullname}}

+

+ +

+

{{ siteUrl }}

- - -
- + + + + + + + +

{{ handler.title | translate}}

- - - -
-
-
-
+ + + + +

{{ 'core.settings.spaceusage' | translate }} +

+

{{ spaceUsage.spaceUsage | coreBytesToSize }}

+
+ + + +
+ + +

{{ 'core.settings.synchronizenow' | translate }} + +

+
+ + + + +
+
+ + +
diff --git a/src/core/features/settings/pages/site/site.module.ts b/src/core/features/settings/pages/site/site.module.ts index 0e6c8a1b2..e6aa8aae0 100644 --- a/src/core/features/settings/pages/site/site.module.ts +++ b/src/core/features/settings/pages/site/site.module.ts @@ -12,26 +12,51 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; +import { Injector, NgModule } from '@angular/core'; +import { RouterModule, ROUTES, Routes } from '@angular/router'; import { CoreSharedModule } from '@/core/shared.module'; import { CoreSitePreferencesPage } from './site'; +import { conditionalRoutes, resolveModuleRoutes } from '@/app/app-routing.module'; +import { SITE_PREFERENCES_ROUTES } from './site-routing'; +import { CoreScreen } from '@services/screen'; -const routes: Routes = [ - { - path: '', - component: CoreSitePreferencesPage, - }, -]; +function buildRoutes(injector: Injector): Routes { + const routes = resolveModuleRoutes(injector, SITE_PREFERENCES_ROUTES); + + const mobileRoutes: Routes = [ + { + path: '', + component: CoreSitePreferencesPage, + }, + ...routes.siblings, + + ]; + + const tabletRoutes: Routes = [ + { + path: '', + component: CoreSitePreferencesPage, + children: routes.siblings, + }, + ]; + + return [ + ...conditionalRoutes(mobileRoutes, () => CoreScreen.instance.isMobile), + ...conditionalRoutes(tabletRoutes, () => CoreScreen.instance.isTablet), + ]; +} @NgModule({ + providers: [ + { provide: ROUTES, multi: true, useFactory: buildRoutes, deps: [Injector] }, + ], declarations: [ CoreSitePreferencesPage, ], imports: [ - RouterModule.forChild(routes), CoreSharedModule, ], + exports: [RouterModule], }) export class CoreSitePreferencesPageModule {} diff --git a/src/core/features/settings/pages/site/site.ts b/src/core/features/settings/pages/site/site.ts index bfed21cdc..c2d1421aa 100644 --- a/src/core/features/settings/pages/site/site.ts +++ b/src/core/features/settings/pages/site/site.ts @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { Params } from '@angular/router'; +import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core'; +import { ActivatedRouteSnapshot, Params } from '@angular/router'; import { IonRefresher } from '@ionic/angular'; -import { CoreSettingsDelegate, CoreSettingsHandlerData } from '../../services/settings-delegate'; +import { CoreSettingsDelegate, CoreSettingsHandlerToDisplay } from '../../services/settings-delegate'; import { CoreEventObserver, CoreEvents, CoreEventSiteUpdatedData } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -26,7 +26,8 @@ import { CoreApp } from '@services/app'; import { CoreSiteInfo } from '@classes/site'; import { Translate } from '@singletons'; import { CoreNavigator } from '@services/navigator'; -import { CoreScreen } from '@services/screen'; +import { CorePageItemsListManager } from '@classes/page-items-list-manager'; +import { CoreSplitViewComponent } from '@components/split-view/split-view'; /** * Page that displays the list of site settings pages. @@ -35,12 +36,13 @@ import { CoreScreen } from '@services/screen'; selector: 'page-core-site-preferences', templateUrl: 'site.html', }) -export class CoreSitePreferencesPage implements OnInit, OnDestroy { +export class CoreSitePreferencesPage implements AfterViewInit, OnDestroy { + + @ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent; + + handlers: CoreSettingsSitePreferencesManager; isIOS: boolean; - selectedPage?: string; - - handlers: CoreSettingsHandlerData[] = []; siteId: string; siteInfo?: CoreSiteInfo; siteName?: string; @@ -50,7 +52,6 @@ export class CoreSitePreferencesPage implements OnInit, OnDestroy { spaceUsage: 0, }; - loaded = false; iosSharedFiles = 0; protected sitesObserver: CoreEventObserver; protected isDestroyed = false; @@ -59,6 +60,7 @@ export class CoreSitePreferencesPage implements OnInit, OnDestroy { this.isIOS = CoreApp.isIOS(); this.siteId = CoreSites.getCurrentSiteId(); + this.handlers = new CoreSettingsSitePreferencesManager(CoreSitePreferencesPage); this.sitesObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, (data: CoreEventSiteUpdatedData) => { if (data.siteId == this.siteId) { @@ -70,30 +72,29 @@ export class CoreSitePreferencesPage implements OnInit, OnDestroy { /** * View loaded. */ - ngOnInit(): void { - // @todo this.selectedPage = route.snapshot.paramMap.get('page') || undefined; + async ngAfterViewInit(): Promise { + const pageToOpen = CoreNavigator.getRouteParam('page'); - this.fetchData().finally(() => { - this.loaded = true; + try { + await this.fetchData(); + } finally { - if (this.selectedPage) { - this.openHandler(this.selectedPage); - } else if (CoreScreen.isTablet) { - if (this.isIOS) { - // @todo - // this.openHandler('CoreSharedFilesListPage', { manage: true, siteId: this.siteId, hideSitePicker: true }); - } else if (this.handlers.length > 0) { - this.openHandler(this.handlers[0].page, this.handlers[0].params); - } + const handler = pageToOpen ? this.handlers.items.find(handler => handler.page == pageToOpen) : undefined; + + if (handler) { + this.handlers.select(handler); + this.handlers.watchSplitViewOutlet(this.splitView); + } else { + this.handlers.start(this.splitView); } - }); + } } /** * Fetch Data. */ protected async fetchData(): Promise { - this.handlers = CoreSettingsDelegate.getHandlers(); + this.handlers.setItems(CoreSettingsDelegate.getHandlers()); const currentSite = CoreSites.getCurrentSite(); this.siteInfo = currentSite!.getInfo(); @@ -170,18 +171,6 @@ export class CoreSitePreferencesPage implements OnInit, OnDestroy { } } - /** - * Open a handler. - * - * @param page Page to open. - * @param params Params of the page to open. - */ - openHandler(page: string, params?: Params): void { - this.selectedPage = page; - // this.splitviewCtrl.push(page, params); - CoreNavigator.navigateToSitePath(page, { params }); - } - /** * Show information about space usage actions. */ @@ -211,3 +200,33 @@ export class CoreSitePreferencesPage implements OnInit, OnDestroy { } } + +/** + * Helper class to manage sections. + */ +class CoreSettingsSitePreferencesManager extends CorePageItemsListManager { + + /** + * @inheritdoc + */ + protected getItemPath(handler: CoreSettingsHandlerToDisplay): string { + return handler.page; + } + + /** + * @inheritdoc + */ + protected getItemQueryParams(handler: CoreSettingsHandlerToDisplay): Params { + return handler.params || {}; + } + + /** + * @inheritdoc + */ + protected getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { + // @todo: routeConfig doesn't have a path after refreshing the app. + // route.component is null too, and route.parent.url is empty. + return route.parent?.routeConfig?.path ?? null; + } + +}