diff --git a/src/app/main/chat/chat.service.ts b/src/app/main/chat/chat.service.ts index ccffbba..c942a9e 100644 --- a/src/app/main/chat/chat.service.ts +++ b/src/app/main/chat/chat.service.ts @@ -56,7 +56,7 @@ export class ChatService { constructor( public firestore: FirestoreService, - public currentUser: CurrentuserService, + public currentUser: CurrentuserService ) { this.subUsersList(); this.subChannelsList(); @@ -464,51 +464,5 @@ export class ChatService { this.mobileOpen = "directmessage"; } } - - searchMessagesAndChannels(query: string): SearchResult[] { - const results: SearchResult[] = []; - - // Channels durchsuchen - this.channelsList.forEach(channel => { - const messages = channel.channelData.messages - ? Array.from(channel.channelData.messages.values()).filter(message => { - return message.message.toLowerCase().includes(query.toLowerCase()); - }) - : []; - - messages.forEach(message => { - results.push({ - type: 'channel', - id: message.id, - name: channel.channelData.name, // Channel-Name - avatar: message.avatar, - message: message.message, // Nachricht - channelName: channel.channelData.name, - channelID: channel.id - }); - }); - }); - - // Direct Messages durchsuchen - Object.values(this.allMessages).forEach((userMessages: Message[]) => { - const matchingMessages = userMessages.filter(message => { - return message.message.toLowerCase().includes(query.toLowerCase()); - }); - - matchingMessages.forEach(message => { - results.push({ - type: 'user', - id: message.id, - name: message.name, // Benutzername - avatar: message.avatar, - message: message.message, // Nachricht - userID: message.id - }); - }); - }); - - return results; - } - } diff --git a/src/app/main/chat/direct-message/direct-message.component.html b/src/app/main/chat/direct-message/direct-message.component.html index f34aede..7118113 100644 --- a/src/app/main/chat/direct-message/direct-message.component.html +++ b/src/app/main/chat/direct-message/direct-message.component.html @@ -187,7 +187,7 @@

{{ chatService.selectedUser.name }}

- + @if (option.avatar && option.avatar.length > 1) { diff --git a/src/app/main/chat/direct-message/direct-message.component.scss b/src/app/main/chat/direct-message/direct-message.component.scss index cd76b34..eb7f8dc 100644 --- a/src/app/main/chat/direct-message/direct-message.component.scss +++ b/src/app/main/chat/direct-message/direct-message.component.scss @@ -689,7 +689,7 @@ } } -::ng-deep::ng-deep div.mat-mdc-autocomplete-panel { +::ng-deep::ng-deep div.directmessage-mention-autocomplete { width: unset !important; display: flex !important; padding: 1.25rem 1.3125rem !important; diff --git a/src/app/main/chat/direct-message/directmessage.service.ts b/src/app/main/chat/direct-message/directmessage.service.ts index c39a6ca..5a89494 100644 --- a/src/app/main/chat/direct-message/directmessage.service.ts +++ b/src/app/main/chat/direct-message/directmessage.service.ts @@ -182,36 +182,49 @@ export class DirectmessageService { getAllMessages() { - this.allMessages = {}; - + this.allMessages = {}; // Leere das Nachrichten-Objekt + + // Durchlaufe alle Benutzer aus der usersList this.chat.usersList.forEach((user) => { + // Erstelle einen eindeutigen Chat-Pfad basierend auf den Benutzer-IDs + const chatId = this.currentUser.currentUser.id < user.id + ? `${this.currentUser.currentUser.id}_${user.id}` + : `${user.id}_${this.currentUser.currentUser.id}`; + const potentialCollectionRef = collection( this.firestore, - `users/${this.currentUser.currentUser.id}/${user.id}`, + `directmessages/${chatId}/messages` ); + + // Sortiere die Nachrichten nach dem Zeitstempel const messagesQuery = query( potentialCollectionRef, - orderBy("time"), + orderBy("time") ); - + + // Setze einen Echtzeitlistener für die Nachrichten onSnapshot(messagesQuery, (messagesSnapshot) => { if (!messagesSnapshot.empty) { + // Stelle sicher, dass das Nachrichten-Objekt für diesen Benutzer existiert if (!this.allMessages[user.id]) { this.allMessages[user.id] = {}; } - + + // Durchlaufe die Nachrichten und speichere sie in allMessages messagesSnapshot.forEach((messageDoc) => { const messageData = messageDoc.data() as Message; - + + // Speichere die Nachricht mit der ID des Dokuments this.allMessages[user.id][messageDoc.id] = { ...messageData, - id: messageDoc.id, + id: messageDoc.id, // Füge die ID der Nachricht hinzu }; }); } }); }); } + async updateMessage(sendedUserID: string, messageId: string, newContent: string): Promise { // Pfad zur spezifischen Nachricht in der Unterkollektion diff --git a/src/app/main/header/header.component.html b/src/app/main/header/header.component.html index 02b302b..fdf4338 100644 --- a/src/app/main/header/header.component.html +++ b/src/app/main/header/header.component.html @@ -33,7 +33,7 @@ Keine Ergebnisse gefunden - + @if (option.avatar && option.avatar.length > 1) { @@ -50,7 +50,15 @@

{{ option.name }}

- + @if (option.avatar && option.avatar.length > 1) { + + } @else { + + }

{{ option.name }}

{{ option.message }}

diff --git a/src/app/main/header/header.component.scss b/src/app/main/header/header.component.scss index 23f16b9..29a6fc1 100644 --- a/src/app/main/header/header.component.scss +++ b/src/app/main/header/header.component.scss @@ -125,7 +125,7 @@ &:hover { cursor: pointer; - background-color: var(--bg-color); + background-color: var(--bg-color) !important; } } diff --git a/src/app/main/header/header.component.ts b/src/app/main/header/header.component.ts index bfd50de..4ec79f8 100644 --- a/src/app/main/header/header.component.ts +++ b/src/app/main/header/header.component.ts @@ -37,6 +37,7 @@ import { SearchResult } from "../../interfaces/search-result"; import { debounceTime, distinctUntilChanged } from "rxjs/operators"; import { of } from 'rxjs'; import { ChatComponent } from "../chat/chat.component"; +import { SearchService } from "./search.service"; @Component({ selector: "app-header", @@ -73,6 +74,7 @@ export class HeaderComponent { private chatService: ChatService, private _bottomSheet: MatBottomSheet, public DMService: DirectmessageService, + private searchService: SearchService ) { // Hier wird der SearchResult-Stream initialisiert @@ -81,7 +83,7 @@ export class HeaderComponent { distinctUntilChanged(), // Ignoriert gleiche Eingaben hintereinander switchMap((query) => { if (typeof query === 'string' && query.trim() !== '') { - return of(this.chatService.searchMessagesAndChannels(query)); + return of(searchService.searchMessagesAndChannels(query)); } else { return of([]); } @@ -89,6 +91,11 @@ export class HeaderComponent { ); } + ngOnInit() { + this.searchService.loadAllChannels(); + this.searchService.loadAllDirectmessages(); + } + openDialog(event: MouseEvent): void { // Sicherstellen, dass event.target tatsächlich ein Element ist. let element = event.target as Element | null; @@ -127,7 +134,8 @@ export class HeaderComponent { } log() { - console.log(this.getChannelMessages()); + console.log(this.searchService.allChannelMessages); + console.log(this.searchService.allDirectMessages); } openBottomSheet(): void { diff --git a/src/app/main/header/search.service.spec.ts b/src/app/main/header/search.service.spec.ts new file mode 100644 index 0000000..23c42c7 --- /dev/null +++ b/src/app/main/header/search.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { SearchService } from './search.service'; + +describe('SearchService', () => { + let service: SearchService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(SearchService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/main/header/search.service.ts b/src/app/main/header/search.service.ts new file mode 100644 index 0000000..c8e8b04 --- /dev/null +++ b/src/app/main/header/search.service.ts @@ -0,0 +1,205 @@ +import { Injectable, OnInit } from '@angular/core'; +import { SearchResult } from '../../interfaces/search-result'; +import { FirestoreService } from '../../firestore.service'; +import { collection, doc, onSnapshot, orderBy, query } from '@angular/fire/firestore'; +import { CurrentuserService } from '../../currentuser.service'; +import { Channel } from '../../interfaces/channel'; +import { Message } from '../../interfaces/message'; +import { ChatService } from '../chat/chat.service'; +import { UsersList } from '../../interfaces/users-list'; + +@Injectable({ + providedIn: 'root' +}) +export class SearchService { + channels: Record = {}; + allChannelMessages: Record = {}; + allDirectMessages: { [userId: string]: { [messageId: string]: any; }; } = {}; + usersList: UsersList[] = []; + + constructor( + private firestore: FirestoreService, + private currentUser: CurrentuserService, + private chatService: ChatService + + ) { } + + + + searchMessagesAndChannels(query: string): SearchResult[] { + const results: SearchResult[] = []; + + // 1. Channels durchsuchen + Object.keys(this.allChannelMessages).forEach(channelId => { + const messages = this.allChannelMessages[channelId].filter(message => { + return message.message.toLowerCase().includes(query.toLowerCase()); + }); + + messages.forEach(message => { + results.push({ + type: 'channel', + id: message.id, + name: message.name, // Channel-Name + avatar: message.avatar, + message: message.message, // Nachricht + channelName: this.channels[channelId].name, + channelID: channelId + }); + }); + }); + + // 2. Direct Messages durchsuchen + Object.keys(this.allDirectMessages).forEach(userId => { + const userMessages = Object.values(this.allDirectMessages[userId]); + + const matchingMessages = userMessages.filter((message: Message) => { + return message.message.toLowerCase().includes(query.toLowerCase()); + }); + + matchingMessages.forEach(message => { + results.push({ + type: 'user', + id: message.id, + name: message.name, // Benutzername + avatar: message.avatar, + message: message.message, // Nachricht + userID: userId + }); + }); + }); + + return results; + } + + + loadAllChannels() { + const channelsRef = this.firestore.channelsRef; + + // Echtzeit-Listener für alle Kanäle + onSnapshot(channelsRef, (querySnapshot) => { + querySnapshot.forEach((channelDoc) => { + const channelId = channelDoc.id; + const channelData = channelDoc.data(); + // Prüfe, ob der aktuelle Benutzer Mitglied des Kanals ist + if (channelData['members'] && channelData['members'].some((member: { id: string; }) => member.id === this.currentUser.currentUser.id)) { + // Überprüfen, ob der Kanal schon geladen wurde + if (!this.channels[channelId]) { + this.channels[channelId] = { + name: channelData["name"] || "", + description: channelData["description"] || "", + creator: channelData["creator"] || "", + members: channelData["members"] || [], + messages: new Map(), + }; + } + + // Nachrichten für diesen Kanal laden + const messagesCollectionRef = collection( + this.firestore.firestore, + `channels/${channelId}/messages` + ); + const messagesQuery = query(messagesCollectionRef, orderBy("time")); + // Nachrichten-Listener für den Kanal + onSnapshot(messagesQuery, (messagesSnapshot) => { + const messages: Message[] = []; + + messagesSnapshot.forEach((doc) => { + const messageData = doc.data() as Message; + this.channels[channelId].messages?.set(doc.id, messageData); + messages.push(messageData); // Nachrichten sammeln + }); + + this.allChannelMessages[channelId] = messages; // Nachrichten für den Kanal speichern + }); + + // Kanaldaten (Name, Beschreibung, Mitglieder) aktualisieren + onSnapshot(doc(channelsRef, channelId), (docSnap) => { + if (docSnap.exists()) { + this.channels[channelId].name = docSnap.data()["name"]; + this.channels[channelId].creator = docSnap.data()["creator"]; + this.channels[channelId].members = docSnap.data()["members"] || []; + this.channels[channelId].description = + docSnap.data()["description"] || ""; + } + }); + } + }); + }); + } + + + loadAllDirectmessages() { + this.allDirectMessages = {}; // Leere das Nachrichten-Objekt + + // Lade die Benutzerliste und starte dann das Laden der Direktnachrichten + this.subUsersList(() => { + // Durchlaufe alle Benutzer aus der usersList + this.usersList.forEach((user) => { + // Erstelle einen eindeutigen Chat-Pfad basierend auf den Benutzer-IDs + const chatId = this.currentUser.currentUser.id < user.id + ? `${this.currentUser.currentUser.id}_${user.id}` + : `${user.id}_${this.currentUser.currentUser.id}`; + + const potentialCollectionRef = collection( + this.firestore.firestore, + `directmessages/${chatId}/messages` + ); + + // Sortiere die Nachrichten nach dem Zeitstempel + const messagesQuery = query( + potentialCollectionRef, + orderBy("time") + ); + + // Setze einen Echtzeitlistener für die Nachrichten + onSnapshot(messagesQuery, (messagesSnapshot) => { + if (!messagesSnapshot.empty) { + // Stelle sicher, dass das Nachrichten-Objekt für diesen Benutzer existiert + if (!this.allDirectMessages[user.id]) { + this.allDirectMessages[user.id] = {}; + } + + // Durchlaufe die Nachrichten und speichere sie in allMessages + messagesSnapshot.forEach((messageDoc) => { + const messageData = messageDoc.data() as Message; + + // Speichere die Nachricht mit der ID des Dokuments + this.allDirectMessages[user.id][messageDoc.id] = { + ...messageData, + id: messageDoc.id, // Füge die ID der Nachricht hinzu + }; + }); + } + }); + }); + }); + } + + subUsersList(callback: () => void) { + let ref = this.firestore.usersRef; + onSnapshot(ref, (list) => { + this.usersList = []; + list.forEach((element) => { + this.usersList.push( + this.setUsersListObj(element.data(), element.id), + ); + }); + + // Wenn die Benutzerliste geladen wurde, rufe den Callback auf + if (this.usersList.length > 0) { + callback(); + } + }); + } + + setUsersListObj(obj: any, id: string): UsersList { + return { + id: id || "", + name: obj.name || "", + avatar: obj.avatar || "", + email: obj.email || "", + online: obj.online || false, + }; + } + +}