mirror of https://github.com/OpenVidu/openvidu.git
ov-components: Add encryption key mismatch warning in chat panel and update translations
parent
ddc7226b64
commit
d229da9e47
|
|
@ -6,6 +6,13 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
@if (hasEncryptionKeyMismatch()) {
|
||||
<div class="encryption-warning">
|
||||
<mat-icon>warning</mat-icon>
|
||||
<p>{{ 'PANEL.CHAT.ENCRYPTION_KEY_MISMATCH' | translate }}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="text-container">
|
||||
<p class="text-info">{{ 'PANEL.CHAT.SUBTITLE' | translate }}</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@
|
|||
"PLACEHOLDER": "发送消息...",
|
||||
"SEND": "发送",
|
||||
"MESSAGE_SENT_NOTIFICATION": "消息已发送",
|
||||
"OPEN_CHAT": "打开"
|
||||
"OPEN_CHAT": "打开",
|
||||
"ENCRYPTION_KEY_MISMATCH": "有参与者使用不同的加密密钥连接。您将不会收到他们的消息。"
|
||||
},
|
||||
"ACTIVITIES": {
|
||||
"TITLE": "活动"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@
|
|||
"PLACEHOLDER": "एक संदेश भेजें ...",
|
||||
"SEND": "भेजें",
|
||||
"MESSAGE_SENT_NOTIFICATION": "संदेश भेजा गया",
|
||||
"OPEN_CHAT": "खोलें"
|
||||
"OPEN_CHAT": "खोलें",
|
||||
"ENCRYPTION_KEY_MISMATCH": "कुछ सदस्य एक अलग एन्क्रिप्शन कुंजी के साथ जुड़े हैं। आपको उनके संदेश प्राप्त नहीं होंगे।"
|
||||
},
|
||||
"ACTIVITIES": {
|
||||
"TITLE": "गतिविधियाँ"
|
||||
|
|
|
|||
|
|
@ -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à"
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@
|
|||
"PLACEHOLDER": "メッセージを送信...",
|
||||
"SEND": "送信する",
|
||||
"MESSAGE_SENT_NOTIFICATION": "メッセージを送信しました",
|
||||
"OPEN_CHAT": "開く"
|
||||
"OPEN_CHAT": "開く",
|
||||
"ENCRYPTION_KEY_MISMATCH": "異なる暗号化キーで接続している参加者がいます。彼らからのメッセージは受信できません。"
|
||||
},
|
||||
"ACTIVITIES": {
|
||||
"TITLE": "アクティビティ"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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<ParticipantModel | undefined>;
|
||||
private localParticipantBS: BehaviorSubject<ParticipantModel | undefined> = new BehaviorSubject<ParticipantModel | undefined>(
|
||||
|
|
@ -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<ParticipantModel[]>;
|
||||
private remoteParticipantsBS: BehaviorSubject<ParticipantModel[]> = new BehaviorSubject<ParticipantModel[]>([]);
|
||||
|
||||
/**
|
||||
* Local participant Signal for reactive programming with Angular signals.
|
||||
* This is a modern alternative to localParticipant$ Observable.
|
||||
* @since Angular 16+
|
||||
*/
|
||||
localParticipantSignal: Signal<ParticipantModel | undefined>;
|
||||
|
||||
/**
|
||||
* Remote participants Signal for reactive programming with Angular signals.
|
||||
* This is a modern alternative to remoteParticipants$ Observable.
|
||||
* @since Angular 16+
|
||||
*/
|
||||
remoteParticipantsSignal: Signal<ParticipantModel[]>;
|
||||
|
||||
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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue