Skip to content

Commit 5a0e686

Browse files
committed
add reply and showing attachment pic
1 parent dd8f7bc commit 5a0e686

8 files changed

Lines changed: 302 additions & 12 deletions

File tree

MangoAPI.Client/src/app/components/chats/chats.component.html

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ <h5>Chats</h5>
224224
/>
225225
<div class="message-wrapper">
226226
<div class="message-content">
227+
<div *ngIf="message.inReplayToAuthor" class="message-reply">
228+
<p class="message-reply-displayname">{{ message.inReplayToAuthor }}</p>
229+
<p class="message-reply-text">{{ message.inReplayToText }}</p>
230+
</div>
227231
<span *ngIf="message.messageAttachmentUrl"
228232
><img
229233
class="message-image"
@@ -278,7 +282,18 @@ <h5>Chats</h5>
278282
</div>
279283
</div>
280284
<div class="message-button">
281-
<img alt="Reply Icon" src="./../../../assets/svg/reply.svg" />
285+
<img
286+
alt="Reply Icon"
287+
src="./../../../assets/svg/reply.svg"
288+
(click)="
289+
onReplyClick(
290+
message.messageId,
291+
message.userDisplayName,
292+
message.messageText,
293+
message.userDisplayNameColour
294+
)
295+
"
296+
/>
282297
</div>
283298
</div>
284299
</div>
@@ -303,6 +318,16 @@ <h5>Chats</h5>
303318
>
304319
{{ message.userDisplayName }}
305320
</div>
321+
<div *ngIf="message.inReplayToAuthor" class="message-reply">
322+
<p
323+
class="message-reply-displayname {{
324+
getDisplayNameColour(message.userDisplayNameColour)
325+
}}"
326+
>
327+
{{ message.inReplayToAuthor }}
328+
</p>
329+
<p class="message-reply-text">{{ message.inReplayToText }}</p>
330+
</div>
306331
<span *ngIf="message.messageAttachmentUrl"
307332
><img
308333
class="message-image"
@@ -317,7 +342,18 @@ <h5>Chats</h5>
317342
{{ toShortTimeString(message.createdAt) }}
318343
</p>
319344
<div class="message-button">
320-
<img alt="Reply Icon" src="./../../../assets/svg/reply.svg" />
345+
<img
346+
alt="Reply Icon"
347+
src="./../../../assets/svg/reply.svg"
348+
(click)="
349+
onReplyClick(
350+
message.messageId,
351+
message.userDisplayName,
352+
message.messageText,
353+
message.userDisplayNameColour
354+
)
355+
"
356+
/>
321357
</div>
322358
</div>
323359
</div>
@@ -327,7 +363,47 @@ <h5>Chats</h5>
327363
</li>
328364
</ul>
329365
</div>
330-
366+
<div *ngIf="_replyStateService.reply" class="reply">
367+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
368+
<svg
369+
class="reply-svg"
370+
fill="#adb5bd"
371+
height="45"
372+
width="45"
373+
viewBox="0 0 45 45"
374+
xmlns="http://www.w3.org/2000/svg"
375+
>
376+
<path
377+
d="M10.53 5.03a.75.75 0 10-1.06-1.06l-6.25 6.25a.75.75 0 000 1.06l6.25 6.25a.75.75 0 101.06-1.06L5.56 11.5H17a3.248 3.248 0 013.25 3.248v4.502a.75.75 0 001.5 0v-4.502A4.748 4.748 0 0017 10H5.56l4.97-4.97z"
378+
/>
379+
</svg>
380+
<div class="reply-container">
381+
<p
382+
class="reply-displayname {{
383+
getDisplayNameColour(_replyStateService.reply.displayNameColour)
384+
}}"
385+
>
386+
{{ _replyStateService.reply.displayName }}
387+
</p>
388+
<p class="reply-text">{{ _replyStateService.reply.text }}</p>
389+
</div>
390+
<img
391+
src="../../../assets/svg/cross.svg"
392+
class="cross-svg"
393+
(click)="_replyStateService.setReplyNull()"
394+
/>
395+
</div>
396+
<div *ngIf="messageAttachment" class="attachment">
397+
<img src="{{messageAttachmentBlobUrl}}" class="attachment-image" alt="">
398+
<div class="attachment-container">
399+
<p class="attachment-filename">{{messageAttachment.name}}</p>
400+
</div>
401+
<img
402+
src="../../../assets/svg/cross.svg"
403+
class="cross-svg"
404+
(click)="removeImageSelected()"
405+
/>
406+
</div>
331407
<div class="chat-footer" *ngIf="activeChat.isMember; else elseNotMember">
332408
<div class="dropdown">
333409
<button class="button-dark button-dark-no-hover align-text-top" data-bs-toggle="dropdown">

