diff --git a/apps/web/src/app-effects.tsx b/apps/web/src/app-effects.tsx index d049f1442..f80141f53 100644 --- a/apps/web/src/app-effects.tsx +++ b/apps/web/src/app-effects.tsx @@ -20,7 +20,6 @@ along with this program. If not, see . import React, { useEffect } from "react"; import { useStore } from "./stores/app-store"; import { useStore as useUserStore } from "./stores/user-store"; -import { useStore as useAttachmentStore } from "./stores/attachment-store"; import { useEditorStore } from "./stores/editor-store"; import { useStore as useAnnouncementStore } from "./stores/announcement-store"; import { resetNotices, scheduleBackups } from "./common/notices"; @@ -51,7 +50,6 @@ export default function AppEffects({ setShow }: AppEffectsProps) { const isFocusMode = useStore((store) => store.isFocusMode); const initUser = useUserStore((store) => store.init); const initStore = useStore((store) => store.init); - const initAttachments = useAttachmentStore((store) => store.init); const setIsVaultCreated = useStore((store) => store.setIsVaultCreated); const initEditorStore = useEditorStore((store) => store.init); const dialogAnnouncements = useAnnouncementStore( @@ -77,7 +75,6 @@ export default function AppEffects({ setShow }: AppEffectsProps) { ); initStore(); - initAttachments(); initEditorStore(); (async function () { @@ -102,7 +99,6 @@ export default function AppEffects({ setShow }: AppEffectsProps) { [ initEditorStore, initStore, - initAttachments, updateLastSynced, refreshNavItems, initUser, diff --git a/apps/web/src/components/attachment/index.tsx b/apps/web/src/components/attachment/index.tsx index 676299d7d..9dddc6123 100644 --- a/apps/web/src/components/attachment/index.tsx +++ b/apps/web/src/components/attachment/index.tsx @@ -209,7 +209,12 @@ export function Attachment({ {status ? ( <> diff --git a/apps/web/src/components/properties/index.tsx b/apps/web/src/components/properties/index.tsx index 54442312f..bd7d707e3 100644 --- a/apps/web/src/components/properties/index.tsx +++ b/apps/web/src/components/properties/index.tsx @@ -666,7 +666,6 @@ function Attachments({ noteId }: { noteId: string }) { } - headerSize={0} renderRow={({ index }) => ( {({ item }) => } diff --git a/apps/web/src/components/virtualized-table/index.tsx b/apps/web/src/components/virtualized-table/index.tsx index d18c083be..e4922b5e4 100644 --- a/apps/web/src/components/virtualized-table/index.tsx +++ b/apps/web/src/components/virtualized-table/index.tsx @@ -17,9 +17,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { Virtualizer, useVirtualizer } from "@tanstack/react-virtual"; -import { Box } from "@theme-ui/components"; +import { Virtualizer } from "@tanstack/react-virtual"; +import { Flex } from "@theme-ui/components"; import React, { useRef } from "react"; +import { TableVirtuoso } from "react-virtuoso"; export type VirtualizedTableRowProps = { item: T; @@ -36,12 +37,10 @@ type VirtualizedTableProps = { mode?: "fixed" | "dynamic"; items: T[]; estimatedSize: number; - headerSize: number; getItemKey: (index: number) => string; - scrollElement?: Element | null; + scrollElement?: HTMLElement | null; context?: C; renderRow: (props: VirtualizedTableRowProps) => JSX.Element | null; - scrollMargin?: number; header: React.ReactNode; style?: React.CSSProperties; }; @@ -50,59 +49,95 @@ export function VirtualizedTable(props: VirtualizedTableProps) { items, getItemKey, scrollElement, - scrollMargin, - headerSize, renderRow: Row, estimatedSize, mode, - virtualizerRef, header, - style, - context + context, + style } = props; const containerRef = useRef(null); - const virtualizer = useVirtualizer({ - count: items.length, - estimateSize: () => estimatedSize, - getItemKey, - getScrollElement: () => - scrollElement || containerRef.current?.closest(".ms-container") || null, - scrollMargin: scrollMargin || containerRef.current?.offsetTop || 0 - }); - - if (virtualizerRef) virtualizerRef.current = virtualizer; - - const virtualItems = virtualizer.getVirtualItems(); return ( - - - {header} - - {virtualItems.map((row, index) => ( - - ))} - -
-
+ getItemKey(index)} + defaultItemHeight={estimatedSize} + fixedHeaderContent={() => <>{header}} + fixedItemHeight={mode === "fixed" ? estimatedSize : undefined} + components={{ + Table: (props) => ( + + ), + TableRow: (props) => { + return ( + + ); + } + }} + /> + ); + + // + + // const virtualizer = useVirtualizer({ + // count: items.length, + // estimateSize: () => estimatedSize, + // getItemKey, + // getScrollElement: () => + // scrollElement || containerRef.current?.closest(".ms-container") || null, + // scrollMargin: scrollMargin || containerRef.current?.offsetTop || 0 + // }); + + // if (virtualizerRef) virtualizerRef.current = virtualizer; + + // const virtualItems = virtualizer.getVirtualItems(); + // return ( + // + //
+ // {header} + // + // {virtualItems.map((row, index) => ( + // + // ))} + // + //
+ // + // ); } diff --git a/apps/web/src/dialogs/attachments-dialog.tsx b/apps/web/src/dialogs/attachments-dialog.tsx index 77dd8c37f..19bc81c0d 100644 --- a/apps/web/src/dialogs/attachments-dialog.tsx +++ b/apps/web/src/dialogs/attachments-dialog.tsx @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { useEffect, useState, memo, useRef } from "react"; +import { useEffect, useState, memo, useRef, startTransition } from "react"; import { Box, Button, @@ -29,7 +29,7 @@ import { Text } from "@theme-ui/components"; import { store, useStore } from "../stores/attachment-store"; -import { ResolvedItem, formatBytes, usePromise } from "@notesnook/common"; +import { formatBytes, usePromise, useResolvedItem } from "@notesnook/common"; import Dialog from "../components/dialog"; import { ChevronDown, @@ -66,6 +66,7 @@ import { FlexScrollContainer } from "../components/scroll-container"; import { BaseDialogProps, DialogManager } from "../common/dialog-manager"; import { ConfirmDialog } from "./confirm"; import { showToast } from "../utils/toast"; +import { Loader } from "../components/loader"; type ToolbarAction = { title: string; @@ -107,7 +108,7 @@ type SortOptions = { type AttachmentsDialogProps = BaseDialogProps; export const AttachmentsDialog = DialogManager.register( function AttachmentsDialog({ onClose }: AttachmentsDialogProps) { - const allAttachments = useStore((store) => store.attachments); + const nonce = useStore((store) => store.nonce); const [attachments, setAttachments] = useState>(); const [counts, setCounts] = useState>({ @@ -125,29 +126,20 @@ export const AttachmentsDialog = DialogManager.register( direction: "asc" }); const currentRoute = useRef("all"); - const refresh = useStore((store) => store.refresh); const download = useStore((store) => store.download); useEffect(() => { - refresh(); - }, [refresh]); + filterAttachments(currentRoute.current) + .sorted({ + sortBy: sortBy.id, + sortDirection: sortBy.direction + }) + .then((value) => startTransition(() => setAttachments(value))); + }, [sortBy, nonce]); useEffect(() => { - (async function () { - setAttachments( - await filterAttachments(currentRoute.current).sorted({ - sortBy: sortBy.id, - sortDirection: sortBy.direction - }) - ); - })(); - }, [sortBy, allAttachments]); - - useEffect(() => { - (async function () { - setCounts(await getCounts()); - })(); - }, [allAttachments]); + getCounts().then((counts) => startTransition(() => setCounts(counts))); + }, [nonce]); return ( */} - {attachments && ( + {attachments ? ( attachments.key(index)} items={attachments.placeholders} context={{ @@ -345,6 +336,8 @@ export const AttachmentsDialog = DialogManager.register( }} renderRow={AttachmentRow} /> + ) : ( + )} @@ -364,23 +357,21 @@ function AttachmentRow( } > ) { - if (!props.context) return null; + const item = useResolvedItem({ + index: props.index, + items: props.context!.attachments, + type: "attachment" + }); + if (!item) return null; return ( - - {({ item }) => ( - props.context?.select(item.id)} - /> - )} - + props.context?.select(item.item.id)} + /> ); } diff --git a/apps/web/src/stores/attachment-store.ts b/apps/web/src/stores/attachment-store.ts index d3bee0f99..3eb40947f 100644 --- a/apps/web/src/stores/attachment-store.ts +++ b/apps/web/src/stores/attachment-store.ts @@ -27,11 +27,11 @@ import { showToast } from "../utils/toast"; import { AttachmentStream } from "../utils/streams/attachment-stream"; import { createZipStream } from "../utils/streams/zip-stream"; import { createWriteStream } from "../utils/stream-saver"; -import { Attachment, VirtualizedGrouping } from "@notesnook/core"; +import { Attachment } from "@notesnook/core"; let abortController: AbortController | undefined = undefined; class AttachmentStore extends BaseStore { - attachments?: VirtualizedGrouping; + nonce = 0; status?: { current: number; total: number }; processing: Record< string, @@ -40,17 +40,10 @@ class AttachmentStore extends BaseStore { refresh = async () => { this.set({ - attachments: await db.attachments.all.sorted({ - sortBy: "dateCreated", - sortDirection: "desc" - }) + nonce: this.get().nonce + 1 }); }; - init = () => { - this.refresh(); - }; - download = async (ids: string[]) => { if (this.get().status) throw new Error(