From 08296793f1ea2ea93c76970ffe3851b0dc51f213 Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Wed, 20 Sep 2023 20:26:52 +0500 Subject: [PATCH] web: improve attachment progress events & ui --- apps/web/src/app-effects.tsx | 59 ++++++++++++++------ apps/web/src/common/app-events.ts | 1 + apps/web/src/components/status-bar/index.tsx | 7 ++- apps/web/src/hooks/use-status.ts | 22 +++++++- apps/web/src/interfaces/fs.ts | 13 ++++- packages/core/src/utils/event-manager.js | 4 +- 6 files changed, 79 insertions(+), 27 deletions(-) diff --git a/apps/web/src/app-effects.tsx b/apps/web/src/app-effects.tsx index b5f0d2834..4cff7d58a 100644 --- a/apps/web/src/app-effects.tsx +++ b/apps/web/src/app-effects.tsx @@ -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(); }; }, []); diff --git a/apps/web/src/common/app-events.ts b/apps/web/src/common/app-events.ts index 87b482a92..7b6c007d1 100644 --- a/apps/web/src/common/app-events.ts +++ b/apps/web/src/common/app-events.ts @@ -24,6 +24,7 @@ export const AppEvents = { UPDATE_ATTACHMENT_PROGRESS: "updateAttachmentProgress", UPDATE_STATUS: "updateStatus", REMOVE_STATUS: "removeStatus", + fileEncrypted: "file:encrypted", checkingForUpdate: "checkingForUpdate", updateAvailable: "updateAvailable", diff --git a/apps/web/src/components/status-bar/index.tsx b/apps/web/src/components/status-bar/index.tsx index e7be8f549..70307a55e 100644 --- a/apps/web/src/components/status-bar/index.tsx +++ b/apps/web/src/components/status-bar/index.tsx @@ -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 - {statuses?.map(({ key, status, progress, icon: Icon }) => { + {statuses?.map((status) => { + const { key, icon: Icon } = status; return ( {Icon ? : } - {progress ? `${progress}% ${status}` : status} + {statusToString(status)} ); diff --git a/apps/web/src/hooks/use-status.ts b/apps/web/src/hooks/use-status.ts index 4aa550601..81528e686 100644 --- a/apps/web/src/hooks/use-status.ts +++ b/apps/web/src/hooks/use-status.ts @@ -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((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(" "); +} diff --git a/apps/web/src/interfaces/fs.ts b/apps/web/src/interfaces/fs.ts index 90196dd91..9aaaf7126 100644 --- a/apps/web/src/interfaces/fs.ts +++ b/apps/web/src/interfaces/fs.ts @@ -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, diff --git a/packages/core/src/utils/event-manager.js b/packages/core/src/utils/event-manager.js index dbea12a2a..97f28a124 100644 --- a/packages/core/src/utils/event-manager.js +++ b/packages/core/src/utils/event-manager.js @@ -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) {