Work on export and moving to Vue composition API

This commit is contained in:
N-Pex 2025-06-27 16:10:25 +02:00
parent b0fae3396d
commit 9a124c5ab9
22 changed files with 660 additions and 906 deletions

View file

@ -1,5 +1,5 @@
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk";
import { EventAttachment, KeanuEventExtension } from "./eventAttachment";
import { EventAttachment, EventAttachmentLoadSrcOptions, EventAttachmentUrlType, KeanuEvent, KeanuEventExtension } from "./eventAttachment";
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import { Counter, ModeOfOperation } from "aes-js";
import { Attachment, AttachmentBatch, AttachmentSendInfo } from "./attachment";
@ -113,44 +113,68 @@ export class AttachmentManager {
return attachment;
}
public getEventAttachment(event: MatrixEvent & KeanuEventExtension): Reactive<EventAttachment> {
private getFileName(event: KeanuEvent) {
const content = event.getContent();
return (content.body || content.filename || "").toLowerCase();
}
private getSrcFileSize(event: KeanuEvent) {
const content = event.getContent();
if (content.info) {
return content.info.size;
}
return 0;
}
public getEventAttachment(event: KeanuEvent): Reactive<EventAttachment> {
let entry = this.cache.get(event.getId());
if (entry !== undefined) {
return entry;
}
const fileSize = this.getSrcFileSize(event);
const attachment: Reactive<EventAttachment> = reactive({
event: event,
name: this.getFileName(event),
srcSize: fileSize,
srcProgress: -1,
thumbnailProgress: -1,
autoDownloadable: fileSize <= this.maxSizeAutoDownloads,
loadSrc: () => Promise.reject("Not implemented"),
loadThumbnail: () => Promise.reject("Not implemented"),
release: () => Promise.reject("Not implemented"),
});
attachment.loadSrc = () => {
if (attachment.src) {
return Promise.resolve(attachment.src);
attachment.loadSrc = (options?: EventAttachmentLoadSrcOptions) => {
if (attachment.src && !options?.asBlob) {
return Promise.resolve({data: attachment.src, type: "src"});
} else if (attachment.srcPromise) {
return attachment.srcPromise;
}
attachment.srcPromise = this._loadEventAttachmentOrThumbnail(event, false, (percent) => {
attachment.srcPromise = this._loadEventAttachmentOrThumbnail(event, false, !!options?.asBlob, (percent) => {
attachment.srcProgress = percent;
}).then((src) => {
attachment.src = src;
return src;
}).then((res) => {
attachment.src = res.data as string;
return res;
});
return attachment.srcPromise;
};
attachment.loadThumbnail = () => {
if (attachment.thumbnail) {
return Promise.resolve(attachment.thumbnail);
return Promise.resolve({data: attachment.thumbnail, type: "thumbnail"});
} else if (attachment.thumbnailPromise) {
return attachment.thumbnailPromise;
}
attachment.thumbnailPromise = this._loadEventAttachmentOrThumbnail(event, true, (percent) => {
attachment.thumbnailPromise = this._loadEventAttachmentOrThumbnail(event, true, false, (percent) => {
attachment.thumbnailProgress = percent;
}).then((thummbnail) => {
attachment.thumbnail = thummbnail;
return thummbnail;
}).then((res) => {
attachment.thumbnail = res.data as string;
if (res.type == "src") {
// Downloaded the src as thumb, so set "src" as well!
attachment.src = res.data as string;
}
return res;
});
return attachment.thumbnailPromise;
};
@ -174,10 +198,13 @@ export class AttachmentManager {
private async _loadEventAttachmentOrThumbnail(
event: MatrixEvent & KeanuEventExtension,
thumbnail: boolean,
asBlob: boolean,
progress?: (percent: number) => void
): Promise<string> {
): Promise<{data: string | Blob, type: EventAttachmentUrlType}> {
await this.matrixClient.decryptEventIfNeeded(event);
let urltype: EventAttachmentUrlType = thumbnail ? "thumbnail" : "src";
const content = event.getContent();
var url = null;
var mime = "image/png";
@ -227,7 +254,7 @@ export class AttachmentManager {
content.file &&
content.file.url &&
event.getContent()?.info?.size > 0 &&
event.getContent()?.info?.size < this.maxSizeAutoDownloads
(!thumbnail || event.getContent()?.info?.size < this.maxSizeAutoDownloads)
) {
// No thumb, use real url
file = content.file;
@ -241,6 +268,7 @@ export class AttachmentManager {
this.useAuthedMedia
);
mime = file.mimetype;
urltype = "src";
}
if (url == null) {
@ -263,7 +291,8 @@ export class AttachmentManager {
const response = await axios.get(url, options);
const bytes = decrypt ? await this.decryptData(file, response) : { buffer: response.data };
return URL.createObjectURL(new Blob([bytes.buffer], { type: mime }));
const blob = new Blob([bytes.buffer], { type: mime });
return {data: asBlob ? blob : URL.createObjectURL(blob), type: urltype};
}
private b64toBuffer(val: any) {

View file

@ -8,16 +8,24 @@ export type KeanuEventExtension = {
replyEvent?: MatrixEvent & KeanuEventExtension;
}
export type EventAttachmentUrlType = "src" | "thumbnail";
export type EventAttachmentLoadSrcOptions = {
asBlob?: boolean;
}
export type EventAttachment = {
event: MatrixEvent & KeanuEventExtension;
name: string;
src?: string;
thumbnail?: string;
srcPromise?: Promise<string>;
thumbnailPromise?: Promise<string>;
srcSize: number;
srcProgress: number;
srcPromise?: Promise<{data: string | Blob, type: EventAttachmentUrlType}>;
thumbnail?: string;
thumbnailProgress: number;
loadSrc: () => void;
loadThumbnail: () => Promise<string>;
thumbnailPromise?: Promise<{data: string | Blob, type: EventAttachmentUrlType}>;
autoDownloadable: boolean;
loadSrc: (options?: EventAttachmentLoadSrcOptions) => Promise<{data: string | Blob, type: EventAttachmentUrlType}>;
loadThumbnail: () => Promise<{data: string | Blob, type: EventAttachmentUrlType}>;
release: (src: boolean, thumbnail: boolean) => void;
};