239 lines
8.4 KiB
TypeScript
239 lines
8.4 KiB
TypeScript
// (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 { Component } from '@angular/core';
|
|
import { IonicPage, NavParams } from 'ionic-angular';
|
|
import { Subscription } from 'rxjs';
|
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
|
import { CoreEventsProvider, CoreEventObserver } from '@providers/events';
|
|
import { CoreSitesProvider } from '@providers/sites';
|
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
|
import { AddonNotificationsProvider } from '../../providers/notifications';
|
|
import { AddonNotificationsHelperProvider } from '../../providers/helper';
|
|
import { CorePushNotificationsDelegate } from '@core/pushnotifications/providers/delegate';
|
|
|
|
/**
|
|
* Page that displays the list of notifications.
|
|
*/
|
|
@IonicPage({ segment: 'addon-notifications-list' })
|
|
@Component({
|
|
selector: 'page-addon-notifications-list',
|
|
templateUrl: 'list.html',
|
|
})
|
|
export class AddonNotificationsListPage {
|
|
|
|
notifications = [];
|
|
notificationsLoaded = false;
|
|
canLoadMore = false;
|
|
loadMoreError = false;
|
|
canMarkAllNotificationsAsRead = false;
|
|
loadingMarkAllNotificationsAsRead = false;
|
|
|
|
protected isCurrentView: boolean;
|
|
protected cronObserver: CoreEventObserver;
|
|
protected pushObserver: Subscription;
|
|
protected pendingRefresh = false;
|
|
|
|
constructor(navParams: NavParams, private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider,
|
|
private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider,
|
|
private utils: CoreUtilsProvider, private notificationsProvider: AddonNotificationsProvider,
|
|
private pushNotificationsDelegate: CorePushNotificationsDelegate,
|
|
private notificationsHelper: AddonNotificationsHelperProvider) {
|
|
}
|
|
|
|
/**
|
|
* View loaded.
|
|
*/
|
|
ionViewDidLoad(): void {
|
|
this.fetchNotifications();
|
|
|
|
this.cronObserver = this.eventsProvider.on(AddonNotificationsProvider.READ_CRON_EVENT, () => {
|
|
if (this.isCurrentView) {
|
|
this.notificationsLoaded = false;
|
|
this.refreshNotifications();
|
|
}
|
|
}, this.sitesProvider.getCurrentSiteId());
|
|
|
|
this.pushObserver = this.pushNotificationsDelegate.on('receive').subscribe((notification) => {
|
|
// New notification received. If it's from current site, refresh the data.
|
|
if (this.isCurrentView && this.utils.isTrueOrOne(notification.notif) &&
|
|
this.sitesProvider.isCurrentSite(notification.site)) {
|
|
|
|
this.notificationsLoaded = false;
|
|
this.refreshNotifications();
|
|
} else if (!this.isCurrentView) {
|
|
this.pendingRefresh = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Convenience function to get notifications. Gets unread notifications first.
|
|
*
|
|
* @param {boolean} refreh Whether we're refreshing data.
|
|
* @return {Promise<any>} Resolved when done.
|
|
*/
|
|
protected fetchNotifications(refresh?: boolean): Promise<any> {
|
|
this.loadMoreError = false;
|
|
|
|
return this.notificationsHelper.getNotifications(refresh ? [] : this.notifications).then((result) => {
|
|
result.notifications.forEach(this.formatText.bind(this));
|
|
|
|
if (refresh) {
|
|
this.notifications = result.notifications;
|
|
} else {
|
|
this.notifications = this.notifications.concat(result.notifications);
|
|
}
|
|
this.canLoadMore = result.canLoadMore;
|
|
|
|
this.markNotificationsAsRead(result.notifications);
|
|
}).catch((error) => {
|
|
this.domUtils.showErrorModalDefault(error, 'addon.notifications.errorgetnotifications', true);
|
|
this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.
|
|
}).finally(() => {
|
|
this.notificationsLoaded = true;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Mark all notifications as read.
|
|
*/
|
|
markAllNotificationsAsRead(): void {
|
|
this.loadingMarkAllNotificationsAsRead = true;
|
|
this.notificationsProvider.markAllNotificationsAsRead().catch(() => {
|
|
// Omit failure.
|
|
}).then(() => {
|
|
const siteId = this.sitesProvider.getCurrentSiteId();
|
|
this.eventsProvider.trigger(AddonNotificationsProvider.READ_CHANGED_EVENT, null, siteId);
|
|
|
|
// All marked as read, refresh the list.
|
|
this.notificationsLoaded = false;
|
|
|
|
return this.refreshNotifications();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Mark notifications as read.
|
|
*
|
|
* @param {any[]} notifications Array of notification objects.
|
|
*/
|
|
protected markNotificationsAsRead(notifications: any[]): void {
|
|
let promise;
|
|
|
|
if (notifications.length > 0) {
|
|
const promises = notifications.map((notification) => {
|
|
if (notification.read) {
|
|
// Already read, don't mark it.
|
|
return Promise.resolve();
|
|
}
|
|
|
|
return this.notificationsProvider.markNotificationRead(notification.id);
|
|
});
|
|
|
|
promise = Promise.all(promises).catch(() => {
|
|
// Ignore errors.
|
|
}).finally(() => {
|
|
this.notificationsProvider.invalidateNotificationsList().finally(() => {
|
|
const siteId = this.sitesProvider.getCurrentSiteId();
|
|
this.eventsProvider.trigger(AddonNotificationsProvider.READ_CHANGED_EVENT, null, siteId);
|
|
});
|
|
});
|
|
} else {
|
|
promise = Promise.resolve();
|
|
}
|
|
|
|
promise.finally(() => {
|
|
// Check if mark all notifications as read is enabled and there are some to read.
|
|
if (this.notificationsProvider.isMarkAllNotificationsAsReadEnabled()) {
|
|
this.loadingMarkAllNotificationsAsRead = true;
|
|
|
|
return this.notificationsProvider.getUnreadNotificationsCount().then((unread) => {
|
|
this.canMarkAllNotificationsAsRead = unread > 0;
|
|
}).finally(() => {
|
|
this.loadingMarkAllNotificationsAsRead = false;
|
|
});
|
|
}
|
|
this.canMarkAllNotificationsAsRead = false;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Refresh notifications.
|
|
*
|
|
* @param {any} [refresher] Refresher.
|
|
* @return Promise<any> Promise resolved when done.
|
|
*/
|
|
refreshNotifications(refresher?: any): Promise<any> {
|
|
return this.notificationsProvider.invalidateNotificationsList().finally(() => {
|
|
return this.fetchNotifications(true).finally(() => {
|
|
if (refresher) {
|
|
refresher.complete();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Load more results.
|
|
*
|
|
* @param {any} [infiniteComplete] Infinite scroll complete function. Only used from core-infinite-loading.
|
|
*/
|
|
loadMoreNotifications(infiniteComplete?: any): void {
|
|
this.fetchNotifications().finally(() => {
|
|
infiniteComplete && infiniteComplete();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Formats the text of a notification.
|
|
*
|
|
* @param {any} notification The notification object.
|
|
*/
|
|
protected formatText(notification: any): void {
|
|
const text = notification.mobiletext.replace(/-{4,}/ig, '');
|
|
notification.mobiletext = this.textUtils.replaceNewLines(text, '<br>');
|
|
}
|
|
|
|
/**
|
|
* User entered the page.
|
|
*/
|
|
ionViewDidEnter(): void {
|
|
this.isCurrentView = true;
|
|
|
|
if (this.pendingRefresh) {
|
|
this.pendingRefresh = false;
|
|
this.notificationsLoaded = false;
|
|
|
|
this.refreshNotifications();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* User left the page.
|
|
*/
|
|
ionViewDidLeave(): void {
|
|
this.isCurrentView = false;
|
|
}
|
|
|
|
/**
|
|
* Page destroyed.
|
|
*/
|
|
ngOnDestroy(): void {
|
|
this.cronObserver && this.cronObserver.off();
|
|
this.pushObserver && this.pushObserver.unsubscribe();
|
|
}
|
|
}
|