MangoAPI.Client/src/app/components/chats/chats.component.ts

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { ModalWindowStateService } from '../../services/states/modalWindowState.service';
2-
import { Component, OnDestroy, OnInit } from '@angular/core';
2+
import {
3+
Component,
4+
OnChanges,
5+
OnDestroy,
6+
OnInit,
7+
Sanitizer,
8+
SecurityContext,
9+
SimpleChanges
10+
} from '@angular/core';
311
import { TokensService } from '../../services/messenger/tokens.service';
412
import { Chat } from '../../types/models/Chat';
513
import { CommunitiesService } from '../../services/api/communities.service';
@@ -15,11 +23,21 @@ import { ValidationService } from '../../services/messenger/validation.service';
1523
import * as signalR from '@microsoft/signalr';
1624
import { EditMessageNotification } from '../../types/models/EditMessageNotification';
1725
import { DeleteMessageNotification } from '../../types/models/DeleteMessageNotification';
18-
import { firstValueFrom, Subject, takeUntil } from 'rxjs';
26+
import {
27+
Subject,
28+
takeUntil,
29+
of,
30+
BehaviorSubject,
31+
firstValueFrom,
32+
distinctUntilKeyChanged
33+
} from 'rxjs';
1934
import { DisplayNameColours } from 'src/app/types/enums/DisplayNameColours';
2035
import { DeleteMessageCommand } from 'src/app/types/requests/DeleteMessageCommand';
2136
import ApiBaseService from 'src/app/services/api/apiBase.service';
2237
import { SendMessageResponse } from '../../types/responses/SendMessageResponse';
38+
import { ReplyStateSerivce } from 'src/app/services/states/replyState.service';
39+
import { Reply } from 'src/app/types/models/Reply';
40+
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
2341

