diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..a6c7c2852 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +*.js diff --git a/.eslintrc.js b/.eslintrc.js index b53547465..842a24fc9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,4 @@ -var appConfig = { +const appConfig = { env: { browser: true, es6: true, diff --git a/.gitignore b/.gitignore index ebdd7f113..a8e7e18ea 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ npm-debug.log* /platforms /plugins /www + +/config/config.*.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..cf9b6ae4c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + + "files.associations": { + "config.json": "jsonc", + "config.*.json": "jsonc", + }, + +} diff --git a/angular.json b/angular.json index 91b0d65b3..7bbf70116 100644 --- a/angular.json +++ b/angular.json @@ -46,12 +46,6 @@ }, "configurations": { "production": { - "fileReplacements": [ - { - "replace": "src/environments/environment.ts", - "with": "src/environments/environment.prod.ts" - } - ], "optimization": true, "outputHashing": "all", "sourceMap": false, diff --git a/src/app/config.json b/config/config.json similarity index 91% rename from src/app/config.json rename to config/config.json index 4749c6bb2..1a9e41f39 100644 --- a/src/app/config.json +++ b/config/config.json @@ -1,9 +1,20 @@ +/** + * Application config. + * + * You can create your own environment files such as "config.prod.json" and "config.dev.json" + * to override some values. The values will be merged, so you don't need to duplicate everything + * in this file. + */ + { "app_id": "com.moodle.moodlemobile", "appname": "Moodle Mobile", "desktopappname": "Moodle Desktop", "versioncode": 3930, + + // @todo This could be read from package.json. "versionname": "3.9.3-dev", + "cache_update_frequency_usually": 420000, "cache_update_frequency_often": 1200000, "cache_update_frequency_sometimes": 3600000, diff --git a/config/utils.js b/config/utils.js new file mode 100644 index 000000000..00f16c041 --- /dev/null +++ b/config/utils.js @@ -0,0 +1,48 @@ +// (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. + +const { execSync } = require('child_process'); +const { resolve } = require('path'); + +export function getConfig(environment) { + const { parse: parseJsonc } = require('jsonc-parser'); + const { readFileSync, existsSync } = require('fs'); + const envSuffixesMap = { + testing: ['test', 'testing'], + development: ['dev', 'development'], + production: ['prod', 'production'], + }; + const config = parseJsonc(readFileSync(resolve('config/config.json')).toString()); + const envSuffixes = (envSuffixesMap[environment] || []); + const envConfigPath = envSuffixes.map(suffix => resolve(`config/config.${suffix}.json`)).find(existsSync); + + if (envConfigPath) { + const envConfig = parseJsonc(readFileSync(envConfigPath).toString()); + + for (const [key, value] of Object.entries(envConfig)) { + config[key] = value; + } + } + + return config; +} + +export function getBuild(environment) { + return { + environment, + isProduction: environment === 'production', + lastCommitHash: execSync('git log -1 --pretty=format:"%H"').toString(), + compilationTime: Date.now(), + }; +} diff --git a/config/webpack.config.js b/config/webpack.config.js index c3ddbe5ca..8a850f580 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { webpack } = require('webpack'); +const webpack = require('webpack'); +const { getConfig, getBuild } = require('./utils'); const { resolve } = require('path'); -module.exports = (config, options, targetOptions) => { +module.exports = config => { config.resolve.alias['@'] = resolve('src'); config.resolve.alias['@addon'] = resolve('src/app/addon'); config.resolve.alias['@app'] = resolve('src/app'); @@ -27,5 +28,14 @@ module.exports = (config, options, targetOptions) => { config.resolve.alias['@services'] = resolve('src/app/services'); config.resolve.alias['@singletons'] = resolve('src/app/singletons'); + config.plugins.push( + new webpack.DefinePlugin({ + 'window.MoodleApp': { + CONFIG: JSON.stringify(getConfig(process.env.NODE_ENV || 'development')), + BUILD: JSON.stringify(getBuild(process.env.NODE_ENV || 'development')), + }, + }), + ); + return config; }; diff --git a/package-lock.json b/package-lock.json index db4ec28a4..738a386c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12519,6 +12519,12 @@ "minimist": "^1.2.5" } }, + "jsonc-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "dev": true + }, "jsonfile": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", diff --git a/package.json b/package.json index 678bdd3f2..94694b8ac 100644 --- a/package.json +++ b/package.json @@ -144,6 +144,7 @@ "gulp-slash": "^1.1.3", "jest": "^26.5.0", "jest-preset-angular": "^8.3.1", + "jsonc-parser": "^2.3.1", "ts-jest": "^26.4.1", "ts-node": "~8.3.0", "typescript": "~3.9.5" diff --git a/src/app/classes/site.ts b/src/app/classes/site.ts index 7ff9b058d..e798c2a64 100644 --- a/src/app/classes/site.ts +++ b/src/app/classes/site.ts @@ -26,7 +26,6 @@ import { CoreTimeUtils } from '@services/utils/time'; import { CoreUrlUtils, CoreUrlParams } from '@services/utils/url'; import { CoreUtils, PromiseDefer } from '@services/utils/utils'; import { CoreConstants } from '@core/constants'; -import CoreConfigConstants from '@app/config.json'; import { SQLiteDB } from '@classes/sqlitedb'; import { CoreError } from '@classes/errors/error'; import { CoreWSError } from '@classes/errors/wserror'; @@ -73,10 +72,10 @@ export class CoreSite { // Possible cache update frequencies. protected readonly UPDATE_FREQUENCIES = [ - CoreConfigConstants.cache_update_frequency_usually || 420000, - CoreConfigConstants.cache_update_frequency_often || 1200000, - CoreConfigConstants.cache_update_frequency_sometimes || 3600000, - CoreConfigConstants.cache_update_frequency_rarely || 43200000, + CoreConstants.CONFIG.cache_update_frequency_usually || 420000, + CoreConstants.CONFIG.cache_update_frequency_often || 1200000, + CoreConstants.CONFIG.cache_update_frequency_sometimes || 3600000, + CoreConstants.CONFIG.cache_update_frequency_rarely || 43200000, ]; // Rest of variables. @@ -227,9 +226,9 @@ export class CoreSite { * @return Site name. */ getSiteName(): string { - if (CoreConfigConstants.sitename) { + if (CoreConstants.CONFIG.sitename) { // Overridden by config. - return CoreConfigConstants.sitename; + return CoreConstants.CONFIG.sitename; } else { return this.infos?.sitename || ''; } @@ -1284,7 +1283,7 @@ export class CoreSite { */ async checkLocalMobilePlugin(retrying?: boolean): Promise { const checkUrl = this.siteUrl + '/local/mobile/check.php'; - const service = CoreConfigConstants.wsextservice; + const service = CoreConstants.CONFIG.wsextservice; if (!service) { // External service not defined. diff --git a/src/app/core/constants.ts b/src/app/core/constants.ts index 41c7c1b3f..087a16e77 100644 --- a/src/app/core/constants.ts +++ b/src/app/core/constants.ts @@ -28,6 +28,7 @@ export const enum ContextLevel { * Static class to contain all the core constants. */ export class CoreConstants { + /* eslint-disable max-len */ static readonly SECONDS_YEAR = 31536000; @@ -100,9 +101,14 @@ export class CoreConstants { static readonly FEATURE_SHOW_DESCRIPTION = 'showdescription'; // True if module can show description on course main page. static readonly FEATURE_USES_QUESTIONS = 'usesquestions'; // True if module uses the question bank. - // Possbile archetypes for modules. + // Possible archetypes for modules. static readonly MOD_ARCHETYPE_OTHER = 0; // Unspecified module archetype. static readonly MOD_ARCHETYPE_RESOURCE = 1; // Resource-like type module. static readonly MOD_ARCHETYPE_ASSIGNMENT = 2; // Assignment module archetype. static readonly MOD_ARCHETYPE_SYSTEM = 3; // System (not user-addable) module archetype. + + // Config & environment constants. + static readonly CONFIG = (window as unknown as MoodleAppWindow).MoodleApp.CONFIG; // Data parsed from config.json files. + static readonly BUILD = (window as unknown as MoodleAppWindow).MoodleApp.BUILD; // Environment info. + } diff --git a/src/app/services/app.ts b/src/app/services/app.ts index 5f983adcd..8d52f1267 100644 --- a/src/app/services/app.ts +++ b/src/app/services/app.ts @@ -20,7 +20,7 @@ import { CoreDB } from '@services/db'; import { CoreEvents, CoreEventsProvider } from '@services/events'; import { CoreUtils, PromiseDefer } from '@services/utils/utils'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; -import CoreConfigConstants from '@app/config.json'; +import { CoreConstants } from '@core/constants'; import { makeSingleton, Keyboard, Network, StatusBar, Platform } from '@singletons/core.singletons'; import { CoreLogger } from '@singletons/logger'; @@ -645,21 +645,21 @@ export class CoreAppProvider { * Set StatusBar color depending on platform. */ setStatusBarColor(): void { - if (typeof CoreConfigConstants.statusbarbgios == 'string' && this.isIOS()) { + if (typeof CoreConstants.CONFIG.statusbarbgios == 'string' && this.isIOS()) { // IOS Status bar properties. StatusBar.instance.overlaysWebView(false); - StatusBar.instance.backgroundColorByHexString(CoreConfigConstants.statusbarbgios); - CoreConfigConstants.statusbarlighttextios ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); - } else if (typeof CoreConfigConstants.statusbarbgandroid == 'string' && this.isAndroid()) { + StatusBar.instance.backgroundColorByHexString(CoreConstants.CONFIG.statusbarbgios); + CoreConstants.CONFIG.statusbarlighttextios ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); + } else if (typeof CoreConstants.CONFIG.statusbarbgandroid == 'string' && this.isAndroid()) { // Android Status bar properties. - StatusBar.instance.backgroundColorByHexString(CoreConfigConstants.statusbarbgandroid); - CoreConfigConstants.statusbarlighttextandroid ? + StatusBar.instance.backgroundColorByHexString(CoreConstants.CONFIG.statusbarbgandroid); + CoreConstants.CONFIG.statusbarlighttextandroid ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); - } else if (typeof CoreConfigConstants.statusbarbg == 'string') { + } else if (typeof CoreConstants.CONFIG.statusbarbg == 'string') { // Generic Status bar properties. this.isIOS() && StatusBar.instance.overlaysWebView(false); - StatusBar.instance.backgroundColorByHexString(CoreConfigConstants.statusbarbg); - CoreConfigConstants.statusbarlighttext ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); + StatusBar.instance.backgroundColorByHexString(CoreConstants.CONFIG.statusbarbg); + CoreConstants.CONFIG.statusbarlighttext ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); } else { // Default Status bar properties. this.isAndroid() ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); @@ -670,14 +670,14 @@ export class CoreAppProvider { * Reset StatusBar color if any was set. */ resetStatusBarColor(): void { - if (typeof CoreConfigConstants.statusbarbgremotetheme == 'string' && - ((typeof CoreConfigConstants.statusbarbgios == 'string' && this.isIOS()) || - (typeof CoreConfigConstants.statusbarbgandroid == 'string' && this.isAndroid()) || - typeof CoreConfigConstants.statusbarbg == 'string')) { + if (typeof CoreConstants.CONFIG.statusbarbgremotetheme == 'string' && + ((typeof CoreConstants.CONFIG.statusbarbgios == 'string' && this.isIOS()) || + (typeof CoreConstants.CONFIG.statusbarbgandroid == 'string' && this.isAndroid()) || + typeof CoreConstants.CONFIG.statusbarbg == 'string')) { // If the status bar has been overriden and there's a fallback color for remote themes, use it now. this.isIOS() && StatusBar.instance.overlaysWebView(false); - StatusBar.instance.backgroundColorByHexString(CoreConfigConstants.statusbarbgremotetheme); - CoreConfigConstants.statusbarlighttextremotetheme ? + StatusBar.instance.backgroundColorByHexString(CoreConstants.CONFIG.statusbarbgremotetheme); + CoreConstants.CONFIG.statusbarlighttextremotetheme ? StatusBar.instance.styleLightContent() : StatusBar.instance.styleDefault(); } } diff --git a/src/app/services/file.ts b/src/app/services/file.ts index 7ad27e5cf..6d9702625 100644 --- a/src/app/services/file.ts +++ b/src/app/services/file.ts @@ -21,7 +21,7 @@ import { CoreWSExternalFile } from '@services/ws'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; -import CoreConfigConstants from '@app/config.json'; +import { CoreConstants } from '@core/constants'; import { CoreError } from '@classes/errors/error'; import { CoreLogger } from '@singletons/logger'; @@ -1227,7 +1227,7 @@ export class CoreFileProvider { return src; } - return src.replace(CoreConfigConstants.ioswebviewscheme + '://localhost/_app_file_', 'file://'); + return src.replace(CoreConstants.CONFIG.ioswebviewscheme + '://localhost/_app_file_', 'file://'); } /** diff --git a/src/app/services/lang.ts b/src/app/services/lang.ts index 5a4046615..8daaa3171 100644 --- a/src/app/services/lang.ts +++ b/src/app/services/lang.ts @@ -14,7 +14,7 @@ import { Injectable } from '@angular/core'; -import CoreConfigConstants from '@app/config.json'; +import { CoreConstants } from '@core/constants'; import { LangChangeEvent } from '@ngx-translate/core'; import { CoreAppProvider } from '@services/app'; import { CoreConfig } from '@services/config'; @@ -29,7 +29,7 @@ import * as moment from 'moment'; export class CoreLangProvider { protected fallbackLanguage = 'en'; // Always use English as fallback language since it contains all strings. - protected defaultLanguage = CoreConfigConstants.default_lang || 'en'; // Lang to use if device lang not valid or is forced. + protected defaultLanguage = CoreConstants.CONFIG.default_lang || 'en'; // Lang to use if device lang not valid or is forced. protected currentLanguage?: string; // Save current language in a variable to speed up the get function. protected customStrings: CoreLanguageObject = {}; // Strings defined using the admin tool. protected customStringsRaw?: string; @@ -252,21 +252,21 @@ export class CoreLangProvider { } // User hasn't defined a language. If default language is forced, use it. - if (CoreConfigConstants.default_lang && CoreConfigConstants.forcedefaultlanguage) { - return CoreConfigConstants.default_lang; + if (CoreConstants.CONFIG.default_lang && CoreConstants.CONFIG.forcedefaultlanguage) { + return CoreConstants.CONFIG.default_lang; } // No forced language, try to get current language from browser. let preferredLanguage = navigator.language.toLowerCase(); if (preferredLanguage.indexOf('-') > -1) { // Language code defined by locale has a dash, like en-US or es-ES. Check if it's supported. - if (CoreConfigConstants.languages && typeof CoreConfigConstants.languages[preferredLanguage] == 'undefined') { + if (CoreConstants.CONFIG.languages && typeof CoreConstants.CONFIG.languages[preferredLanguage] == 'undefined') { // Code is NOT supported. Fallback to language without dash. E.g. 'en-US' would fallback to 'en'. preferredLanguage = preferredLanguage.substr(0, preferredLanguage.indexOf('-')); } } - if (typeof CoreConfigConstants.languages[preferredLanguage] == 'undefined') { + if (typeof CoreConstants.CONFIG.languages[preferredLanguage] == 'undefined') { // Language not supported, use default language. return this.defaultLanguage; } diff --git a/src/app/services/local-notifications.ts b/src/app/services/local-notifications.ts index 9c2175d44..6db15b711 100644 --- a/src/app/services/local-notifications.ts +++ b/src/app/services/local-notifications.ts @@ -26,7 +26,6 @@ import { CoreSite } from '@classes/site'; import { CoreQueueRunner } from '@classes/queue-runner'; import { CoreError } from '@classes/errors/error'; import { CoreConstants } from '@core/constants'; -import CoreConfigConstants from '@app/config.json'; import { makeSingleton, NgZone, Platform, Translate, LocalNotifications, Push, Device } from '@singletons/core.singletons'; import { CoreLogger } from '@singletons/logger'; @@ -611,7 +610,7 @@ export class CoreLocalNotificationsProvider { if (CoreApp.instance.isAndroid()) { notification.icon = notification.icon || 'res://icon'; notification.smallIcon = notification.smallIcon || 'res://smallicon'; - notification.color = notification.color || CoreConfigConstants.notificoncolor; + notification.color = notification.color || CoreConstants.CONFIG.notificoncolor; if (notification.led !== false) { let ledColor = 'FF9900'; diff --git a/src/app/services/sites.ts b/src/app/services/sites.ts index 923803668..d589c941b 100644 --- a/src/app/services/sites.ts +++ b/src/app/services/sites.ts @@ -24,7 +24,6 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; import { CoreConstants } from '@core/constants'; -import CoreConfigConstants from '@app/config.json'; import { CoreSite, CoreSiteWSPreSets, @@ -278,7 +277,7 @@ export class CoreSitesProvider { * @return Site data if it's a demo site, undefined otherwise. */ getDemoSiteData(name: string): CoreSitesDemoSiteData | undefined { - const demoSites = CoreConfigConstants.demo_sites; + const demoSites = CoreConstants.CONFIG.demo_sites; name = name.toLowerCase(); if (typeof demoSites != 'undefined' && typeof demoSites[name] != 'undefined') { @@ -396,7 +395,7 @@ export class CoreSitesProvider { }); } - data.service = data.service || CoreConfigConstants.wsservice; + data.service = data.service || CoreConstants.CONFIG.wsservice; this.services[siteUrl] = data.service; // No need to store it in DB. if (data.coreSupported || (data.code != CoreConstants.LOGIN_SSO_CODE && data.code != CoreConstants.LOGIN_SSO_INAPP_CODE)) { @@ -746,7 +745,7 @@ export class CoreSitesProvider { } // Return default service. - return CoreConfigConstants.wsservice; + return CoreConstants.CONFIG.wsservice; } /** @@ -883,7 +882,7 @@ export class CoreSitesProvider { } const requiredVersion = this.convertVersionName(config.tool_mobile_minimumversion); - const appVersion = this.convertVersionName(CoreConfigConstants.versionname); + const appVersion = this.convertVersionName(CoreConstants.CONFIG.versionname); if (requiredVersion > appVersion) { const storesConfig: CoreStoreConfig = { @@ -1215,7 +1214,7 @@ export class CoreSitesProvider { id: site.id, siteUrl: site.siteUrl, fullName: siteInfo?.fullname, - siteName: CoreConfigConstants.sitename ?? siteInfo?.sitename, + siteName: CoreConstants.CONFIG.sitename ?? siteInfo?.sitename, avatar: siteInfo?.userpictureurl, siteHomeId: siteInfo?.siteid || 1, }; diff --git a/src/app/services/update-manager.ts b/src/app/services/update-manager.ts index daa952309..2245269e6 100644 --- a/src/app/services/update-manager.ts +++ b/src/app/services/update-manager.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreConfig } from '@services/config'; import { CoreInitHandler, CoreInitDelegate } from '@services/init'; -import CoreConfigConstants from '@app/config.json'; +import { CoreConstants } from '@core/constants'; import { makeSingleton } from '@singletons/core.singletons'; import { CoreLogger } from '@singletons/logger'; @@ -49,7 +49,7 @@ export class CoreUpdateManagerProvider implements CoreInitHandler { */ async load(): Promise { const promises = []; - const versionCode = CoreConfigConstants.versioncode; + const versionCode = CoreConstants.CONFIG.versioncode; const versionApplied = await CoreConfig.instance.get(VERSION_APPLIED, 0); diff --git a/src/app/services/utils/url.ts b/src/app/services/utils/url.ts index c5ceb35a3..51725c131 100644 --- a/src/app/services/utils/url.ts +++ b/src/app/services/utils/url.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { CoreLang } from '@services/lang'; import { CoreTextUtils } from '@services/utils/text'; -import CoreConfigConstants from '@app/config.json'; +import { CoreConstants } from '@/app/core/constants'; import { makeSingleton } from '@singletons/core.singletons'; import { CoreUrl } from '@singletons/url'; @@ -442,7 +442,7 @@ export class CoreUrlUtilsProvider { return scheme == 'cdvfile' || scheme == 'file' || scheme == 'filesystem' || - scheme == CoreConfigConstants.ioswebviewscheme; + scheme == CoreConstants.CONFIG.ioswebviewscheme; } /** diff --git a/src/app/singletons/logger.ts b/src/app/singletons/logger.ts index c31c3d008..0c49642f0 100644 --- a/src/app/singletons/logger.ts +++ b/src/app/singletons/logger.ts @@ -13,8 +13,8 @@ // limitations under the License. import moment from 'moment'; -import { environment } from '@/environments/environment'; +import { CoreConstants } from '@core/constants'; /** * Log function type. @@ -57,7 +57,7 @@ export class CoreLogger { */ static getInstance(className: string): CoreLogger { // Disable log on production. - if (environment.production) { + if (CoreConstants.BUILD.isProduction) { // eslint-disable-next-line no-console console.warn('Log is disabled in production app'); diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts deleted file mode 100644 index c4075fc01..000000000 --- a/src/environments/environment.prod.ts +++ /dev/null @@ -1,17 +0,0 @@ -// (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. - -export const environment = { - production: true, -}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts deleted file mode 100644 index c52655b35..000000000 --- a/src/environments/environment.ts +++ /dev/null @@ -1,30 +0,0 @@ -// (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. - -// This file can be replaced during build by using the `fileReplacements` array. -// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. -// The list of file replacements can be found in `angular.json`. - -export const environment = { - production: false, -}; - -/* - * For easier debugging in development mode, you can import the following file - * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. - * - * This import should be commented out in production mode because it will have a negative impact - * on performance if an error is thrown. - */ -// import 'zone.js/dist/zone-error'; // Included with Angular CLI. diff --git a/src/main.ts b/src/main.ts index 89a9097b2..12a0be150 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,9 +16,9 @@ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; +import { CoreConstants } from './app/core/constants'; -if (environment.production) { +if (CoreConstants.BUILD.isProduction) { enableProdMode(); } diff --git a/src/tests/setup.ts b/src/tests/setup.ts index aba69b950..0a2d9049f 100644 --- a/src/tests/setup.ts +++ b/src/tests/setup.ts @@ -12,4 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +/* eslint-disable @typescript-eslint/naming-convention */ + import 'jest-preset-angular'; + +import { getConfig, getBuild } from '../../config/utils'; + +(window as unknown as MoodleAppWindow).MoodleApp = { + CONFIG: getConfig('testing'), + BUILD: getBuild('testing'), +}; diff --git a/src/types/global.d.ts b/src/types/global.d.ts index fb74b1408..2e42b5cb4 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -12,17 +12,69 @@ // See the License for the specific language governing permissions and // limitations under the License. -import ''; +/* eslint-disable @typescript-eslint/naming-convention */ + +import { CoreSitesDemoSiteData } from '@/app/services/sites'; declare global { interface Window { - - // eslint-disable-next-line @typescript-eslint/naming-convention __Zone_disable_customElements: boolean; - } + type MoodleAppWindow = { + MoodleApp: { + CONFIG: { + app_id: string; + appname: string; + desktopappname: 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>; + font_sizes: number[]; + customurlscheme: string; + siteurl: string; + sitename: string; + multisitesdisplay: string; + sitefindersettings: Record; + onlyallowlistedsites: boolean; + skipssoconfirmation: boolean; + forcedefaultlanguage: boolean; + privacypolicy: string; + notificoncolor: string; + statusbarbg: boolean; + statusbarlighttext: boolean; + statusbarbgios: string; + statusbarlighttextios: boolean; + statusbarbgandroid: string; + statusbarlighttextandroid: boolean; + statusbarbgremotetheme: string; + statusbarlighttextremotetheme: boolean; + enableanalytics: boolean; + enableonboarding: boolean; + forceColorScheme: string; + forceLoginLogo: boolean; + ioswebviewscheme: string; + appstores: Record; + }; + + BUILD: { + environment: string; + isProduction: boolean; + lastCommitHash: string; + compilationTime: number; + }; + }; + }; + } /**