forked from CIT/Vmeda.Online
		
	MOBILE-3320 core: Refactor initializers
This commit is contained in:
		
							parent
							
								
									af0b3aa2b9
								
							
						
					
					
						commit
						f1bc354be6
					
				
							
								
								
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -3312,6 +3312,12 @@ | ||||
|       "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "@types/webpack-env": { | ||||
|       "version": "1.16.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz", | ||||
|       "integrity": "sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "@types/webpack-sources": { | ||||
|       "version": "0.1.8", | ||||
|       "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", | ||||
|  | ||||
| @ -131,6 +131,7 @@ | ||||
|     "@ionic/angular-toolkit": "^2.3.0", | ||||
|     "@types/faker": "^5.1.3", | ||||
|     "@types/node": "^12.12.64", | ||||
|     "@types/webpack-env": "^1.16.0", | ||||
|     "@typescript-eslint/eslint-plugin": "4.3.0", | ||||
|     "@typescript-eslint/parser": "4.3.0", | ||||
|     "eslint": "^7.6.0", | ||||
|  | ||||
| @ -12,9 +12,10 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { ApplicationInitStatus, APP_INITIALIZER, Injector } from '@angular/core'; | ||||
| import { ApplicationInitStatus, APP_INITIALIZER, Injectable, Injector } from '@angular/core'; | ||||
| import { setSingletonsInjector } from '@singletons'; | ||||
| 
 | ||||
