feat: Add pm
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
Subject,
|
||||
filter,
|
||||
type Observable
|
||||
} from 'rxjs';
|
||||
import { RealtimeSessionFacade } from '../../../../core/realtime';
|
||||
import { selectAllUsers } from '../../../../store/users/users.selectors';
|
||||
import type { ChatEvent, User } from '../../../../shared-kernel';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PeerDeliveryService {
|
||||
private readonly webrtc = inject(RealtimeSessionFacade);
|
||||
private readonly store = inject(Store);
|
||||
private readonly users = this.store.selectSignal(selectAllUsers);
|
||||
private readonly networkRestoredSubject = new Subject<void>();
|
||||
|
||||
readonly directMessageEvents$: Observable<ChatEvent> = this.webrtc.onMessageReceived.pipe(
|
||||
filter((event) => event.type === 'direct-message' || event.type === 'direct-message-status' || event.type === 'direct-message-mutation')
|
||||
);
|
||||
|
||||
readonly peerConnected$ = this.webrtc.onPeerConnected;
|
||||
readonly networkRestored$ = this.networkRestoredSubject.asObservable();
|
||||
|
||||
constructor() {
|
||||
this.installNetworkTestHooks();
|
||||
}
|
||||
|
||||
sendViaWebRTC(recipientId: string, event: ChatEvent): boolean {
|
||||
if (this.isOfflineOverrideEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const peerId = this.resolvePeerId(recipientId);
|
||||
|
||||
if (!peerId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.webrtc.sendToPeer(peerId, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
handleAck(recipientId: string, event: ChatEvent): boolean {
|
||||
return this.sendViaWebRTC(recipientId, event);
|
||||
}
|
||||
|
||||
requestUserAvatar(recipientId: string): boolean {
|
||||
return this.sendViaWebRTC(recipientId, {
|
||||
type: 'user-avatar-request',
|
||||
oderId: recipientId
|
||||
});
|
||||
}
|
||||
|
||||
syncOnReconnect(onReconnect: () => void): void {
|
||||
this.peerConnected$.subscribe(() => onReconnect());
|
||||
}
|
||||
|
||||
private resolvePeerId(recipientId: string): string | null {
|
||||
const connectedPeerIds = new Set(this.webrtc.getConnectedPeers());
|
||||
|
||||
if (connectedPeerIds.has(recipientId)) {
|
||||
return recipientId;
|
||||
}
|
||||
|
||||
const user = this.users().find((candidate: User) =>
|
||||
candidate.id === recipientId || candidate.oderId === recipientId || candidate.peerId === recipientId
|
||||
);
|
||||
const candidates = [
|
||||
user?.oderId,
|
||||
user?.peerId,
|
||||
user?.id
|
||||
].filter((candidate): candidate is string => !!candidate);
|
||||
|
||||
return candidates.find((candidate) => connectedPeerIds.has(candidate)) ?? null;
|
||||
}
|
||||
|
||||
private isOfflineOverrideEnabled(): boolean {
|
||||
return typeof window !== 'undefined'
|
||||
&& !!(window as Window & { metoyouDmNetworkOffline?: boolean }).metoyouDmNetworkOffline;
|
||||
}
|
||||
|
||||
private installNetworkTestHooks(): void {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const testWindow = window as Window & {
|
||||
simulateOffline?: () => void;
|
||||
simulateOnline?: () => void;
|
||||
metoyouDmNetworkOffline?: boolean;
|
||||
};
|
||||
|
||||
testWindow.simulateOffline = () => {
|
||||
testWindow.metoyouDmNetworkOffline = true;
|
||||
};
|
||||
|
||||
testWindow.simulateOnline = () => {
|
||||
testWindow.metoyouDmNetworkOffline = false;
|
||||
this.networkRestoredSubject.next();
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user