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), |             loadChildren: () => import('./pages/list/list.module').then(m => m.AddonNotificationsListPageModule), | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             path: 'notification', | ||||||
|  |             loadChildren: () => import('./pages/notification/notification.module') | ||||||
|  |                 .then(m => m.AddonNotificationsNotificationPageModule), | ||||||
|  |         }, | ||||||
|         ...buildTabMainRoutes(injector, { |         ...buildTabMainRoutes(injector, { | ||||||
|             redirectTo: 'list', |             redirectTo: 'list', | ||||||
|             pathMatch: 'full', |             pathMatch: 'full', | ||||||
|  | |||||||
| @ -18,15 +18,17 @@ import { Subscription } from 'rxjs'; | |||||||
| 
 | 
 | ||||||
| import { CoreSites } from '@services/sites'; | import { CoreSites } from '@services/sites'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| import { CoreTextUtils } from '@services/utils/text'; |  | ||||||
| import { CoreUtils } from '@services/utils/utils'; | import { CoreUtils } from '@services/utils/utils'; | ||||||
| import { CoreEvents, CoreEventObserver } from '@singletons/events'; | import { CoreEvents, CoreEventObserver } from '@singletons/events'; | ||||||
| import { | import { | ||||||
|     AddonNotifications, |     AddonNotifications, | ||||||
|     AddonNotificationsNotificationMessageFormatted, |  | ||||||
|     AddonNotificationsProvider, |     AddonNotificationsProvider, | ||||||
| } from '../../services/notifications'; | } from '../../services/notifications'; | ||||||
| import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; | import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; | ||||||
|  | import { | ||||||
|  |     AddonNotificationsHelper, | ||||||
|  |     AddonNotificationsNotificationToRender, | ||||||
|  | } from '@addons/notifications/services/notifications-helper'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page that displays the list of notifications. |  * Page that displays the list of notifications. | ||||||
| @ -38,7 +40,7 @@ import { CorePushNotificationsDelegate } from '@features/pushnotifications/servi | |||||||
| }) | }) | ||||||
| export class AddonNotificationsListPage implements OnInit, OnDestroy { | export class AddonNotificationsListPage implements OnInit, OnDestroy { | ||||||
| 
 | 
 | ||||||
|     notifications: FormattedNotification[] = []; |     notifications: AddonNotificationsNotificationToRender[] = []; | ||||||
|     notificationsLoaded = false; |     notificationsLoaded = false; | ||||||
|     canLoadMore = false; |     canLoadMore = false; | ||||||
|     loadMoreError = false; |     loadMoreError = false; | ||||||
| @ -94,7 +96,8 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy { | |||||||
|         try { |         try { | ||||||
|             const result = await AddonNotifications.getNotifications(refresh ? [] : this.notifications); |             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) { |             if (refresh) { | ||||||
|                 this.notifications = notifications; |                 this.notifications = notifications; | ||||||
| @ -135,7 +138,7 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy { | |||||||
|      * |      * | ||||||
|      * @param notifications Array of notification objects. |      * @param notifications Array of notification objects. | ||||||
|      */ |      */ | ||||||
|     protected async markNotificationsAsRead(notifications: FormattedNotification[]): Promise<void> { |     protected async markNotificationsAsRead(notifications: AddonNotificationsNotificationToRender[]): Promise<void> { | ||||||
|         if (notifications.length > 0) { |         if (notifications.length > 0) { | ||||||
|             const promises = notifications.map(async (notification) => { |             const promises = notifications.map(async (notification) => { | ||||||
|                 if (notification.read) { |                 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. |      * 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 CoreUtils.ignoreErrors(AddonNotifications.invalidateNotificationsList(notification.site)); | ||||||
| 
 | 
 | ||||||
|         await CoreNavigator.navigateToSitePath( |         await CoreNavigator.navigateToSitePath( | ||||||
|             AddonNotificationsMainMenuHandlerService.PAGE_NAME, |             `${AddonNotificationsMainMenuHandlerService.PAGE_NAME}/list`, | ||||||
|             { |             { | ||||||
|                 siteId: notification.site, |                 siteId: notification.site, | ||||||
|                 preferCurrentTab: false, |                 preferCurrentTab: false, | ||||||
|  |                 nextNavigation: { | ||||||
|  |                     path: '../notification', | ||||||
|  |                     options: { | ||||||
|  |                         params: { notification }, | ||||||
|  |                     }, | ||||||
|  |                 }, | ||||||
|             }, |             }, | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| @ -139,7 +145,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi | |||||||
| 
 | 
 | ||||||
| export const AddonNotificationsPushClickHandler = makeSingleton(AddonNotificationsPushClickHandlerService); | export const AddonNotificationsPushClickHandler = makeSingleton(AddonNotificationsPushClickHandlerService); | ||||||
| 
 | 
 | ||||||
| type AddonNotificationsNotificationData = CorePushNotificationsNotificationBasicData & { | export type AddonNotificationsNotificationData = CorePushNotificationsNotificationBasicData & { | ||||||
|     contexturl?: string; // URL related to the notification.
 |     contexturl?: string; // URL related to the notification.
 | ||||||
|     savedmessageid?: number; // Notification ID (optional).
 |     savedmessageid?: number; // Notification ID (optional).
 | ||||||
|     id?: number; // Notification ID (optional).
 |     id?: number; // Notification ID (optional).
 | ||||||
|  | |||||||
| @ -18,12 +18,14 @@ import { CoreUtils } from '@services/utils/utils'; | |||||||
| import { makeSingleton } from '@singletons'; | import { makeSingleton } from '@singletons'; | ||||||
| import { AddonMessageOutputDelegate } from '@addons/messageoutput/services/messageoutput-delegate'; | import { AddonMessageOutputDelegate } from '@addons/messageoutput/services/messageoutput-delegate'; | ||||||
| import { | import { | ||||||
|  |     AddonNotificationsNotificationMessageFormatted, | ||||||
|     AddonNotificationsPreferences, |     AddonNotificationsPreferences, | ||||||
|     AddonNotificationsPreferencesComponent, |     AddonNotificationsPreferencesComponent, | ||||||
|     AddonNotificationsPreferencesNotification, |     AddonNotificationsPreferencesNotification, | ||||||
|     AddonNotificationsPreferencesNotificationProcessor, |     AddonNotificationsPreferencesNotificationProcessor, | ||||||
|     AddonNotificationsPreferencesProcessor, |     AddonNotificationsPreferencesProcessor, | ||||||
| } from './notifications'; | } from './notifications'; | ||||||
|  | import { CoreTextUtils } from '@services/utils/text'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Service that provides some helper functions for notifications. |  * Service that provides some helper functions for notifications. | ||||||
| @ -31,6 +33,25 @@ import { | |||||||
| @Injectable({ providedIn: 'root' }) | @Injectable({ providedIn: 'root' }) | ||||||
| export class AddonNotificationsHelperProvider { | 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. |      * Format preferences data. | ||||||
|      * |      * | ||||||
| @ -119,6 +140,16 @@ export class AddonNotificationsHelperProvider { | |||||||
|         return result; |         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); | export const AddonNotificationsHelper = makeSingleton(AddonNotificationsHelperProvider); | ||||||
| @ -151,3 +182,11 @@ export type AddonNotificationsPreferencesNotificationFormatted = AddonNotificati | |||||||
| export type AddonNotificationsPreferencesProcessorFormatted = AddonNotificationsPreferencesProcessor & { | export type AddonNotificationsPreferencesProcessorFormatted = AddonNotificationsPreferencesProcessor & { | ||||||
|     supported?: boolean; // Calculated in the app. Whether the processor is supported in the app.
 |     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.
 |             // Go to the site initial page.
 | ||||||
|             this.page |             this.page | ||||||
|                 ? await CoreNavigator.navigateToSitePath(this.page, { params: this.pageOptions }) |                 ? await CoreNavigator.navigateToSitePath(this.page, this.pageOptions) | ||||||
|                 : await CoreNavigator.navigateToSiteHome(); |                 : await CoreNavigator.navigateToSiteHome(); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             CoreLoginHelper.treatUserTokenError(this.siteUrl, error, this.username, password); |             CoreLoginHelper.treatUserTokenError(this.siteUrl, error, this.username, password); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user