web: improve attachment progress events & ui

This commit is contained in:
Abdullah Atta
2023-09-20 20:26:52 +05:00
committed by Ammar Ahmed
parent 3b6fde2ea6
commit 08296793f1
6 changed files with 79 additions and 27 deletions

View File

@@ -123,34 +123,46 @@ export default function AppEffects({ setShow }: AppEffectsProps) {
// );
function handleDownloadUploadProgress(
type: "download" | "upload",
type: ProcessingType,
total: number,
current: number
) {
const [key, status] = getProcessingStatusFromType(type);
console.log("handleDownloadUploadProgresss", key, status, current, total);
if (current === total) {
removeStatus(key);
} else {
updateStatus({
key,
status: `${status} attachments (${current}/${total})`,
status: `${status} attachments`,
current,
total,
progress: 0
});
}
}
const fileDownloadedEvent = EV.subscribe(
EVENTS.fileDownloaded,
const fileDownloadEvents = EV.subscribeMulti(
[EVENTS.fileDownloaded, EVENTS.fileDownload],
({ total, current }: { total: number; current: number }) => {
handleDownloadUploadProgress("download", total, current);
}
},
null
);
const fileUploadedEvent = EV.subscribe(
EVENTS.fileUploaded,
const fileUploadEvents = EV.subscribeMulti(
[EVENTS.fileUploaded, EVENTS.fileUpload],
({ total, current }: { total: number; current: number }) => {
handleDownloadUploadProgress("upload", total, current);
},
null
);
const fileEncrypted = AppEventManager.subscribe(
AppEvents.fileEncrypted,
({ total, current }: { total: number; current: number }) => {
handleDownloadUploadProgress("encrypt", total, current);
}
);
@@ -169,21 +181,36 @@ export default function AppEffects({ setShow }: AppEffectsProps) {
if (!key) return;
const percent = Math.round((loaded / total) * 100);
const text = getStatus(key)?.status || `${status} attachment`;
const oldStatus = getStatus(key);
const text = oldStatus?.status || `${status} attachment`;
updateStatus({
key,
status: text,
progress: loaded === total ? 100 : percent
});
if (
(!oldStatus ||
(oldStatus.total === undefined &&
oldStatus.current === undefined) ||
oldStatus.total === oldStatus.current) &&
loaded === total
) {
removeStatus(key);
} else {
updateStatus({
...oldStatus,
key,
status: text,
progress: loaded === total ? 100 : percent
});
}
}
);
registerKeyMap();
return () => {
fileUploadedEvent.unsubscribe();
fileDownloadedEvent.unsubscribe();
progressEvent.unsubscribe();
[
...fileDownloadEvents,
...fileUploadEvents,
progressEvent,
fileEncrypted
].forEach((e) => e.unsubscribe());
// systemTimeInvalidEvent.unsubscribe();
};
}, []);

View File

@@ -24,6 +24,7 @@ export const AppEvents = {
UPDATE_ATTACHMENT_PROGRESS: "updateAttachmentProgress",
UPDATE_STATUS: "updateStatus",
REMOVE_STATUS: "removeStatus",
fileEncrypted: "file:encrypted",
checkingForUpdate: "checkingForUpdate",
updateAvailable: "updateAvailable",

View File

@@ -40,7 +40,7 @@ import {
showIssueDialog,
showUpdateAvailableNotice
} from "../../common/dialog-controller";
import useStatus from "../../hooks/use-status";
import useStatus, { statusToString } from "../../hooks/use-status";
import { ScopedThemeProvider } from "../theme-provider";
import { checkForUpdate, installUpdate } from "../../utils/updater";
import { toTitleCase } from "@notesnook/common";
@@ -132,7 +132,8 @@ function StatusBar() {
Report an issue
</Text>
</Button>
{statuses?.map(({ key, status, progress, icon: Icon }) => {
{statuses?.map((status) => {
const { key, icon: Icon } = status;
return (
<Flex
key={key}
@@ -141,7 +142,7 @@ function StatusBar() {
>
{Icon ? <Icon size={12} /> : <Loading size={12} />}
<Text variant="subBody" ml={1} sx={{ color: "paragraph" }}>
{progress ? `${progress}% ${status}` : status}
{statusToString(status)}
</Text>
</Flex>
);

View File

@@ -24,6 +24,8 @@ import { Icon } from "../components/icons";
type Status = {
key: string;
status: string;
total?: number;
current?: number;
progress?: number;
icon?: Icon | null;
};
@@ -36,13 +38,20 @@ interface IStatusStore {
const useStatusStore = create<IStatusStore>((set, get) => ({
statuses: {},
getStatus: (key: string) => get().statuses[key],
updateStatus: ({ key, status, progress, icon }: Status) =>
updateStatus: ({ key, status, progress, icon, current, total }: Status) =>
set(
produce((state) => {
if (!key) return;
const { statuses } = state;
const statusText = status || statuses[key]?.status;
statuses[key] = { key, status: statusText, progress, icon };
statuses[key] = {
current,
total,
key,
status: statusText,
progress,
icon
};
})
),
removeStatus: (key) =>
@@ -63,3 +72,12 @@ export default function useStatus() {
export const updateStatus = useStatusStore.getState().updateStatus;
export const removeStatus = useStatusStore.getState().removeStatus;
export const getStatus = useStatusStore.getState().getStatus;
export function statusToString(status: Status) {
const parts: string[] = [];
if (status.progress) parts.push(`${status.progress}%`);
parts.push(status.status);
if (status.total !== undefined && status.current !== undefined)
parts.push(`(${status.current}/${status.total})`);
return parts.join(" ");
}

View File

@@ -24,7 +24,6 @@ import { AppEventManager, AppEvents } from "../common/app-events";
import { StreamableFS } from "@notesnook/streamable-fs";
import { NNCrypto } from "./nncrypto";
import hosts from "@notesnook/core/dist/utils/constants";
import { sendAttachmentsProgressEvent } from "@notesnook/core/dist/common";
import { saveAs } from "file-saver";
import { showToast } from "../utils/toast";
import { db } from "../common/db";
@@ -61,7 +60,11 @@ async function writeEncryptedFile(
// let offset = 0;
// let encrypted = 0;
const fileHandle = await streamablefs.createFile(hash, file.size, file.type);
sendAttachmentsProgressEvent("encrypt", hash, 1, 0);
AppEventManager.publish(AppEvents.fileEncrypted, {
hash,
total: 1,
current: 0
});
const { iv, stream } = await NNCrypto.createEncryptionStream(key);
await file
@@ -82,7 +85,11 @@ async function writeEncryptedFile(
)
.pipeTo(fileHandle.writeable);
sendAttachmentsProgressEvent("encrypt", hash, 1, 1);
AppEventManager.publish(AppEvents.fileEncrypted, {
hash,
total: 1,
current: 1
});
return {
chunkSize: CHUNK_SIZE,

View File

@@ -27,9 +27,7 @@ class EventManager {
}
subscribeMulti(names, handler, thisArg) {
names.forEach((name) => {
this.subscribe(name, handler.bind(thisArg));
});
return names.map((name) => this.subscribe(name, handler.bind(thisArg)));
}
subscribe(name, handler, once = false) {