| @Injectable() | ||||
| export class CoreApplicationInitStatus extends ApplicationInitStatus { | ||||
| 
 | ||||
|     constructor(injector: Injector) { | ||||
|  | ||||
| @ -15,18 +15,14 @@ | ||||
| import { HTTP_INTERCEPTORS } from '@angular/common/http'; | ||||
| import { ApplicationInitStatus, Injector, NgModule } from '@angular/core'; | ||||
| 
 | ||||
| import { Platform } from '@ionic/angular'; | ||||
| 
 | ||||
| import { CoreApplicationInitStatus } from './classes/application-init-status'; | ||||
| import { CoreFeaturesModule } from './features/features.module'; | ||||
| import { CoreFile } from './services/file'; | ||||
| import { CoreInit, CoreInitDelegate } from './services/init'; | ||||
| import { CoreInterceptor } from './classes/interceptor'; | ||||
| import { CoreSites, CORE_SITE_SCHEMAS } from './services/sites'; | ||||
| import { CoreUpdateManager } from './services/update-manager'; | ||||
| import { CORE_SITE_SCHEMAS } from './services/sites'; | ||||
| import { SITE_SCHEMA as FILEPOOL_SITE_SCHEMA } from './services/db/filepool'; | ||||
| import { SITE_SCHEMA as SITES_SITE_SCHEMA } from './services/db/sites'; | ||||
| import { SITE_SCHEMA as SYNC_SITE_SCHEMA } from './services/db/sync'; | ||||
| import { getInitializerProviders } from './initializers'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     imports: [ | ||||
| @ -44,42 +40,7 @@ import { SITE_SCHEMA as SYNC_SITE_SCHEMA } from './services/db/sync'; | ||||
|             ], | ||||
|             multi: true, | ||||
|         }, | ||||
|         ...getInitializerProviders(), | ||||
|     ], | ||||
| }) | ||||
| export class CoreModule { | ||||
| 
 | ||||
|     constructor(platform: Platform) { | ||||
|         // Register a handler for platform ready.
 | ||||
|         CoreInit.instance.registerProcess({ | ||||
|             name: 'CorePlatformReady', | ||||
|             priority: CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 400, | ||||
|             blocking: true, | ||||
|             load: async () => { | ||||
|                 await platform.ready(); | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         // Register the update manager as an init process.
 | ||||
|         CoreInit.instance.registerProcess(CoreUpdateManager.instance); | ||||
| 
 | ||||
|         // Restore the user's session during the init process.
 | ||||
|         CoreInit.instance.registerProcess({ | ||||
|             name: 'CoreRestoreSession', | ||||
|             priority: CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 200, | ||||
|             blocking: false, | ||||
|             load: CoreSites.instance.restoreSession.bind(CoreSites.instance), | ||||
|         }); | ||||
| 
 | ||||
|         // Register clear app tmp folder.
 | ||||
|         CoreInit.instance.registerProcess({ | ||||
|             name: 'CoreClearTmpFolder', | ||||
|             priority: CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 150, | ||||
|             blocking: false, | ||||
|             load: CoreFile.instance.clearTmpFolder.bind(CoreFile.instance), | ||||
|         }); | ||||
| 
 | ||||
|         // Execute the init processes.
 | ||||
|         CoreInit.instance.executeInitProcesses(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| export class CoreModule {} | ||||
|  | ||||
| @ -12,10 +12,9 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { APP_INITIALIZER, NgModule } from '@angular/core'; | ||||
| import { Platform } from '@ionic/angular'; | ||||
| 
 | ||||
| import { CoreInitDelegate } from '@services/init'; | ||||
| import { CoreEmulatorHelperProvider } from './services/emulator-helper'; | ||||
| import { CoreEmulatorComponentsModule } from './components/components.module'; | ||||
| 
 | ||||
| @ -141,20 +140,18 @@ import { ZipMock } from './services/zip'; | ||||
|             deps: [Platform, File], | ||||
|             useFactory: (platform: Platform, file: File): Zip => platform.is('cordova') ? new Zip() : new ZipMock(file), | ||||
|         }, | ||||
|         { | ||||
|             provide: APP_INITIALIZER, | ||||
|             deps: [Platform, CoreEmulatorHelperProvider], | ||||
|             useFactory: (platform: Platform, helperProvider: CoreEmulatorHelperProvider) => () => { | ||||
|                 if (platform.is('cordova')) { | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 return helperProvider.load(); | ||||
|             }, | ||||
|             multi: true, | ||||
|         }, | ||||
|     ], | ||||
| }) | ||||
| export class CoreEmulatorModule { | ||||
| 
 | ||||
|     constructor( | ||||
|         platform: Platform, | ||||
|         initDelegate: CoreInitDelegate, | ||||
|         helper: CoreEmulatorHelperProvider, | ||||
|     ) { | ||||
| 
 | ||||
|         if (!platform.is('cordova')) { | ||||
|             // Register an init process to load the Mocks that need it.
 | ||||
|             initDelegate.registerProcess(helper); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| export class CoreEmulatorModule {} | ||||
|  | ||||
| @ -16,7 +16,6 @@ import { Injectable } from '@angular/core'; | ||||
| import { File } from '@ionic-native/file/ngx'; | ||||
| 
 | ||||
| import { CoreFile } from '@services/file'; | ||||
| import { CoreInitDelegate, CoreInitHandler } from '@services/init'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| import { FileMock } from './file'; | ||||
| @ -25,14 +24,8 @@ import { FileTransferErrorMock } from './file-transfer'; | ||||
| /** | ||||
|  * Helper service for the emulator feature. It also acts as an init handler. | ||||
|  */ | ||||
| @Injectable({ | ||||
|     providedIn: 'root', | ||||
| }) | ||||
| export class CoreEmulatorHelperProvider implements CoreInitHandler { | ||||
| 
 | ||||
|     name = 'CoreEmulator'; | ||||
|     priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 500; | ||||
|     blocking = true; | ||||
| @Injectable({ providedIn: 'root' }) | ||||
| export class CoreEmulatorHelperProvider { | ||||
| 
 | ||||
|     protected logger: CoreLogger; | ||||
| 
 | ||||
|  | ||||
| @ -16,8 +16,7 @@ import { Component, OnInit } from '@angular/core'; | ||||
| import { NavController } from '@ionic/angular'; | ||||
| 
 | ||||
| import { CoreApp, CoreRedirectData } from '@services/app'; | ||||
| import { CoreInit } from '@services/init'; | ||||
| import { SplashScreen } from '@singletons'; | ||||
| import { ApplicationInit, SplashScreen } from '@singletons'; | ||||
| import { CoreConstants } from '@/core/constants'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { CoreLoginHelper } from '@features/login/services/login-helper'; | ||||
| @ -39,7 +38,7 @@ export class CoreLoginInitPage implements OnInit { | ||||
|      */ | ||||
|     async ngOnInit(): Promise<void> { | ||||
|         // Wait for the app to be ready.
 | ||||
|         await CoreInit.instance.ready(); | ||||
|         await ApplicationInit.instance.donePromise; | ||||
| 
 | ||||
|         // Check if there was a pending redirect.
 | ||||
|         const redirectData = CoreApp.instance.getRedirect(); | ||||
|  | ||||
| @ -15,10 +15,9 @@ | ||||
| import { NavController } from '@ionic/angular'; | ||||
| 
 | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreInit } from '@services/init'; | ||||
| import { CoreLoginInitPage } from '@features/login/pages/init/init'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { SplashScreen } from '@singletons'; | ||||
| import { ApplicationInit, SplashScreen } from '@singletons'; | ||||
| 
 | ||||
| import { mock, mockSingleton, renderComponent, RenderConfig } from '@/testing/utils'; | ||||
| 
 | ||||
| @ -29,7 +28,7 @@ describe('CoreLoginInitPage', () => { | ||||
| 
 | ||||
|     beforeEach(() => { | ||||
|         mockSingleton(CoreApp, { getRedirect: () => ({}) }); | ||||
|         mockSingleton(CoreInit, { ready: () => Promise.resolve() }); | ||||
|         mockSingleton(ApplicationInit, { donePromise: Promise.resolve() }); | ||||
|         mockSingleton(CoreSites, { isLoggedIn: () => false }); | ||||
|         mockSingleton(SplashScreen, ['hide']); | ||||
| 
 | ||||
| @ -52,7 +51,7 @@ describe('CoreLoginInitPage', () => { | ||||
|         const fixture = await renderComponent(CoreLoginInitPage, config); | ||||
| 
 | ||||
|         fixture.componentInstance.ngOnInit(); | ||||
|         await CoreInit.instance.ready(); | ||||
|         await ApplicationInit.instance.donePromise; | ||||
| 
 | ||||
|         expect(navController.navigateRoot).toHaveBeenCalledWith('/login/sites'); | ||||
|     }); | ||||
|  | ||||
| @ -15,8 +15,8 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { Router, CanLoad, CanActivate, UrlTree } from '@angular/router'; | ||||
| 
 | ||||
| import { CoreInit } from '@services/init'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { ApplicationInit } from '@singletons'; | ||||
| 
 | ||||
| @Injectable({ providedIn: 'root' }) | ||||
| export class AuthGuard implements CanLoad, CanActivate { | ||||
| @ -32,7 +32,7 @@ export class AuthGuard implements CanLoad, CanActivate { | ||||
|     } | ||||
| 
 | ||||
|     private async guard(): Promise<true | UrlTree> { | ||||
|         await CoreInit.instance.ready(); | ||||
|         await ApplicationInit.instance.donePromise; | ||||
| 
 | ||||
|         return CoreSites.instance.isLoggedIn() || this.router.parseUrl('/login'); | ||||
|     } | ||||
|  | ||||
							
								
								
									
										19
									
								
								src/core/initializers/clear-tmp-folder.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/core/initializers/clear-tmp-folder.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // (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 { CoreFile } from '@services/file'; | ||||
| 
 | ||||
| export default async function(): Promise<void> { | ||||
|     await CoreFile.instance.clearTmpFolder(); | ||||
| } | ||||
							
								
								
									
										33
									
								
								src/core/initializers/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/initializers/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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 { APP_INITIALIZER, Provider } from '@angular/core'; | ||||
| 
 | ||||
| export function getInitializerProviders(): Provider[] { | ||||
|     const context = require.context('./', false, /\.ts$/); | ||||
| 
 | ||||
|     return context.keys().reduce((providers, fileName) => { | ||||
|         const name = (fileName.match(/^(?:\.\/)?(.+)\.ts$/) || [])[1]; | ||||
| 
 | ||||
|         if (typeof name !== 'undefined' && name !== 'index') { | ||||
|             providers.push({ | ||||
|                 provide: APP_INITIALIZER, | ||||
|                 useValue: context(fileName).default, | ||||
|                 multi: true, | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         return providers; | ||||
|     }, [] as Provider[]); | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/core/initializers/load-update-manager.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/core/initializers/load-update-manager.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // (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 { CoreUpdateManager } from '@services/update-manager'; | ||||
| 
 | ||||
| export default async function(): Promise<void> { | ||||
|     await CoreUpdateManager.instance.load(); | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/core/initializers/override-window-open.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/core/initializers/override-window-open.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| // (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 { Platform } from '@singletons'; | ||||
| 
 | ||||
| export default async function(): Promise<void> { | ||||
|     await Platform.instance.ready(); | ||||
| 
 | ||||
|     if (!window.cordova?.InAppBrowser) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     window.open = window.cordova.InAppBrowser.open; | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/core/initializers/prepare-automated-tests.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/core/initializers/prepare-automated-tests.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| // (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 { ApplicationRef } from '@angular/core'; | ||||
| import { CoreApp, CoreAppProvider } from '@services/app'; | ||||
| import { CoreCron, CoreCronDelegate } from '@services/cron'; | ||||
| import { Application } from '@singletons'; | ||||
| 
 | ||||
| type AutomatedTestsWindow = Window & { | ||||
|     appRef?: ApplicationRef; | ||||
|     appProvider?: CoreAppProvider; | ||||
|     cronProvider?: CoreCronDelegate; | ||||
| }; | ||||
| 
 | ||||
| function initializeAutomatedTestsWindow(window: AutomatedTestsWindow) { | ||||
|     window.appRef = Application.instance; | ||||
|     window.appProvider = CoreApp.instance; | ||||
|     window.cronProvider = CoreCron.instance; | ||||
| } | ||||
| 
 | ||||
| export default function(): void { | ||||
|     if (!CoreAppProvider.isAutomated()) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     initializeAutomatedTestsWindow(window); | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/core/initializers/restore-session.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/core/initializers/restore-session.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // (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 { CoreSites } from '@services/sites'; | ||||
| 
 | ||||
| export default async function(): Promise<void> { | ||||
|     await CoreSites.instance.restoreSession(); | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/core/initializers/subscribe-to-keyboard-events.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/initializers/subscribe-to-keyboard-events.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| // (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 { CoreApp } from '@services/app'; | ||||
| import { NgZone, Keyboard } from '@singletons'; | ||||
| 
 | ||||
| export default function(): void { | ||||
|     const zone = NgZone.instance; | ||||
|     const app = CoreApp.instance; | ||||
|     const keyboard = Keyboard.instance; | ||||
| 
 | ||||
|     // Execute callbacks in the Angular zone, so change detection doesn't stop working.
 | ||||
|     keyboard.onKeyboardShow().subscribe(data => zone.run(() => app.onKeyboardShow(data.keyboardHeight))); | ||||
|     keyboard.onKeyboardHide().subscribe(() => zone.run(() => app.onKeyboardHide())); | ||||
|     keyboard.onKeyboardWillShow().subscribe(() => zone.run(() => app.onKeyboardWillShow())); | ||||
|     keyboard.onKeyboardWillHide().subscribe(() => zone.run(() => app.onKeyboardWillHide())); | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/core/initializers/wait-for-platform-ready.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/core/initializers/wait-for-platform-ready.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| // (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 { Platform } from '@singletons'; | ||||
| 
 | ||||
| export default async function(): Promise<void> { | ||||
|     await Platform.instance.ready(); | ||||
| } | ||||
| @ -12,7 +12,7 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Injectable, NgZone, ApplicationRef } from '@angular/core'; | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { Params, Router } from '@angular/router'; | ||||
| import { Connection } from '@ionic-native/network/ngx'; | ||||
| 
 | ||||
| @ -57,60 +57,17 @@ export class CoreAppProvider { | ||||
|     // Variables for DB.
 | ||||
|     protected createVersionsTableReady: Promise<void>; | ||||
| 
 | ||||
|     constructor( | ||||
|         appRef: ApplicationRef, | ||||
|         zone: NgZone, | ||||
|         protected router: Router, | ||||
|     ) { | ||||
|     constructor(protected router: Router) { | ||||
|         this.logger = CoreLogger.getInstance('CoreAppProvider'); | ||||
|         this.db = CoreDB.instance.getDB(DBNAME); | ||||
| 
 | ||||
|         // Create the schema versions table.
 | ||||
|         this.createVersionsTableReady = this.db.createTableFromSchema(SCHEMA_VERSIONS_TABLE_SCHEMA); | ||||
| 
 | ||||
|         Keyboard.instance.onKeyboardShow().subscribe((data) => { | ||||
|             // Execute the callback in the Angular zone, so change detection doesn't stop working.
 | ||||
|             zone.run(() => { | ||||
|                 document.body.classList.add('keyboard-is-open'); | ||||
|                 this.setKeyboardShown(true); | ||||
|                 // Error on iOS calculating size.
 | ||||
|                 // More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 .
 | ||||
|                 CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, data.keyboardHeight); | ||||
|             }); | ||||
|         }); | ||||
|         Keyboard.instance.onKeyboardHide().subscribe(() => { | ||||
|             // Execute the callback in the Angular zone, so change detection doesn't stop working.
 | ||||
|             zone.run(() => { | ||||
|                 document.body.classList.remove('keyboard-is-open'); | ||||
|                 this.setKeyboardShown(false); | ||||
|                 CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, 0); | ||||
|             }); | ||||
|         }); | ||||
|         Keyboard.instance.onKeyboardWillShow().subscribe(() => { | ||||
|             // Execute the callback in the Angular zone, so change detection doesn't stop working.
 | ||||
|             zone.run(() => { | ||||
|                 this.keyboardOpening = true; | ||||
|                 this.keyboardClosing = false; | ||||
|             }); | ||||
|         }); | ||||
|         Keyboard.instance.onKeyboardWillHide().subscribe(() => { | ||||
|             // Execute the callback in the Angular zone, so change detection doesn't stop working.
 | ||||
|             zone.run(() => { | ||||
|                 this.keyboardOpening = false; | ||||
|                 this.keyboardClosing = true; | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // @todo
 | ||||
|         // this.platform.registerBackButtonAction(() => {
 | ||||
|         //     this.backButtonAction();
 | ||||
|         // }, 100);
 | ||||
| 
 | ||||
|         // Export the app provider and appRef to control the application in Behat tests.
 | ||||
|         if (CoreAppProvider.isAutomated()) { | ||||
|             (<WindowForAutomatedTests> window).appProvider = this; | ||||
|             (<WindowForAutomatedTests> window).appRef = appRef; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -429,6 +386,44 @@ export class CoreAppProvider { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Notify that Keyboard has been shown. | ||||
|      * | ||||
|      * @param keyboardHeight Keyboard height. | ||||
|      */ | ||||
|     onKeyboardShow(keyboardHeight: number): void { | ||||
|         document.body.classList.add('keyboard-is-open'); | ||||
|         this.setKeyboardShown(true); | ||||
|         // Error on iOS calculating size.
 | ||||
|         // More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 .
 | ||||
|         CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, keyboardHeight); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Notify that Keyboard has been hidden. | ||||
|      */ | ||||
|     onKeyboardHide(): void { | ||||
|         document.body.classList.remove('keyboard-is-open'); | ||||
|         this.setKeyboardShown(false); | ||||
|         CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, 0); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Notify that Keyboard is about to be shown. | ||||
|      */ | ||||
|     onKeyboardWillShow(): void { | ||||
|         this.keyboardOpening = true; | ||||
|         this.keyboardClosing = false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Notify that Keyboard is about to be hidden. | ||||
|      */ | ||||
|     onKeyboardWillHide(): void { | ||||
|         this.keyboardOpening = false; | ||||
|         this.keyboardClosing = true; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set keyboard shown or hidden. | ||||
|      * | ||||
| @ -735,11 +730,3 @@ export type CoreAppSchema = { | ||||
|      */ | ||||
|     migrate?(db: SQLiteDB, oldVersion: number): Promise<void>; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Extended window type for automated tests. | ||||
|  */ | ||||
| export type WindowForAutomatedTests = Window & { | ||||
|     appProvider?: CoreAppProvider; | ||||
|     appRef?: ApplicationRef; | ||||
| }; | ||||
|  | ||||
| @ -14,7 +14,7 @@ | ||||
| 
 | ||||
| import { Injectable, NgZone } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreApp, CoreAppProvider } from '@services/app'; | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreConfig } from '@services/config'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| import { CoreConstants } from '@/core/constants'; | ||||
| @ -57,11 +57,6 @@ export class CoreCronDelegate { | ||||
|                 this.startNetworkHandlers(); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // Export the sync provider so Behat tests can trigger cron tasks without waiting.
 | ||||
|         if (CoreAppProvider.isAutomated()) { | ||||
|             (<WindowForAutomatedTests> window).cronProvider = this; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -532,10 +527,3 @@ export interface CoreCronHandler { | ||||
|      */ | ||||
|     execute?(siteId?: string, force?: boolean): Promise<void>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Extended window type for automated tests. | ||||
|  */ | ||||
| export type WindowForAutomatedTests = Window & { | ||||
|     cronProvider?: CoreCronDelegate; | ||||
| }; | ||||
|  | ||||
| @ -18,7 +18,6 @@ import { Md5 } from 'ts-md5/dist/md5'; | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreEvents } from '@singletons/events'; | ||||
| import { CoreFile } from '@services/file'; | ||||
| import { CoreInit } from '@services/init'; | ||||
| import { CorePluginFile } from '@services/plugin-file-delegate'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { CoreWS, CoreWSExternalFile } from '@services/ws'; | ||||
| @ -31,7 +30,7 @@ import { CoreUtils, PromiseDefer } from '@services/utils/utils'; | ||||
| import { SQLiteDB } from '@classes/sqlitedb'; | ||||
| import { CoreError } from '@classes/errors/error'; | ||||
| import { CoreConstants } from '@/core/constants'; | ||||
| import { makeSingleton, Network, NgZone, Translate } from '@singletons'; | ||||
| import { ApplicationInit, makeSingleton, Network, NgZone, Translate } from '@singletons'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| import { | ||||
|     APP_SCHEMA, | ||||
| @ -108,7 +107,7 @@ export class CoreFilepoolProvider { | ||||
|      */ | ||||
|     protected async init(): Promise<void> { | ||||
|         // Waiting for the app to be ready to start processing the queue.
 | ||||
|         await CoreInit.instance.ready(); | ||||
|         await ApplicationInit.instance.donePromise; | ||||
| 
 | ||||
|         this.checkQueueProcessing(); | ||||
| 
 | ||||
|  | ||||
| @ -1,179 +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.
 | ||||
| 
 | ||||
| import { Injectable } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreUtils, PromiseDefer, OrderedPromiseData } from '@services/utils/utils'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| 
 | ||||
| /** | ||||
|  * Interface that all init handlers must implement. | ||||
|  */ | ||||
| export type CoreInitHandler = { | ||||
|     /** | ||||
|      * A name to identify the handler. | ||||
|      */ | ||||
|     name: string; | ||||
| 
 | ||||
|     /** | ||||
|      * The highest priority is executed first. You should use values lower than MAX_RECOMMENDED_PRIORITY. | ||||
|      */ | ||||
|     priority?: number; | ||||
| 
 | ||||
|     /** | ||||
|      * Set this to true when this process should be resolved before any following one. | ||||
|      */ | ||||
|     blocking?: boolean; | ||||
| 
 | ||||
|     /** | ||||
|      * Function to execute during the init process. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     load(): Promise<void>; | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
|  * Provider for initialisation mechanisms. | ||||
|  */ | ||||
| @Injectable({ providedIn: 'root' }) | ||||
| export class CoreInitDelegate { | ||||
| 
 | ||||
|     static readonly DEFAULT_PRIORITY = 100; // Default priority for init processes.
 | ||||
|     static readonly MAX_RECOMMENDED_PRIORITY = 600; | ||||
| 
 | ||||
|     protected initProcesses: { [s: string]: CoreInitHandler } = {}; | ||||
|     protected logger: CoreLogger; | ||||
|     protected readiness?: CoreInitReadinessPromiseDefer<void>; | ||||
| 
 | ||||
|     constructor() { | ||||
|         this.logger = CoreLogger.getInstance('CoreInitDelegate'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Executes the registered init processes. | ||||
|      * | ||||
|      * Reserved for core use, do not call directly. | ||||
|      */ | ||||
|     executeInitProcesses(): void { | ||||
|         const ordered: CoreInitHandler[] = []; | ||||
| 
 | ||||
|         if (typeof this.readiness == 'undefined') { | ||||
|             this.initReadiness(); | ||||
|         } | ||||
| 
 | ||||
|         // Re-ordering by priority.
 | ||||
|         for (const name in this.initProcesses) { | ||||
|             ordered.push(this.initProcesses[name]); | ||||
|         } | ||||
|         ordered.sort((a, b) => (b.priority || 0) - (a.priority || 0)); | ||||
| 
 | ||||
|         const orderedPromises: OrderedPromiseData[] = ordered.map((data: CoreInitHandler) => ({ | ||||
|             function: this.prepareProcess.bind(this, data), | ||||
|             blocking: !!data.blocking, | ||||
|         })); | ||||
| 
 | ||||
|         // Execute all the processes in order to solve dependencies.
 | ||||
|         CoreUtils.instance.executeOrderedPromises(orderedPromises).finally(this.readiness!.resolve); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Init the readiness promise. | ||||
|      */ | ||||
|     protected initReadiness(): void { | ||||
|         this.readiness = CoreUtils.instance.promiseDefer(); | ||||
| 
 | ||||
|         // eslint-disable-next-line promise/catch-or-return
 | ||||
|         this.readiness.promise.then(() => this.readiness!.resolved = true); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Instantly returns if the app is ready. | ||||
|      * | ||||
|      * @return Whether it's ready. | ||||
|      */ | ||||
|     isReady(): boolean { | ||||
|         return this.readiness?.resolved || false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to return a function that executes the process. | ||||
|      * | ||||
|      * @param data The data of the process. | ||||
|      * @return Promise of the process. | ||||
|      */ | ||||
|     protected async prepareProcess(data: CoreInitHandler): Promise<void> { | ||||
|         this.logger.debug(`Executing init process '${data.name}'`); | ||||
| 
 | ||||
|         try { | ||||
|             await data.load(); | ||||
|         } catch (e) { | ||||
|             this.logger.error('Error while calling the init process \'' + data.name + '\'. ' + e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Notifies when the app is ready. This returns a promise that is resolved when the app is initialised. | ||||
|      * | ||||
|      * @return Resolved when the app is initialised. Never rejected. | ||||
|      */ | ||||
|     async ready(): Promise<void> { | ||||
|         if (typeof this.readiness == 'undefined') { | ||||
|             // Prevent race conditions if this is called before executeInitProcesses.
 | ||||
|             this.initReadiness(); | ||||
|         } | ||||
| 
 | ||||
|         await this.readiness!.promise; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Registers an initialisation process. | ||||
|      * | ||||
|      * @description | ||||
|      * Init processes can be used to add initialisation logic to the app. Anything that should block the user interface while | ||||
|      * some processes are done should be an init process. It is recommended to use a priority lower than MAX_RECOMMENDED_PRIORITY | ||||
|      * to make sure that your process does not happen before some essential other core processes. | ||||
|      * | ||||
|      * An init process should never change state or prompt user interaction. | ||||
|      * | ||||
|      * This delegate cannot be used by site plugins. | ||||
|      * | ||||
|      * @param instance The instance of the handler. | ||||
|      */ | ||||
|     registerProcess(handler: CoreInitHandler): void { | ||||
|         if (typeof handler.priority == 'undefined') { | ||||
|             handler.priority = CoreInitDelegate.DEFAULT_PRIORITY; | ||||
|         } | ||||
| 
 | ||||
|         if (typeof this.initProcesses[handler.name] != 'undefined') { | ||||
|             this.logger.log(`Process '${handler.name}' already registered.`); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.logger.log(`Registering process '${handler.name}'.`); | ||||
|         this.initProcesses[handler.name] = handler; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export class CoreInit extends makeSingleton(CoreInitDelegate) {} | ||||
| 
 | ||||
| /** | ||||
|  * Deferred promise for init readiness. | ||||
|  */ | ||||
| type CoreInitReadinessPromiseDefer<T> = PromiseDefer<T> & { | ||||
|     resolved?: boolean; // If true, readiness have been resolved.
 | ||||
| }; | ||||
| @ -15,10 +15,9 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreConfig } from '@services/config'; | ||||
| import { CoreInitHandler, CoreInitDelegate } from '@services/init'; | ||||
| import { CoreConstants } from '@/core/constants'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| 
 | ||||
| const VERSION_APPLIED = 'version_applied'; | ||||
| 
 | ||||
| @ -28,12 +27,7 @@ const VERSION_APPLIED = 'version_applied'; | ||||
|  * This service handles processes that need to be run when updating the app, like migrate Ionic 1 database data to Ionic 3. | ||||
|  */ | ||||
| @Injectable({ providedIn: 'root' }) | ||||
| export class CoreUpdateManagerProvider implements CoreInitHandler { | ||||
| 
 | ||||
|     // Data for init delegate.
 | ||||
|     name = 'CoreUpdateManager'; | ||||
|     priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 300; | ||||
|     blocking = true; | ||||
| export class CoreUpdateManagerProvider { | ||||
| 
 | ||||
|     protected logger: CoreLogger; | ||||
| 
 | ||||
|  | ||||
| @ -26,9 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom'; | ||||
| import { CoreMimetypeUtils } from '@services/utils/mimetype'; | ||||
| import { CoreTextUtils } from '@services/utils/text'; | ||||
| import { CoreWSError } from '@classes/errors/wserror'; | ||||
| import { | ||||
|     makeSingleton, Clipboard, InAppBrowser, Platform, FileOpener, WebIntent, QRScanner, Translate, | ||||
| } from '@singletons'; | ||||
| import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, QRScanner, Translate } from '@singletons'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| 
 | ||||
| type TreeNode<T> = T & { children: TreeNode<T>[] }; | ||||
| @ -48,9 +46,6 @@ export class CoreUtilsProvider { | ||||
| 
 | ||||
|     constructor(protected zone: NgZone) { | ||||
|         this.logger = CoreLogger.getInstance('CoreUtilsProvider'); | ||||
| 
 | ||||
|         // eslint-disable-next-line promise/catch-or-return
 | ||||
|         Platform.instance.ready().then(() => this.overrideWindowOpen()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -1606,17 +1601,6 @@ export class CoreUtilsProvider { | ||||
|         return new Promise(resolve => setTimeout(resolve, milliseconds)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Override native window.open with InAppBrowser if available. | ||||
|      */ | ||||
|     private overrideWindowOpen() { | ||||
|         if (!window.cordova?.InAppBrowser) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         window.open = window.cordova.InAppBrowser.open; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export class CoreUtils extends makeSingleton(CoreUtilsProvider) {} | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Injector, NgZone as NgZoneService } from '@angular/core'; | ||||
| import { ApplicationRef, ApplicationInitStatus, Injector, NgZone as NgZoneService } from '@angular/core'; | ||||
| import { HttpClient } from '@angular/common/http'; | ||||
| 
 | ||||
| import { | ||||
| @ -111,6 +111,8 @@ export class LoadingController extends makeSingleton(LoadingControllerService) { | ||||
| export class ModalController extends makeSingleton(ModalControllerService) {} | ||||
| export class ToastController extends makeSingleton(ToastControllerService) {} | ||||
| export class GestureController extends makeSingleton(GestureControllerService) {} | ||||
| export class ApplicationInit extends makeSingleton(ApplicationInitStatus) {} | ||||
| export class Application extends makeSingleton(ApplicationRef) {} | ||||
| 
 | ||||
| // Convert external libraries injectables.
 | ||||
| export class Translate extends makeSingleton(TranslateService) {} | ||||
|  | ||||
| @ -7,7 +7,8 @@ | ||||
|       "cordova-plugin-inappbrowser", | ||||
|       "cordova", | ||||
|       "dom-mediacapture-record", | ||||
|       "node" | ||||
|       "node", | ||||
|       "webpack-env" | ||||
|     ], | ||||
|     "paths": { | ||||
|       "@classes/*": ["core/classes/*"], | ||||
|  | ||||
| @ -26,7 +26,8 @@ | ||||
|         "dom-mediacapture-record", | ||||
|         "faker", | ||||
|         "jest", | ||||
|         "node" | ||||
|         "node", | ||||
|         "webpack-env" | ||||
|     ], | ||||
|     "paths": { | ||||
|       "@classes/*": ["core/classes/*"], | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user