diff --git a/src/app/components/chat/chat.service.ts b/src/app/components/chat/chat.service.ts index ebd8347..1669871 100644 --- a/src/app/components/chat/chat.service.ts +++ b/src/app/components/chat/chat.service.ts @@ -20,7 +20,7 @@ export class ChatService implements OnDestroy { private isDecrypting = false; private recipientPublicKey: string; private message: string; - private decryptedPrivateKey:string; + private decryptedPrivateKey:string=""; private _chat: BehaviorSubject = new BehaviorSubject(null); private _chats: BehaviorSubject = new BehaviorSubject(null); private _contact: BehaviorSubject = new BehaviorSubject(null); @@ -148,80 +148,26 @@ export class ChatService implements OnDestroy { } async getChats(): Promise> { - try { - const storedChats = await this._indexedDBService.getAllChatsWithLastMessage(); - - if (storedChats && storedChats.length > 0) { - this.chatList = storedChats; - this._chats.next(this.chatList); - - const pubkeys = storedChats.map(chat => chat.contact.pubKey); - console.log(pubkeys); - - this.updateMetadataInChunks(pubkeys); - } - } catch (error) { - console.error('Error fetching or updating chats:', error); - } - return this.getChatListStream(); } - private async updateMetadataInChunks(pubkeys: string[]): Promise { - try { - const chunkSize = 20; - for (let i = 0; i < pubkeys.length; i += chunkSize) { - const chunk = pubkeys.slice(i, i + chunkSize); - - const metadataList = await this._metadataService.fetchMetadataForMultipleKeys(chunk); - - metadataList.forEach(metadata => { - this.updateContactInChats(metadata.pubkey, metadata.metadata); - }); - - await this.sleep(2000); - } - } catch (error) { - console.error('Error updating metadata for chats:', error); - } - } - - private updateContactInChats(pubKey: string, updatedMetadata: any): void { - const chatToUpdate = this.chatList.find(chat => chat.contact.pubKey === pubKey); - - if (chatToUpdate) { - chatToUpdate.contact = { - ...chatToUpdate.contact, - ...updatedMetadata - }; - - this.chatList = this.chatList.map(chat => chat.contact.pubKey === pubKey ? chatToUpdate : chat); - - this._chats.next(this.chatList); - - this._indexedDBService.saveChat(chatToUpdate); - } - } - - private sleep(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); - } - async InitSubscribeToChatList(): Promise> { const pubkey = this._signerService.getPublicKey(); const useExtension = await this._signerService.isUsingExtension(); - this.decryptedPrivateKey = await this._signerService.getDecryptedSecretKey(); - return this.subscribeToChatList(pubkey, useExtension, this.decryptedPrivateKey); + const useSecretKey = await this._signerService.isUsingSecretKey(); + + if (useSecretKey){this.decryptedPrivateKey = await this._signerService.getDecryptedSecretKey(); +} + return this.subscribeToChatList(pubkey, useExtension,useSecretKey, this.decryptedPrivateKey); } - subscribeToChatList(pubkey: string, useExtension: boolean, decryptedSenderPrivateKey: string): Observable { + subscribeToChatList(pubkey: string, useExtension: boolean, useSecretKey:boolean, decryptedSenderPrivateKey: string): Observable { this._relayService.ensureConnectedRelays().then(async () => { - const lastSavedTimestamp = await this._indexedDBService.getLastSavedTimestamp(); const filters: Filter[] = [ - { kinds: [EncryptedDirectMessage], authors: [pubkey], since: Math.floor(lastSavedTimestamp / 1000) }, - { kinds: [EncryptedDirectMessage], '#p': [pubkey], since: Math.floor(lastSavedTimestamp / 1000) } + { kinds: [EncryptedDirectMessage], authors: [pubkey] }, + { kinds: [EncryptedDirectMessage], '#p': [pubkey] } ]; this._relayService.getPool().subscribeMany(this._relayService.getConnectedRelays(), filters, { @@ -236,7 +182,7 @@ export class ChatService implements OnDestroy { if (event.created_at > lastTimestamp) { this.messageQueue.push(event); - await this.processNextMessage(pubkey, useExtension, decryptedSenderPrivateKey); + await this.processNextMessage(pubkey, useExtension,useSecretKey, decryptedSenderPrivateKey); } }, oneose: () => { @@ -249,7 +195,7 @@ export class ChatService implements OnDestroy { return this.getChatListStream(); } - private async processNextMessage(pubkey: string, useExtension: boolean, decryptedSenderPrivateKey: string): Promise { + private async processNextMessage(pubkey: string, useExtension: boolean, useSecretKey: boolean, decryptedSenderPrivateKey: string): Promise { if (this.isDecrypting || this.messageQueue.length === 0) return; this.isDecrypting = true; @@ -266,9 +212,11 @@ export class ChatService implements OnDestroy { if (!otherPartyPubKey) continue; + const decryptedMessage = await this.decryptReceivedMessage( event, useExtension, + useSecretKey, decryptedSenderPrivateKey, otherPartyPubKey ); @@ -277,12 +225,7 @@ export class ChatService implements OnDestroy { const messageTimestamp = event.created_at; this.addOrUpdateChatList(otherPartyPubKey, decryptedMessage, messageTimestamp, isSentByUser); - const chatToUpdate = this.chatList.find(chat => chat.id === otherPartyPubKey); - if (chatToUpdate) { - await this._indexedDBService.saveChat(chatToUpdate); - await this._indexedDBService.saveLastSavedTimestamp(messageTimestamp * 1000); - this._chat.next(chatToUpdate); - } + } } } catch (error) { @@ -293,6 +236,7 @@ export class ChatService implements OnDestroy { } + private addOrUpdateChatList(pubKey: string, message: string, createdAt: number, isMine: boolean): void { const existingChat = this.chatList.find(chat => chat.contact?.pubKey === pubKey); @@ -336,8 +280,7 @@ export class ChatService implements OnDestroy { messages: [newMessage] }; this.chatList.push(newChat); - this.fetchMetadataForPubKey(pubKey); - } + } this.chatList.sort((a, b) => Number(b.lastMessageAt!) - Number(a.lastMessageAt!)); @@ -345,19 +288,7 @@ export class ChatService implements OnDestroy { } - private fetchMetadataForPubKey(pubKey: string): void { - this._metadataService.fetchMetadataWithCache(pubKey) - .then(metadata => { - const chat = this.chatList.find(chat => chat.contact?.pubKey === pubKey); - if (chat && metadata) { - chat.contact = { ...chat.contact, ...metadata }; - this._chats.next(this.chatList); - } - }) - .catch(error => { - console.error(`Failed to fetch metadata for pubKey: ${pubKey}`, error); - }); - } + getChatListStream(): Observable { return this._chats.asObservable(); @@ -366,12 +297,13 @@ export class ChatService implements OnDestroy { private async decryptReceivedMessage( event: NostrEvent, useExtension: boolean, + useSecretKey:boolean, decryptedSenderPrivateKey: string, recipientPublicKey: string ): Promise { if (useExtension) { return await this._signerService.decryptMessageWithExtension(recipientPublicKey, event.content); - } else { + } else if(useSecretKey){ return await this._signerService.decryptMessage(decryptedSenderPrivateKey, recipientPublicKey, event.content); } } @@ -388,10 +320,12 @@ export class ChatService implements OnDestroy { onevent: async (event: NostrEvent) => { const isSentByMe = event.pubkey === myPubKey; const senderOrRecipientPubKey = isSentByMe ? pubKey : event.pubkey; - + const useExtension = await this._signerService.isUsingExtension(); + const useSecretKey = await this._signerService.isUsingSecretKey(); const decryptedMessage = await this.decryptReceivedMessage( event, - await this._signerService.isUsingExtension(), + useExtension, + useSecretKey, this.decryptedPrivateKey, senderOrRecipientPubKey ); @@ -404,7 +338,6 @@ export class ChatService implements OnDestroy { } }, oneose: () => { - console.log(`Closed subscription for loading history of chat: ${pubKey}`); } }); } diff --git a/src/app/components/chat/chats/chats.component.html b/src/app/components/chat/chats/chats.component.html index 7201a12..9048fc7 100644 --- a/src/app/components/chat/chats/chats.component.html +++ b/src/app/components/chat/chats/chats.component.html @@ -1,20 +1,16 @@
- + @if (drawerComponent === 'new-chat') { - + } @if (drawerComponent === 'profile') { - + } @@ -22,268 +18,179 @@ @if (chats && chats.length > 0) { -
- -
-
-
-
- @if (profile.picture) { - Profile picture - } - @if (!profile.picture) { -
- {{ profile.name.charAt(0) }} -
- } -
-
- {{ profile.name }} +
+ +
+
+
+
+ @if (profile.picture) { + Profile picture + } + @if (!profile.picture) { +
+ {{ profile.name.charAt(0) }}
+ } +
+
+ {{ profile.name }}
- - + - + - + - + - - + + - - -
- -
- - + Settings + + + +
+ +
+ + - - -
+ "> + +
+
- - +
} @else { -
- + -
- No chats -
+ ">
+
+ No chats
+
} @if (chats && chats.length > 0) { -
- -
+ }"> + +
} diff --git a/src/app/components/chat/chats/chats.component.ts b/src/app/components/chat/chats/chats.component.ts index eeaa32b..d7b150d 100644 --- a/src/app/components/chat/chats/chats.component.ts +++ b/src/app/components/chat/chats/chats.component.ts @@ -1,4 +1,4 @@ -import { NgClass } from '@angular/common'; +import { CommonModule, NgClass } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -40,7 +40,8 @@ import { AgoPipe } from 'app/shared/ago.pipe'; NgClass, RouterLink, RouterOutlet, - AgoPipe + AgoPipe, + CommonModule ], }) export class ChatsComponent implements OnInit, OnDestroy { @@ -97,8 +98,8 @@ export class ChatsComponent implements OnInit, OnDestroy { // Mark for check this._changeDetectorRef.markForCheck(); }); - this._chatService.InitSubscribeToChatList(); + } /** diff --git a/src/app/components/chat/contact-info/contact-info.component.html b/src/app/components/chat/contact-info/contact-info.component.html index d5ad670..38a23ca 100644 --- a/src/app/components/chat/contact-info/contact-info.component.html +++ b/src/app/components/chat/contact-info/contact-info.component.html @@ -17,6 +17,7 @@ } diff --git a/src/app/components/chat/conversation/conversation.component.html b/src/app/components/chat/conversation/conversation.component.html index b735841..edbb87a 100644 --- a/src/app/components/chat/conversation/conversation.component.html +++ b/src/app/components/chat/conversation/conversation.component.html @@ -49,6 +49,7 @@ Contact picture } diff --git a/src/app/components/chat/new-chat/new-chat.component.html b/src/app/components/chat/new-chat/new-chat.component.html index ebf9b5e..645c053 100644 --- a/src/app/components/chat/new-chat/new-chat.component.html +++ b/src/app/components/chat/new-chat/new-chat.component.html @@ -43,6 +43,7 @@ Contact picture } diff --git a/src/app/components/chat/profile/profile.component.html b/src/app/components/chat/profile/profile.component.html index 4e54d8e..3ffcedf 100644 --- a/src/app/components/chat/profile/profile.component.html +++ b/src/app/components/chat/profile/profile.component.html @@ -31,6 +31,7 @@ } diff --git a/src/app/services/indexed-db.service.ts b/src/app/services/indexed-db.service.ts index 937f419..7d392ae 100644 --- a/src/app/services/indexed-db.service.ts +++ b/src/app/services/indexed-db.service.ts @@ -15,8 +15,6 @@ export class IndexedDBService { private userStore: LocalForage; private projectsStore: LocalForage; private projectStatsStore: LocalForage; - private chatStore: LocalForage; - private timestampStore: LocalForage; constructor() { @@ -45,22 +43,6 @@ export class IndexedDBService { description: 'Store for project statistics', }); - this.chatStore = localForage.createInstance({ - driver: localForage.INDEXEDDB, - name: 'angor-hub', - version: 1.0, - storeName: 'chats', - description: 'Store for chat information', - }); - - this.timestampStore = localForage.createInstance({ - driver: localForage.INDEXEDDB, - name: 'angor-hub', - version: 1.0, - storeName: 'timestamps', - description: 'Store for last update timestamps', - }); - this.loadAllProjectsFromDB(); this.loadAllProjectStatsFromDB(); @@ -233,99 +215,4 @@ export class IndexedDBService { } } - - async saveChat(chat: Chat): Promise { - try { - await this.chatStore.setItem(chat.id, chat); - } catch (error) { - console.error('Error saving chat to IndexedDB:', error); - } - } - - async getChat(pubKey: string): Promise { - try { - const chat = await this.chatStore.getItem(pubKey); - if (chat) { - return chat; - } else { - console.warn(`Chat with pubKey ${pubKey} not found in IndexedDB.`); - return null; - } - } catch (error) { - console.error(`Error retrieving chat with pubKey ${pubKey} from IndexedDB:`, error); - return null; - } - } - - - async getAllChats(): Promise { - try { - const chats: Chat[] = []; - - await this.chatStore.iterate((value) => { - chats.push(value); - }); - - chats.sort((a, b) => { - const dateA = Number(a.lastMessageAt); - const dateB = Number(b.lastMessageAt); - return dateB - dateA; - }); - - return chats; - } catch (error) { - console.error('Error getting chats from IndexedDB:', error); - return []; - } - } - - - async getAllChatsWithLastMessage(): Promise { - try { - const chats: Chat[] = []; - - await this.chatStore.iterate((value) => { - const lastMessage = value.messages[value.messages.length - 1]; - - const chatWithLastMessage = { - ...value, - messages: [lastMessage] - }; - - chats.push(chatWithLastMessage); - }); - - chats.sort((a, b) => { - const dateA = Number(a.lastMessageAt); - const dateB = Number(b.lastMessageAt); - return dateB - dateA; - }); - - return chats; - } catch (error) { - console.error('Error getting chats with last message from IndexedDB:', error); - return []; - } -} - - - - - async saveLastSavedTimestamp(timestamp: number): Promise { - try { - await this.timestampStore.setItem('lastSavedTimestamp', timestamp); - } catch (error) { - console.error('Error saving last update timestamp in IndexedDB:', error); - } - } - - async getLastSavedTimestamp(): Promise { - try { - const timestamp = await this.timestampStore.getItem('lastSavedTimestamp'); - return timestamp || 0; - } catch (error) { - console.error('Error getting last saved timestamp from IndexedDB:', error); - return 0; - } - } -} + }