MOBILE-2328 notifications: PR fixes and emulator missing code
parent
133866598e
commit
ee7808643b
|
@ -28,7 +28,6 @@ import { AddonMessageOutputAirnotifierProvider } from '../../providers/airnotifi
|
|||
})
|
||||
export class AddonMessageOutputAirnotifierDevicesPage implements OnDestroy {
|
||||
|
||||
title = '';
|
||||
devices = [];
|
||||
devicesLoaded = false;
|
||||
|
||||
|
@ -108,8 +107,8 @@ export class AddonMessageOutputAirnotifierDevicesPage implements OnDestroy {
|
|||
/**
|
||||
* Enable or disable a certain device.
|
||||
*
|
||||
* @param {any} device
|
||||
* @param {boolean} enable
|
||||
* @param {any} device The device object.
|
||||
* @param {boolean} enable True to enable the device, false to disable it.
|
||||
*/
|
||||
enableDevice(device: any, enable: boolean): void {
|
||||
device.updating = true;
|
||||
|
|
|
@ -70,7 +70,7 @@ export class AddonMessageOutputAirnotifierProvider {
|
|||
/**
|
||||
* Get user devices.
|
||||
*
|
||||
* @param {string} [siteid] Site ID. If not defined, use current site.
|
||||
* @param {string} [siteId] Site ID. If not defined, use current site.
|
||||
* @return {Promise<any>} Promise resolved with the devices.
|
||||
*/
|
||||
getUserDevices(siteId?: string): Promise<any> {
|
||||
|
|
|
@ -24,6 +24,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
|
|||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||
import { AddonPushNotificationsProvider } from '@addon/pushnotifications/providers/pushnotifications';
|
||||
import { AddonPushNotificationsDelegate } from '@addon/pushnotifications/providers/delegate';
|
||||
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
|
||||
|
||||
/**
|
||||
* Handler to inject an option into main menu.
|
||||
|
@ -46,7 +47,7 @@ export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler, CoreCr
|
|||
private eventsProvider: CoreEventsProvider, private appProvider: CoreAppProvider,
|
||||
private localNotificationsProvider: CoreLocalNotificationsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private pushNotificationsProvider: AddonPushNotificationsProvider, utils: CoreUtilsProvider,
|
||||
pushNotificationsDelegate: AddonPushNotificationsDelegate) {
|
||||
pushNotificationsDelegate: AddonPushNotificationsDelegate, private emulatorHelper: CoreEmulatorHelperProvider) {
|
||||
|
||||
eventsProvider.on(AddonMessagesProvider.READ_CHANGED_EVENT, (data) => {
|
||||
this.updateBadge(data.siteId);
|
||||
|
@ -132,9 +133,9 @@ export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler, CoreCr
|
|||
}
|
||||
|
||||
if (this.appProvider.isDesktop() && this.localNotificationsProvider.isAvailable()) {
|
||||
// @todo
|
||||
/*$mmEmulatorHelper.checkNewNotifications(
|
||||
AddonMessagesProvider.PUSH_SIMULATION_COMPONENT, this.fetchMessages, this.getTitleAndText, siteId);*/
|
||||
this.emulatorHelper.checkNewNotifications(
|
||||
AddonMessagesProvider.PUSH_SIMULATION_COMPONENT,
|
||||
this.fetchMessages.bind(this), this.getTitleAndText.bind(this), siteId);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
|
|
|
@ -20,6 +20,7 @@ import { CoreUserProvider } from '@core/user/providers/user';
|
|||
import { AddonMessagesOfflineProvider } from './messages-offline';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
|
||||
|
||||
/**
|
||||
* Service to handle messages.
|
||||
|
@ -40,7 +41,8 @@ export class AddonMessagesProvider {
|
|||
|
||||
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider,
|
||||
private userProvider: CoreUserProvider, private messagesOffline: AddonMessagesOfflineProvider,
|
||||
private utils: CoreUtilsProvider, private timeUtils: CoreTimeUtilsProvider) {
|
||||
private utils: CoreUtilsProvider, private timeUtils: CoreTimeUtilsProvider,
|
||||
private emulatorHelper: CoreEmulatorHelperProvider) {
|
||||
this.logger = logger.getInstance('AddonMessagesProvider');
|
||||
}
|
||||
|
||||
|
@ -1088,7 +1090,6 @@ export class AddonMessagesProvider {
|
|||
|
||||
/**
|
||||
* Store the last received message if it's newer than the last stored.
|
||||
* @todo
|
||||
*
|
||||
* @param {number} userIdFrom ID of the useridfrom retrieved, 0 for all users.
|
||||
* @param {any} message Last message received.
|
||||
|
@ -1096,10 +1097,10 @@ export class AddonMessagesProvider {
|
|||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
protected storeLastReceivedMessageIfNeeded(userIdFrom: number, message: any, siteId?: string): Promise<any> {
|
||||
/*let component = mmaMessagesPushSimulationComponent;
|
||||
const component = AddonMessagesProvider.PUSH_SIMULATION_COMPONENT;
|
||||
|
||||
// Get the last received message.
|
||||
return $mmEmulatorHelper.getLastReceivedNotification(component, siteId).then((lastMessage) => {
|
||||
return this.emulatorHelper.getLastReceivedNotification(component, siteId).then((lastMessage) => {
|
||||
if (userIdFrom > 0 && (!message || !lastMessage)) {
|
||||
// Seeing a single discussion. No received message or cannot know if it really is the last received message. Stop.
|
||||
return;
|
||||
|
@ -1110,9 +1111,8 @@ export class AddonMessagesProvider {
|
|||
return;
|
||||
}
|
||||
|
||||
return $mmEmulatorHelper.storeLastReceivedNotification(component, message, siteId);
|
||||
});*/
|
||||
return Promise.resolve();
|
||||
return this.emulatorHelper.storeLastReceivedNotification(component, message, siteId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,8 +32,5 @@ import { AddonNotificationsActionsComponent } from './actions/actions';
|
|||
exports: [
|
||||
AddonNotificationsActionsComponent
|
||||
],
|
||||
entryComponents: [
|
||||
AddonNotificationsActionsComponent
|
||||
]
|
||||
})
|
||||
export class AddonNotificationsComponentsModule {}
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
<img [src]="notification.profileimageurlfrom || 'assets/img/user-avatar.png'" core-external-content [alt]="'core.pictureof' | translate:{$a: notification.userfromfullname}" role="presentation">
|
||||
</ion-avatar>
|
||||
<h2>{{notification.userfromfullname}}</h2>
|
||||
<div item-end *ngIf="!notification.timeread"><ion-icon name="record" color=""></ion-icon></div>
|
||||
<div item-end *ngIf="!notification.timeread"><ion-icon name="record" color="primary"></ion-icon></div>
|
||||
<p>{{notification.timecreated | coreDateDayOrTime}}</p>
|
||||
</ion-item>
|
||||
<ion-item text-wrap>
|
||||
<p><core-format-text [text]="formatText(notification.mobiletext | coreCreateLinks)"></core-format-text></p>
|
||||
<p><core-format-text [text]="notification.mobiletext | coreCreateLinks"></core-format-text></p>
|
||||
</ion-item>
|
||||
<addon-notifications-actions [contextUrl]="notification.contexturl" [courseId]="notification.courseid"></addon-notifications-actions>
|
||||
</ion-card>
|
||||
|
|
|
@ -70,8 +70,8 @@ export class AddonNotificationsListPage {
|
|||
/**
|
||||
* Convenience function to get notifications. Gets unread notifications first.
|
||||
*
|
||||
* @param {boolean} refreh
|
||||
* @return {Primise<any>} Resolved when done.
|
||||
* @param {boolean} refreh Whether we're refreshing data.
|
||||
* @return {Promise<any>} Resolved when done.
|
||||
*/
|
||||
protected fetchNotifications(refresh?: boolean): Promise<any> {
|
||||
if (refresh) {
|
||||
|
@ -83,6 +83,9 @@ export class AddonNotificationsListPage {
|
|||
|
||||
return this.notificationsProvider.getUnreadNotifications(this.unreadCount, limit).then((unread) => {
|
||||
let promise;
|
||||
|
||||
unread.forEach(this.formatText.bind(this));
|
||||
|
||||
/* Don't add the unread notifications to this.notifications yet. If there are no unread notifications
|
||||
that causes that the "There are no notifications" message is shown in pull to refresh. */
|
||||
this.unreadCount += unread.length;
|
||||
|
@ -91,6 +94,7 @@ export class AddonNotificationsListPage {
|
|||
// Limit not reached. Get read notifications until reach the limit.
|
||||
const readLimit = limit - unread.length;
|
||||
promise = this.notificationsProvider.getReadNotifications(this.readCount, readLimit).then((read) => {
|
||||
read.forEach(this.formatText.bind(this));
|
||||
this.readCount += read.length;
|
||||
if (refresh) {
|
||||
this.notifications = unread.concat(read);
|
||||
|
@ -127,7 +131,7 @@ export class AddonNotificationsListPage {
|
|||
/**
|
||||
* Mark notifications as read.
|
||||
*
|
||||
* @param {any[]} notifications
|
||||
* @param {any[]} notifications Array of notification objects.
|
||||
*/
|
||||
protected markNotificationsAsRead(notifications: any[]): void {
|
||||
if (notifications.length > 0) {
|
||||
|
@ -172,14 +176,12 @@ export class AddonNotificationsListPage {
|
|||
|
||||
/**
|
||||
* Formats the text of a notification.
|
||||
* @param {string} text
|
||||
* @return {string} Formatted text.
|
||||
*
|
||||
* @param {any} notification The notification object.
|
||||
*/
|
||||
formatText(text: string): string {
|
||||
text = text.replace(/-{4,}/ig, '');
|
||||
text = this.textUtils.replaceNewLines(text, '<br>');
|
||||
|
||||
return text;
|
||||
protected formatText(notification: any): void {
|
||||
const text = notification.mobiletext.replace(/-{4,}/ig, '');
|
||||
notification.mobiletext = this.textUtils.replaceNewLines(text, '<br>');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
page-addon-notifications-settings {
|
||||
.list-header {
|
||||
margin-bottom: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
|
@ -115,7 +115,7 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
/**
|
||||
* Load a processor.
|
||||
*
|
||||
* @param {any} processor
|
||||
* @param {any} processor Processor object.
|
||||
*/
|
||||
protected loadProcessor(processor: any): void {
|
||||
if (!processor) {
|
||||
|
@ -242,7 +242,7 @@ export class AddonNotificationsSettingsPage implements OnDestroy {
|
|||
/**
|
||||
* Change the notification sound setting.
|
||||
*
|
||||
* @param {enabled} enabled
|
||||
* @param {enabled} enabled True to enable the notification sound, false to disable it.
|
||||
*/
|
||||
changeNotificationSound(enabled: boolean): void {
|
||||
this.configProvider.set(CoreConstants.SETTINGS_NOTIFICATION_SOUND, enabled).finally(() => {
|
||||
|
|
|
@ -18,6 +18,8 @@ import { CoreCronHandler } from '@providers/cron';
|
|||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
|
||||
import { AddonNotificationsProvider } from './notifications';
|
||||
|
||||
/**
|
||||
|
@ -29,7 +31,8 @@ export class AddonNotificationsCronHandler implements CoreCronHandler {
|
|||
|
||||
constructor(private appProvider: CoreAppProvider, private eventsProvider: CoreEventsProvider,
|
||||
private sitesProvider: CoreSitesProvider, private localNotifications: CoreLocalNotificationsProvider,
|
||||
private notificationsProvider: AddonNotificationsProvider) {}
|
||||
private notificationsProvider: AddonNotificationsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private emulatorHelper: CoreEmulatorHelperProvider) {}
|
||||
|
||||
/**
|
||||
* Get the time between consecutive executions.
|
||||
|
@ -73,12 +76,37 @@ export class AddonNotificationsCronHandler implements CoreCronHandler {
|
|||
}
|
||||
|
||||
if (this.appProvider.isDesktop() && this.localNotifications.isAvailable()) {
|
||||
/* @todo
|
||||
$mmEmulatorHelper.checkNewNotifications(
|
||||
mmaNotificationsPushSimulationComponent, fetchNotifications, getTitleAndText, siteId);
|
||||
*/
|
||||
this.emulatorHelper.checkNewNotifications(
|
||||
AddonNotificationsProvider.PUSH_SIMULATION_COMPONENT,
|
||||
this.fetchNotifications.bind(this), this.getTitleAndText.bind(this), siteId);
|
||||
}
|
||||
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest unread notifications from a site.
|
||||
*
|
||||
* @param {string} siteId Site ID.
|
||||
* @return {Promise<any[]>} Promise resolved with the notifications.
|
||||
*/
|
||||
protected fetchNotifications(siteId: string): Promise<any[]> {
|
||||
return this.notificationsProvider.getUnreadNotifications(0, undefined, true, false, true, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a notification, return the title and the text for the notification.
|
||||
*
|
||||
* @param {any} notification Notification.
|
||||
* @return {Promise<any>} Promise resvoled with an object with title and text.
|
||||
*/
|
||||
protected getTitleAndText(notification: any): Promise<any> {
|
||||
const data = {
|
||||
title: notification.userfromfullname,
|
||||
text: notification.mobiletext.replace(/-{4,}/ig, '')
|
||||
};
|
||||
data.text = this.textUtils.replaceNewLines(data.text, '<br>');
|
||||
|
||||
return Promise.resolve(data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ export class AddonNotificationsMainMenuHandler implements CoreMainMenuHandler {
|
|||
/**
|
||||
* Triggers an update for the badge number and loading status. Mandatory if showBadge is enabled.
|
||||
*
|
||||
* @param {string} siteId Site ID or current Site if undefined.
|
||||
* @param {string} [siteId] Site ID or current Site if undefined.
|
||||
*/
|
||||
updateBadge(siteId?: string): void {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CoreLoggerProvider } from '@providers/logger';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
|
||||
|
||||
/**
|
||||
* Service to handle notifications.
|
||||
|
@ -27,14 +28,15 @@ export class AddonNotificationsProvider {
|
|||
|
||||
static READ_CHANGED_EVENT = 'addon_notifications_read_changed_event';
|
||||
static READ_CRON_EVENT = 'addon_notifications_read_cron_event';
|
||||
static PUSH_SIMULATION_COMPONENT = 'AddonMessagesPushSimulation';
|
||||
static PUSH_SIMULATION_COMPONENT = 'AddonNotificationsPushSimulation';
|
||||
static LIST_LIMIT = 20;
|
||||
|
||||
protected ROOT_CACHE_KEY = 'mmaNotifications:';
|
||||
protected logger;
|
||||
|
||||
constructor(logger: CoreLoggerProvider, private appProvider: CoreAppProvider, private sitesProvider: CoreSitesProvider,
|
||||
private timeUtils: CoreTimeUtilsProvider, private userProvider: CoreUserProvider) {
|
||||
private timeUtils: CoreTimeUtilsProvider, private userProvider: CoreUserProvider,
|
||||
private emulatorHelper: CoreEmulatorHelperProvider) {
|
||||
this.logger = logger.getInstance('AddonNotificationsProvider');
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,7 @@ export class AddonNotificationsProvider {
|
|||
/**
|
||||
* Get notification preferences.
|
||||
*
|
||||
* @param {string} [siteid] Site ID. If not defined, use current site.
|
||||
* @param {string} [siteId] Site ID. If not defined, use current site.
|
||||
* @return {Promise<any>} Promise resolved with the notification preferences.
|
||||
*/
|
||||
getNotificationPreferences(siteId?: string): Promise<any> {
|
||||
|
@ -141,11 +143,9 @@ export class AddonNotificationsProvider {
|
|||
const notifications = response.messages;
|
||||
this.formatNotificationsData(notifications);
|
||||
if (this.appProvider.isDesktop() && toDisplay && !read && limitFrom === 0) {
|
||||
/* @todo
|
||||
// Store the last received notification. Don't block the user for this.
|
||||
$mmEmulatorHelper.storeLastReceivedNotification(
|
||||
mmaNotificationsPushSimulationComponent, notifications[0], siteId);
|
||||
*/
|
||||
this.emulatorHelper.storeLastReceivedNotification(
|
||||
AddonNotificationsProvider.PUSH_SIMULATION_COMPONENT, notifications[0], siteId);
|
||||
}
|
||||
|
||||
return notifications;
|
||||
|
|
|
@ -25,6 +25,7 @@ import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreConfigProvider } from '@providers/config';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import { CoreConfigConstants } from '../../../configconstants';
|
||||
|
||||
/**
|
||||
|
@ -89,8 +90,7 @@ export class AddonPushNotificationsProvider {
|
|||
* @return {Promise<PushOptions>} Promise with the push options resolved when done.
|
||||
*/
|
||||
protected getOptions(): Promise<PushOptions> {
|
||||
// @todo: CoreSettingsProvider.NOTIFICATION_SOUND
|
||||
return this.configProvider.get('CoreSettingsProvider.NOTIFICATION_SOUND', true).then((soundEnabled) => {
|
||||
return this.configProvider.get(CoreConstants.SETTINGS_NOTIFICATION_SOUND, true).then((soundEnabled) => {
|
||||
return {
|
||||
android: {
|
||||
senderID: CoreConfigConstants.gcmpn,
|
||||
|
|
|
@ -35,6 +35,7 @@ import { SQLite } from '@ionic-native/sqlite';
|
|||
import { Zip } from '@ionic-native/zip';
|
||||
|
||||
// Services that Mock Ionic Native in browser an desktop.
|
||||
import { BadgeMock } from './providers/badge';
|
||||
import { CameraMock } from './providers/camera';
|
||||
import { ClipboardMock } from './providers/clipboard';
|
||||
import { FileMock } from './providers/file';
|
||||
|
@ -44,6 +45,7 @@ import { InAppBrowserMock } from './providers/inappbrowser';
|
|||
import { LocalNotificationsMock } from './providers/local-notifications';
|
||||
import { MediaCaptureMock } from './providers/media-capture';
|
||||
import { NetworkMock } from './providers/network';
|
||||
import { PushMock } from './providers/push';
|
||||
import { ZipMock } from './providers/zip';
|
||||
|
||||
import { CoreEmulatorHelperProvider } from './providers/helper';
|
||||
|
@ -89,7 +91,14 @@ export const IONIC_NATIVE_PROVIDERS = [
|
|||
imports: [
|
||||
],
|
||||
providers: [
|
||||
Badge, // @todo: Mock
|
||||
{
|
||||
provide: Badge,
|
||||
deps: [CoreAppProvider],
|
||||
useFactory: (appProvider: CoreAppProvider): Badge => {
|
||||
// Use platform instead of CoreAppProvider to prevent circular dependencies.
|
||||
return appProvider.isMobile() ? new Badge() : new BadgeMock(appProvider);
|
||||
}
|
||||
},
|
||||
CoreEmulatorHelperProvider,
|
||||
CoreEmulatorCaptureHelperProvider,
|
||||
{
|
||||
|
@ -162,7 +171,14 @@ export const IONIC_NATIVE_PROVIDERS = [
|
|||
return platform.is('cordova') ? new Network() : new NetworkMock();
|
||||
}
|
||||
},
|
||||
Push, // @todo: Mock
|
||||
{
|
||||
provide: Push,
|
||||
deps: [CoreAppProvider],
|
||||
useFactory: (appProvider: CoreAppProvider): Push => {
|
||||
// Use platform instead of CoreAppProvider to prevent circular dependencies.
|
||||
return appProvider.isMobile() ? new Push() : new PushMock(appProvider);
|
||||
}
|
||||
},
|
||||
SplashScreen,
|
||||
StatusBar,
|
||||
SQLite,
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
// (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 { Badge } from '@ionic-native/badge';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
|
||||
/**
|
||||
* Emulates the Cordova Push plugin in desktop apps and in browser.
|
||||
*/
|
||||
@Injectable()
|
||||
export class BadgeMock implements Badge {
|
||||
|
||||
constructor(private appProvider: CoreAppProvider) {}
|
||||
|
||||
/**
|
||||
* Clear the badge of the app icon.
|
||||
*
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
clear(): Promise<boolean> {
|
||||
return Promise.reject('clear is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the badge of the app icon.
|
||||
* @param {number} badgeNumber The new badge number.
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
set(badgeNumber: number): Promise<any> {
|
||||
if (!this.appProvider.isDesktop()) {
|
||||
return Promise.reject('set is not supported in browser');
|
||||
}
|
||||
|
||||
try {
|
||||
const app = require('electron').remote.app;
|
||||
if (app.setBadgeCount(badgeNumber)) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
} catch (ex) {
|
||||
return Promise.reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the badge of the app icon.
|
||||
*
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
get(): Promise<any> {
|
||||
if (!this.appProvider.isDesktop()) {
|
||||
return Promise.reject('get is not supported in browser');
|
||||
}
|
||||
|
||||
try {
|
||||
const app = require('electron').remote.app;
|
||||
|
||||
return Promise.resolve(app.getBadgeCount());
|
||||
} catch (ex) {
|
||||
return Promise.reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the badge number.
|
||||
*
|
||||
* @param {number} increaseBy Count to add to the current badge number
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
increase(increaseBy: number): Promise<any> {
|
||||
return Promise.reject('increase is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease the badge number.
|
||||
*
|
||||
* @param {number} decreaseBy Count to subtract from the current badge number
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
decrease(decreaseBy: number): Promise<any> {
|
||||
return Promise.reject('decrease is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check support to show badges.
|
||||
*
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
isSupported(): Promise<any> {
|
||||
return Promise.reject('isSupported is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the app has permission to show badges.
|
||||
*
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
hasPermission(): Promise<any> {
|
||||
return Promise.reject('hasPermission is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register permission to set badge notifications
|
||||
*
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
requestPermission(): Promise<any> {
|
||||
return Promise.reject('requestPermission is only supported in mobile devices');
|
||||
}
|
||||
}
|
|
@ -17,9 +17,15 @@ import { CoreFileProvider } from '@providers/file';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { File } from '@ionic-native/file';
|
||||
import { LocalNotifications } from '@ionic-native/local-notifications';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreInitDelegate, CoreInitHandler } from '@providers/init';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { FileTransferErrorMock } from './file-transfer';
|
||||
import { CoreEmulatorCaptureHelperProvider } from './capture-helper';
|
||||
import { CoreConstants } from '../../constants';
|
||||
|
||||
/**
|
||||
* Helper service for the emulator feature. It also acts as an init handler.
|
||||
|
@ -30,9 +36,38 @@ export class CoreEmulatorHelperProvider implements CoreInitHandler {
|
|||
priority = CoreInitDelegate.MAX_RECOMMENDED_PRIORITY + 500;
|
||||
blocking = true;
|
||||
|
||||
protected logger;
|
||||
|
||||
// Variables for database.
|
||||
protected LAST_RECEIVED_NOTIFICATION_TABLE = 'core_emulator_last_received_notification';
|
||||
protected tablesSchema = [
|
||||
{
|
||||
name: this.LAST_RECEIVED_NOTIFICATION_TABLE,
|
||||
columns: [
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT'
|
||||
},
|
||||
{
|
||||
name: 'id',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timecreated',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['component']
|
||||
}
|
||||
];
|
||||
|
||||
constructor(private file: File, private fileProvider: CoreFileProvider, private utils: CoreUtilsProvider,
|
||||
initDelegate: CoreInitDelegate, private localNotif: LocalNotifications,
|
||||
private captureHelper: CoreEmulatorCaptureHelperProvider) { }
|
||||
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');
|
||||
sitesProvider.createTablesFromSchema(this.tablesSchema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the Mocks that need it.
|
||||
|
@ -52,4 +87,130 @@ export class CoreEmulatorHelperProvider implements CoreInitHandler {
|
|||
|
||||
return this.utils.allPromises(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are new notifications, triggering a local notification if found.
|
||||
* Only for desktop apps since they don't support push notifications.
|
||||
*
|
||||
* @param {string} component Component to check.
|
||||
* @param {Function} fetchFn Function that receives a site ID and returns a Promise resolved with an array of notifications.
|
||||
* @param {Function} getDataFn Function that receives a notification and returns a promise resolved with the title and text.
|
||||
* @param {string} [siteId] Site ID to check. If not defined, check all sites.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param {string} component Component to check.
|
||||
* @param {Function} fetchFn Function that receives a site ID and returns a Promise resolved with an array of notifications.
|
||||
* @param {Function} getDataFn Function that receives a notification and returns a promise resolved with the title and text.
|
||||
* @param {string} siteId Site ID to check.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
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) => {
|
||||
const localNotif = {
|
||||
id: 1,
|
||||
at: new Date(),
|
||||
title: titleAndText.title,
|
||||
text: titleAndText.text,
|
||||
data: {
|
||||
notif: notification,
|
||||
site: siteId
|
||||
}
|
||||
};
|
||||
|
||||
return this.localNotifProvider.schedule(localNotif, component, siteId);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last notification received in a certain site for a certain component.
|
||||
*
|
||||
* @param {string} component Component of the notification to get.
|
||||
* @param {string} siteId Site ID of the notification.
|
||||
* @return {Promise<any>} Promise resolved with the notification or false if not found.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param {string} component Component of the notification to store.
|
||||
* @param {any} notification Notification to store.
|
||||
* @param {string} siteId Site ID of the notification.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
// (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 { Observable } from 'rxjs/Observable';
|
||||
import { Channel, EventResponse, Push, PushEvent, PushObject, PushOptions } from '@ionic-native/push';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
|
||||
/**
|
||||
* Emulates the Cordova Push plugin in desktop apps and in browser.
|
||||
*/
|
||||
@Injectable()
|
||||
export class PushMock implements Push {
|
||||
|
||||
constructor(private appProvider: CoreAppProvider) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Init push notifications
|
||||
*
|
||||
* @param {PushOptions} options
|
||||
* @return {PushObject}
|
||||
*/
|
||||
init(options: PushOptions): PushObject {
|
||||
return new PushObjectMock(this.appProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the push notification permission has been granted.
|
||||
*
|
||||
* @return {Promise<{isEnabled: boolean}>} Returns a Promise that resolves with an object with one property: isEnabled, a
|
||||
* boolean that indicates if permission has been granted.
|
||||
*/
|
||||
hasPermission(): Promise<{isEnabled: boolean}> {
|
||||
return Promise.reject('hasPermission is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new notification channel for Android O and above.
|
||||
*
|
||||
* @param {Channel} channel
|
||||
*/
|
||||
createChannel(channel?: Channel): Promise<any> {
|
||||
return Promise.reject('createChannel is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a notification channel for Android O and above.
|
||||
*
|
||||
* @param {string} id
|
||||
*/
|
||||
deleteChannel(id?: string): Promise<any> {
|
||||
return Promise.reject('deleteChannel is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of currently configured channels.
|
||||
*
|
||||
* @return {Promise<Channel[]>}
|
||||
*/
|
||||
listChannels(): Promise<Channel[]> {
|
||||
return Promise.reject('listChannels is only supported in mobile devices');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates the PushObject class in desktop apps and in browser.
|
||||
*/
|
||||
export class PushObjectMock extends PushObject {
|
||||
|
||||
constructor(private appProvider: CoreAppProvider) {
|
||||
super({});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener
|
||||
* @param event {string}
|
||||
* @return {Observable<EventResponse>}
|
||||
*/
|
||||
on(event: PushEvent): Observable<EventResponse> {
|
||||
return Observable.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* The unregister method is used when the application no longer wants to receive push notifications.
|
||||
* Beware that this cleans up all event handlers previously registered,
|
||||
* so you will need to re-register them if you want them to function again without an application reload.
|
||||
*/
|
||||
unregister(): Promise<any> {
|
||||
return Promise.reject('unregister is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the badge count visible when the app is not running
|
||||
*
|
||||
* The count is an integer indicating what number should show up in the badge.
|
||||
* Passing 0 will clear the badge.
|
||||
* Each notification event contains a data.count value which can be used to set the badge to correct number.
|
||||
*
|
||||
* @param count
|
||||
*/
|
||||
setApplicationIconBadgeNumber(count?: number): Promise<any> {
|
||||
if (!this.appProvider.isDesktop()) {
|
||||
return Promise.reject('setApplicationIconBadgeNumber is not supported in browser');
|
||||
}
|
||||
|
||||
try {
|
||||
const app = require('electron').remote.app;
|
||||
if (app.setBadgeCount(count)) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
} catch (ex) {
|
||||
return Promise.reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current badge count visible when the app is not running
|
||||
* successHandler gets called with an integer which is the current badge count
|
||||
*/
|
||||
getApplicationIconBadgeNumber(): Promise<number> {
|
||||
if (!this.appProvider.isDesktop()) {
|
||||
return Promise.reject('getApplicationIconBadgeNumber is not supported in browser');
|
||||
}
|
||||
|
||||
try {
|
||||
const app = require('electron').remote.app;
|
||||
|
||||
return Promise.resolve(app.getBadgeCount());
|
||||
} catch (ex) {
|
||||
return Promise.reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iOS only
|
||||
* Tells the OS that you are done processing a background push notification.
|
||||
* successHandler gets called when background push processing is successfully completed.
|
||||
* @param [id]
|
||||
*/
|
||||
finish(id?: string): Promise<any> {
|
||||
return Promise.reject('finish is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the OS to clear all notifications from the Notification Center
|
||||
*/
|
||||
clearAllNotifications(): Promise<any> {
|
||||
return Promise.reject('clearAllNotifications is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* The subscribe method is used when the application wants to subscribe a new topic to receive push notifications.
|
||||
* @param topic {string} Topic to subscribe to.
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
subscribe(topic: string): Promise<any> {
|
||||
return Promise.reject('subscribe is only supported in mobile devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* The unsubscribe method is used when the application no longer wants to receive push notifications from a specific topic but
|
||||
* continue to receive other push messages.
|
||||
*
|
||||
* @param topic {string} Topic to unsubscribe from.
|
||||
* @return {Promise<any>}
|
||||
*/
|
||||
unsubscribe(topic: string): Promise<any> {
|
||||
return Promise.reject('unsubscribe is only supported in mobile devices');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue