Migrate media thread views to composition API
This commit is contained in:
parent
77eebafb79
commit
44578048aa
22 changed files with 1144 additions and 598 deletions
|
|
@ -1,21 +1,12 @@
|
|||
import { MatrixClient, MatrixEvent } from "matrix-js-sdk";
|
||||
import { KeanuEventExtension } from "./eventAttachment";
|
||||
import { EventAttachment, KeanuEventExtension } from "./eventAttachment";
|
||||
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
|
||||
import { Counter, ModeOfOperation } from "aes-js";
|
||||
import { Attachment } from "./attachment";
|
||||
import proofmode from "../plugins/proofmode";
|
||||
import imageSize from "image-size";
|
||||
import imageResize from "image-resize";
|
||||
import { reactive } from "vue";
|
||||
|
||||
type CacheEntry = {
|
||||
attachment?: string;
|
||||
thumbnail?: string;
|
||||
attachmentPromise?: Promise<string>;
|
||||
thumbnailPromise?: Promise<string>;
|
||||
attachmentProgress?: ((progress: number) => void)[];
|
||||
thumbnailProgress?: ((progress: number) => void)[];
|
||||
};
|
||||
import { Reactive, reactive } from "vue";
|
||||
|
||||
export class AttachmentManager {
|
||||
matrixClient: MatrixClient;
|
||||
|
|
@ -23,7 +14,7 @@ export class AttachmentManager {
|
|||
maxSizeUploads: number;
|
||||
maxSizeAutoDownloads: number;
|
||||
|
||||
cache: Map<string | undefined, CacheEntry>;
|
||||
cache: Map<string | undefined, Reactive<EventAttachment>>;
|
||||
|
||||
constructor(matrixClient: MatrixClient, useAuthedMedia: boolean, maxSizeAutoDownloads: number) {
|
||||
this.matrixClient = matrixClient;
|
||||
|
|
@ -34,9 +25,12 @@ export class AttachmentManager {
|
|||
this.cache = new Map();
|
||||
|
||||
// Get max upload size
|
||||
this.matrixClient.getMediaConfig(useAuthedMedia).then((config) => {
|
||||
this.matrixClient
|
||||
.getMediaConfig(useAuthedMedia)
|
||||
.then((config) => {
|
||||
this.maxSizeUploads = config["m.upload.size"] ?? 0;
|
||||
}).catch(() => {});
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
public createAttachment(file: File): Attachment {
|
||||
|
|
@ -88,9 +82,13 @@ export class AttachmentManager {
|
|||
width: newWidth,
|
||||
height: newHeight,
|
||||
};
|
||||
|
||||
|
||||
// Use scaled version if the image does not contain C2PA
|
||||
attachment.useScaled = attachment.scaledFile !== undefined && (attachment.proof === undefined || attachment.proof.integrity === undefined || attachment.proof.integrity.c2pa === undefined)
|
||||
attachment.useScaled =
|
||||
attachment.scaledFile !== undefined &&
|
||||
(attachment.proof === undefined ||
|
||||
attachment.proof.integrity === undefined ||
|
||||
attachment.proof.integrity.c2pa === undefined);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Resize failed:", err);
|
||||
|
|
@ -110,76 +108,62 @@ export class AttachmentManager {
|
|||
return attachment;
|
||||
}
|
||||
|
||||
public async loadEventAttachment(
|
||||
event: MatrixEvent & KeanuEventExtension,
|
||||
progress?: (percent: number) => void,
|
||||
outputObject?: { src: string; thumbnailSrc: string }
|
||||
): Promise<string> {
|
||||
console.error("GET ATTACHMENT FOR EVENT", event.getId());
|
||||
|
||||
const entry = this.cache.get(event.getId()) ?? {};
|
||||
if (entry.attachment) {
|
||||
if (outputObject) {
|
||||
outputObject.src = entry.attachment;
|
||||
}
|
||||
return entry.attachment;
|
||||
public getEventAttachment(event: MatrixEvent & KeanuEventExtension): Reactive<EventAttachment> {
|
||||
let entry = this.cache.get(event.getId());
|
||||
if (entry !== undefined) {
|
||||
return entry;
|
||||
}
|
||||
if (!entry.attachmentPromise) {
|
||||
entry.attachmentPromise = this._loadEventAttachmentOrThumbnail(event, false, progress)
|
||||
.then((attachment) => {
|
||||
entry.attachment = attachment;
|
||||
return attachment;
|
||||
})
|
||||
.catch((err) => {
|
||||
entry.attachmentPromise = undefined;
|
||||
throw err;
|
||||
});
|
||||
this.cache.set(event.getId(), entry);
|
||||
}
|
||||
entry.attachmentProgress = (entry.attachmentProgress ?? []).concat();
|
||||
return entry.attachmentPromise.then((attachment) => {
|
||||
console.error("GOT ATTACHMENT", attachment);
|
||||
if (outputObject) {
|
||||
outputObject.src = attachment;
|
||||
}
|
||||
return attachment;
|
||||
const attachment: Reactive<EventAttachment> = reactive({
|
||||
event: event,
|
||||
srcProgress: -1,
|
||||
thumbnailProgress: -1,
|
||||
loadSrc: () => Promise.reject("Not implemented"),
|
||||
loadThumbnail: () => Promise.reject("Not implemented"),
|
||||
release: () => Promise.reject("Not implemented"),
|
||||
});
|
||||
}
|
||||
|
||||
public async loadEventThumbnail(
|
||||
event: MatrixEvent & KeanuEventExtension,
|
||||
progress?: (percent: number) => void,
|
||||
outputObject?: { src: string; thumbnailSrc: string }
|
||||
): Promise<string> {
|
||||
console.error("GET THUMB FOR EVENT", event.getId());
|
||||
|
||||
const entry = this.cache.get(event.getId()) ?? {};
|
||||
if (entry.thumbnail) {
|
||||
if (outputObject) {
|
||||
outputObject.thumbnailSrc = entry.thumbnail;
|
||||
attachment.loadSrc = () => {
|
||||
if (attachment.src) {
|
||||
return Promise.resolve(attachment.src);
|
||||
} else if (attachment.srcPromise) {
|
||||
return attachment.srcPromise;
|
||||
}
|
||||
return entry.thumbnail;
|
||||
}
|
||||
|
||||
if (!entry.thumbnailPromise) {
|
||||
entry.thumbnailPromise = this._loadEventAttachmentOrThumbnail(event, true, progress)
|
||||
.then((thummbnail) => {
|
||||
entry.thumbnail = thummbnail;
|
||||
attachment.srcPromise = this._loadEventAttachmentOrThumbnail(event, false, (percent) => {
|
||||
attachment.srcProgress = percent;
|
||||
}).then((src) => {
|
||||
attachment.src = src;
|
||||
return src;
|
||||
});
|
||||
return attachment.srcPromise;
|
||||
};
|
||||
attachment.loadThumbnail = () => {
|
||||
if (attachment.thumbnail) {
|
||||
return Promise.resolve(attachment.thumbnail);
|
||||
} else if (attachment.thumbnailPromise) {
|
||||
return attachment.thumbnailPromise;
|
||||
}
|
||||
attachment.thumbnailPromise = this._loadEventAttachmentOrThumbnail(event, true, (percent) => {
|
||||
attachment.thumbnailProgress = percent;
|
||||
}).then((thummbnail) => {
|
||||
attachment.thumbnail = thummbnail;
|
||||
return thummbnail;
|
||||
})
|
||||
.catch((err) => {
|
||||
entry.thumbnailPromise = undefined;
|
||||
throw err;
|
||||
});
|
||||
this.cache.set(event.getId(), entry);
|
||||
}
|
||||
return entry.thumbnailPromise.then((thumbnail) => {
|
||||
console.error("GOT THUMB", thumbnail);
|
||||
if (outputObject) {
|
||||
outputObject.thumbnailSrc = thumbnail;
|
||||
return attachment.thumbnailPromise;
|
||||
};
|
||||
attachment.release = (src: boolean, thumbnail: boolean) => {
|
||||
// TODO - figure out logic
|
||||
if (entry) {
|
||||
// TODO - abortable promises
|
||||
this.cache.delete(event.getId());
|
||||
if (attachment.src) {
|
||||
URL.revokeObjectURL(attachment.src);
|
||||
}
|
||||
if (attachment.thumbnail) {
|
||||
URL.revokeObjectURL(attachment.thumbnail);
|
||||
}
|
||||
}
|
||||
return thumbnail;
|
||||
});
|
||||
}
|
||||
this.cache.set(event.getId(), attachment!);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
private async _loadEventAttachmentOrThumbnail(
|
||||
|
|
@ -277,21 +261,6 @@ export class AttachmentManager {
|
|||
return URL.createObjectURL(new Blob([bytes.buffer], { type: mime }));
|
||||
}
|
||||
|
||||
releaseEvent(event: MatrixEvent & KeanuEventExtension): void {
|
||||
console.error("Release event", event.getId());
|
||||
const entry = this.cache.get(event.getId());
|
||||
if (entry) {
|
||||
// TODO - abortable promises
|
||||
this.cache.delete(event.getId());
|
||||
if (entry.attachment) {
|
||||
URL.revokeObjectURL(entry.attachment);
|
||||
}
|
||||
if (entry.thumbnail) {
|
||||
URL.revokeObjectURL(entry.thumbnail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private b64toBuffer(val: any) {
|
||||
const baseValue = val.replaceAll("-", "+").replaceAll("_", "/");
|
||||
return Buffer.from(baseValue, "base64");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { MatrixEvent } from "matrix-js-sdk";
|
||||
import { MatrixEvent, Room } from "matrix-js-sdk";
|
||||
|
||||
export type KeanuEventExtension = {
|
||||
isMxThread?: boolean;
|
||||
isChannelMessage?: boolean;
|
||||
isPinned?: boolean;
|
||||
parentThread?: MatrixEvent & KeanuEventExtension;
|
||||
replyEvent?: MatrixEvent & KeanuEventExtension;
|
||||
}
|
||||
|
||||
export type EventAttachment = {
|
||||
|
|
@ -12,4 +14,15 @@ export type EventAttachment = {
|
|||
thumbnail?: string;
|
||||
srcPromise?: Promise<string>;
|
||||
thumbnailPromise?: Promise<string>;
|
||||
srcProgress: number;
|
||||
thumbnailProgress: number;
|
||||
loadSrc: () => void;
|
||||
loadThumbnail: () => Promise<string>;
|
||||
release: (src: boolean, thumbnail: boolean) => void;
|
||||
};
|
||||
|
||||
export type KeanuEvent = MatrixEvent & KeanuEventExtension;
|
||||
|
||||
export type KeanuRoom = Room & {
|
||||
displayType: "im.keanu.room_type_default" | "im.keanu.room_type_voice" | "im.keanu.room_type_file" | "im.keanu.room_type_channel" | undefined;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue