diff --git a/src/pages/chat/chat.ts b/src/pages/chat/chat.ts index aa18aa4..a41a669 100755 --- a/src/pages/chat/chat.ts +++ b/src/pages/chat/chat.ts @@ -375,18 +375,56 @@ class ChatElement extends HTMLElement { return; } - this.selectedMemberId = String(memberId); + this.selectedMember = member; const chatHeader = this.shadowRoot?.querySelector('#chat-header'); const messagesContainer = this.shadowRoot?.querySelector('#messages'); if (!chatHeader || !messagesContainer) return; - const memberAddress = String(memberId); - const emojis = await addressToEmoji(memberAddress); + const memberId = this.selectedMember[0]; + const emojis = await addressToEmoji(memberId); chatHeader.textContent = `Chat with ${emojis}`; messagesContainer.innerHTML = ''; + // Filter processes for the children of current process + const children = await service.getChildrenOfProcess(this.processId); + + let messagesProcess: Process | null = null; + console.log(this.processRoles); + const processRoles = this.processRoles; + for (const child of children) { + const roles = await this.getRoles(child); + // Check that we and the other members are in the role + if (!service.isChildRole(processRoles, roles)) { + console.error('Child process roles are not a subset of parent') + continue; + } + if (!service.rolesContainsMember(roles, this.selectedMember)) { + console.error('Member is not part of the process'); + continue; + } + if (!service.rolesContainsUs(roles)) { + console.error('We\'re not part of child process'); + continue; + } + messagesProcess = child; + } + + if (messagesProcess === null) { + console.log('Create a new child process'); + // We need to create a new process + try { + const res = await service.createDmProcess(member, this.processId); + await service.handleApiReturn(res); + } catch (e) { + console.error(e); + return; + } + } else { + console.log('Found child process', messagesProcess); + } + const dbRequest = indexedDB.open('4nk'); dbRequest.onerror = () => { diff --git a/src/services/service.ts b/src/services/service.ts index b13d8bc..29371c2 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -326,6 +326,69 @@ export default class Services { } } + public async createDmProcess( + otherMember: string[], + parentProcess: string, + ): Promise { + try { + console.log('🚀 Début createMessagingProcess'); + console.log('📝 Parent Process ID:', parentProcess); + console.log('👥 Other Member:', otherMember); + + if (!this.isPaired()) { + throw new Error('Device not paired'); + } + + const myAddresses = await this.getMemberFromDevice(); + console.log('🔑 Mes adresses:', myAddresses); + + if (!myAddresses) { + throw new Error('No paired member found'); + } + + const messagingTemplate = { + parent_id: parentProcess, + message: '', + roles: { + dm: { + members: [ + { sp_addresses: myAddresses }, + { sp_addresses: otherMember } + ], + validation_rules: [ + { + quorum: 0.01, + fields: ['message'], + min_sig_member: 0.01, + }, + ], + storages: [storageUrl] + } + } + }; + + console.log('📋 Template final:', JSON.stringify(messagingTemplate, null, 2)); + console.log('👥 Création du process message comme enfant de:', parentProcess); + + const relayAddress = this.getAllRelays()[0]['spAddress']; + const feeRate = 1; + const initState = JSON.stringify(messagingTemplate); + + const result = this.sdkClient.create_new_process( + JSON.stringify(messagingTemplate), + null, + relayAddress, + feeRate + ); + // console.log('✅ Process message créé:', result); + + return result; + } catch (e) { + console.error('❌ Erreur:', e); + throw e; + } + } + // Create prd update for current process and update public createPrdUpdate(processId: string, stateId: string): ApiReturn { try { @@ -641,6 +704,39 @@ export default class Services { } } + isChildRole(parent: any, child: any): bool { + try { + this.sdkClient.is_child_role(JSON.stringify(parent), JSON.stringify(child)); + } catch (e) { + console.error(e); + return false; + } + + return true; + } + + rolesContainsUs(roles: any): bool { + try { + this.sdkClient.roles_contains_us(JSON.stringify(roles)); + } catch (e) { + console.error(e); + return false; + } + + return true; + } + + rolesContainsMember(roles: any, member: string[]): bool { + try { + this.sdkClient.roles_contains_member(JSON.stringify(roles), member); + } catch (e) { + console.error(e); + return false; + } + + return true; + } + async dumpWallet() { const wallet = await this.sdkClient.dump_wallet(); console.log('🚀 ~ Services ~ dumpWallet ~ wallet:', wallet); @@ -742,6 +838,27 @@ export default class Services { return processes; } + public async getChildrenOfProcess(processId: string): Promise { + const processes = await this.getProcesses(); + + const res = []; + for (const [hash, process] of Object.entries(processes)) { + const firstState = process.states[0]; + const pcdCommitment = firstState['pcd_commitment']; + try { + const parentIdHash = pcdCommitment['parent_id']; + const diff = await this.getDiffByValue(parentIdHash); + if (diff['new_value'] === processId) { + res.push(process); + } + } catch (e) { + continue; + } + } + + return res; + } + public async restoreProcessesFromBackUp(processes: Record) { const db = await Database.getInstance(); for (const [commitedIn, process] of Object.entries(processes)) {