2019-09-26 12:43:29 +02:00
|
|
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
2017-11-08 14:48:34 +01:00
|
|
|
//
|
|
|
|
// 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';
|
2018-03-01 16:55:49 +01:00
|
|
|
import { CoreFileProvider } from '@providers/file';
|
|
|
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
2017-11-08 14:48:34 +01:00
|
|
|
import { File } from '@ionic-native/file';
|
2019-01-23 13:20:25 +01:00
|
|
|
import { LocalNotifications, ILocalNotification } from '@ionic-native/local-notifications';
|
2018-04-09 11:44:12 +02:00
|
|
|
import { CoreAppProvider } from '@providers/app';
|
2018-03-01 16:55:49 +01:00
|
|
|
import { CoreInitDelegate, CoreInitHandler } from '@providers/init';
|
2018-04-09 11:44:12 +02:00
|
|
|
import { CoreLoggerProvider } from '@providers/logger';
|
2019-02-01 11:02:03 +01:00
|
|
|
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
2018-04-09 11:44:12 +02:00
|
|
|
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
|
|
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
2017-11-09 13:00:08 +01:00
|
|
|
import { FileTransferErrorMock } from './file-transfer';
|
2018-01-08 09:21:51 +01:00
|
|
|
import { CoreEmulatorCaptureHelperProvider } from './capture-helper';
|
2018-04-09 11:44:12 +02:00
|
|
|
import { CoreConstants } from '../../constants';
|
2017-11-08 14:48:34 +01:00
|
|
|
|
|
|
|
/**
|
2018-01-08 09:21:51 +01:00
|
|
|
* Helper service for the emulator feature. It also acts as an init handler.
|
2017-11-08 14:48:34 +01:00
|
|
|
*/
|
|
|
|
@Injectable()
|
2017-11-21 16:35:41 +01:00
|
|
|
export class CoreEmulatorHelperProvider implements CoreInitHandler {
|
2017-11-08 14:48:34 +01:00
|
|
|
name = 'CoreEmulator';
|
2017-11-21 09:56:16 +01:00
|
|
|
priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 500;
|
2017-11-08 14:48:34 +01:00
|
|
|
blocking = true;
|
|
|
|
|
2018-04-09 11:44:12 +02:00
|
|
|
protected logger;
|
|
|
|
|
|
|
|
// Variables for database.
|
|
|
|
protected LAST_RECEIVED_NOTIFICATION_TABLE = 'core_emulator_last_received_notification';
|
2019-02-01 11:02:03 +01:00
|
|
|
protected siteSchema: CoreSiteSchema = {
|
|
|
|
name: 'CoreEmulatorHelperProvider',
|
|
|
|
version: 1,
|
|
|
|
tables: [
|
|
|
|
{
|
|
|
|
name: this.LAST_RECEIVED_NOTIFICATION_TABLE,
|
|
|
|
columns: [
|
|
|
|
{
|
|
|
|
name: 'component',
|
|
|
|
type: 'TEXT'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'id',
|
|
|
|
type: 'INTEGER',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'timecreated',
|
|
|
|
type: 'INTEGER',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
primaryKeys: ['component']
|
|
|
|
}
|
|
|
|
]
|
|
|
|
};
|
2018-04-09 11:44:12 +02:00
|
|
|
|
2017-11-08 14:48:34 +01:00
|
|
|
constructor(private file: File, private fileProvider: CoreFileProvider, private utils: CoreUtilsProvider,
|
2018-04-09 11:44:12 +02:00
|
|
|
logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private localNotif: LocalNotifications,
|
|
|
|
private captureHelper: CoreEmulatorCaptureHelperProvider, private timeUtils: CoreTimeUtilsProvider,
|
|
|
|
private appProvider: CoreAppProvider, private localNotifProvider: CoreLocalNotificationsProvider) {
|
|
|
|
this.logger = logger.getInstance('CoreEmulatorHelper');
|
2019-02-01 11:02:03 +01:00
|
|
|
sitesProvider.registerSiteSchema(this.siteSchema);
|
2018-04-09 11:44:12 +02:00
|
|
|
}
|
2017-11-14 15:43:03 +01:00
|
|
|
|
2017-11-08 14:48:34 +01:00
|
|
|
/**
|
|
|
|
* Load the Mocks that need it.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @return Promise resolved when loaded.
|
2017-11-08 14:48:34 +01:00
|
|
|
*/
|
2018-01-29 10:05:20 +01:00
|
|
|
load(): Promise<void> {
|
|
|
|
const promises = [];
|
2017-11-08 14:48:34 +01:00
|
|
|
|
2018-01-29 10:05:20 +01:00
|
|
|
promises.push((<any> this.file).load().then((basePath: string) => {
|
2017-11-08 14:48:34 +01:00
|
|
|
this.fileProvider.setHTMLBasePath(basePath);
|
|
|
|
}));
|
2018-01-29 10:05:20 +01:00
|
|
|
promises.push((<any> this.localNotif).load());
|
2018-01-08 09:21:51 +01:00
|
|
|
promises.push(this.captureHelper.load());
|
2017-11-14 15:43:03 +01:00
|
|
|
|
2018-01-29 10:05:20 +01:00
|
|
|
(<any> window).FileTransferError = FileTransferErrorMock;
|
2017-11-08 14:48:34 +01:00
|
|
|
|
|
|
|
return this.utils.allPromises(promises);
|
|
|
|
}
|
2018-04-09 11:44:12 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if there are new notifications, triggering a local notification if found.
|
|
|
|
* Only for desktop apps since they don't support push notifications.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param component Component to check.
|
|
|
|
* @param fetchFn Function that receives a site ID and returns a Promise resolved with an array of notifications.
|
|
|
|
* @param getDataFn Function that receives a notification and returns a promise resolved with the title and text.
|
|
|
|
* @param siteId Site ID to check. If not defined, check all sites.
|
|
|
|
* @return Promise resolved when done.
|
2018-04-09 11:44:12 +02:00
|
|
|
*/
|
|
|
|
checkNewNotifications(component: string, fetchFn: Function, getDataFn: Function, siteId?: string): Promise<any> {
|
|
|
|
if (!this.appProvider.isDesktop() || !this.localNotifProvider.isAvailable()) {
|
|
|
|
return Promise.resolve(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.appProvider.isOnline()) {
|
|
|
|
this.logger.debug('Cannot check push notifications because device is offline.');
|
|
|
|
|
|
|
|
return Promise.reject(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
let promise: Promise<string[]>;
|
|
|
|
if (!siteId) {
|
|
|
|
// No site ID defined, check all sites.
|
|
|
|
promise = this.sitesProvider.getSitesIds();
|
|
|
|
} else {
|
|
|
|
promise = Promise.resolve([siteId]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return promise.then((siteIds) => {
|
|
|
|
const sitePromises = siteIds.map((siteId) => {
|
|
|
|
// Check new notifications for each site.
|
|
|
|
return this.checkNewNotificationsForSite(component, fetchFn, getDataFn, siteId);
|
|
|
|
});
|
|
|
|
|
|
|
|
return Promise.all(sitePromises);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if there are new notifications for a certain site, triggering a local notification if found.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param component Component to check.
|
|
|
|
* @param fetchFn Function that receives a site ID and returns a Promise resolved with an array of notifications.
|
|
|
|
* @param getDataFn Function that receives a notification and returns a promise resolved with the title and text.
|
|
|
|
* @param siteId Site ID to check.
|
|
|
|
* @return Promise resolved when done.
|
2018-04-09 11:44:12 +02:00
|
|
|
*/
|
|
|
|
protected checkNewNotificationsForSite(component: string, fetchFn: Function, getDataFn: Function, siteId: string)
|
|
|
|
: Promise<any> {
|
|
|
|
// Get the last received notification in the app.
|
|
|
|
return this.getLastReceivedNotification(component, siteId).then((lastNotification) => {
|
|
|
|
// Now fetch the latest notifications from the server.
|
|
|
|
return fetchFn(siteId).then((notifications) => {
|
|
|
|
if (!lastNotification || !notifications.length) {
|
|
|
|
// No last notification stored (first call) or no new notifications. Stop.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const notification = notifications[0];
|
|
|
|
|
|
|
|
if (notification.id == lastNotification.id || notification.timecreated <= lastNotification.timecreated ||
|
|
|
|
this.timeUtils.timestamp() - notification.timecreated > CoreConstants.SECONDS_DAY) {
|
|
|
|
// There are no new notifications or the newest one happened more than a day ago, stop.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There is a new notification, show it.
|
|
|
|
return getDataFn(notification).then((titleAndText) => {
|
2019-03-22 13:08:03 +01:00
|
|
|
// Set some calculated data.
|
|
|
|
notification.site = siteId;
|
|
|
|
notification.name = notification.name || notification.eventtype;
|
|
|
|
|
2019-01-23 13:20:25 +01:00
|
|
|
const localNotif: ILocalNotification = {
|
2018-04-09 11:44:12 +02:00
|
|
|
id: 1,
|
|
|
|
title: titleAndText.title,
|
|
|
|
text: titleAndText.text,
|
2019-03-22 13:08:03 +01:00
|
|
|
data: notification
|
2018-04-09 11:44:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
return this.localNotifProvider.schedule(localNotif, component, siteId);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the last notification received in a certain site for a certain component.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param component Component of the notification to get.
|
|
|
|
* @param siteId Site ID of the notification.
|
|
|
|
* @return Promise resolved with the notification or false if not found.
|
2018-04-09 11:44:12 +02:00
|
|
|
*/
|
|
|
|
getLastReceivedNotification(component: string, siteId: string): Promise<any> {
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
return site.getDb().getRecord(this.LAST_RECEIVED_NOTIFICATION_TABLE, {component: component});
|
|
|
|
}).catch(() => {
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store the last notification received in a certain site.
|
|
|
|
*
|
2019-09-10 16:48:56 +02:00
|
|
|
* @param component Component of the notification to store.
|
|
|
|
* @param notification Notification to store.
|
|
|
|
* @param siteId Site ID of the notification.
|
|
|
|
* @return Promise resolved when done.
|
2018-04-09 11:44:12 +02:00
|
|
|
*/
|
|
|
|
storeLastReceivedNotification(component: string, notification: any, siteId: string): Promise<any> {
|
|
|
|
if (!notification) {
|
|
|
|
// No notification, store a fake one.
|
|
|
|
notification = {id: -1, timecreated: 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
|
|
|
const entry = {
|
|
|
|
component: component,
|
|
|
|
id: notification.id,
|
|
|
|
timecreated: notification.timecreated,
|
|
|
|
};
|
|
|
|
|
|
|
|
return site.getDb().insertRecord(this.LAST_RECEIVED_NOTIFICATION_TABLE, entry);
|
|
|
|
});
|
|
|
|
}
|
2017-11-08 14:48:34 +01:00
|
|
|
}
|