MOBILE-4021 notification: add split-view
parent
b67d27fc0e
commit
fa4ad175cc
|
@ -0,0 +1,47 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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 { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source';
|
||||
import { AddonNotifications } from '../services/notifications';
|
||||
import { AddonNotificationsHelper, AddonNotificationsNotificationToRender } from '../services/notifications-helper';
|
||||
|
||||
/**
|
||||
* Provides a list of notifications
|
||||
*/
|
||||
export class AddonsNotificationsNotificationsSource extends CoreRoutedItemsManagerSource<AddonNotificationsNotificationToRender> {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async loadPageItems(page: number): Promise<{
|
||||
items: AddonNotificationsNotificationToRender[];
|
||||
hasMoreItems: boolean;
|
||||
}> {
|
||||
// TODO this should be refactored to avoid using the existing items.
|
||||
const { notifications, canLoadMore } = await AddonNotifications.getNotifications(page === 0 ? [] : this.getItems() ?? []);
|
||||
|
||||
return {
|
||||
items: notifications.map(notification => AddonNotificationsHelper.formatNotificationText(notification)),
|
||||
hasMoreItems: canLoadMore,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getItemPath(notification: AddonNotificationsNotificationToRender): string {
|
||||
return notification.id.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -12,10 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { conditionalRoutes } from '@/app/app-routing.module';
|
||||
import { Injector, NgModule } from '@angular/core';
|
||||
import { RouterModule, ROUTES, Routes } from '@angular/router';
|
||||
|
||||
import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||
import { CoreScreen } from '@services/screen';
|
||||
import { AddonNotificationsMainMenuHandlerService } from './services/handlers/mainmenu';
|
||||
|
||||
function buildRoutes(injector: Injector): Routes {
|
||||
|
@ -27,6 +29,13 @@ function buildRoutes(injector: Injector): Routes {
|
|||
},
|
||||
loadChildren: () => import('./pages/list/list.module').then(m => m.AddonNotificationsListPageModule),
|
||||
},
|
||||
...conditionalRoutes([
|
||||
{
|
||||
path: 'list/:id',
|
||||
loadChildren: () => import('./pages/notification/notification.module')
|
||||
.then(m => m.AddonNotificationsNotificationPageModule),
|
||||
},
|
||||
], () => CoreScreen.isMobile),
|
||||
{
|
||||
path: 'notification',
|
||||
loadChildren: () => import('./pages/notification/notification.module')
|
||||
|
|
|
@ -11,66 +11,72 @@
|
|||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="limited-width">
|
||||
<ion-refresher slot="fixed" [disabled]="!notificationsLoaded" (ionRefresh)="refreshNotifications($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="notificationsLoaded">
|
||||
<ion-content>
|
||||
<core-split-view>
|
||||
<ion-refresher slot="fixed" [disabled]="!notifications.loaded" (ionRefresh)="refreshNotifications($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="notifications.loaded">
|
||||
|
||||
<ion-item *ngFor="let notification of notifications" class="ion-text-wrap" [attr.aria-label]="
|
||||
notification.timeread
|
||||
? notification.subject
|
||||
: 'addon.notifications.unreadnotification' | translate: {$a: notification.subject}"
|
||||
(click)="openNotification(notification)" button [detail]="false" lines="full">
|
||||
<core-user-avatar *ngIf="notification.useridfrom > 0" [user]="notification" slot="start"
|
||||
[profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname"
|
||||
[userId]="notification.useridfrom">
|
||||
<div class="core-avatar-extra-img" *ngIf="notification.iconurl && !notification.modname">
|
||||
<img [src]="notification.iconurl" alt="" role="presentation">
|
||||
</div>
|
||||
<core-mod-icon *ngIf="notification.modname" [modicon]="notification.iconurl" [modname]="notification.modname"
|
||||
[showAlt]="false">
|
||||
</core-mod-icon>
|
||||
</core-user-avatar>
|
||||
<ion-item *ngFor="let notification of notifications.items" class="ion-text-wrap"
|
||||
[attr.aria-current]="notifications.getItemAriaCurrent(notification)" [attr.aria-label]="
|
||||
notification.timeread
|
||||
? notification.subject
|
||||
: 'addon.notifications.unreadnotification' | translate: {$a: notification.subject}"
|
||||
(click)="notifications.select(notification)" button [detail]="false" lines="full">
|
||||
|
||||
<ng-container *ngIf="notification.useridfrom <= 0 && notification.iconurl">
|
||||
<div class="core-notification-icon" *ngIf="!notification.modname" slot="start">
|
||||
<img [src]="notification.iconurl" alt="" role="presentation">
|
||||
</div>
|
||||
<core-mod-icon *ngIf="notification.modname" [modicon]="notification.iconurl" [modname]="notification.modname"
|
||||
[showAlt]="false" class="core-notification-icon" slot="start">
|
||||
</core-mod-icon>
|
||||
</ng-container>
|
||||
<core-user-avatar *ngIf="notification.useridfrom > 0" [user]="notification" slot="start"
|
||||
[profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname"
|
||||
[userId]="notification.useridfrom">
|
||||
<div class="core-avatar-extra-img" *ngIf="notification.iconurl && !notification.modname">
|
||||
<img [src]="notification.iconurl" alt="" role="presentation">
|
||||
</div>
|
||||
<core-mod-icon *ngIf="notification.modname" [modicon]="notification.iconurl" [modname]="notification.modname"
|
||||
[showAlt]="false">
|
||||
</core-mod-icon>
|
||||
</core-user-avatar>
|
||||
|
||||
<ion-label>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="notification.subject" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p>{{ notification.timecreated | coreTimeAgo }}<ng-container *ngIf="notification.useridfrom > 0"> · {{
|
||||
notification.userfromfullname }}</ng-container>
|
||||
</p>
|
||||
</ion-label>
|
||||
<ion-note slot="end" *ngIf="!notification.timeread">
|
||||
<ion-icon name="fas-circle" color="primary" aria-hidden="true"></ion-icon>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
<ng-container *ngIf="notification.useridfrom <= 0 && notification.iconurl">
|
||||
<div class="core-notification-icon" *ngIf="!notification.modname" slot="start">
|
||||
<img [src]="notification.iconurl" alt="" role="presentation">
|
||||
</div>
|
||||
<core-mod-icon *ngIf="notification.modname" [modicon]="notification.iconurl" [modname]="notification.modname"
|
||||
[showAlt]="false" class="core-notification-icon" slot="start">
|
||||
</core-mod-icon>
|
||||
</ng-container>
|
||||
|
||||
<core-empty-box *ngIf="!notifications || notifications.length <= 0" icon="far-bell"
|
||||
[message]="'addon.notifications.therearentnotificationsyet' | translate">
|
||||
</core-empty-box>
|
||||
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreNotifications($event)" [error]="loadMoreError">
|
||||
</core-infinite-loading>
|
||||
</core-loading>
|
||||
<ion-label>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="notification.subject" contextLevel="system" [contextInstanceId]="0"
|
||||
[wsNotFiltered]="true">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p>{{ notification.timecreated | coreTimeAgo }}<ng-container *ngIf="notification.useridfrom > 0"> · {{
|
||||
notification.userfromfullname }}</ng-container>
|
||||
</p>
|
||||
</ion-label>
|
||||
<ion-note slot="end" *ngIf="!notification.timeread">
|
||||
<ion-icon name="fas-circle" color="primary" aria-hidden="true"></ion-icon>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
|
||||
<core-empty-box *ngIf="!notifications || notifications.empty" icon="far-bell"
|
||||
[message]="'addon.notifications.therearentnotificationsyet' | translate">
|
||||
</core-empty-box>
|
||||
<core-infinite-loading [enabled]="notifications.loaded && !notifications.completed" (action)="fetchMoreNotifications($event)"
|
||||
[error]="fetchMoreNotificationsFailed">
|
||||
</core-infinite-loading>
|
||||
</core-loading>
|
||||
|
||||
|
||||
<div class="mark-all-as-read" slot="fixed" collapsible-footer appearOnBottom>
|
||||
<ion-chip *ngIf="notificationsLoaded && canMarkAllNotificationsAsRead" [disabled]="loadingMarkAllNotificationsAsRead"
|
||||
color="primary" (click)="markAllNotificationsAsRead()">
|
||||
<ion-icon name="fas-eye" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
|
||||
<ion-spinner [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
|
||||
</ion-spinner>
|
||||
{{ 'addon.notifications.markallread' | translate }}
|
||||
</ion-chip>
|
||||
</div>
|
||||
<div class="mark-all-as-read" slot="fixed" collapsible-footer appearOnBottom>
|
||||
<ion-chip *ngIf="notifications.loaded && canMarkAllNotificationsAsRead" [disabled]="loadingMarkAllNotificationsAsRead"
|
||||
color="primary" (click)="markAllNotificationsAsRead()">
|
||||
<ion-icon name="fas-eye" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
|
||||
<ion-spinner [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
|
||||
</ion-spinner>
|
||||
{{ 'addon.notifications.markallread' | translate }}
|
||||
</ion-chip>
|
||||
</div>
|
||||
</core-split-view>
|
||||
</ion-content>
|
||||
|
|
|
@ -18,11 +18,20 @@ import { RouterModule, Routes } from '@angular/router';
|
|||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { AddonNotificationsListPage } from './list';
|
||||
import { CoreMainMenuComponentsModule } from '@features/mainmenu/components/components.module';
|
||||
import { conditionalRoutes } from '@/app/app-routing.module';
|
||||
import { CoreScreen } from '@services/screen';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: AddonNotificationsListPage,
|
||||
children: conditionalRoutes([
|
||||
{
|
||||
path: ':id',
|
||||
loadChildren: () => import('../../pages/notification/notification.module')
|
||||
.then(m => m.AddonNotificationsNotificationPageModule),
|
||||
},
|
||||
], () => CoreScreen.isTablet),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -12,26 +12,26 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreEvents, CoreEventObserver } from '@singletons/events';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import {
|
||||
AddonNotifications,
|
||||
AddonNotificationsProvider,
|
||||
AddonNotifications, AddonNotificationsProvider,
|
||||
} from '../../services/notifications';
|
||||
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
|
||||
import {
|
||||
AddonNotificationsHelper,
|
||||
AddonNotificationsNotificationToRender,
|
||||
} from '@addons/notifications/services/notifications-helper';
|
||||
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
||||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
import { AddonsNotificationsNotificationsSource } from '@addons/notifications/classes/notifications-source';
|
||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||
import { AddonNotificationsNotificationToRender } from '@addons/notifications/services/notifications-helper';
|
||||
|
||||
/**
|
||||
* Page that displays the list of notifications.
|
||||
|
@ -41,12 +41,11 @@ import { CoreTimeUtils } from '@services/utils/time';
|
|||
templateUrl: 'list.html',
|
||||
styleUrls: ['list.scss', '../../notifications.scss'],
|
||||
})
|
||||
export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
||||
export class AddonNotificationsListPage implements AfterViewInit, OnDestroy {
|
||||
|
||||
notifications: AddonNotificationsNotificationToRender[] = [];
|
||||
notificationsLoaded = false;
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
|
||||
notifications!: CoreListItemsManager<AddonNotificationsNotificationToRender, AddonsNotificationsNotificationsSource>;
|
||||
fetchMoreNotificationsFailed = false;
|
||||
canMarkAllNotificationsAsRead = false;
|
||||
loadingMarkAllNotificationsAsRead = false;
|
||||
|
||||
|
@ -56,18 +55,33 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
protected pushObserver?: Subscription;
|
||||
protected pendingRefresh = false;
|
||||
|
||||
constructor() {
|
||||
try {
|
||||
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
||||
AddonsNotificationsNotificationsSource,
|
||||
[],
|
||||
);
|
||||
|
||||
this.notifications = new CoreListItemsManager(source, AddonNotificationsListPage);
|
||||
} catch(error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
CoreNavigator.back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.fetchNotifications();
|
||||
async ngAfterViewInit(): Promise<void> {
|
||||
await this.fetchInitialNotifications();
|
||||
|
||||
this.notifications.start(this.splitView);
|
||||
|
||||
this.cronObserver = CoreEvents.on(AddonNotificationsProvider.READ_CRON_EVENT, () => {
|
||||
if (!this.isCurrentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.notificationsLoaded = false;
|
||||
this.refreshNotifications();
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
|
||||
|
@ -83,7 +97,6 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
this.notificationsLoaded = false;
|
||||
this.refreshNotifications();
|
||||
});
|
||||
|
||||
|
@ -92,7 +105,7 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
const notification = this.notifications.find((notification) => notification.id === data.id);
|
||||
const notification = this.notifications.items.find((notification) => notification.id === data.id);
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
@ -109,34 +122,47 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Convenience function to get notifications. Gets unread notifications first.
|
||||
*
|
||||
* @param refresh Whether we're refreshing data.
|
||||
* @return Resolved when done.
|
||||
* @param reload Whether to reload the list or load the next page.
|
||||
*/
|
||||
protected async fetchNotifications(refresh?: boolean): Promise<void> {
|
||||
this.loadMoreError = false;
|
||||
protected async fetchNotifications(reload: boolean): Promise<void> {
|
||||
reload
|
||||
? await this.notifications.reload()
|
||||
: await this.notifications.load();
|
||||
|
||||
this.fetchMoreNotificationsFailed = false;
|
||||
this.loadMarkAllAsReadButton();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the initial batch of notifications.
|
||||
*/
|
||||
private async fetchInitialNotifications(): Promise<void> {
|
||||
try {
|
||||
const result = await AddonNotifications.getNotifications(refresh ? [] : this.notifications);
|
||||
|
||||
const notifications = result.notifications
|
||||
.map((notification) => AddonNotificationsHelper.formatNotificationText(notification));
|
||||
|
||||
if (refresh) {
|
||||
this.notifications = notifications;
|
||||
} else {
|
||||
this.notifications = this.notifications.concat(notifications);
|
||||
}
|
||||
this.canLoadMore = result.canLoadMore;
|
||||
|
||||
await this.loadMarkAllAsReadButton();
|
||||
await this.fetchNotifications(true);
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.notifications.errorgetnotifications', true);
|
||||
this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.
|
||||
} finally {
|
||||
this.notificationsLoaded = true;
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading notifications');
|
||||
|
||||
this.notifications.reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a new batch of Notifications.
|
||||
*
|
||||
* @param complete Completion callback.
|
||||
*/
|
||||
async fetchMoreNotifications(complete: () => void): Promise<void> {
|
||||
try {
|
||||
await this.fetchNotifications(false);
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading more notifications');
|
||||
|
||||
this.fetchMoreNotificationsFailed = true;
|
||||
}
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all notifications as read.
|
||||
*
|
||||
|
@ -151,9 +177,6 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
time: CoreTimeUtils.timestamp(),
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
|
||||
// All marked as read, refresh the list.
|
||||
this.notificationsLoaded = false;
|
||||
|
||||
await this.refreshNotifications();
|
||||
}
|
||||
|
||||
|
@ -179,38 +202,12 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
* Refresh notifications.
|
||||
*
|
||||
* @param refresher Refresher.
|
||||
* @return Promise<any> Promise resolved when done.
|
||||
*/
|
||||
async refreshNotifications(refresher?: IonRefresher): Promise<void> {
|
||||
await CoreUtils.ignoreErrors(AddonNotifications.invalidateNotificationsList());
|
||||
await CoreUtils.ignoreErrors(this.fetchNotifications(true));
|
||||
|
||||
try {
|
||||
await this.fetchNotifications(true);
|
||||
} finally {
|
||||
refresher?.complete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load more results.
|
||||
*
|
||||
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
||||
*/
|
||||
async loadMoreNotifications(infiniteComplete?: () => void): Promise<void> {
|
||||
try {
|
||||
await this.fetchNotifications();
|
||||
} finally {
|
||||
infiniteComplete?.();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Notification page.
|
||||
*
|
||||
* @param notification Notification to open.
|
||||
*/
|
||||
openNotification(notification: AddonNotificationsNotificationToRender): void {
|
||||
CoreNavigator.navigate('../notification', { params: { notification } });
|
||||
refresher?.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,7 +221,6 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
this.pendingRefresh = false;
|
||||
this.notificationsLoaded = false;
|
||||
|
||||
this.refreshNotifications();
|
||||
}
|
||||
|
@ -243,6 +239,7 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
|
|||
this.cronObserver?.off();
|
||||
this.readObserver?.off();
|
||||
this.pushObserver?.unsubscribe();
|
||||
this.notifications?.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,18 +12,19 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { AddonsNotificationsNotificationsSource } from '@addons/notifications/classes/notifications-source';
|
||||
import { AddonNotificationsNotificationData } from '@addons/notifications/services/handlers/push-click';
|
||||
import { AddonNotifications } from '@addons/notifications/services/notifications';
|
||||
import {
|
||||
AddonNotificationsHelper,
|
||||
AddonNotificationsNotificationToRender,
|
||||
} from '@addons/notifications/services/notifications-helper';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreContentLinksAction, CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Page to render a notification.
|
||||
|
@ -58,28 +59,14 @@ export class AddonNotificationsNotificationPage implements OnInit {
|
|||
let notification: AddonNotificationsNotification;
|
||||
|
||||
try {
|
||||
notification = CoreNavigator.getRequiredRouteParam('notification');
|
||||
notification = this.getCurrentNotification();
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
|
||||
CoreNavigator.back();
|
||||
await CoreDomUtils.showErrorModal(error);
|
||||
await CoreNavigator.back();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!('subject' in notification)) {
|
||||
// Try to find the notification using the WebService, it contains a better message.
|
||||
const notifId = Number(notification.savedmessageid);
|
||||
const result = await CoreUtils.ignoreErrors(
|
||||
AddonNotifications.getNotifications([], { siteId: notification.site }),
|
||||
);
|
||||
|
||||
const foundNotification = result?.notifications.find(notif => notif.id === notifId);
|
||||
if (foundNotification) {
|
||||
notification = AddonNotificationsHelper.formatNotificationText(foundNotification);
|
||||
}
|
||||
}
|
||||
|
||||
if ('subject' in notification) {
|
||||
this.subject = notification.subject;
|
||||
this.content = notification.mobiletext || notification.fullmessagehtml;
|
||||
|
@ -89,8 +76,10 @@ export class AddonNotificationsNotificationPage implements OnInit {
|
|||
this.iconUrl = notification.iconurl;
|
||||
if (notification.moodlecomponent?.startsWith('mod_') && notification.iconurl) {
|
||||
const modname = notification.moodlecomponent.substring(4);
|
||||
if (notification.iconurl.match('/theme/image.php/[^/]+/' + modname + '/[-0-9]*/') ||
|
||||
notification.iconurl.match('/theme/image.php/[^/]+/' + notification.moodlecomponent + '/[-0-9]*/')) {
|
||||
if (
|
||||
notification.iconurl.match('/theme/image.php/[^/]+/' + modname + '/[-0-9]*/') ||
|
||||
notification.iconurl.match('/theme/image.php/[^/]+/' + notification.moodlecomponent + '/[-0-9]*/')
|
||||
) {
|
||||
this.modname = modname;
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +99,39 @@ export class AddonNotificationsNotificationPage implements OnInit {
|
|||
this.loaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load notifications
|
||||
*
|
||||
* @param notificationId Notification id.
|
||||
* @return Found notification
|
||||
*/
|
||||
loadNotifications(notificationId: number): AddonNotificationsNotification {
|
||||
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
||||
AddonsNotificationsNotificationsSource,
|
||||
[],
|
||||
);
|
||||
const notification = source.getItems()?.find(({ id }) => id === notificationId);
|
||||
|
||||
if (!notification) {
|
||||
throw new CoreError(`Notification with id ${notificationId} not found`);
|
||||
}
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load current notification if it's found
|
||||
*
|
||||
* @return Found notification
|
||||
*/
|
||||
getCurrentNotification(): AddonNotificationsNotification {
|
||||
const pushNotification: AddonNotificationsNotificationData | undefined = CoreNavigator.getRouteParam('notification');
|
||||
|
||||
return this.loadNotifications(
|
||||
pushNotification ? Number(pushNotification?.savedmessageid) : CoreNavigator.getRequiredRouteNumberParam('id'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load notification actions
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue