feat: Add emoji and alot of other fixes

This commit is contained in:
2026-06-05 05:40:18 +02:00
parent ca069e2f61
commit 6865147e8f
72 changed files with 3885 additions and 413 deletions

View File

@@ -1,16 +1,20 @@
import { Injectable, inject } from '@angular/core';
import { take } from 'rxjs';
import { Store } from '@ngrx/store';
import { recordDebugNetworkFileChunk } from '../../../../infrastructure/realtime/logging/debug-network-metrics';
import { RealtimeSessionFacade } from '../../../../core/realtime';
import { selectCurrentUserId } from '../../../../store/users/users.selectors';
import { AttachmentStorageService } from '../../infrastructure/services/attachment-storage.service';
import { MAX_AUTO_SAVE_SIZE_BYTES } from '../../domain/constants/attachment.constants';
import { shouldPersistDownloadedAttachment } from '../../domain/logic/attachment.logic';
import { shouldCopyUploaderMediaToAppData, shouldPersistDownloadedAttachment } from '../../domain/logic/attachment.logic';
import type { Attachment, AttachmentMeta } from '../../domain/models/attachment.model';
import {
ATTACHMENT_TRANSFER_EWMA_CURRENT_WEIGHT,
ATTACHMENT_TRANSFER_EWMA_PREVIOUS_WEIGHT,
DEFAULT_ATTACHMENT_MIME_TYPE,
FILE_NOT_FOUND_REQUEST_ERROR,
NO_CONNECTED_PEERS_REQUEST_ERROR
NO_CONNECTED_PEERS_REQUEST_ERROR,
UPLOADER_LOCAL_FILE_MISSING_ERROR
} from '../../domain/constants/attachment-transfer.constants';
import {
type FileAnnounceEvent,
@@ -46,6 +50,7 @@ interface ValidFileChunkPayload {
@Injectable({ providedIn: 'root' })
export class AttachmentTransferService {
private readonly ngrxStore = inject(Store);
private readonly webrtc = inject(RealtimeSessionFacade);
private readonly runtimeStore = inject(AttachmentRuntimeStore);
private readonly attachmentStorage = inject(AttachmentStorageService);
@@ -79,10 +84,12 @@ export class AttachmentTransferService {
return result;
}
registerSyncedAttachments(
async registerSyncedAttachments(
attachmentMap: Record<string, AttachmentMeta[]>,
messageRoomIds?: Record<string, string>
): void {
): Promise<void> {
await this.persistence.whenReady();
if (messageRoomIds) {
for (const [messageId, roomId] of Object.entries(messageRoomIds)) {
this.runtimeStore.rememberMessageRoom(messageId, roomId);
@@ -119,12 +126,28 @@ export class AttachmentTransferService {
}
}
requestFromAnyPeer(messageId: string, attachment: Attachment): void {
async requestFromAnyPeer(messageId: string, attachment: Attachment): Promise<void> {
const clearedRequestError = this.clearAttachmentRequestError(attachment);
if (!attachment.available) {
const restoredLocally = await this.persistence.tryRestoreAttachmentFromLocal(attachment);
if (restoredLocally) {
this.runtimeStore.touch();
return;
}
}
const connectedPeers = this.webrtc.getConnectedPeers();
const currentUserId = await this.resolveCurrentUserId();
const isUploader = !!attachment.uploaderPeerId &&
!!currentUserId &&
attachment.uploaderPeerId === currentUserId;
if (connectedPeers.length === 0) {
attachment.requestError = NO_CONNECTED_PEERS_REQUEST_ERROR;
attachment.requestError = isUploader
? UPLOADER_LOCAL_FILE_MISSING_ERROR
: NO_CONNECTED_PEERS_REQUEST_ERROR;
this.runtimeStore.touch();
console.warn('[Attachments] No connected peers to request file from');
return;
@@ -157,12 +180,12 @@ export class AttachmentTransferService {
}
}
requestImageFromAnyPeer(messageId: string, attachment: Attachment): void {
this.requestFromAnyPeer(messageId, attachment);
requestImageFromAnyPeer(messageId: string, attachment: Attachment): Promise<void> {
return this.requestFromAnyPeer(messageId, attachment);
}
requestFile(messageId: string, attachment: Attachment): void {
this.requestFromAnyPeer(messageId, attachment);
requestFile(messageId: string, attachment: Attachment): Promise<void> {
return this.requestFromAnyPeer(messageId, attachment);
}
hasPendingRequest(messageId: string, fileId: string): boolean {
@@ -209,6 +232,36 @@ export class AttachmentTransferService {
if (attachment.size <= MAX_AUTO_SAVE_SIZE_BYTES) {
void this.persistence.saveFileToDisk(attachment, file);
} else if (shouldCopyUploaderMediaToAppData(
attachment,
attachment.filePath,
this.attachmentStorage.canCopyFiles()
)) {
const savedPath = await this.persistence.persistUploadCopyFromSourcePath(attachment, attachment.filePath!);
if (savedPath) {
const fileUrl = await this.attachmentStorage.getFileUrl(savedPath);
if (fileUrl) {
attachment.objectUrl = fileUrl;
attachment.available = true;
}
}
} else if (
this.isPlayableMedia(attachment) &&
attachment.size > MAX_AUTO_SAVE_SIZE_BYTES &&
this.attachmentStorage.canWriteFiles()
) {
const savedPath = await this.persistence.saveFileToDisk(attachment, file);
if (savedPath) {
const fileUrl = await this.attachmentStorage.getFileUrl(savedPath);
if (fileUrl) {
attachment.objectUrl = fileUrl;
attachment.available = true;
}
}
}
const fileAnnounceEvent: FileAnnounceEvent = {
@@ -471,6 +524,15 @@ export class AttachmentTransferService {
);
}
private resolveCurrentUserId(): Promise<string | null> {
return new Promise<string | null>((resolve) => {
this.ngrxStore
.select(selectCurrentUserId)
.pipe(take(1))
.subscribe((userId) => resolve(userId));
});
}
private buildTransferKey(messageId: string, fileId: string, peerId: string): string {
return `${messageId}:${fileId}:${peerId}`;
}