MOBILE-4081 core: Clean up emulator module

main
Noel De Martin 2022-06-20 18:26:27 +02:00
parent ed50d3d76a
commit 34863362c8
6 changed files with 134 additions and 108 deletions

View File

@ -47,7 +47,7 @@ import { CORE_CONTENTLINKS_SERVICES } from '@features/contentlinks/contentlinks.
import { CORE_COURSE_SERVICES } from '@features/course/course.module'; import { CORE_COURSE_SERVICES } from '@features/course/course.module';
import { CORE_COURSES_SERVICES } from '@features/courses/courses.module'; import { CORE_COURSES_SERVICES } from '@features/courses/courses.module';
import { CORE_EDITOR_SERVICES } from '@features/editor/editor.module'; import { CORE_EDITOR_SERVICES } from '@features/editor/editor.module';
import { IONIC_NATIVE_SERVICES } from '@features/emulator/emulator.module'; import { CORE_NATIVE_SERVICES } from '@features/native/native.module';
import { CORE_FILEUPLOADER_SERVICES } from '@features/fileuploader/fileuploader.module'; import { CORE_FILEUPLOADER_SERVICES } from '@features/fileuploader/fileuploader.module';
import { CORE_FILTER_SERVICES } from '@features/filter/filter.module'; import { CORE_FILTER_SERVICES } from '@features/filter/filter.module';
import { CORE_GRADES_SERVICES } from '@features/grades/grades.module'; import { CORE_GRADES_SERVICES } from '@features/grades/grades.module';
@ -285,7 +285,7 @@ export class CoreCompileProvider {
...CORE_STYLE_SERVICES, ...CORE_STYLE_SERVICES,
...CORE_USER_SERVICES, ...CORE_USER_SERVICES,
...CORE_XAPI_SERVICES, ...CORE_XAPI_SERVICES,
...IONIC_NATIVE_SERVICES, ...CORE_NATIVE_SERVICES,
...this.OTHER_SERVICES, ...this.OTHER_SERVICES,
...extraProviders, ...extraProviders,
...ADDON_BADGES_SERVICES, ...ADDON_BADGES_SERVICES,

View File

@ -13,63 +13,21 @@
// limitations under the License. // limitations under the License.
import { APP_INITIALIZER, NgModule } from '@angular/core'; import { APP_INITIALIZER, NgModule } from '@angular/core';
import { Platform } from '@ionic/angular';
import { CoreEmulatorHelperProvider } from './services/emulator-helper'; import { CoreEmulatorHelper } from './services/emulator-helper';
import { CoreEmulatorComponentsModule } from './components/components.module'; import { CoreEmulatorComponentsModule } from './components/components.module';
// Ionic Native services. // Ionic Native services.
import { Badge } from '@ionic-native/badge/ngx';
import { Camera } from '@ionic-native/camera/ngx'; import { Camera } from '@ionic-native/camera/ngx';
import { Chooser } from '@ionic-native/chooser/ngx';
import { Clipboard } from '@ionic-native/clipboard/ngx'; import { Clipboard } from '@ionic-native/clipboard/ngx';
import { Device } from '@ionic-native/device/ngx';
import { Diagnostic } from '@ionic-native/diagnostic/ngx';
import { File } from '@ionic-native/file/ngx'; import { File } from '@ionic-native/file/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx'; import { FileOpener } from '@ionic-native/file-opener/ngx';
import { FileTransfer } from '@ionic-native/file-transfer/ngx'; import { FileTransfer } from '@ionic-native/file-transfer/ngx';
import { Geolocation } from '@ionic-native/geolocation/ngx'; import { Geolocation } from '@ionic-native/geolocation/ngx';
import { HTTP } from '@ionic-native/http/ngx';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';
import { WebView } from '@ionic-native/ionic-webview/ngx';
import { Keyboard } from '@ionic-native/keyboard/ngx';
import { LocalNotifications } from '@ionic-native/local-notifications/ngx';
import { Media } from '@ionic-native/media/ngx';
import { MediaCapture } from '@ionic-native/media-capture/ngx'; import { MediaCapture } from '@ionic-native/media-capture/ngx';
import { Push } from '@ionic-native/push/ngx';
import { QRScanner } from '@ionic-native/qr-scanner/ngx';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { SQLite } from '@ionic-native/sqlite/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { WebIntent } from '@ionic-native/web-intent/ngx';
import { Zip } from '@ionic-native/zip/ngx'; import { Zip } from '@ionic-native/zip/ngx';
export const IONIC_NATIVE_SERVICES = [
Badge,
Camera,
Chooser,
Clipboard,
Device,
Diagnostic,
File,
FileOpener,
FileTransfer,
Geolocation,
HTTP,
InAppBrowser,
Keyboard,
LocalNotifications,
Media,
MediaCapture,
Push,
QRScanner,
SplashScreen,
StatusBar,
SQLite,
WebIntent,
WebView,
Zip,
];
// Mock services. // Mock services.
import { CameraMock } from './services/camera'; import { CameraMock } from './services/camera';
import { ClipboardMock } from './services/clipboard'; import { ClipboardMock } from './services/clipboard';
@ -80,6 +38,7 @@ import { GeolocationMock } from './services/geolocation';
import { InAppBrowserMock } from './services/inappbrowser'; import { InAppBrowserMock } from './services/inappbrowser';
import { MediaCaptureMock } from './services/media-capture'; import { MediaCaptureMock } from './services/media-capture';
import { ZipMock } from './services/zip'; import { ZipMock } from './services/zip';
import { CorePlatform } from '@services/platform';
/** /**
* This module handles the emulation of Cordova plugins in browser and desktop. * This module handles the emulation of Cordova plugins in browser and desktop.
@ -91,81 +50,54 @@ import { ZipMock } from './services/zip';
* functions we check if the app is running in mobile or not, and then provide the right service to use. * functions we check if the app is running in mobile or not, and then provide the right service to use.
*/ */
@NgModule({ @NgModule({
declarations: [
],
imports: [ imports: [
CoreEmulatorComponentsModule, CoreEmulatorComponentsModule,
], ],
providers: [ providers: [
Badge,
{ {
provide: Camera, provide: Camera,
deps: [Platform], useFactory: (): Camera => CorePlatform.is('cordova') ? new Camera() : new CameraMock(),
useFactory: (platform: Platform): Camera => platform.is('cordova') ? new Camera() : new CameraMock(),
}, },
Chooser,
{ {
provide: Clipboard, provide: Clipboard,
deps: [Platform], // Use platform instead of AppProvider to prevent errors with singleton injection. useFactory: (): Clipboard => CorePlatform.is('cordova') ? new Clipboard() : new ClipboardMock(),
useFactory: (platform: Platform): Clipboard => platform.is('cordova') ? new Clipboard() : new ClipboardMock(),
}, },
Device,
Diagnostic,
{ {
provide: File, provide: File,
deps: [Platform], useFactory: (): File => CorePlatform.is('cordova') ? new File() : new FileMock(),
useFactory: (platform: Platform): File => platform.is('cordova') ? new File() : new FileMock(),
}, },
{ {
provide: FileOpener, provide: FileOpener,
deps: [Platform], useFactory: (): FileOpener => CorePlatform.is('cordova') ? new FileOpener() : new FileOpenerMock(),
useFactory: (platform: Platform): FileOpener => platform.is('cordova') ? new FileOpener() : new FileOpenerMock(),
}, },
{ {
provide: FileTransfer, provide: FileTransfer,
deps: [Platform], useFactory: (): FileTransfer => CorePlatform.is('cordova') ? new FileTransfer() : new FileTransferMock(),
useFactory: (platform: Platform): FileTransfer => platform.is('cordova') ? new FileTransfer() : new FileTransferMock(),
}, },
{ {
provide: Geolocation, provide: Geolocation,
deps: [Platform], useFactory: (): Geolocation => CorePlatform.is('cordova') ? new Geolocation() : new GeolocationMock(),
useFactory: (platform: Platform): Geolocation => platform.is('cordova') ? new Geolocation() : new GeolocationMock(),
}, },
HTTP,
{ {
provide: InAppBrowser, provide: InAppBrowser,
deps: [Platform], useFactory: (): InAppBrowser => CorePlatform.is('cordova') ? new InAppBrowser() : new InAppBrowserMock(),
useFactory: (platform: Platform): InAppBrowser => platform.is('cordova') ? new InAppBrowser() : new InAppBrowserMock(),
}, },
Keyboard,
LocalNotifications,
Media,
{ {
provide: MediaCapture, provide: MediaCapture,
deps: [Platform], useFactory: (): MediaCapture => CorePlatform.is('cordova') ? new MediaCapture() : new MediaCaptureMock(),
useFactory: (platform: Platform): MediaCapture => platform.is('cordova') ? new MediaCapture() : new MediaCaptureMock(),
}, },
Push,
QRScanner,
SplashScreen,
SQLite,
StatusBar,
WebIntent,
WebView,
{ {
provide: Zip, provide: Zip,
deps: [Platform, File], useFactory: (): Zip => CorePlatform.is('cordova') ? new Zip() : new ZipMock(),
useFactory: (platform: Platform, file: File): Zip => platform.is('cordova') ? new Zip() : new ZipMock(file),
}, },
{ {
provide: APP_INITIALIZER, provide: APP_INITIALIZER,
deps: [Platform, CoreEmulatorHelperProvider], useFactory: () => () => {
useFactory: (platform: Platform, helperProvider: CoreEmulatorHelperProvider) => () => { if (CorePlatform.is('cordova')) {
if (platform.is('cordova')) {
return; return;
} }
return helperProvider.load(); return CoreEmulatorHelper.load();
}, },
multi: true, multi: true,
}, },

View File

@ -13,10 +13,9 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { File } from '@ionic-native/file/ngx';
import { CoreFile } from '@services/file'; import { CoreFile } from '@services/file';
import { CoreUtils } from '@services/utils/utils'; import { File, makeSingleton } from '@singletons';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
import { FileMock } from './file'; import { FileMock } from './file';
import { FileTransferErrorMock } from './file-transfer'; import { FileTransferErrorMock } from './file-transfer';
@ -29,9 +28,7 @@ export class CoreEmulatorHelperProvider {
protected logger: CoreLogger; protected logger: CoreLogger;
constructor( constructor() {
protected file: File,
) {
this.logger = CoreLogger.getInstance('CoreEmulatorHelper'); this.logger = CoreLogger.getInstance('CoreEmulatorHelper');
} }
@ -40,18 +37,18 @@ export class CoreEmulatorHelperProvider {
* *
* @return Promise resolved when loaded. * @return Promise resolved when loaded.
*/ */
load(): Promise<void> { async load(): Promise<void> {
const promises: Promise<unknown>[] = [];
window.FileTransferError = FileTransferErrorMock; window.FileTransferError = FileTransferErrorMock;
promises.push((<FileMock> this.file).load().then((basePath: string) => { const fileService = File.instance;
if (fileService instanceof FileMock) {
const basePath = await fileService.load();
CoreFile.setHTMLBasePath(basePath); CoreFile.setHTMLBasePath(basePath);
}
return;
}));
return CoreUtils.allPromises(promises);
} }
} }
export const CoreEmulatorHelper = makeSingleton(CoreEmulatorHelperProvider);

View File

@ -13,10 +13,10 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { File } from '@ionic-native/file/ngx';
import { Zip } from '@ionic-native/zip/ngx'; import { Zip } from '@ionic-native/zip/ngx';
import * as JSZip from 'jszip'; import * as JSZip from 'jszip';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { File } from '@singletons';
/** /**
* Emulates the Cordova Zip plugin in browser. * Emulates the Cordova Zip plugin in browser.
@ -24,10 +24,6 @@ import { CoreText } from '@singletons/text';
@Injectable() @Injectable()
export class ZipMock extends Zip { export class ZipMock extends Zip {
constructor(private file: File) {
super();
}
/** /**
* Create a directory. It creates all the foldes in dirPath 1 by 1 to prevent errors. * Create a directory. It creates all the foldes in dirPath 1 by 1 to prevent errors.
* *
@ -42,7 +38,7 @@ export class ZipMock extends Zip {
for (let i = 0; i < folders.length; i++) { for (let i = 0; i < folders.length; i++) {
const folder = folders[i]; const folder = folders[i];
await this.file.createDir(destination, folder, true); await File.createDir(destination, folder, true);
// Folder created, add it to the destination path. // Folder created, add it to the destination path.
destination = CoreText.concatenatePaths(destination, folder); destination = CoreText.concatenatePaths(destination, folder);
@ -69,7 +65,7 @@ export class ZipMock extends Zip {
try { try {
// Read the file first. // Read the file first.
const data = await this.file.readAsArrayBuffer(sourceDir, sourceName); const data = await File.readAsArrayBuffer(sourceDir, sourceName);
// Now load the file using the JSZip library. // Now load the file using the JSZip library.
await zip.loadAsync(data); await zip.loadAsync(data);
@ -83,7 +79,7 @@ export class ZipMock extends Zip {
const destParent = destination.substring(0, destination.lastIndexOf('/')); const destParent = destination.substring(0, destination.lastIndexOf('/'));
const destFolderName = destination.substring(destination.lastIndexOf('/') + 1); const destFolderName = destination.substring(destination.lastIndexOf('/') + 1);
await this.file.createDir(destParent, destFolderName, true); await File.createDir(destParent, destFolderName, true);
const total = Object.keys(zip.files).length; const total = Object.keys(zip.files).length;
let loaded = 0; let loaded = 0;
@ -107,7 +103,7 @@ export class ZipMock extends Zip {
// File read and parent folder created, now write the file. // File read and parent folder created, now write the file.
const parentFolder = CoreText.concatenatePaths(destination, fileDir); const parentFolder = CoreText.concatenatePaths(destination, fileDir);
await this.file.writeFile(parentFolder, fileName, fileData, { replace: true }); await File.writeFile(parentFolder, fileName, fileData, { replace: true });
} else { } else {
// It's a folder, create it if it doesn't exist. // It's a folder, create it if it doesn't exist.
await this.createDir(destination, name); await this.createDir(destination, name);

View File

@ -41,6 +41,7 @@ import { CoreUserToursModule } from './usertours/user-tours.module';
import { CoreUserModule } from './user/user.module'; import { CoreUserModule } from './user/user.module';
import { CoreViewerModule } from './viewer/viewer.module'; import { CoreViewerModule } from './viewer/viewer.module';
import { CoreXAPIModule } from './xapi/xapi.module'; import { CoreXAPIModule } from './xapi/xapi.module';
import { CoreNativeModule } from '@features/native/native.module';
@NgModule({ @NgModule({
imports: [ imports: [
@ -50,13 +51,13 @@ import { CoreXAPIModule } from './xapi/xapi.module';
CoreCourseModule, CoreCourseModule,
CoreCoursesModule, CoreCoursesModule,
CoreEditorModule, CoreEditorModule,
CoreEmulatorModule,
CoreFileUploaderModule, CoreFileUploaderModule,
CoreFilterModule, CoreFilterModule,
CoreGradesModule, CoreGradesModule,
CoreH5PModule, CoreH5PModule,
CoreLoginModule, CoreLoginModule,
CoreMainMenuModule, CoreMainMenuModule,
CoreNativeModule,
CorePushNotificationsModule, CorePushNotificationsModule,
CoreQuestionModule, CoreQuestionModule,
CoreRatingModule, CoreRatingModule,
@ -71,6 +72,9 @@ import { CoreXAPIModule } from './xapi/xapi.module';
CoreUserModule, CoreUserModule,
CoreViewerModule, CoreViewerModule,
CoreXAPIModule, CoreXAPIModule,
// Import last to allow overrides.
CoreEmulatorModule,
], ],
}) })
export class CoreFeaturesModule {} export class CoreFeaturesModule {}

View File

@ -0,0 +1,97 @@
// (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 { NgModule } from '@angular/core';
import { Badge } from '@ionic-native/badge/ngx';
import { Camera } from '@ionic-native/camera/ngx';
import { Chooser } from '@ionic-native/chooser/ngx';
import { Clipboard } from '@ionic-native/clipboard/ngx';
import { Device } from '@ionic-native/device/ngx';
import { Diagnostic } from '@ionic-native/diagnostic/ngx';
import { File } from '@ionic-native/file/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { FileTransfer } from '@ionic-native/file-transfer/ngx';
import { Geolocation } from '@ionic-native/geolocation/ngx';
import { HTTP } from '@ionic-native/http/ngx';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';
import { WebView } from '@ionic-native/ionic-webview/ngx';
import { Keyboard } from '@ionic-native/keyboard/ngx';
import { LocalNotifications } from '@ionic-native/local-notifications/ngx';
import { Media } from '@ionic-native/media/ngx';
import { MediaCapture } from '@ionic-native/media-capture/ngx';
import { Push } from '@ionic-native/push/ngx';
import { QRScanner } from '@ionic-native/qr-scanner/ngx';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { SQLite } from '@ionic-native/sqlite/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { WebIntent } from '@ionic-native/web-intent/ngx';
import { Zip } from '@ionic-native/zip/ngx';
export const CORE_NATIVE_SERVICES = [
Badge,
Camera,
Chooser,
Clipboard,
Device,
Diagnostic,
File,
FileOpener,
FileTransfer,
Geolocation,
HTTP,
InAppBrowser,
Keyboard,
LocalNotifications,
Media,
MediaCapture,
Push,
QRScanner,
SplashScreen,
StatusBar,
SQLite,
WebIntent,
WebView,
Zip,
];
@NgModule({
providers: [
Badge,
Camera,
Chooser,
Clipboard,
Device,
Diagnostic,
File,
FileOpener,
FileTransfer,
Geolocation,
HTTP,
InAppBrowser,
Keyboard,
LocalNotifications,
Media,
MediaCapture,
Push,
QRScanner,
SplashScreen,
SQLite,
StatusBar,
WebIntent,
WebView,
Zip,
],
})
export class CoreNativeModule {}