show decrypt progress

This commit is contained in:
Roland Osborne 2024-12-18 11:43:10 -08:00
parent f2bf282026
commit ae2f4f7813
6 changed files with 5394 additions and 8028 deletions

View File

@ -21,6 +21,12 @@
z-index: 1;
transition: all 400ms;
.progress {
position: absolute;
bottom: 16px;
width: 25%;
}
.close {
position: absolute;
top: 16px;

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import { MediaAsset } from '../../conversation/Conversation';
import { useImageAsset } from './useImageAsset.hook';
import { ActionIcon, Image } from '@mantine/core'
import { Progress, ActionIcon, Image } from '@mantine/core'
import classes from './ImageAsset.module.css'
import { IconX } from '@tabler/icons-react'
@ -46,6 +46,9 @@ export function ImageAsset({ topicId, asset }: { topicId: string, asset: MediaAs
<img className={classes.image} src={state.dataUrl} />
</div>
)}
{ state.loading && state.loadPercent > 0 && (
<Progress className={classes.progress} value={state.loadPercent} />
)}
<ActionIcon className={classes.close} variant="subtle" size="lg" onClick={hide}>
<IconX size="lg" />
</ActionIcon>

View File

@ -9,6 +9,8 @@ export function useImageAsset(topicId: string, asset: MediaAsset) {
const [state, setState] = useState({
thumbUrl: null,
dataUrl: null,
loading: false,
loadPercent: 0,
})
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -40,13 +42,15 @@ export function useImageAsset(topicId: string, asset: MediaAsset) {
loadImage: async () => {
const { focus } = app.state;
const assetId = asset.image ? asset.image.full : asset.encrypted ? asset.encrypted.parts : null;
if (focus && assetId != null) {
if (focus && assetId != null && !state.loading) {
updateState({ loading: true, loadPercent: 0 });
try {
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId);
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId, (loadPercent: number)=>{ updateState({ loadPercent }) });
updateState({ dataUrl });
} catch (err) {
console.log(err);
}
updateState({ loading: false });
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -131,7 +131,7 @@ export interface Focus {
viewMoreTopics(): Promise<void>;
getTopicAssetUrl(topicId: string, assetId: string, progress: (percent: number) => boolean): Promise<string>;
getTopicAssetUrl(topicId: string, assetId: string, progress?: (percent: number) => boolean|void): Promise<string>;
flagTopic(topicId: string): Promise<void>;
setBlockTopic(topicId: string): Promise<void>;

View File

@ -241,7 +241,7 @@ export class FocusModule implements Focus {
}
}
private downloadBlock(topicId: string, blockId: string): Promise<string> {
private downloadBlock(topicId: string, blockId: string, progress: (percent: number)=>void): Promise<string> {
const { cardId, channelId, connection } = this;
if (!connection) {
throw new Error('disconnected from channel');
@ -253,6 +253,7 @@ export class FocusModule implements Focus {
return new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onprogress = (ev: ProgressEvent<EventTarget>)=>{ progress((ev.loaded * 100) / ev.total) };
xhr.setRequestHeader('Content-Type', 'text/plain');
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
@ -761,7 +762,7 @@ export class FocusModule implements Focus {
await this.removeRemoteChannelTopic(topicId);
}
public async getTopicAssetUrl(topicId: string, assetId: string, progress: null | ((percent: number) => boolean)): Promise<string> {
public async getTopicAssetUrl(topicId: string, assetId: string, progress?: ((percent: number) => boolean|void)): Promise<string> {
const entry = this.topicEntries.get(topicId);
if (!entry) {
throw new Error('topic entry not found');
@ -783,7 +784,21 @@ export class FocusModule implements Focus {
const write = await media.write();
this.closeMedia.push(write.close);
for (let i = 0; i < asset.split.length; i++) {
const block = await this.downloadBlock(topicId, asset.split[i].partId);
let download = true;
const block = await this.downloadBlock(topicId, asset.split[i].partId, (percent: number)=>{
if (progress && download !== false) {
download = progress(Math.floor((i * 100 + percent) / asset.split.length));
}
});
if (download === false) {
throw new Error('aborted asset load');
}
if (progress) {
download = progress(Math.floor((i * 100) / asset.split.length));
}
if (download === false) {
throw new Error('aborted asset load');
}
const { data } = await crypto.aesDecrypt(block, asset.split[i].blockIv, channelKey);
await write.setData(data);
}