2442
@Component({
2543
selector: 'app-chats',
@@ -36,7 +54,8 @@ export class ChatsComponent implements OnInit, OnDestroy {
3654
private _router: Router,
3755
private _validationService: ValidationService,
3856
private _apiBaseService: ApiBaseService,
39-
public _modalWindowStateService: ModalWindowStateService
57+
public _modalWindowStateService: ModalWindowStateService,
58+
public _replyStateService: ReplyStateSerivce
4059
) {}
4160

4261
private connectionBuilder: signalR.HubConnectionBuilder = new signalR.HubConnectionBuilder();
@@ -68,16 +87,19 @@ export class ChatsComponent implements OnInit, OnDestroy {
6887
title: ''
6988
};
7089

71-
public activeChatId = '';
90+
public activeChatId: string = '';
7291
public messages: Message[] = [];
7392

7493
public messageAttachment: File | null = null;
94+
public messageAttachmentBlobUrl: string | ArrayBuffer | null = '';
7595
public messageText = '';
76-
public messageAttachmentUrl = '';
96+
public messageAttachmentUrl: string = '';
7797
public searchChatQuery = '';
7898
public searchMessagesQuery = '';
7999
public chatFilter = 'All chats';
80100

101+
public activeChatBehaviorSubject = new BehaviorSubject<Chat>(this.activeChat);
102+
81103
componentDestroyed$: Subject<boolean> = new Subject();
82104

83105
public get routingConstants(): typeof RoutingConstants {
@@ -89,6 +111,14 @@ export class ChatsComponent implements OnInit, OnDestroy {
89111
}
90112

91113
initializeView(): void {
114+
this.activeChatBehaviorSubject
115+
.pipe(distinctUntilKeyChanged('chatId'))
116+
.subscribe(() => {
117+
this._replyStateService.setReplyNull()
118+
this.messageAttachment = null
119+
this.messageAttachmentBlobUrl = null
120+
});
121+
92122
const tokens = this._tokensService.getTokens();
93123

94124
if (!tokens) {
@@ -144,8 +174,32 @@ export class ChatsComponent implements OnInit, OnDestroy {
144174
.catch((err) => console.error(err.toString()));
145175
}
146176

147-
imageSelected(event: any) {
177+
onReplyClick(
178+
messageId: string,
179+
displayName: string,
180+
text: string,
181+
displayNameColour: DisplayNameColours
182+
) {
183+
const replyEntity = new Reply(messageId, displayName, text, displayNameColour);
184+
185+
this._replyStateService.setReply(replyEntity);
186+
this.scrollToEnd();
187+
}
188+
189+
async imageSelected(event: any) {
148190
this.messageAttachment = event.target.files[0];
191+
192+
var reader = new FileReader();
193+
reader.onload = () => {
194+
console.log(reader.result);
195+
this.messageAttachmentBlobUrl = reader.result
196+
};
197+
reader.readAsDataURL(event.target.files[0]);
198+
}
199+
200+
removeImageSelected() {
201+
this.messageAttachment = null;
202+
this.messageAttachmentBlobUrl = null;
149203
}
150204

151205
onOpenImageClick(imageLink: string): void {
@@ -275,8 +329,13 @@ export class ChatsComponent implements OnInit, OnDestroy {
275329
}
276330

277331
this.activeChatId = chatId;
278-
this.activeChat = this.chats.filter((x) => x.chatId === this.activeChatId)[0];
332+
const newActiveChat = this.chats.filter((x) => x.chatId === this.activeChatId)[0];
333+
this.activeChat = newActiveChat;
334+
335+
this.activeChatBehaviorSubject.next(newActiveChat);
336+
279337
this.getChatMessages(this.activeChatId);
338+
this.scrollToEnd();
280339
}
281340

282341
chatContainsMessages(chat: Chat): boolean {
@@ -426,6 +485,11 @@ export class ChatsComponent implements OnInit, OnDestroy {
426485
sendMessageFormData.append('messageText', newMessageText);
427486
sendMessageFormData.append('chatId', this.activeChatId);
428487
sendMessageFormData.append('messageId', messageId);
488+
sendMessageFormData.append(
489+
'inReplayToAuthor',
490+
this._replyStateService.reply?.displayName ?? ''
491+
);
492+
sendMessageFormData.append('inReplayToText', this._replyStateService.reply?.text ?? '');
429493

430494
if (this.messageAttachment) {
431495
sendMessageFormData.append('Attachment', this.messageAttachment);
@@ -440,13 +504,17 @@ export class ChatsComponent implements OnInit, OnDestroy {
440504
newMessageText,
441505
isoString,
442506
true,
443-
tokens.userProfilePictureUrl
507+
tokens.userProfilePictureUrl,
508+
this._replyStateService.reply?.displayName ?? null,
509+
this._replyStateService.reply?.text ?? null
444510
);
445511

446512
this.clearMessageInput();
447513

448514
this.messages.push(newMessage);
449515

516+
this._replyStateService.setReplyNull();
517+
450518
const sendMessage$ = this._messagesService.sendMessage(sendMessageFormData);
451519

452520
const response = await firstValueFrom<SendMessageResponse>(sendMessage$);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Injectable } from '@angular/core';
2+
import { Reply } from './../../types/models/Reply';
3+
4+
5+
@Injectable({
6+
providedIn: 'root'
7+
})
8+
export class ReplyStateSerivce {
9+
public reply: Reply | null = null;
10+
11+
public setReply(replyEntity: Reply) {
12+
this.reply = replyEntity;
13+
}
14+
15+
public setReplyNull() {
16+
this.reply = null;
17+
}
18+
}

MangoAPI.Client/src/app/types/models/Message.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ export class Message {
2424
messageText: string,
2525
createdAt: string,
2626
self: boolean,
27-
messageAuthorPictureUrl: string
27+
messageAuthorPictureUrl: string,
28+
inReplayToAuthor: string | null,
29+
inReplayToText: string | null
2830
) {
2931
this.messageId = messageId;
3032
this.userId = userId;
@@ -35,5 +37,7 @@ export class Message {
3537
this.createdAt = createdAt;
3638
this.self = self;
3739
this.messageAuthorPictureUrl = messageAuthorPictureUrl;
40+
this.inReplayToAuthor = inReplayToAuthor ?? null;
41+
this.inReplayToText = inReplayToText ?? null;
3842
}
3943
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { DisplayNameColours } from "../enums/DisplayNameColours";
2+
3+
export class Reply {
4+
public messageId: string;
5+
public displayName: string;
6+
public text: string;
7+
public displayNameColour: DisplayNameColours;
8+
9+
constructor(messageId: string, displayName: string, text: string, displayNameColour: DisplayNameColours) {
10+
this.messageId = messageId;
11+
this.displayName = displayName;
12+
this.text = text;
13+
this.displayNameColour = displayNameColour;
14+
}
15+
}
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 2 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)