From d229da9e47e1c30daeb5e4e2be8875f11dfe928c Mon Sep 17 00:00:00 2001 From: Carlos Santos <4a.santos@gmail.com> Date: Wed, 17 Dec 2025 17:39:04 +0100 Subject: [PATCH] ov-components: Add encryption key mismatch warning in chat panel and update translations --- .../chat-panel/chat-panel.component.html | 7 ++++ .../chat-panel/chat-panel.component.scss | 26 +++++++++++++++ .../panel/chat-panel/chat-panel.component.ts | 31 ++++++++++++++---- .../src/lib/lang/cn.json | 3 +- .../src/lib/lang/de.json | 3 +- .../src/lib/lang/en.json | 3 +- .../src/lib/lang/es.json | 3 +- .../src/lib/lang/fr.json | 3 +- .../src/lib/lang/hi.json | 3 +- .../src/lib/lang/it.json | 3 +- .../src/lib/lang/ja.json | 3 +- .../src/lib/lang/nl.json | 3 +- .../src/lib/lang/pt.json | 3 +- .../participant/participant.service.ts | 32 +++++++++++++++++-- 14 files changed, 106 insertions(+), 20 deletions(-) diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.html b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.html index 8b3903655..b7e3bbe78 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.html +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.html @@ -6,6 +6,13 @@ + @if (hasEncryptionKeyMismatch()) { +
+ warning +

{{ 'PANEL.CHAT.ENCRYPTION_KEY_MISMATCH' | translate }}

+
+ } +

{{ 'PANEL.CHAT.SUBTITLE' | translate }}

diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.scss b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.scss index 1e8ed5c7b..0e163bb6e 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.scss +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.scss @@ -1,3 +1,29 @@ +.encryption-warning { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + padding: 12px; + margin: 10px; + background-color: rgba(255, 152, 0, 0.1); + border: 1px solid rgba(255, 152, 0, 0.5); + border-radius: var(--ov-surface-radius); + color: var(--ov-warn-color, #ff9800); + font-size: 13px; + + mat-icon { + font-size: 20px; + width: 20px; + height: 20px; + } + + p { + margin: 0; + line-height: 1.4; + width: fit-content; + } +} + .text-container { color: var(--ov-text-primary-color); text-align: center; diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts index 494d944c7..fde7bd583 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/components/panel/chat-panel/chat-panel.component.ts @@ -1,9 +1,11 @@ -import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, ElementRef, OnInit, ViewChild } from '@angular/core'; import { Subject, takeUntil } from 'rxjs'; import { ChatMessage } from '../../../models/chat.model'; import { PanelType } from '../../../models/panel.model'; import { ChatService } from '../../../services/chat/chat.service'; +import { E2eeService } from '../../../services/e2ee/e2ee.service'; import { PanelService } from '../../../services/panel/panel.service'; +import { ParticipantService } from '../../../services/participant/participant.service'; /** * @@ -20,15 +22,15 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { /** * @ignore */ - @ViewChild('chatScroll') chatScroll: ElementRef; + @ViewChild('chatScroll') chatScroll: ElementRef = new ElementRef(null); /** * @ignore */ - @ViewChild('chatInput') chatInput: ElementRef; + @ViewChild('chatInput') chatInput: ElementRef = new ElementRef(null); /** * @ignore */ - message: string; + message: string = ''; /** * @ignore */ @@ -42,8 +44,10 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { constructor( private chatService: ChatService, private panelService: PanelService, - private cd: ChangeDetectorRef - ) {} + private cd: ChangeDetectorRef, + private e2eeService: E2eeService, + private participantService: ParticipantService + ) { } /** * @ignore @@ -73,7 +77,7 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { /** * @ignore */ - eventKeyPress(event) { + eventKeyPress(event: KeyboardEvent): void { // Pressed 'Enter' key if (event && event.keyCode === 13) { event.preventDefault(); @@ -109,6 +113,19 @@ export class ChatPanelComponent implements OnInit, AfterViewInit { this.panelService.togglePanel(PanelType.CHAT); } + /** + * @ignore + */ + hasEncryptionKeyMismatch = computed(() => { + if (!this.e2eeService.isEnabled) { + return false; + } + const remoteParticipants = this.participantService.remoteParticipantsSignal(); + return remoteParticipants.some(p => p.hasEncryptionError); + }); + + + private subscribeToMessages() { this.chatService.chatMessages$.pipe(takeUntil(this.destroy$)).subscribe((messages: ChatMessage[]) => { this.messageList = messages; diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/cn.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/cn.json index 761e7a442..9f91aaaf9 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/cn.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/cn.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "发送消息...", "SEND": "发送", "MESSAGE_SENT_NOTIFICATION": "消息已发送", - "OPEN_CHAT": "打开" + "OPEN_CHAT": "打开", + "ENCRYPTION_KEY_MISMATCH": "有参与者使用不同的加密密钥连接。您将不会收到他们的消息。" }, "ACTIVITIES": { "TITLE": "活动" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/de.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/de.json index d031b2043..1e4e5717e 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/de.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/de.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Eine Nachricht senden...", "SEND": "Senden", "MESSAGE_SENT_NOTIFICATION": "Nachricht gesendet", - "OPEN_CHAT": "ÖFFNEN" + "OPEN_CHAT": "ÖFFNEN", + "ENCRYPTION_KEY_MISMATCH": "Es gibt Teilnehmer, die mit einem anderen Verschlüsselungsschlüssel verbunden sind. Sie werden deren Nachrichten nicht empfangen." }, "ACTIVITIES": { "TITLE": "Aktivitäten" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/en.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/en.json index 73a6d605d..a7037543a 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/en.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/en.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Send a message...", "SEND": "Send", "MESSAGE_SENT_NOTIFICATION": "message sent", - "OPEN_CHAT": "OPEN" + "OPEN_CHAT": "OPEN", + "ENCRYPTION_KEY_MISMATCH": "There are participants connected with a different encryption key. You will not receive messages from them." }, "PARTICIPANTS": { "TITLE": "Participants", diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/es.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/es.json index b2321499d..4e0b4ecd8 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/es.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/es.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Enviar mensaje...", "SEND": "Enviar", "MESSAGE_SENT_NOTIFICATION": "mensaje enviado", - "OPEN_CHAT": "ABRIR" + "OPEN_CHAT": "ABRIR", + "ENCRYPTION_KEY_MISMATCH": "Hay participantes conectados con una clave de cifrado diferente a la tuya. No recibirás mensajes de ellos." }, "ACTIVITIES": { "TITLE": "Actividades" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/fr.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/fr.json index fa3fd96f4..10d074cc7 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/fr.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/fr.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Envoyer un message...", "SEND": "Envoyer", "MESSAGE_SENT_NOTIFICATION": "message envoyé", - "OPEN_CHAT": "OUVRIR" + "OPEN_CHAT": "OUVRIR", + "ENCRYPTION_KEY_MISMATCH": "Il y a des participants connectés avec une clé de chiffrement différente. Vous ne recevrez pas leurs messages." }, "ACTIVITIES": { "TITLE": "Activités" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/hi.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/hi.json index 2927e8ab9..73e970af7 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/hi.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/hi.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "एक संदेश भेजें ...", "SEND": "भेजें", "MESSAGE_SENT_NOTIFICATION": "संदेश भेजा गया", - "OPEN_CHAT": "खोलें" + "OPEN_CHAT": "खोलें", + "ENCRYPTION_KEY_MISMATCH": "कुछ सदस्य एक अलग एन्क्रिप्शन कुंजी के साथ जुड़े हैं। आपको उनके संदेश प्राप्त नहीं होंगे।" }, "ACTIVITIES": { "TITLE": "गतिविधियाँ" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/it.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/it.json index 5ae318268..31b31823c 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/it.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/it.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Invia un messaggio...", "SEND": "Invia", "MESSAGE_SENT_NOTIFICATION": "messaggio inviato", - "OPEN_CHAT": "APRI" + "OPEN_CHAT": "APRI", + "ENCRYPTION_KEY_MISMATCH": "Ci sono partecipanti connessi con una chiave di crittografia diversa. Non riceverai i loro messaggi." }, "ACTIVITIES": { "TITLE": "Attività" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/ja.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/ja.json index 1e765764c..2db21771e 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/ja.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/ja.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "メッセージを送信...", "SEND": "送信する", "MESSAGE_SENT_NOTIFICATION": "メッセージを送信しました", - "OPEN_CHAT": "開く" + "OPEN_CHAT": "開く", + "ENCRYPTION_KEY_MISMATCH": "異なる暗号化キーで接続している参加者がいます。彼らからのメッセージは受信できません。" }, "ACTIVITIES": { "TITLE": "アクティビティ" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/nl.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/nl.json index 3a7e83547..88ec689c0 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/nl.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/nl.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Stuur een bericht ...", "SEND": "Versturen", "MESSAGE_SENT_NOTIFICATION": "bericht verzonden", - "OPEN_CHAT": "OPENEN" + "OPEN_CHAT": "OPENEN", + "ENCRYPTION_KEY_MISMATCH": "Er zijn deelnemers verbonden met een andere versleutelingssleutel. U ontvangt hun berichten niet." }, "ACTIVITIES": { "TITLE": "Activiteiten" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/pt.json b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/pt.json index 37f5bbf2e..a4bde0ee7 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/pt.json +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/lang/pt.json @@ -85,7 +85,8 @@ "PLACEHOLDER": "Enviar uma mensagem...", "SEND": "Enviar", "MESSAGE_SENT_NOTIFICATION": "mensagem enviada", - "OPEN_CHAT": "ABRIR" + "OPEN_CHAT": "ABRIR", + "ENCRYPTION_KEY_MISMATCH": "Existem participantes conectados com uma chave de criptografia diferente. Você não receberá mensagens deles." }, "ACTIVITIES": { "TITLE": "Atividades" diff --git a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/participant/participant.service.ts b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/participant/participant.service.ts index 2d3194980..eafa40fe4 100644 --- a/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/participant/participant.service.ts +++ b/openvidu-components-angular/projects/openvidu-components-angular/src/lib/services/participant/participant.service.ts @@ -1,4 +1,5 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Signal } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { BehaviorSubject, Observable } from 'rxjs'; import { ILogger } from '../../models/logger.model'; import { ParticipantModel, ParticipantProperties } from '../../models/participant.model'; @@ -6,7 +7,6 @@ import { OpenViduComponentsConfigService } from '../config/directive-config.serv import { GlobalConfigService } from '../config/global-config.service'; import { LoggerService } from '../logger/logger.service'; -import { OpenViduService } from '../openvidu/openvidu.service'; import { AudioCaptureOptions, DataPublishOptions, @@ -19,8 +19,9 @@ import { VideoCaptureOptions, VideoPresets } from 'livekit-client'; -import { StorageService } from '../storage/storage.service'; import { E2eeService } from '../e2ee/e2ee.service'; +import { OpenViduService } from '../openvidu/openvidu.service'; +import { StorageService } from '../storage/storage.service'; @Injectable({ providedIn: 'root' @@ -28,6 +29,7 @@ import { E2eeService } from '../e2ee/e2ee.service'; export class ParticipantService { /** * Local participant Observable which pushes the local participant object in every update. + * @deprecated Please prefer `localParticipantSignal` for reactive updates and `localParticipant$` when using RxJS. */ localParticipant$: Observable; private localParticipantBS: BehaviorSubject = new BehaviorSubject( @@ -36,9 +38,25 @@ export class ParticipantService { /** * Remote participants Observable which pushes the remote participants array in every update. + * @deprecated Please prefer `remoteParticipantsSignal` for reactive updates and `remoteParticipants$` when using RxJS. */ remoteParticipants$: Observable; private remoteParticipantsBS: BehaviorSubject = new BehaviorSubject([]); + + /** + * Local participant Signal for reactive programming with Angular signals. + * This is a modern alternative to localParticipant$ Observable. + * @since Angular 16+ + */ + localParticipantSignal: Signal; + + /** + * Remote participants Signal for reactive programming with Angular signals. + * This is a modern alternative to remoteParticipants$ Observable. + * @since Angular 16+ + */ + remoteParticipantsSignal: Signal; + private localParticipant: ParticipantModel | undefined; private remoteParticipants: ParticipantModel[] = []; private log: ILogger; @@ -57,6 +75,10 @@ export class ParticipantService { this.log = this.loggerSrv.get('ParticipantService'); this.localParticipant$ = this.localParticipantBS.asObservable(); this.remoteParticipants$ = this.remoteParticipantsBS.asObservable(); + + // Create signals from observables for modern reactive programming + this.localParticipantSignal = toSignal(this.localParticipant$, { initialValue: undefined }); + this.remoteParticipantsSignal = toSignal(this.remoteParticipants$, { initialValue: [] }); } /** @@ -81,6 +103,8 @@ export class ParticipantService { /** * Returns the local participant object. + * + * @deprecated Please prefer `localParticipantSignal()` for reactive updates and `localParticipant$` when using RxJS. */ getLocalParticipant(): ParticipantModel | undefined { return this.localParticipant; @@ -435,6 +459,8 @@ export class ParticipantService { /** * Returns all remote participants in the room. + * + * @deprecated Please prefer `remoteParticipantsSignal()` for automatic reactive updates or `remoteParticipants$` when using Observables. */ getRemoteParticipants(): ParticipantModel[] { return this.remoteParticipants;