MOBILE-3320 comments: Show comments as messages
parent
e7d4588bcf
commit
5a15d1722f
|
@ -1,95 +0,0 @@
|
|||
// (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 { Component, ViewChild, ElementRef, Input } from '@angular/core';
|
||||
import { CoreComments } from '@features/comments/services/comments';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreForms } from '@singletons/form';
|
||||
import { ModalController } from '@singletons';
|
||||
|
||||
/**
|
||||
* Component that displays a text area for composing a comment.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-comments-add',
|
||||
templateUrl: 'add.html',
|
||||
})
|
||||
export class CoreCommentsAddComponent {
|
||||
|
||||
@ViewChild('commentForm') formElement?: ElementRef;
|
||||
|
||||
@Input() protected contextLevel!: string;
|
||||
@Input() protected instanceId!: number;
|
||||
@Input() protected componentName!: string;
|
||||
@Input() protected itemId!: number;
|
||||
@Input() protected area = '';
|
||||
@Input() content = '';
|
||||
|
||||
processing = false;
|
||||
|
||||
/**
|
||||
* Send the comment or store it offline.
|
||||
*
|
||||
* @param e Event.
|
||||
*/
|
||||
async addComment(e: Event): Promise<void> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
CoreApp.closeKeyboard();
|
||||
const loadingModal = await CoreDomUtils.showModalLoading('core.sending', true);
|
||||
// Freeze the add comment button.
|
||||
this.processing = true;
|
||||
try {
|
||||
const commentsResponse = await CoreComments.addComment(
|
||||
this.content,
|
||||
this.contextLevel,
|
||||
this.instanceId,
|
||||
this.componentName,
|
||||
this.itemId,
|
||||
this.area,
|
||||
);
|
||||
|
||||
CoreForms.triggerFormSubmittedEvent(
|
||||
this.formElement,
|
||||
!!commentsResponse,
|
||||
CoreSites.getCurrentSiteId(),
|
||||
);
|
||||
|
||||
ModalController.dismiss(commentsResponse).finally(() => {
|
||||
CoreDomUtils.showToast(
|
||||
commentsResponse ? 'core.comments.eventcommentcreated' : 'core.datastoredoffline',
|
||||
true,
|
||||
3000,
|
||||
);
|
||||
});
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
this.processing = false;
|
||||
} finally {
|
||||
loadingModal.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close modal.
|
||||
*/
|
||||
closeModal(): void {
|
||||
CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
|
||||
ModalController.dismiss();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<h2>{{ 'core.comments.addcomment' | translate }}</h2>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
||||
<ion-icon name="fas-times" slot="icon-only" aria-hidden=true></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<form name="itemEdit" (ngSubmit)="addComment($event)" #commentForm>
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<ion-textarea placeholder="{{ 'core.comments.addcomment' | translate }}" rows="5" [(ngModel)]="content"
|
||||
name="content" required="required">
|
||||
</ion-textarea>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<div class="ion-padding">
|
||||
<ion-button expand="block" type="submit" [disabled]="processing || content.length < 1">
|
||||
{{ 'core.comments.savecomment' | translate }}
|
||||
</ion-button>
|
||||
</div>
|
||||
</form>
|
||||
</ion-content>
|
|
@ -14,20 +14,17 @@
|
|||
|
||||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CoreCommentsAddComponent } from './add/add-modal';
|
||||
import { CoreCommentsCommentsComponent } from './comments/comments';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCommentsCommentsComponent,
|
||||
CoreCommentsAddComponent,
|
||||
],
|
||||
imports: [
|
||||
CoreSharedModule,
|
||||
],
|
||||
exports: [
|
||||
CoreCommentsCommentsComponent,
|
||||
CoreCommentsAddComponent,
|
||||
],
|
||||
})
|
||||
export class CoreCommentsComponentsModule {}
|
||||
|
|
|
@ -34,75 +34,95 @@
|
|||
[message]="'core.comments.nocomments' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<ion-card class="core-warning-card" *ngIf="hasOffline">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
{{ 'core.thereisdatatosync' | translate:{$a: 'core.comments.comments' | translate | lowercase } }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
<!-- Load previous messages. -->
|
||||
<core-infinite-loading [enabled]="canLoadMore" position="top" (action)="loadPrevious($event)" [error]="loadMoreError">
|
||||
</core-infinite-loading>
|
||||
|
||||
<ion-card *ngIf="offlineComment" (click)="addComment($event)">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<core-user-avatar [user]="offlineComment" slot="start"></core-user-avatar>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ offlineComment.fullname }}</p>
|
||||
<p>
|
||||
<ion-icon name="fas-clock" aria-hidden="true"></ion-icon> {{ 'core.notsent' | translate }}
|
||||
</p>
|
||||
</ion-label>
|
||||
<ion-button *ngIf="showDelete" slot="end" fill="clear" [@coreSlideInOut]="'fromRight'" color="danger"
|
||||
(click)="deleteComment($event, offlineComment)" [attr.aria-label]="'core.delete' | translate">
|
||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<core-format-text clean="true" [text]="offlineComment.content" [contextLevel]="contextLevel"
|
||||
[contextInstanceId]="instanceId" [courseId]="courseId">
|
||||
</core-format-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
<ion-list class="addon-messages-discussion-container">
|
||||
<ng-container *ngFor="let comment of comments; index as index; last as last">
|
||||
|
||||
<ion-card *ngFor="let comment of comments">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<core-user-avatar [user]="comment" slot="start"></core-user-avatar>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ comment.fullname }}</p>
|
||||
<p *ngIf="!comment.deleted">{{ comment.timecreated * 1000 | coreFormatDate: 'strftimerecentfull' }}</p>
|
||||
<p *ngIf="comment.deleted">
|
||||
<ion-icon name="fas-trash" aria-hidden="true"></ion-icon> <span class="ion-text-wrap">
|
||||
{{ 'core.deletedoffline' | translate }}
|
||||
</span>
|
||||
<p class="ion-text-center addon-messages-date" *ngIf="comment.showDate">
|
||||
{{ comment.timecreated * 1000 | coreFormatDate: "strftimedayshort" }}
|
||||
</p>
|
||||
</ion-label>
|
||||
<ion-button *ngIf="showDelete && !comment.deleted && comment.delete" slot="end" fill="clear"
|
||||
[@coreSlideInOut]="'fromRight'" color="danger" (click)="deleteComment($event, comment)"
|
||||
[attr.aria-label]="'core.delete' | translate">
|
||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button *ngIf="showDelete && comment.deleted" slot="end" fill="clear" color="danger"
|
||||
(click)="undoDeleteComment($event, comment)" [attr.aria-label]="'core.restore' | translate">
|
||||
<ion-icon name="fas-undo-alt" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
|
||||
<ion-item class="ion-text-wrap addon-message"
|
||||
[class.addon-message-mine]="comment.userid == currentUserId"
|
||||
[class.addon-message-not-mine]="comment.userid != currentUserId"
|
||||
[class.addon-message-no-user]="!comment.showUserData"
|
||||
[@coreSlideInOut]="comment.userid == currentUserId ? '' : 'fromLeft'">
|
||||
<ion-label>
|
||||
<!-- User data. -->
|
||||
<h2 class="addon-message-user" *ngIf="comment.showUserData">
|
||||
<core-user-avatar slot="start" [user]="comment" [linkProfile]="false">
|
||||
</core-user-avatar>
|
||||
<div>{{ comment.fullname }}</div>
|
||||
</h2>
|
||||
|
||||
<p class="addon-message-text">
|
||||
<core-format-text [text]="comment.content" [contextLevel]="contextLevel" [contextInstanceId]="instanceId"
|
||||
[courseId]="courseId">
|
||||
</core-format-text>
|
||||
</p>
|
||||
</ion-label>
|
||||
<ion-note>
|
||||
<ng-container *ngIf="!comment.deleted">
|
||||
{{ comment.timecreated * 1000 | coreFormatDate: 'strftimetime' }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="comment.deleted">
|
||||
<ion-icon name="fas-trash" aria-hidden="true"></ion-icon> <span class="ion-text-wrap">
|
||||
{{ 'core.deletedoffline' | translate }}
|
||||
</span>
|
||||
</ng-container>
|
||||
</ion-note>
|
||||
<div class="tail" *ngIf="comment.showTail"></div>
|
||||
<ion-button *ngIf="showDelete && !comment.deleted && comment.delete" slot="end" fill="clear"
|
||||
[@coreSlideInOut]="'fromRight'" color="danger" (click)="deleteComment($event, comment)"
|
||||
[attr.aria-label]="'core.delete' | translate" class="addon-messages-delete-button">
|
||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button *ngIf="showDelete && comment.deleted" slot="end" fill="clear" color="danger"
|
||||
(click)="undoDeleteComment($event, comment)" [attr.aria-label]="'core.restore' | translate"
|
||||
class="addon-messages-delete-button">
|
||||
<ion-icon name="fas-undo-alt" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</ng-container>
|
||||
|
||||
<ion-item
|
||||
*ngIf="offlineComment"
|
||||
class="ion-text-wrap addon-message addon-message-mine"
|
||||
>
|
||||
<ion-label>
|
||||
<!-- User data. -->
|
||||
<p class="ion-text-center">
|
||||
<ion-icon name="fas-exclamation-triangle" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.thereisdatatosync' | translate:{$a: 'core.comments.comments' | translate | lowercase } }}
|
||||
</p>
|
||||
|
||||
<p class="addon-message-text">
|
||||
<core-format-text [text]="offlineComment.content" [contextLevel]="contextLevel" [contextInstanceId]="instanceId"
|
||||
[courseId]="courseId">
|
||||
</core-format-text>
|
||||
</p>
|
||||
</ion-label>
|
||||
<ion-note>
|
||||
<ion-icon name="fas-clock" aria-hidden="true"></ion-icon> {{ 'core.notsent' | translate }}
|
||||
</ion-note>
|
||||
<div class="tail"></div>
|
||||
<ion-button *ngIf="showDelete" slot="end" fill="clear"
|
||||
[@coreSlideInOut]="'fromRight'" color="danger" (click)="deleteComment($event, offlineComment)"
|
||||
[attr.aria-label]="'core.delete' | translate" class="addon-messages-delete-button">
|
||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMore($event)" [error]="loadMoreError"></core-infinite-loading>
|
||||
</core-loading>
|
||||
|
||||
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canAddComments">
|
||||
<ion-fab-button (click)="addComment($event)" [attr.aria-label]="'core.comments.addcomment' | translate">
|
||||
<ion-icon name="fas-plus" aria-hidden="true"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
<ion-footer color="light" class="footer-adjustable" *ngIf="commentsLoaded">
|
||||
<ion-toolbar color="light">
|
||||
<core-send-message-form [sendDisabled]="sending" [message]="newComment"
|
||||
(onSubmit)="addComment($event)" [placeholder]="'core.comments.addcomment' | translate">
|
||||
</core-send-message-form>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreAnimations } from '@components/animations';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import {
|
||||
CoreComments,
|
||||
|
@ -33,13 +33,14 @@ import { CoreNavigator } from '@services/navigator';
|
|||
import { Translate } from '@singletons';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreCommentsOffline } from '@features/comments/services/comments-offline';
|
||||
import { CoreCommentsDBRecord } from '@features/comments/services/database/comments';
|
||||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
import { CoreCommentsAddComponent } from '@features/comments/components/add/add-modal';
|
||||
import { CoreApp } from '@services/app';
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
* Page that displays comments.
|
||||
|
@ -48,12 +49,13 @@ import { CoreCommentsAddComponent } from '@features/comments/components/add/add-
|
|||
selector: 'page-core-comments-viewer',
|
||||
templateUrl: 'viewer.html',
|
||||
animations: [CoreAnimations.SLIDE_IN_OUT],
|
||||
styleUrls: ['viewer.scss'],
|
||||
})
|
||||
export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild(IonContent) content?: IonContent;
|
||||
|
||||
comments: CoreCommentsDataWithUser[] = [];
|
||||
comments: CoreCommentsDataToDisplay[] = [];
|
||||
commentsLoaded = false;
|
||||
contextLevel!: ContextLevel;
|
||||
instanceId!: number;
|
||||
|
@ -73,10 +75,12 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
syncIcon = CoreConstants.ICON_LOADING;
|
||||
offlineComment?: CoreCommentsOfflineWithUser;
|
||||
currentUserId: number;
|
||||
sending = false;
|
||||
newComment = '';
|
||||
|
||||
protected addDeleteCommentsAvailable = false;
|
||||
protected syncObserver?: CoreEventObserver;
|
||||
protected currentUser?: CoreUserProfile;
|
||||
protected viewDestroyed = false;
|
||||
|
||||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
|
@ -95,8 +99,6 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
this.refreshIcon = CoreConstants.ICON_LOADING;
|
||||
this.syncIcon = CoreConstants.ICON_LOADING;
|
||||
|
||||
this.content?.scrollToTop();
|
||||
|
||||
this.page = 0;
|
||||
this.comments = [];
|
||||
this.fetchComments(false);
|
||||
|
@ -151,7 +153,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
);
|
||||
this.canAddComments = this.addDeleteCommentsAvailable && !!commentsResponse.canpost;
|
||||
|
||||
let comments = commentsResponse.comments.sort((a, b) => b.timecreated - a.timecreated);
|
||||
let comments = commentsResponse.comments.sort((a, b) => a.timecreated - b.timecreated);
|
||||
if (typeof commentsResponse.count != 'undefined') {
|
||||
this.canLoadMore = (this.comments.length + comments.length) < commentsResponse.count;
|
||||
} else {
|
||||
|
@ -162,7 +164,13 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
|
||||
comments = await Promise.all(comments.map((comment) => this.loadCommentProfile(comment)));
|
||||
|
||||
this.comments = this.comments.concat(comments);
|
||||
this.comments = comments.concat(this.comments);
|
||||
|
||||
this.comments.forEach((comment, index) => {
|
||||
comment.showDate = this.showDate(comment, this.comments[index - 1]);
|
||||
comment.showUserData = this.showUserData(comment, this.comments[index - 1]);
|
||||
comment.showTail = this.showTail(comment, this.comments[index + 1]);
|
||||
});
|
||||
|
||||
this.canDeleteComments = this.addDeleteCommentsAvailable &&
|
||||
(this.hasOffline || this.comments.some((comment) => !!comment.delete));
|
||||
|
@ -179,6 +187,10 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
this.commentsLoaded = true;
|
||||
this.refreshIcon = CoreConstants.ICON_REFRESH;
|
||||
this.syncIcon = CoreConstants.ICON_SYNC;
|
||||
|
||||
if (this.page == 0) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -189,7 +201,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
||||
* @return Resolved when done.
|
||||
*/
|
||||
loadMore(infiniteComplete?: () => void): Promise<void> {
|
||||
loadPrevious(infiniteComplete?: () => void): Promise<void> {
|
||||
this.page++;
|
||||
this.canLoadMore = false;
|
||||
|
||||
|
@ -262,34 +274,41 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a new comment to the list.
|
||||
* Send the comment or store it offline.
|
||||
*
|
||||
* @param e Event.
|
||||
* @param text Comment text to add.
|
||||
*/
|
||||
async addComment(e: Event): Promise<void> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
async addComment(text: string): Promise<void> {
|
||||
CoreApp.closeKeyboard();
|
||||
const loadingModal = await CoreDomUtils.showModalLoading('core.sending', true);
|
||||
// Freeze the add comment button.
|
||||
this.sending = true;
|
||||
try {
|
||||
const commentsResponse = await CoreComments.addComment(
|
||||
text,
|
||||
this.contextLevel,
|
||||
this.instanceId,
|
||||
this.componentName,
|
||||
this.itemId,
|
||||
this.area,
|
||||
);
|
||||
|
||||
const params: Params = {
|
||||
contextLevel: this.contextLevel,
|
||||
instanceId: this.instanceId,
|
||||
componentName: this.componentName,
|
||||
itemId: this.itemId,
|
||||
area: this.area,
|
||||
content: this.offlineComment ? this.offlineComment!.content : '',
|
||||
};
|
||||
CoreDomUtils.showToast(
|
||||
commentsResponse ? 'core.comments.eventcommentcreated' : 'core.datastoredoffline',
|
||||
true,
|
||||
3000,
|
||||
);
|
||||
|
||||
const comment = await CoreDomUtils.openModal<CoreCommentsDataWithUser>({
|
||||
component: CoreCommentsAddComponent,
|
||||
componentProps: params,
|
||||
});
|
||||
|
||||
if (comment) {
|
||||
if (commentsResponse) {
|
||||
this.invalidateComments();
|
||||
|
||||
const addedComments = await this.loadCommentProfile(comment);
|
||||
const addedComments = await this.loadCommentProfile(commentsResponse);
|
||||
addedComments.showDate = this.showDate(addedComments, this.comments[this.comments.length - 1]);
|
||||
addedComments.showUserData = this.showUserData(addedComments, this.comments[this.comments.length - 1]);
|
||||
addedComments.showTail = this.showTail(addedComments, this.comments[this.comments.length + 1]);
|
||||
|
||||
// Add the comment to the top.
|
||||
this.comments = [addedComments].concat(this.comments);
|
||||
this.comments = this.comments.concat([addedComments]);
|
||||
this.canDeleteComments = this.addDeleteCommentsAvailable;
|
||||
|
||||
CoreEvents.trigger(CoreCommentsProvider.COMMENTS_COUNT_CHANGED_EVENT, {
|
||||
|
@ -301,9 +320,18 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
countChange: 1,
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
|
||||
} else if (comment === false) {
|
||||
} else if (commentsResponse === false) {
|
||||
// Comments added in offline mode.
|
||||
return this.loadOfflineData();
|
||||
await this.loadOfflineData();
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
} finally {
|
||||
loadingModal.dismiss();
|
||||
this.sending = false;
|
||||
|
||||
// New comments.
|
||||
this.scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +341,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
* @param e Click event.
|
||||
* @param comment Comment to delete.
|
||||
*/
|
||||
async deleteComment(e: Event, comment: CoreCommentsDataWithUser | CoreCommentsOfflineWithUser): Promise<void> {
|
||||
async deleteComment(e: Event, comment: CoreCommentsDataToDisplay | CoreCommentsOfflineWithUser): Promise<void> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
@ -397,7 +425,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
* @param comment Comment object.
|
||||
* @return Promise resolved with modified comment when done.
|
||||
*/
|
||||
protected async loadCommentProfile(comment: CoreCommentsDataWithUser): Promise<CoreCommentsDataWithUser> {
|
||||
protected async loadCommentProfile(comment: CoreCommentsDataToDisplay): Promise<CoreCommentsDataToDisplay> {
|
||||
// Get the user profile image.
|
||||
try {
|
||||
const user = await CoreUser.getProfile(comment.userid!, undefined, true);
|
||||
|
@ -411,6 +439,54 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user info should be displayed for the current message.
|
||||
* User data is only displayed if the previous message was from another user.
|
||||
*
|
||||
* @param comment Comment object.
|
||||
* @param prevComment Previous comment object.
|
||||
* @return Whether user data should be shown.
|
||||
*/
|
||||
protected showUserData(
|
||||
comment: CoreCommentsDataToDisplay,
|
||||
prevComment?: CoreCommentsDataToDisplay,
|
||||
): boolean {
|
||||
return comment.userid != this.currentUserId && (!prevComment || prevComment.userid != comment.userid || !!comment.showDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a css tail should be shown.
|
||||
*
|
||||
* @param comment Comment object.
|
||||
* @param nextComment Previous comment object.
|
||||
* @return Whether user data should be shown.
|
||||
*/
|
||||
protected showTail(
|
||||
comment: CoreCommentsDataToDisplay,
|
||||
nextComment?: CoreCommentsDataToDisplay,
|
||||
): boolean {
|
||||
return !nextComment || nextComment.userid != comment.userid || !!nextComment.showDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the date should be displayed between messages (when the day changes at midnight for example).
|
||||
*
|
||||
* @param comment Comment object.
|
||||
* @param prevComment Previous comment object.
|
||||
* @return True if messages are from diferent days, false othetwise.
|
||||
*/
|
||||
protected showDate(
|
||||
comment: CoreCommentsDataToDisplay,
|
||||
prevComment?: CoreCommentsDataToDisplay,
|
||||
): boolean {
|
||||
if (!prevComment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if day has changed.
|
||||
return !moment(comment.timecreated * 1000).isSame(prevComment.timecreated * 1000, 'day');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load offline comments.
|
||||
*
|
||||
|
@ -434,14 +510,10 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!this.currentUser) {
|
||||
this.currentUser = await CoreUser.getProfile(this.currentUserId, undefined, true);
|
||||
if (this.newComment == '') {
|
||||
this.newComment = this.offlineComment!.content;
|
||||
}
|
||||
|
||||
if (this.currentUser) {
|
||||
this.offlineComment!.profileimageurl = this.currentUser.profileimageurl;
|
||||
this.offlineComment!.fullname = this.currentUser.fullname;
|
||||
}
|
||||
this.offlineComment!.userid = this.currentUserId;
|
||||
|
||||
return;
|
||||
|
@ -481,7 +553,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
* @param e Click event.
|
||||
* @param comment Comment to delete.
|
||||
*/
|
||||
async undoDeleteComment(e: Event, comment: CoreCommentsDataWithUser): Promise<void> {
|
||||
async undoDeleteComment(e: Event, comment: CoreCommentsDataToDisplay): Promise<void> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
|
@ -491,6 +563,18 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
this.showDelete = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll bottom when render has finished.
|
||||
*/
|
||||
protected scrollToBottom(): void {
|
||||
// Need a timeout to leave time to the view to be rendered.
|
||||
setTimeout(() => {
|
||||
if (!this.viewDestroyed) {
|
||||
this.content?.scrollToBottom();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle delete.
|
||||
*/
|
||||
|
@ -502,15 +586,19 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
* Page destroyed.
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.syncObserver && this.syncObserver.off();
|
||||
this.syncObserver?.off();
|
||||
this.viewDestroyed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type CoreCommentsDataWithUser = CoreCommentsData & {
|
||||
export type CoreCommentsDataToDisplay = CoreCommentsData & {
|
||||
profileimageurl?: string;
|
||||
fullname?: string;
|
||||
deleted?: boolean;
|
||||
showDate?: boolean;
|
||||
showTail?: boolean;
|
||||
showUserData?: boolean;
|
||||
};
|
||||
|
||||
export type CoreCommentsOfflineWithUser = CoreCommentsDBRecord & {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@import "~theme/components/discussion.scss";
|
Loading…
Reference in New Issue