MOBILE-2261 core: Emulate simple Cordova plugins
SQLite, Clipboard, Globalization, Network and URL Schememain
parent
e3d5c95c87
commit
4ebc79fca7
|
@ -116,10 +116,10 @@
|
||||||
<plugin name="phonegap-plugin-push" spec="~1.10.5">
|
<plugin name="phonegap-plugin-push" spec="~1.10.5">
|
||||||
<variable name="SENDER_ID" value="694767596569" />
|
<variable name="SENDER_ID" value="694767596569" />
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin name="cordova-universal-clipboard" spec="~0.1.0" />
|
|
||||||
<plugin name="nl.kingsquare.cordova.background-audio" spec="~1.0.1" />
|
<plugin name="nl.kingsquare.cordova.background-audio" spec="~1.0.1" />
|
||||||
<plugin name="ch.ti8m.documenthandler" spec="https://github.com/ti8m/DocumentHandler" />
|
<plugin name="ch.ti8m.documenthandler" spec="https://github.com/ti8m/DocumentHandler" />
|
||||||
<plugin name="net.tunts.webintent" spec="https://github.com/Tunts/WebIntent" />
|
<plugin name="net.tunts.webintent" spec="https://github.com/Tunts/WebIntent" />
|
||||||
<plugin name="cordova-sqlite-storage" spec="~2.0.4" />
|
<plugin name="cordova-sqlite-storage" spec="~2.0.4" />
|
||||||
<plugin name="cordova-plugin-ionic-webview" spec="~1.1.16" />
|
<plugin name="cordova-plugin-ionic-webview" spec="~1.1.16" />
|
||||||
|
<plugin name="cordova-clipboard" spec="~1.1.0" />
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -54,11 +54,21 @@
|
||||||
"resolved": "https://registry.npmjs.org/@angular/tsc-wrapped/-/tsc-wrapped-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/tsc-wrapped/-/tsc-wrapped-4.4.3.tgz",
|
||||||
"integrity": "sha1-LT84IQodTbA/yG3PHglYErhc0Rk="
|
"integrity": "sha1-LT84IQodTbA/yG3PHglYErhc0Rk="
|
||||||
},
|
},
|
||||||
|
"@ionic-native/clipboard": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ionic-native/clipboard/-/clipboard-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-dutKKMnpyhFeEPc09O5MzrtPKtv13f3X4mCmDmUEj5CExMecTOhox/rnIB70t8GP2/3bTC/CSr39DhkLLS8MzA=="
|
||||||
|
},
|
||||||
"@ionic-native/core": {
|
"@ionic-native/core": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-4.3.0.tgz",
|
||||||
"integrity": "sha512-Pf0qCzqlVFmIpZpvo35Kl0e+1K8GUgPMcKBnN57gWh+5Ecj3dPcb+MbP4murJo/dnFsIYPYdXRZRf74hjo6gtw=="
|
"integrity": "sha512-Pf0qCzqlVFmIpZpvo35Kl0e+1K8GUgPMcKBnN57gWh+5Ecj3dPcb+MbP4murJo/dnFsIYPYdXRZRf74hjo6gtw=="
|
||||||
},
|
},
|
||||||
|
"@ionic-native/globalization": {
|
||||||
|
"version": "4.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@ionic-native/globalization/-/globalization-4.3.2.tgz",
|
||||||
|
"integrity": "sha512-sDyriA3/xspu6RM8arEOlhOkSxvRwLDNdvbBoZ59i+Dn5i6bjoE4hMMEFvUlnzvOZKn5GusurrWPz5cmfA9aPw=="
|
||||||
|
},
|
||||||
"@ionic-native/keyboard": {
|
"@ionic-native/keyboard": {
|
||||||
"version": "4.3.2",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/@ionic-native/keyboard/-/keyboard-4.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/@ionic-native/keyboard/-/keyboard-4.3.2.tgz",
|
||||||
|
@ -110,6 +120,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
|
"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
|
||||||
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
|
"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
|
||||||
},
|
},
|
||||||
|
"@types/cordova-plugin-globalization": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cordova-plugin-globalization/-/cordova-plugin-globalization-0.0.3.tgz",
|
||||||
|
"integrity": "sha1-ySA6HENtPS0DBXiffJwrq6i6KK0="
|
||||||
|
},
|
||||||
"@types/cordova-plugin-network-information": {
|
"@types/cordova-plugin-network-information": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/cordova-plugin-network-information/-/cordova-plugin-network-information-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/cordova-plugin-network-information/-/cordova-plugin-network-information-0.0.3.tgz",
|
||||||
|
@ -120,6 +135,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/localforage/-/localforage-0.0.30.tgz",
|
"resolved": "https://registry.npmjs.org/@types/localforage/-/localforage-0.0.30.tgz",
|
||||||
"integrity": "sha1-PWCmv23aOOP4pGlhFZg3nx9klQk="
|
"integrity": "sha1-PWCmv23aOOP4pGlhFZg3nx9klQk="
|
||||||
},
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"version": "8.0.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.47.tgz",
|
||||||
|
"integrity": "sha512-kOwL746WVvt/9Phf6/JgX/bsGQvbrK5iUgzyfwZNcKVFcjAUVSpF9HxevLTld2SG9aywYHOILj38arDdY1r/iQ=="
|
||||||
|
},
|
||||||
"@types/promise.prototype.finally": {
|
"@types/promise.prototype.finally": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/promise.prototype.finally/-/promise.prototype.finally-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/promise.prototype.finally/-/promise.prototype.finally-2.0.2.tgz",
|
||||||
|
|
|
@ -33,7 +33,9 @@
|
||||||
"@angular/http": "4.4.3",
|
"@angular/http": "4.4.3",
|
||||||
"@angular/platform-browser": "4.4.3",
|
"@angular/platform-browser": "4.4.3",
|
||||||
"@angular/platform-browser-dynamic": "4.4.3",
|
"@angular/platform-browser-dynamic": "4.4.3",
|
||||||
|
"@ionic-native/clipboard": "^4.3.2",
|
||||||
"@ionic-native/core": "4.3.0",
|
"@ionic-native/core": "4.3.0",
|
||||||
|
"@ionic-native/globalization": "^4.3.2",
|
||||||
"@ionic-native/keyboard": "^4.3.2",
|
"@ionic-native/keyboard": "^4.3.2",
|
||||||
"@ionic-native/network": "^4.3.2",
|
"@ionic-native/network": "^4.3.2",
|
||||||
"@ionic-native/splash-screen": "4.3.0",
|
"@ionic-native/splash-screen": "4.3.0",
|
||||||
|
@ -43,7 +45,9 @@
|
||||||
"@ngx-translate/core": "^8.0.0",
|
"@ngx-translate/core": "^8.0.0",
|
||||||
"@ngx-translate/http-loader": "^2.0.0",
|
"@ngx-translate/http-loader": "^2.0.0",
|
||||||
"@types/cordova": "0.0.34",
|
"@types/cordova": "0.0.34",
|
||||||
|
"@types/cordova-plugin-globalization": "0.0.3",
|
||||||
"@types/cordova-plugin-network-information": "0.0.3",
|
"@types/cordova-plugin-network-information": "0.0.3",
|
||||||
|
"@types/node": "^8.0.47",
|
||||||
"@types/promise.prototype.finally": "^2.0.2",
|
"@types/promise.prototype.finally": "^2.0.2",
|
||||||
"electron-builder-squirrel-windows": "^19.3.0",
|
"electron-builder-squirrel-windows": "^19.3.0",
|
||||||
"electron-windows-notifications": "^1.1.13",
|
"electron-windows-notifications": "^1.1.13",
|
||||||
|
@ -58,5 +62,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ionic/app-scripts": "3.0.0",
|
"@ionic/app-scripts": "3.0.0",
|
||||||
"typescript": "2.3.4"
|
"typescript": "2.3.4"
|
||||||
|
},
|
||||||
|
"browser": {
|
||||||
|
"electron": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { ErrorHandler, NgModule } from '@angular/core';
|
import { ErrorHandler, NgModule } from '@angular/core';
|
||||||
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
|
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
import { SplashScreen } from '@ionic-native/splash-screen';
|
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||||
import { StatusBar } from '@ionic-native/status-bar';
|
import { StatusBar } from '@ionic-native/status-bar';
|
||||||
import { SQLite } from '@ionic-native/sqlite';
|
import { SQLite } from '@ionic-native/sqlite';
|
||||||
import { Keyboard } from '@ionic-native/keyboard';
|
import { Keyboard } from '@ionic-native/keyboard';
|
||||||
import { Network } from '@ionic-native/network';
|
|
||||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
|
|
||||||
|
@ -16,6 +15,7 @@ import { CoreLoggerProvider } from '../providers/logger';
|
||||||
import { CoreDbProvider } from '../providers/db';
|
import { CoreDbProvider } from '../providers/db';
|
||||||
import { CoreAppProvider } from '../providers/app';
|
import { CoreAppProvider } from '../providers/app';
|
||||||
import { CoreConfigProvider } from '../providers/config';
|
import { CoreConfigProvider } from '../providers/config';
|
||||||
|
import { CoreEmulatorModule } from '../core/emulator/emulator.module';
|
||||||
|
|
||||||
// For translate loader. AoT requires an exported function for factories.
|
// For translate loader. AoT requires an exported function for factories.
|
||||||
export function createTranslateLoader(http: HttpClient) {
|
export function createTranslateLoader(http: HttpClient) {
|
||||||
|
@ -28,6 +28,7 @@ export function createTranslateLoader(http: HttpClient) {
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
HttpClientModule,
|
||||||
IonicModule.forRoot(MyApp),
|
IonicModule.forRoot(MyApp),
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
loader: {
|
loader: {
|
||||||
|
@ -35,7 +36,8 @@ export function createTranslateLoader(http: HttpClient) {
|
||||||
useFactory: (createTranslateLoader),
|
useFactory: (createTranslateLoader),
|
||||||
deps: [HttpClient]
|
deps: [HttpClient]
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
|
CoreEmulatorModule
|
||||||
],
|
],
|
||||||
bootstrap: [IonicApp],
|
bootstrap: [IonicApp],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
|
@ -46,12 +48,11 @@ export function createTranslateLoader(http: HttpClient) {
|
||||||
SplashScreen,
|
SplashScreen,
|
||||||
SQLite,
|
SQLite,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Network,
|
|
||||||
{provide: ErrorHandler, useClass: IonicErrorHandler},
|
{provide: ErrorHandler, useClass: IonicErrorHandler},
|
||||||
CoreLoggerProvider,
|
CoreLoggerProvider,
|
||||||
CoreDbProvider,
|
CoreDbProvider,
|
||||||
CoreAppProvider,
|
CoreAppProvider,
|
||||||
CoreConfigProvider,
|
CoreConfigProvider
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { SQLiteDB } from '../../../classes/sqlitedb';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to mock the interaction with the SQLite database.
|
||||||
|
*/
|
||||||
|
export class SQLiteDBMock extends SQLiteDB {
|
||||||
|
promise: Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and open the database.
|
||||||
|
*
|
||||||
|
* @param {string} name Database name.
|
||||||
|
*/
|
||||||
|
constructor(public name: string) {
|
||||||
|
super(name, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the database.
|
||||||
|
*
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
close() : Promise<any> {
|
||||||
|
// WebSQL databases aren't closed.
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop all the data in the database.
|
||||||
|
*
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
emptyDatabase() : Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.db.transaction(tx => {
|
||||||
|
// Query all tables from sqlite_master that we have created and can modify.
|
||||||
|
let args = [],
|
||||||
|
query = `SELECT * FROM sqlite_master
|
||||||
|
WHERE name NOT LIKE 'sqlite\\_%' escape '\\' AND name NOT LIKE '\\_%' escape '\\'`;
|
||||||
|
|
||||||
|
tx.executeSql(query, args, (tx, result) => {
|
||||||
|
if (result.rows.length <= 0) {
|
||||||
|
// No tables to delete, stop.
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop all the tables.
|
||||||
|
let promises = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < result.rows.length; i++) {
|
||||||
|
promises.push(new Promise((resolve, reject) => {
|
||||||
|
// Drop the table.
|
||||||
|
let name = JSON.stringify(result.rows.item(i).name);
|
||||||
|
tx.executeSql('DROP TABLE ' + name, [], resolve, reject);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.all(promises).then(resolve, reject);
|
||||||
|
}, reject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a SQL query.
|
||||||
|
*
|
||||||
|
* @param {string} sql SQL query to execute.
|
||||||
|
* @param {any[]} params Query parameters.
|
||||||
|
* @return {Promise<any>} Promise resolved with the result.
|
||||||
|
*/
|
||||||
|
protected execute(sql: string, params?: any[]) : Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// With WebSQL, all queries must be run in a transaction.
|
||||||
|
this.db.transaction((tx) => {
|
||||||
|
tx.executeSql(sql, params, (tx, results) => {
|
||||||
|
resolve(results);
|
||||||
|
}, reject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a set of SQL queries. This operation is atomic.
|
||||||
|
*
|
||||||
|
* @param {any[]} sqlStatements SQL statements to execute.
|
||||||
|
* @return {Promise<any>} Promise resolved with the result.
|
||||||
|
*/
|
||||||
|
protected executeBatch(sqlStatements: any[]) : Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Create a transaction to execute the queries.
|
||||||
|
this.db.transaction((tx) => {
|
||||||
|
let promises = [];
|
||||||
|
|
||||||
|
// Execute all the queries. Each statement can be a string or an array.
|
||||||
|
sqlStatements.forEach((statement) => {
|
||||||
|
promises.push(new Promise((resolve, reject) => {
|
||||||
|
let query,
|
||||||
|
params;
|
||||||
|
|
||||||
|
if (Array.isArray(statement)) {
|
||||||
|
query = statement[0];
|
||||||
|
params = statement[1];
|
||||||
|
} else {
|
||||||
|
query = statement;
|
||||||
|
params = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.executeSql(query, params, (tx, results) => {
|
||||||
|
resolve(results);
|
||||||
|
}, reject);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(promises).then(resolve, reject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the database.
|
||||||
|
*/
|
||||||
|
init(): void {
|
||||||
|
// This DB is for desktop apps, so use a big size to be sure it isn't filled.
|
||||||
|
this.db = (<any>window).openDatabase(this.name, '1.0', this.name, 500 * 1024 * 1024);
|
||||||
|
this.promise = Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the database. Only needed if it was closed before, a database is automatically opened when created.
|
||||||
|
*
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
open() : Promise<any> {
|
||||||
|
// WebSQL databases can't closed, so the open method isn't needed.
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { Platform } from 'ionic-angular';
|
||||||
|
|
||||||
|
import { CoreAppProvider } from '../../providers/app';
|
||||||
|
import { Clipboard } from '@ionic-native/clipboard';
|
||||||
|
import { Globalization } from '@ionic-native/globalization';
|
||||||
|
import { Network } from '@ionic-native/network';
|
||||||
|
import { ClipboardMock } from './providers/clipboard';
|
||||||
|
import { GlobalizationMock } from './providers/globalization';
|
||||||
|
import { NetworkMock } from './providers/network';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
ClipboardMock,
|
||||||
|
GlobalizationMock,
|
||||||
|
{
|
||||||
|
provide: Clipboard,
|
||||||
|
deps: [CoreAppProvider],
|
||||||
|
useFactory: (appProvider: CoreAppProvider) => {
|
||||||
|
return appProvider.isMobile() ? new Clipboard() : new ClipboardMock(appProvider);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: Globalization,
|
||||||
|
deps: [CoreAppProvider],
|
||||||
|
useFactory: (appProvider: CoreAppProvider) => {
|
||||||
|
return appProvider.isMobile() ? new Globalization() : new GlobalizationMock(appProvider);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: Network,
|
||||||
|
deps: [Platform],
|
||||||
|
useFactory: (platform: Platform) => {
|
||||||
|
// Use platform instead of CoreAppProvider to prevent circular dependencies.
|
||||||
|
return platform.is('cordova') ? new Network() : new NetworkMock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class CoreEmulatorModule {
|
||||||
|
constructor(appProvider: CoreAppProvider) {
|
||||||
|
let win = <any>window; // Convert the "window" to "any" type to be able to use non-standard properties.
|
||||||
|
|
||||||
|
// Emulate Custom URL Scheme plugin in desktop apps.
|
||||||
|
if (appProvider.isDesktop()) {
|
||||||
|
require('electron').ipcRenderer.on('mmAppLaunched', function(event, url) {
|
||||||
|
win.handleOpenURL && win.handleOpenURL(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { Clipboard } from '@ionic-native/clipboard';
|
||||||
|
import { CoreAppProvider } from '../../../providers/app';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates the Cordova Clipboard plugin in desktop apps and in browser.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class ClipboardMock extends Clipboard {
|
||||||
|
isDesktop: boolean;
|
||||||
|
clipboard: any;
|
||||||
|
copyTextarea: HTMLTextAreaElement;
|
||||||
|
|
||||||
|
constructor(appProvider: CoreAppProvider) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.isDesktop = appProvider.isDesktop();
|
||||||
|
if (this.isDesktop) {
|
||||||
|
this.clipboard = require('electron').clipboard;
|
||||||
|
} else {
|
||||||
|
// In browser the text must be selected in order to copy it. Create a hidden textarea to put the text in it.
|
||||||
|
this.copyTextarea = document.createElement('textarea');
|
||||||
|
this.copyTextarea.className = 'mm-browser-copy-area';
|
||||||
|
this.copyTextarea.setAttribute('aria-hidden', 'true');
|
||||||
|
document.body.appendChild(this.copyTextarea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy some text to the clipboard.
|
||||||
|
*
|
||||||
|
* @param {string} text The text to copy.
|
||||||
|
* @return {Promise<any>} Promise resolved when copied.
|
||||||
|
*/
|
||||||
|
copy(text: string) : Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this.isDesktop) {
|
||||||
|
this.clipboard.writeText(text);
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
// Put the text in the hidden textarea and select it.
|
||||||
|
this.copyTextarea.innerHTML = text;
|
||||||
|
this.copyTextarea.select();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (document.execCommand('copy')) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.copyTextarea.innerHTML = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the text stored in the clipboard.
|
||||||
|
*
|
||||||
|
* @return {Promise<any>} Promise resolved with the text.
|
||||||
|
*/
|
||||||
|
paste() : Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (this.isDesktop) {
|
||||||
|
resolve(this.clipboard.readText());
|
||||||
|
} else {
|
||||||
|
// Paste the text in the hidden textarea and get it.
|
||||||
|
this.copyTextarea.innerHTML = '';
|
||||||
|
this.copyTextarea.select();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (document.execCommand('paste')) {
|
||||||
|
resolve(this.copyTextarea.innerHTML);
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.copyTextarea.innerHTML = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { Globalization } from '@ionic-native/globalization';
|
||||||
|
import { CoreAppProvider } from '../../../providers/app';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates the Cordova Globalization plugin in desktop apps and in browser.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class GlobalizationMock extends Globalization {
|
||||||
|
|
||||||
|
constructor(private appProvider: CoreAppProvider) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current locale.
|
||||||
|
*
|
||||||
|
* @return {string} Locale name.
|
||||||
|
*/
|
||||||
|
private getCurrentlocale() : string {
|
||||||
|
// Get browser language.
|
||||||
|
var navLang = (<any>navigator).userLanguage || navigator.language;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (this.appProvider.isDesktop()) {
|
||||||
|
var locale = require('electron').remote.app.getLocale();
|
||||||
|
return locale || navLang;
|
||||||
|
} else {
|
||||||
|
return navLang;
|
||||||
|
}
|
||||||
|
} catch(ex) {
|
||||||
|
// Something went wrong, return browser language.
|
||||||
|
return navLang;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current locale name.
|
||||||
|
*
|
||||||
|
* @return {Promise<{value: string}>} Promise resolved with an object with the language string.
|
||||||
|
*/
|
||||||
|
getLocaleName() : Promise<{value: string}> {
|
||||||
|
var locale = this.getCurrentlocale();
|
||||||
|
if (locale) {
|
||||||
|
return Promise.resolve({value: locale});
|
||||||
|
} else {
|
||||||
|
var error = {code: GlobalizationError.UNKNOWN_ERROR, message: 'Cannot get language'};
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the current preferred language.
|
||||||
|
*
|
||||||
|
* @return {Promise<{value: string}>} Promise resolved with an object with the language string.
|
||||||
|
*/
|
||||||
|
getPreferredLanguage() : Promise<{value: string}> {
|
||||||
|
return this.getLocaleName();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { Network } from '@ionic-native/network';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates the Cordova Globalization plugin in desktop apps and in browser.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class NetworkMock extends Network {
|
||||||
|
type: null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
(<any>window).Connection = {
|
||||||
|
UNKNOWN: 'unknown',
|
||||||
|
ETHERNET: 'ethernet',
|
||||||
|
WIFI: 'wifi',
|
||||||
|
CELL_2G: '2g',
|
||||||
|
CELL_3G: '3g',
|
||||||
|
CELL_4G: '4g',
|
||||||
|
CELL: 'cellular',
|
||||||
|
NONE: 'none'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable to watch connection changes.
|
||||||
|
*
|
||||||
|
* @return {Observable<any>} Observable.
|
||||||
|
*/
|
||||||
|
onchange(): Observable<any> {
|
||||||
|
return Observable.merge(this.onConnect(), this.onDisconnect());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable to notify when the app is connected.
|
||||||
|
*
|
||||||
|
* @return {Observable<any>} Observable.
|
||||||
|
*/
|
||||||
|
onConnect() : Observable<any> {
|
||||||
|
let observable = new Subject<any>();
|
||||||
|
|
||||||
|
window.addEventListener('online', (ev) => {
|
||||||
|
observable.next(ev);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
return observable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable to notify when the app is disconnected.
|
||||||
|
*
|
||||||
|
* @return {Observable<any>} Observable.
|
||||||
|
*/
|
||||||
|
onDisconnect() : Observable<any> {
|
||||||
|
let observable = new Subject<any>();
|
||||||
|
|
||||||
|
window.addEventListener('offline', (ev) => {
|
||||||
|
observable.next(ev);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
return observable;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { SQLite } from '@ionic-native/sqlite';
|
import { SQLite } from '@ionic-native/sqlite';
|
||||||
import { Platform } from 'ionic-angular';
|
import { Platform } from 'ionic-angular';
|
||||||
import { SQLiteDB } from '../classes/sqlitedb';
|
import { SQLiteDB } from '../classes/sqlitedb';
|
||||||
|
import { SQLiteDBMock } from '../core/emulator/classes/sqlitedb';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This service allows interacting with the local database to store and retrieve data.
|
* This service allows interacting with the local database to store and retrieve data.
|
||||||
|
@ -38,7 +39,11 @@ export class CoreDbProvider {
|
||||||
*/
|
*/
|
||||||
getDB(name: string, forceNew?: boolean) : SQLiteDB {
|
getDB(name: string, forceNew?: boolean) : SQLiteDB {
|
||||||
if (typeof this.dbInstances[name] === 'undefined' || forceNew) {
|
if (typeof this.dbInstances[name] === 'undefined' || forceNew) {
|
||||||
this.dbInstances[name] = new SQLiteDB(name, this.sqlite, this.platform);
|
if (this.platform.is('cordova')) {
|
||||||
|
this.dbInstances[name] = new SQLiteDB(name, this.sqlite, this.platform);
|
||||||
|
} else {
|
||||||
|
this.dbInstances[name] = new SQLiteDBMock(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.dbInstances[name];
|
return this.dbInstances[name];
|
||||||
}
|
}
|
||||||
|
@ -60,15 +65,18 @@ export class CoreDbProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(() => {
|
return promise.then(() => {
|
||||||
|
let db = this.dbInstances[name];
|
||||||
delete this.dbInstances[name];
|
delete this.dbInstances[name];
|
||||||
|
|
||||||
return this.sqlite.deleteDatabase({
|
if (this.platform.is('cordova')) {
|
||||||
name: name,
|
return this.sqlite.deleteDatabase({
|
||||||
location: 'default'
|
name: name,
|
||||||
});
|
location: 'default'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// In WebSQL we cannot delete the database, just empty it.
|
||||||
|
return db.emptyDatabase();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue