mirror of
https://github.com/balzack/databag.git
synced 2025-05-04 15:35:16 +00:00
show decrypt progress
This commit is contained in:
parent
f2bf282026
commit
ae2f4f7813
@ -21,6 +21,12 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
transition: all 400ms;
|
transition: all 400ms;
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 16px;
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
.close {
|
.close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { MediaAsset } from '../../conversation/Conversation';
|
import { MediaAsset } from '../../conversation/Conversation';
|
||||||
import { useImageAsset } from './useImageAsset.hook';
|
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 classes from './ImageAsset.module.css'
|
||||||
import { IconX } from '@tabler/icons-react'
|
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} />
|
<img className={classes.image} src={state.dataUrl} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{ state.loading && state.loadPercent > 0 && (
|
||||||
|
<Progress className={classes.progress} value={state.loadPercent} />
|
||||||
|
)}
|
||||||
<ActionIcon className={classes.close} variant="subtle" size="lg" onClick={hide}>
|
<ActionIcon className={classes.close} variant="subtle" size="lg" onClick={hide}>
|
||||||
<IconX size="lg" />
|
<IconX size="lg" />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
@ -9,6 +9,8 @@ export function useImageAsset(topicId: string, asset: MediaAsset) {
|
|||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
thumbUrl: null,
|
thumbUrl: null,
|
||||||
dataUrl: null,
|
dataUrl: null,
|
||||||
|
loading: false,
|
||||||
|
loadPercent: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -40,13 +42,15 @@ export function useImageAsset(topicId: string, asset: MediaAsset) {
|
|||||||
loadImage: async () => {
|
loadImage: async () => {
|
||||||
const { focus } = app.state;
|
const { focus } = app.state;
|
||||||
const assetId = asset.image ? asset.image.full : asset.encrypted ? asset.encrypted.parts : null;
|
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 {
|
try {
|
||||||
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId);
|
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId, (loadPercent: number)=>{ updateState({ loadPercent }) });
|
||||||
updateState({ dataUrl });
|
updateState({ dataUrl });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
updateState({ loading: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13380
app/client/web/yarn.lock
13380
app/client/web/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -131,7 +131,7 @@ export interface Focus {
|
|||||||
|
|
||||||
viewMoreTopics(): Promise<void>;
|
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>;
|
flagTopic(topicId: string): Promise<void>;
|
||||||
setBlockTopic(topicId: string): Promise<void>;
|
setBlockTopic(topicId: string): Promise<void>;
|
||||||
|
@ -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;
|
const { cardId, channelId, connection } = this;
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
throw new Error('disconnected from channel');
|
throw new Error('disconnected from channel');
|
||||||
@ -253,6 +253,7 @@ export class FocusModule implements Focus {
|
|||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', url, true);
|
xhr.open('GET', url, true);
|
||||||
|
xhr.onprogress = (ev: ProgressEvent<EventTarget>)=>{ progress((ev.loaded * 100) / ev.total) };
|
||||||
xhr.setRequestHeader('Content-Type', 'text/plain');
|
xhr.setRequestHeader('Content-Type', 'text/plain');
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
if (xhr.status >= 200 && xhr.status < 300) {
|
if (xhr.status >= 200 && xhr.status < 300) {
|
||||||
@ -761,7 +762,7 @@ export class FocusModule implements Focus {
|
|||||||
await this.removeRemoteChannelTopic(topicId);
|
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);
|
const entry = this.topicEntries.get(topicId);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
throw new Error('topic entry not found');
|
throw new Error('topic entry not found');
|
||||||
@ -783,7 +784,21 @@ export class FocusModule implements Focus {
|
|||||||
const write = await media.write();
|
const write = await media.write();
|
||||||
this.closeMedia.push(write.close);
|
this.closeMedia.push(write.close);
|
||||||
for (let i = 0; i < asset.split.length; i++) {
|
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);
|
const { data } = await crypto.aesDecrypt(block, asset.split[i].blockIv, channelKey);
|
||||||
await write.setData(data);
|
await write.setData(data);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user