forked from EVOgeek/Vmeda.Online
		
	Merge pull request #2980 from dpalou/MOBILE-3829
MOBILE-3829 notifications: Display notification clicked in new page
This commit is contained in:
		
						commit
						07fae0152a
					
				| @ -27,6 +27,11 @@ function buildRoutes(injector: Injector): Routes { | ||||
|             }, | ||||
|             loadChildren: () => import('./pages/list/list.module').then(m => m.AddonNotificationsListPageModule), | ||||
|         }, | ||||
|         { | ||||
|             path: 'notification', | ||||
|             loadChildren: () => import('./pages/notification/notification.module') | ||||
|                 .then(m => m.AddonNotificationsNotificationPageModule), | ||||
|         }, | ||||
|         ...buildTabMainRoutes(injector, { | ||||
|             redirectTo: 'list', | ||||
|             pathMatch: 'full', | ||||
|  | ||||
| @ -18,15 +18,17 @@ import { Subscription } from 'rxjs'; | ||||
| 
 | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { CoreDomUtils } from '@services/utils/dom'; | ||||
| import { CoreTextUtils } from '@services/utils/text'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| import { CoreEvents, CoreEventObserver } from '@singletons/events'; | ||||
| import { | ||||
|     AddonNotifications, | ||||
|     AddonNotificationsNotificationMessageFormatted, | ||||
|     AddonNotificationsProvider, | ||||
| } from '../../services/notifications'; | ||||
| import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; | ||||
| import { | ||||
|     AddonNotificationsHelper, | ||||
|     AddonNotificationsNotificationToRender, | ||||
| } from '@addons/notifications/services/notifications-helper'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the list of notifications. | ||||
| @ -38,7 +40,7 @@ import { CorePushNotificationsDelegate } from '@features/pushnotifications/servi | ||||
| }) | ||||
| export class AddonNotificationsListPage implements OnInit, OnDestroy { | ||||
| 
 | ||||
|     notifications: FormattedNotification[] = []; | ||||
|     notifications: AddonNotificationsNotificationToRender[] = []; | ||||
|     notificationsLoaded = false; | ||||
|     canLoadMore = false; | ||||
|     loadMoreError = false; | ||||
| @ -94,7 +96,8 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy { | ||||
|         try { | ||||
|             const result = await AddonNotifications.getNotifications(refresh ? [] : this.notifications); | ||||
| 
 | ||||
|             const notifications = result.notifications.map((notification) => this.formatText(notification)); | ||||
|             const notifications = result.notifications | ||||
|                 .map((notification) => AddonNotificationsHelper.formatNotificationText(notification)); | ||||
| 
 | ||||
|             if (refresh) { | ||||
|                 this.notifications = notifications; | ||||
| @ -135,7 +138,7 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy { | ||||
|      * | ||||
|      * @param notifications Array of notification objects. | ||||
|      */ | ||||
|     protected async markNotificationsAsRead(notifications: FormattedNotification[]): Promise<void> { | ||||
|     protected async markNotificationsAsRead(notifications: AddonNotificationsNotificationToRender[]): Promise<void> { | ||||
|         if (notifications.length > 0) { | ||||
|             const promises = notifications.map(async (notification) => { | ||||
|                 if (notification.read) { | ||||
| @ -194,33 +197,6 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Formats the text of a notification. | ||||
|      * | ||||
|      * @param notification The notification object. | ||||
|      */ | ||||
|     protected formatText(notification: AddonNotificationsNotificationMessageFormatted): FormattedNotification { | ||||
|         const formattedNotification: FormattedNotification = notification; | ||||
|         formattedNotification.displayfullhtml = this.shouldDisplayFullHtml(notification); | ||||
|         formattedNotification.iconurl = formattedNotification.iconurl || undefined; // Make sure the property exists.
 | ||||
| 
 | ||||
|         formattedNotification.mobiletext = formattedNotification.displayfullhtml ? | ||||
|             notification.fullmessagehtml : | ||||
|             CoreTextUtils.replaceNewLines((formattedNotification.mobiletext || '').replace(/-{4,}/ig, ''), '<br>'); | ||||
| 
 | ||||
|         return formattedNotification; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether we should display full HTML of the notification. | ||||
|      * | ||||
|      * @param notification Notification. | ||||
|      * @return Whether to display full HTML. | ||||
|      */ | ||||
|     protected shouldDisplayFullHtml(notification: FormattedNotification): boolean { | ||||
|         return notification.component == 'mod_forum' && notification.eventtype == 'digests'; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * User entered the page. | ||||
|      */ | ||||
| @ -253,8 +229,3 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy { | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| type FormattedNotification = AddonNotificationsNotificationMessageFormatted & { | ||||
|     displayfullhtml?: boolean; // Whether to display the full HTML of the notification.
 | ||||
|     iconurl?: string; | ||||
| }; | ||||
|  | ||||
| @ -0,0 +1,30 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <h2>{{ 'addon.notifications.notifications' | translate }}</h2> | ||||
|     </ion-toolbar> | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <core-loading [hideUntil]="loaded"> | ||||
|         <ion-item class="ion-text-wrap" lines="none" [attr.aria-label]="subject"> | ||||
|             <core-user-avatar *ngIf="userIdFrom > 0" slot="start" [userId]="userIdFrom" [profileUrl]="profileImageUrlFrom" | ||||
|                 [fullname]="userFromFullName" [extraIcon]="iconUrl"></core-user-avatar> | ||||
| 
 | ||||
|             <img *ngIf="userIdFrom <= 0 && iconUrl" [src]="iconUrl" alt="" | ||||
|                 role="presentation" class="core-notification-icon" slot="start"> | ||||
| 
 | ||||
|             <ion-label> | ||||
|                 <p class="item-heading">{{ subject }}</p> | ||||
|                 <p *ngIf="userIdFrom > 0">{{ userFromFullName }}</p> | ||||
|             </ion-label> | ||||
|         </ion-item> | ||||
|         <ion-item class="ion-text-wrap"> | ||||
|             <ion-label> | ||||
|                 <core-format-text [text]="content | coreCreateLinks" contextLevel="system" [contextInstanceId]="0"> | ||||
|                 </core-format-text> | ||||
|             </ion-label> | ||||
|         </ion-item> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
| @ -0,0 +1,40 @@ | ||||
| // (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 { NgModule } from '@angular/core'; | ||||
| import { RouterModule, Routes } from '@angular/router'; | ||||
| 
 | ||||
| import { CoreSharedModule } from '@/core/shared.module'; | ||||
| import { AddonNotificationsComponentsModule } from '../../components/components.module'; | ||||
| import { AddonNotificationsNotificationPage } from './notification'; | ||||
| 
 | ||||
| const routes: Routes = [ | ||||
|     { | ||||
|         path: '', | ||||
|         component: AddonNotificationsNotificationPage, | ||||
|     }, | ||||
| ]; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     imports: [ | ||||
|         RouterModule.forChild(routes), | ||||
|         CoreSharedModule, | ||||
|         AddonNotificationsComponentsModule, | ||||
|     ], | ||||
|     declarations: [ | ||||
|         AddonNotificationsNotificationPage, | ||||
|     ], | ||||
|     exports: [RouterModule], | ||||
| }) | ||||
| export class AddonNotificationsNotificationPageModule {} | ||||
							
								
								
									
										90
									
								
								src/addons/notifications/pages/notification/notification.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/addons/notifications/pages/notification/notification.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| // (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 { 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 { CoreNavigator } from '@services/navigator'; | ||||
| import { CoreDomUtils } from '@services/utils/dom'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| 
 | ||||
| /** | ||||
|  * Page to render a notification. | ||||
|  */ | ||||
| @Component({ | ||||
|     selector: 'page-addon-notifications-notification', | ||||
|     templateUrl: 'notification.html', | ||||
| }) | ||||
| export class AddonNotificationsNotificationPage implements OnInit { | ||||
| 
 | ||||
|     subject = ''; // Notification subject.
 | ||||
|     content = ''; // Notification content.
 | ||||
|     userIdFrom = -1; // User ID who sent the notification.
 | ||||
|     profileImageUrlFrom?: string; // Avatar of the user who sent the notification.
 | ||||
|     userFromFullName?: string; // Name of the user who sent the notification.
 | ||||
|     iconUrl?: string; // Icon URL.
 | ||||
|     loaded = false; | ||||
| 
 | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     async ngOnInit(): Promise<void> { | ||||
|         let notification: AddonNotificationsNotificationToRender | AddonNotificationsNotificationData; | ||||
| 
 | ||||
|         try { | ||||
|             notification = CoreNavigator.getRequiredRouteParam('notification'); | ||||
|         } catch (error) { | ||||
|             CoreDomUtils.showErrorModal(error); | ||||
| 
 | ||||
|             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; | ||||
|             this.userIdFrom = notification.useridfrom; | ||||
|             this.profileImageUrlFrom = notification.profileimageurlfrom; | ||||
|             this.userFromFullName = notification.userfromfullname; | ||||
|             this.iconUrl = notification.iconurl; | ||||
|         } else { | ||||
|             this.subject = notification.title || ''; | ||||
|             this.content = notification.message || ''; | ||||
|             this.userIdFrom = notification.userfromid ? Number(notification.userfromid) : -1; | ||||
|             this.profileImageUrlFrom = notification.senderImage; | ||||
|             this.userFromFullName = notification.userfromfullname; | ||||
|         } | ||||
| 
 | ||||
|         this.loaded = true; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -127,10 +127,16 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi | ||||
|         await CoreUtils.ignoreErrors(AddonNotifications.invalidateNotificationsList(notification.site)); | ||||
| 
 | ||||
|         await CoreNavigator.navigateToSitePath( | ||||
|             AddonNotificationsMainMenuHandlerService.PAGE_NAME, | ||||
|             `${AddonNotificationsMainMenuHandlerService.PAGE_NAME}/list`, | ||||
|             { | ||||
|                 siteId: notification.site, | ||||
|                 preferCurrentTab: false, | ||||
|                 nextNavigation: { | ||||
|                     path: '../notification', | ||||
|                     options: { | ||||
|                         params: { notification }, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         ); | ||||
|     } | ||||
| @ -139,7 +145,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi | ||||
| 
 | ||||
| export const AddonNotificationsPushClickHandler = makeSingleton(AddonNotificationsPushClickHandlerService); | ||||
| 
 | ||||
| type AddonNotificationsNotificationData = CorePushNotificationsNotificationBasicData & { | ||||
| export type AddonNotificationsNotificationData = CorePushNotificationsNotificationBasicData & { | ||||
|     contexturl?: string; // URL related to the notification.
 | ||||
|     savedmessageid?: number; // Notification ID (optional).
 | ||||
|     id?: number; // Notification ID (optional).
 | ||||
|  | ||||
| @ -18,12 +18,14 @@ import { CoreUtils } from '@services/utils/utils'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { AddonMessageOutputDelegate } from '@addons/messageoutput/services/messageoutput-delegate'; | ||||
| import { | ||||
|     AddonNotificationsNotificationMessageFormatted, | ||||
|     AddonNotificationsPreferences, | ||||
|     AddonNotificationsPreferencesComponent, | ||||
|     AddonNotificationsPreferencesNotification, | ||||
|     AddonNotificationsPreferencesNotificationProcessor, | ||||
|     AddonNotificationsPreferencesProcessor, | ||||
| } from './notifications'; | ||||
| import { CoreTextUtils } from '@services/utils/text'; | ||||
| 
 | ||||
| /** | ||||
|  * Service that provides some helper functions for notifications. | ||||
| @ -31,6 +33,25 @@ import { | ||||
| @Injectable({ providedIn: 'root' }) | ||||
| export class AddonNotificationsHelperProvider { | ||||
| 
 | ||||
|     /** | ||||
|      * Formats the text of a notification. | ||||
|      * | ||||
|      * @param notification The notification object. | ||||
|      */ | ||||
|     formatNotificationText( | ||||
|         notification: AddonNotificationsNotificationMessageFormatted, | ||||
|     ): AddonNotificationsNotificationToRender { | ||||
|         const formattedNotification: AddonNotificationsNotificationToRender = notification; | ||||
|         formattedNotification.displayfullhtml = this.shouldDisplayFullHtml(notification); | ||||
|         formattedNotification.iconurl = formattedNotification.iconurl || undefined; // Make sure the property exists.
 | ||||
| 
 | ||||
|         formattedNotification.mobiletext = formattedNotification.displayfullhtml ? | ||||
|             notification.fullmessagehtml : | ||||
|             CoreTextUtils.replaceNewLines((formattedNotification.mobiletext || '').replace(/-{4,}/ig, ''), '<br>'); | ||||
| 
 | ||||
|         return formattedNotification; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Format preferences data. | ||||
|      * | ||||
| @ -119,6 +140,16 @@ export class AddonNotificationsHelperProvider { | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether we should display full HTML of the notification. | ||||
|      * | ||||
|      * @param notification Notification. | ||||
|      * @return Whether to display full HTML. | ||||
|      */ | ||||
|     protected shouldDisplayFullHtml(notification: AddonNotificationsNotificationToRender): boolean { | ||||
|         return notification.component == 'mod_forum' && notification.eventtype == 'digests'; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export const AddonNotificationsHelper = makeSingleton(AddonNotificationsHelperProvider); | ||||
| @ -151,3 +182,11 @@ export type AddonNotificationsPreferencesNotificationFormatted = AddonNotificati | ||||
| export type AddonNotificationsPreferencesProcessorFormatted = AddonNotificationsPreferencesProcessor & { | ||||
|     supported?: boolean; // Calculated in the app. Whether the processor is supported in the app.
 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Notification with some calculated data to render it. | ||||
|  */ | ||||
| export type AddonNotificationsNotificationToRender = AddonNotificationsNotificationMessageFormatted & { | ||||
|     displayfullhtml?: boolean; // Whether to display the full HTML of the notification.
 | ||||
|     iconurl?: string; | ||||
| }; | ||||
|  | ||||
| @ -209,7 +209,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { | ||||
| 
 | ||||
|             // Go to the site initial page.
 | ||||
|             this.page | ||||
|                 ? await CoreNavigator.navigateToSitePath(this.page, { params: this.pageOptions }) | ||||
|                 ? await CoreNavigator.navigateToSitePath(this.page, this.pageOptions) | ||||
|                 : await CoreNavigator.navigateToSiteHome(); | ||||
|         } catch (error) { | ||||
|             CoreLoginHelper.treatUserTokenError(this.siteUrl, error, this.username, password); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user