From 787eb3531b9b59b28781051a58776fd6826c74fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 15 Jun 2018 10:08:02 +0200 Subject: [PATCH] MOBILE-2430 notifications: Improve local notifications design --- src/app/app.scss | 37 +++++++++++ src/providers/local-notifications.ts | 93 ++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/app/app.scss b/src/app/app.scss index 1dad14d49..63c59cae4 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -754,4 +754,41 @@ canvas[core-chart] { &::before { padding-top: percentage(1 / 1); } +} + +ion-alert.core-inapp-notification { + pointer-events: none; + position: fixed; + align-items: start; + + ion-backdrop { + display: none; + } + + .alert-wrapper { + width: $toast-width; + max-width: $toast-max-width; + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3); + padding: 2px 0; + border-radius: 0; + pointer-events: auto; + } + + .alert-head { + padding: 5px 10px; + text-align: left; + h2 { + font-size: 14px; + } + } + + .alert-message { + padding: 5px 10px; + text-align: left; + p { + font-size: 14px; + margin-top: 5px; + margin-bottom: 5px; + } + } } \ No newline at end of file diff --git a/src/providers/local-notifications.ts b/src/providers/local-notifications.ts index 41d2d18ee..7afa1db58 100644 --- a/src/providers/local-notifications.ts +++ b/src/providers/local-notifications.ts @@ -13,12 +13,12 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { Platform } from 'ionic-angular'; +import { Platform, Alert, AlertController } from 'ionic-angular'; import { LocalNotifications, ILocalNotification } from '@ionic-native/local-notifications'; +import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from './app'; import { CoreConfigProvider } from './config'; import { CoreLoggerProvider } from './logger'; -import { CoreDomUtilsProvider } from './utils/dom'; import { CoreTextUtilsProvider } from './utils/text'; import { CoreUtilsProvider } from './utils/utils'; import { SQLiteDB } from '@classes/sqlitedb'; @@ -107,10 +107,17 @@ export class CoreLocalNotificationsProvider { protected codes: { [s: string]: number } = {}; protected codeRequestsQueue = {}; protected observables = {}; + protected alertNotification: Alert; + protected currentNotification = { + title: '', + texts: [], + ids: [], + timeouts: [] + }; constructor(logger: CoreLoggerProvider, private localNotifications: LocalNotifications, private platform: Platform, private appProvider: CoreAppProvider, private utils: CoreUtilsProvider, private configProvider: CoreConfigProvider, - private domUtils: CoreDomUtilsProvider, private textUtils: CoreTextUtilsProvider) { + private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private alertCtrl: AlertController) { this.logger = logger.getInstance('CoreLocalNotificationsProvider'); this.appDB = appProvider.getDB(); this.appDB.createTablesFromSchema(this.tablesSchema); @@ -470,13 +477,89 @@ export class CoreLocalNotificationsProvider { * @param {CoreILocalNotification} notification Notification. */ showNotificationPopover(notification: CoreILocalNotification): void { - // @todo Improve it. For now, show Toast. + if (!notification || !notification.title || !notification.text) { // Invalid data. return; } - this.domUtils.showToast(notification.text, false, 4000); + const clearAlert = (all: boolean = false): void => { + // Only erase first notification. + if (!all && this.alertNotification && this.currentNotification.ids.length > 1) { + this.currentNotification.texts.shift(); + this.currentNotification.ids.shift(); + clearTimeout(this.currentNotification.timeouts.shift()); + + const text = '

' + this.currentNotification.texts.join('

') + '

'; + this.alertNotification.setMessage(text); + } else { + // Close the alert and reset the current object. + if (this.alertNotification && !all) { + this.alertNotification.dismiss(); + } + + this.alertNotification = null; + this.currentNotification.title = ''; + this.currentNotification.texts = []; + this.currentNotification.ids = []; + this.currentNotification.timeouts.forEach((time) => { + clearTimeout(time); + }); + this.currentNotification.timeouts = []; + } + }; + + if (this.alertNotification && this.currentNotification.title == notification.title) { + if (this.currentNotification.ids.indexOf(notification.id) != -1) { + // Notification already shown, don't show it again, just renew the timeout. + return; + } + + // Same title and the notification is shown, update it. + this.currentNotification.texts.push(notification.text); + this.currentNotification.ids.push(notification.id); + if (this.currentNotification.texts.length > 3) { + this.currentNotification.texts.shift(); + this.currentNotification.ids.shift(); + clearTimeout(this.currentNotification.timeouts.shift()); + } + } else { + this.currentNotification.timeouts.forEach((time) => { + clearTimeout(time); + }); + this.currentNotification.timeouts = []; + + // Not shown or title is different, set new data. + this.currentNotification.title = notification.title; + this.currentNotification.texts = [notification.text]; + this.currentNotification.ids = [notification.id]; + } + + const text = '

' + this.currentNotification.texts.join('

') + '

'; + if (this.alertNotification) { + this.alertNotification.setTitle(this.currentNotification.title); + this.alertNotification.setMessage(text); + } else { + this.alertNotification = this.alertCtrl.create({ + title: this.currentNotification.title, + message: text, + cssClass: 'core-inapp-notification', + enableBackdropDismiss: false, + buttons: [{ + text: this.translate.instant('core.dismiss'), + role: 'cancel', + handler: (): void => { + clearAlert(true); + } + }] + }); + } + + this.alertNotification.present(); + + this.currentNotification.timeouts.push(setTimeout(() => { + clearAlert(); + }, 4000)); } /**