feat: Add emoji and alot of other fixes
This commit is contained in:
@@ -7,10 +7,13 @@ import { AttachmentStorageService } from '../../infrastructure/services/attachme
|
||||
import type { Attachment, AttachmentMeta } from '../../domain/models/attachment.model';
|
||||
import { MAX_AUTO_SAVE_SIZE_BYTES } from '../../domain/constants/attachment.constants';
|
||||
import { LEGACY_ATTACHMENTS_STORAGE_KEY } from '../../domain/constants/attachment-transfer.constants';
|
||||
import { mergeAttachmentLocalPaths } from '../../domain/logic/attachment-persistence.rules';
|
||||
import { AttachmentRuntimeStore } from './attachment-runtime.store';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AttachmentPersistenceService {
|
||||
private initPromise: Promise<void> | null = null;
|
||||
|
||||
private readonly runtimeStore = inject(AttachmentRuntimeStore);
|
||||
private readonly ngrxStore = inject(Store);
|
||||
private readonly attachmentStorage = inject(AttachmentStorageService);
|
||||
@@ -51,11 +54,26 @@ export class AttachmentPersistenceService {
|
||||
}
|
||||
}
|
||||
|
||||
whenReady(): Promise<void> {
|
||||
if (this.database.isReady()) {
|
||||
return this.initFromDatabase();
|
||||
}
|
||||
|
||||
return this.initPromise ?? Promise.resolve();
|
||||
}
|
||||
|
||||
async persistAttachmentMeta(attachment: Attachment): Promise<void> {
|
||||
if (!this.database.isReady())
|
||||
return;
|
||||
|
||||
try {
|
||||
const storedRecords = await this.database.getAttachmentsForMessage(attachment.messageId);
|
||||
const storedRecord = storedRecords.find((record) => record.id === attachment.id);
|
||||
const localPaths = mergeAttachmentLocalPaths(attachment, storedRecord);
|
||||
|
||||
attachment.filePath = localPaths.filePath ?? undefined;
|
||||
attachment.savedPath = localPaths.savedPath ?? undefined;
|
||||
|
||||
await this.database.saveAttachment({
|
||||
id: attachment.id,
|
||||
messageId: attachment.messageId,
|
||||
@@ -64,8 +82,8 @@ export class AttachmentPersistenceService {
|
||||
mime: attachment.mime,
|
||||
isImage: attachment.isImage,
|
||||
uploaderPeerId: attachment.uploaderPeerId,
|
||||
filePath: attachment.filePath,
|
||||
savedPath: attachment.savedPath
|
||||
filePath: localPaths.filePath ?? undefined,
|
||||
savedPath: localPaths.savedPath ?? undefined
|
||||
});
|
||||
} catch { /* persistence is best-effort */ }
|
||||
}
|
||||
@@ -87,9 +105,73 @@ export class AttachmentPersistenceService {
|
||||
}
|
||||
|
||||
async initFromDatabase(): Promise<void> {
|
||||
await this.loadFromDatabase();
|
||||
await this.migrateFromLocalStorage();
|
||||
await this.tryLoadSavedFiles();
|
||||
if (!this.initPromise) {
|
||||
this.initPromise = this.runInitFromDatabase();
|
||||
}
|
||||
|
||||
return this.initPromise;
|
||||
}
|
||||
|
||||
async tryRestoreAttachmentFromLocal(attachment: Attachment): Promise<boolean> {
|
||||
if (attachment.available) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let diskPath = await this.attachmentStorage.resolveExistingPath(attachment);
|
||||
|
||||
if (!diskPath) {
|
||||
const roomName = await this.resolveStorageContainerName(attachment);
|
||||
|
||||
diskPath = await this.attachmentStorage.resolveCanonicalStoredPath(attachment, roomName);
|
||||
|
||||
if (diskPath) {
|
||||
attachment.savedPath = diskPath;
|
||||
void this.persistAttachmentMeta(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
if (!diskPath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (await this.restoreMediaAttachmentFromFileUrl(attachment, diskPath)) {
|
||||
attachment.requestError = undefined;
|
||||
return true;
|
||||
}
|
||||
|
||||
const base64 = await this.attachmentStorage.readFile(diskPath);
|
||||
|
||||
if (!base64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.restoreAttachmentFromDisk(attachment, base64);
|
||||
attachment.requestError = undefined;
|
||||
return true;
|
||||
}
|
||||
|
||||
async persistUploadCopyFromSourcePath(attachment: Attachment, sourcePath: string): Promise<string | null> {
|
||||
try {
|
||||
const storageContainer = await this.resolveStorageContainerName(attachment);
|
||||
const diskPath = await this.attachmentStorage.createWritableFile(attachment, storageContainer);
|
||||
|
||||
if (!diskPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const copied = await this.attachmentStorage.copyFile(sourcePath, diskPath);
|
||||
|
||||
if (!copied) {
|
||||
await this.attachmentStorage.deleteFile(diskPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
attachment.savedPath = diskPath;
|
||||
await this.persistAttachmentMeta(attachment);
|
||||
return diskPath;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async resolveMessageRoomId(messageId: string): Promise<string | null> {
|
||||
@@ -173,50 +255,20 @@ export class AttachmentPersistenceService {
|
||||
} catch { /* migration is best-effort */ }
|
||||
}
|
||||
|
||||
private async runInitFromDatabase(): Promise<void> {
|
||||
await this.loadFromDatabase();
|
||||
await this.migrateFromLocalStorage();
|
||||
await this.tryLoadSavedFiles();
|
||||
}
|
||||
|
||||
private async tryLoadSavedFiles(): Promise<void> {
|
||||
try {
|
||||
let hasChanges = false;
|
||||
|
||||
for (const [, attachments] of this.runtimeStore.getAttachmentEntries()) {
|
||||
for (const attachment of attachments) {
|
||||
if (attachment.available)
|
||||
continue;
|
||||
|
||||
if (attachment.savedPath) {
|
||||
if (await this.restoreMediaAttachmentFromFileUrl(attachment, attachment.savedPath)) {
|
||||
hasChanges = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const savedBase64 = await this.attachmentStorage.readFile(attachment.savedPath);
|
||||
|
||||
if (savedBase64) {
|
||||
this.restoreAttachmentFromDisk(attachment, savedBase64);
|
||||
hasChanges = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (attachment.filePath) {
|
||||
if (await this.restoreMediaAttachmentFromFileUrl(attachment, attachment.filePath)) {
|
||||
hasChanges = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const originalBase64 = await this.attachmentStorage.readFile(attachment.filePath);
|
||||
|
||||
if (originalBase64) {
|
||||
this.restoreAttachmentFromDisk(attachment, originalBase64);
|
||||
hasChanges = true;
|
||||
|
||||
if (attachment.size <= MAX_AUTO_SAVE_SIZE_BYTES && attachment.objectUrl) {
|
||||
const response = await fetch(attachment.objectUrl);
|
||||
|
||||
void this.saveFileToDisk(attachment, await response.blob());
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (await this.tryRestoreAttachmentFromLocal(attachment)) {
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user