From 684afd3cee6c21fc1e2913682149fffcf22eda03 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 10 Jun 2021 14:50:05 +0200 Subject: [PATCH 1/5] MOBILE-3320 DX: Extract config declarations --- moodle.config.example.json | 5 +--- src/core/constants.ts | 48 ++----------------------------- src/types/config.d.ts | 59 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 50 deletions(-) create mode 100644 src/types/config.d.ts diff --git a/moodle.config.example.json b/moodle.config.example.json index a94e15ea6..a0dfaea29 100644 --- a/moodle.config.example.json +++ b/moodle.config.example.json @@ -4,10 +4,7 @@ * You can create your own environment files such as "moodle.config.prod.json" and "moodle.config.dev.json" * to override some values. The values will be merged, so you don't need to duplicate everything in this file. */ - { - // @todo This could be read from package.json. - "versionname": "3.9.3-dev", - // Override default language here. + // You can find all the properties you can configure in src/types/config.d.ts "default_lang": "es" } diff --git a/src/core/constants.ts b/src/core/constants.ts index 173704da3..bbba1fdbd 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -12,13 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* eslint-disable @typescript-eslint/naming-convention */ - -import { CoreColorScheme, CoreZoomLevel } from '@features/settings/services/settings-helper'; -import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mainmenu'; -import { CoreSitesDemoSiteData } from '@services/sites'; import envJson from '@/assets/env.json'; -import { OpenFileAction } from '@services/utils/utils'; +import { EnvironmentConfig } from '@/types/config'; /** * Context levels enumeration. @@ -141,46 +136,7 @@ export class CoreConstants { } -export interface EnvironmentConfig { - app_id: string; - appname: string; - versioncode: number; - versionname: string; - cache_update_frequency_usually: number; - cache_update_frequency_often: number; - cache_update_frequency_sometimes: number; - cache_update_frequency_rarely: number; - default_lang: string; - languages: Record; - wsservice: string; - wsextservice: string; - demo_sites: Record; - zoomlevels: Record; - customurlscheme: string; - siteurl: string; - sitename: string; - multisitesdisplay: string; - sitefindersettings: Record; - onlyallowlistedsites: boolean; - skipssoconfirmation: boolean; - forcedefaultlanguage: boolean; - privacypolicy: string; - notificoncolor: string; - enableanalytics: boolean; - enableonboarding: boolean; - forceColorScheme: CoreColorScheme; - forceLoginLogo: boolean; - ioswebviewscheme: string; - appstores: Record; - displayqroncredentialscreen?: boolean; - displayqronsitescreen?: boolean; - forceOpenLinksIn: 'app' | 'browser'; - iOSDefaultOpenFileAction?: OpenFileAction; - customMainMenuItems?: CoreMainMenuLocalizedCustomItem[]; - feedbackFormUrl?: string | false; -}; - -export interface EnvironmentBuild { +interface EnvironmentBuild { version: string; isProduction: boolean; isTesting: boolean; diff --git a/src/types/config.d.ts b/src/types/config.d.ts new file mode 100644 index 000000000..497a3b8a4 --- /dev/null +++ b/src/types/config.d.ts @@ -0,0 +1,59 @@ +// (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 { CoreColorScheme, CoreZoomLevel } from '@features/settings/services/settings-helper'; +import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mainmenu'; +import { CoreSitesDemoSiteData } from '@services/sites'; +import { OpenFileAction } from '@services/utils/utils'; + +/* eslint-disable @typescript-eslint/naming-convention */ + +export interface EnvironmentConfig { + app_id: string; + appname: string; + versioncode: number; + versionname: string; // @todo This could be removed and use build variables instead. + cache_update_frequency_usually: number; + cache_update_frequency_often: number; + cache_update_frequency_sometimes: number; + cache_update_frequency_rarely: number; + default_lang: string; + languages: Record; + wsservice: string; + wsextservice: string; + demo_sites: Record; + zoomlevels: Record; + customurlscheme: string; + siteurl: string; + sitename: string; + multisitesdisplay: string; + sitefindersettings: Record; + onlyallowlistedsites: boolean; + skipssoconfirmation: boolean; + forcedefaultlanguage: boolean; + privacypolicy: string; + notificoncolor: string; + enableanalytics: boolean; + enableonboarding: boolean; + forceColorScheme: CoreColorScheme; + forceLoginLogo: boolean; + ioswebviewscheme: string; + appstores: Record; + displayqroncredentialscreen?: boolean; + displayqronsitescreen?: boolean; + forceOpenLinksIn: 'app' | 'browser'; + iOSDefaultOpenFileAction?: OpenFileAction; + customMainMenuItems?: CoreMainMenuLocalizedCustomItem[]; + feedbackFormUrl?: string | false; +} From b396bfdf6f369ea3bb1f8b8f2f3ad40bf88859e5 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 10 Jun 2021 14:50:28 +0200 Subject: [PATCH 2/5] MOBILE-3320 DX: Add mobile scripts --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 31f1ad798..08c4afd5a 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,10 @@ "build": "ionic build", "build:prod": "NODE_ENV=production ionic build --prod", "build:test": "NODE_ENV=testing ionic build", + "dev:android": "ionic cordova run android --livereload", + "dev:ios": "ionic cordova run ios --livereload", + "prod:android": "NODE_ENV=production ionic cordova run android --aot", + "prod:ios": "NODE_ENV=production ionic cordova run ios --aot", "test": "NODE_ENV=testing gulp && jest --verbose", "test:ci": "NODE_ENV=testing gulp && jest -ci --runInBand --verbose", "test:watch": "NODE_ENV=testing gulp watch & jest --watch", From e2987a44b7ec700a1e96c89ccd85f0bb57f492b2 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 10 Jun 2021 14:53:53 +0200 Subject: [PATCH 3/5] MOBILE-3320 navigation: Remove path tracking --- .../pages/discussion/discussion.page.ts | 4 +-- .../services/handlers/user-send-message.ts | 1 + .../mod/feedback/components/index/index.ts | 1 + src/addons/mod/feedback/pages/form/form.ts | 9 +++---- src/core/services/navigator.ts | 25 +------------------ 5 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/addons/messages/pages/discussion/discussion.page.ts b/src/addons/messages/pages/discussion/discussion.page.ts index e9eb9b880..89e954d6a 100644 --- a/src/addons/messages/pages/discussion/discussion.page.ts +++ b/src/addons/messages/pages/discussion/discussion.page.ts @@ -158,15 +158,13 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView * Setup code for the page. */ async ngOnInit(): Promise { - // Disable the profile button if we're already coming from a profile. - const backViewPage = CoreNavigator.getPreviousPath(); - this.showInfo = !backViewPage || !CoreTextUtils.matchesGlob(backViewPage, '**/user/profile'); this.route.queryParams.subscribe(async (params) => { const oldConversationId = this.conversationId; const oldUserId = this.userId; this.conversationId = CoreNavigator.getRouteNumberParam('conversationId', { params }) || undefined; this.userId = CoreNavigator.getRouteNumberParam('userId', { params }) || undefined; + this.showInfo = !params.hideInfo; if (oldConversationId != this.conversationId || oldUserId != this.userId) { // Showing reload again can break animations. diff --git a/src/addons/messages/services/handlers/user-send-message.ts b/src/addons/messages/services/handlers/user-send-message.ts index bfb9f3b79..548d69d51 100644 --- a/src/addons/messages/services/handlers/user-send-message.ts +++ b/src/addons/messages/services/handlers/user-send-message.ts @@ -77,6 +77,7 @@ export class AddonMessagesSendMessageUserHandlerService implements CoreUserProfi const pageParams: Params = { showKeyboard: true, userId: user.id, + hideInfo: true, }; CoreNavigator.navigateToSitePath('/messages/discussion', { params: pageParams }); }, diff --git a/src/addons/mod/feedback/components/index/index.ts b/src/addons/mod/feedback/components/index/index.ts index cf2799220..3e77a7941 100644 --- a/src/addons/mod/feedback/components/index/index.ts +++ b/src/addons/mod/feedback/components/index/index.ts @@ -361,6 +361,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity { params: { preview, + fromIndex: true, }, }, ); diff --git a/src/addons/mod/feedback/pages/form/form.ts b/src/addons/mod/feedback/pages/form/form.ts index f365b6a9e..8d8612304 100644 --- a/src/addons/mod/feedback/pages/form/form.ts +++ b/src/addons/mod/feedback/pages/form/form.ts @@ -61,6 +61,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { title?: string; preview = false; + fromIndex = false; cmId!: number; courseId!: number; feedback?: AddonModFeedbackWSFeedback; @@ -96,6 +97,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { this.currentPage = CoreNavigator.getRouteNumberParam('page'); this.title = CoreNavigator.getRouteParam('title'); this.preview = !!CoreNavigator.getRouteBooleanParam('preview'); + this.fromIndex = !!CoreNavigator.getRouteBooleanParam('fromIndex'); await this.fetchData(); @@ -373,10 +375,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { * Function to link implemented features. */ showAnalysis(): void { - const indexPath = AddonModFeedbackModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.cmId}`; - const previousPath = CoreNavigator.getPreviousPath(); - - if (previousPath.match(new RegExp(indexPath + '$'))) { + if (this.fromIndex) { // Previous page is the index page, go back. CoreEvents.trigger(AddonModFeedbackProvider.FORM_SUBMITTED, { feedbackId: this.feedback!.id, @@ -389,7 +388,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { return; } - CoreNavigator.navigateToSitePath(indexPath, { + CoreNavigator.navigateToSitePath(AddonModFeedbackModuleHandlerService.PAGE_NAME + `/${this.courseId}/${this.cmId}`, { params: { module: this.module, tab: 'analysis', diff --git a/src/core/services/navigator.ts b/src/core/services/navigator.ts index da03518ff..a70122071 100644 --- a/src/core/services/navigator.ts +++ b/src/core/services/navigator.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { ActivatedRoute, NavigationStart, Params, Router as RouterService } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import { NavigationOptions } from '@ionic/angular/providers/nav-controller'; @@ -28,7 +28,6 @@ import { CoreUrlUtils } from '@services/utils/url'; import { CoreTextUtils } from '@services/utils/text'; import { makeSingleton, NavController, Router } from '@singletons'; import { CoreScreen } from './screen'; -import { filter } from 'rxjs/operators'; import { CoreApp } from './app'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; @@ -75,17 +74,6 @@ export class CoreNavigatorService { protected storedParams: Record = {}; protected lastParamId = 0; - protected currentPath?: string; - protected previousPath?: string; - - // @todo Param router is an optional param to let the mocking work. - constructor(router?: RouterService) { - router?.events.pipe(filter(event => event instanceof NavigationStart)).subscribe((routerEvent: NavigationStart) => { - // Using NavigationStart instead of NavigationEnd so it can be check on ngOnInit. - this.previousPath = this.currentPath; - this.currentPath = routerEvent.url; - }); - } /** * Check whether the active route is using the given path. @@ -267,17 +255,6 @@ export class CoreNavigatorService { return CoreUrlUtils.removeUrlParams(Router.url); } - /** - * Get the previous navigation route path. - * - * @return Previous path. - */ - getPreviousPath(): string { - // @todo: Remove this method and the used attributes. - // This is a quick workarround to avoid loops. Ie, in messages we can navigate to user profile and there to messages. - return CoreUrlUtils.removeUrlParams(this.previousPath || ''); - } - /** * Iterately get the params checking parent routes. * From 4b2b1c1e3e550c7795fc9a964b91cea18f8fda81 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 10 Jun 2021 14:55:09 +0200 Subject: [PATCH 4/5] MOBILE-3320 navigation: Review pending TODOs --- .../features/login/pages/credentials/credentials.ts | 1 - src/core/features/login/pages/reconnect/reconnect.ts | 12 ++++-------- src/core/features/mainmenu/pages/home/home.ts | 2 +- .../features/settings/services/settings-helper.ts | 1 - src/core/services/navigator.ts | 7 ------- src/core/services/sites.ts | 7 ++----- 6 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/core/features/login/pages/credentials/credentials.ts b/src/core/features/login/pages/credentials/credentials.ts index c50e0ddc5..714b06934 100644 --- a/src/core/features/login/pages/credentials/credentials.ts +++ b/src/core/features/login/pages/credentials/credentials.ts @@ -261,7 +261,6 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { this.siteId = id; - // @todo test that this is working properly. await CoreNavigator.navigateToSiteHome({ params: { urlToOpen: this.urlToOpen } }); } catch (error) { CoreLoginHelper.treatUserTokenError(siteUrl, error, username, password); diff --git a/src/core/features/login/pages/reconnect/reconnect.ts b/src/core/features/login/pages/reconnect/reconnect.ts index 850f8f050..f48433217 100644 --- a/src/core/features/login/pages/reconnect/reconnect.ts +++ b/src/core/features/login/pages/reconnect/reconnect.ts @@ -23,7 +23,7 @@ import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site'; import { CoreEvents } from '@singletons/events'; import { CoreError } from '@classes/errors/error'; -import { CoreNavigationOptions, CoreNavigator, CoreRedirectPayload } from '@services/navigator'; +import { CoreNavigationOptions, CoreNavigator } from '@services/navigator'; import { CoreForms } from '@singletons/form'; /** @@ -208,13 +208,9 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { this.credForm.controls['password'].reset(); // Go to the site initial page. - // @todo test that this is working properly (could we use navigateToSitePath instead?). - await CoreNavigator.navigateToSiteHome({ - params: { - redirectPath: this.page, - redirectOptions: this.pageOptions, - } as CoreRedirectPayload, - }); + this.page + ? await CoreNavigator.navigateToSitePath(this.page, { params: this.pageOptions }) + : await CoreNavigator.navigateToSiteHome(); } catch (error) { CoreLoginHelper.treatUserTokenError(this.siteUrl, error, this.username, password); diff --git a/src/core/features/mainmenu/pages/home/home.ts b/src/core/features/mainmenu/pages/home/home.ts index d8c38e377..201215b47 100644 --- a/src/core/features/mainmenu/pages/home/home.ts +++ b/src/core/features/mainmenu/pages/home/home.ts @@ -59,7 +59,7 @@ export class CoreMainMenuHomePage implements OnInit { */ ngOnInit(): void { this.route.queryParams.subscribe((params: Partial & { urlToOpen?: string }) => { - this.urlToOpen = params.urlToOpen; + this.urlToOpen = params.urlToOpen ?? this.urlToOpen; if (params.redirectPath) { this.pendingRedirect = { diff --git a/src/core/features/settings/services/settings-helper.ts b/src/core/features/settings/services/settings-helper.ts index 7144656c3..713407274 100644 --- a/src/core/features/settings/services/settings-helper.ts +++ b/src/core/features/settings/services/settings-helper.ts @@ -455,7 +455,6 @@ export class CoreSettingsHelperProvider { */ canIUsePrefersColorScheme(): boolean { // The following check will check browser support but system may differ from that. - // @todo Detect SO support to watch media query. return window.matchMedia('(prefers-color-scheme)').media !== 'not all'; } diff --git a/src/core/services/navigator.ts b/src/core/services/navigator.ts index a70122071..b31e38079 100644 --- a/src/core/services/navigator.ts +++ b/src/core/services/navigator.ts @@ -199,8 +199,6 @@ export class CoreNavigatorService { const siteId = options.siteId ?? CoreSites.getCurrentSiteId(); const navigationOptions: CoreNavigationOptions = CoreObject.without(options, ['siteId']); - // @todo: When this function was in ContentLinksHelper, this code was inside NgZone. Check if it's needed. - // If the path doesn't belong to a site, call standard navigation. if (siteId === CoreConstants.NO_SITE_ID) { return this.navigate(path, { @@ -408,10 +406,6 @@ export class CoreNavigatorService { * @return Whether navigation suceeded. */ protected async navigateToMainMenuPath(path: string, options: CoreNavigationOptions = {}): Promise { - // Due to DeepLinker, we need to remove the path from the URL before going to main menu. - // IonTabs checks the URL to determine which path to load for deep linking, so we clear the URL. - // @todo this.location.replaceState(''); - options = { preferCurrentTab: true, ...options, @@ -441,7 +435,6 @@ export class CoreNavigatorService { } // Open the path within the default main tab. - // @todo test that this is working as expected return this.navigate(`/main/${DEFAULT_MAIN_MENU_TAB}`, { ...options, params: { diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index 0c1dd10ce..2d14bda21 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -752,7 +752,6 @@ export class CoreSitesProvider { }; const siteId = this.getCurrentSiteId(); - const downloadUrl = CoreApp.getAppStoreUrl(storesConfig); if (downloadUrl != null) { @@ -773,10 +772,8 @@ export class CoreSitesProvider { } if (siteId) { - // Logout if it's the currentSite. - if (siteId == this.getCurrentSiteId()) { - await this.logout(); - } + // Logout the currentSite. + await this.logout(); // Always expire the token. await this.setSiteLoggedOut(siteId, true); From 4c305e954e6a2c3b24ff0806541332e97e53e0b3 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Thu, 10 Jun 2021 14:55:32 +0200 Subject: [PATCH 5/5] MOBILE-3320 e2e: Expose urlSchemes --- src/core/initializers/prepare-automated-tests.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/initializers/prepare-automated-tests.ts b/src/core/initializers/prepare-automated-tests.ts index 2f3961dde..46531f44f 100644 --- a/src/core/initializers/prepare-automated-tests.ts +++ b/src/core/initializers/prepare-automated-tests.ts @@ -16,6 +16,7 @@ import { ApplicationRef } from '@angular/core'; import { CorePushNotifications, CorePushNotificationsProvider } from '@features/pushnotifications/services/pushnotifications'; import { CoreApp, CoreAppProvider } from '@services/app'; import { CoreCronDelegate, CoreCronDelegateService } from '@services/cron'; +import { CoreCustomURLSchemes, CoreCustomURLSchemesProvider } from '@services/urlschemes'; import { Application } from '@singletons'; type AutomatedTestsWindow = Window & { @@ -23,6 +24,7 @@ type AutomatedTestsWindow = Window & { appProvider?: CoreAppProvider; cronProvider?: CoreCronDelegateService; pushNotifications?: CorePushNotificationsProvider; + urlSchemes?: CoreCustomURLSchemesProvider; }; function initializeAutomatedTestsWindow(window: AutomatedTestsWindow) { @@ -30,6 +32,7 @@ function initializeAutomatedTestsWindow(window: AutomatedTestsWindow) { window.appProvider = CoreApp.instance; window.cronProvider = CoreCronDelegate.instance; window.pushNotifications = CorePushNotifications.instance; + window.urlSchemes = CoreCustomURLSchemes.instance; } export default function(): void {