diff --git a/apps/web/src/components/list-container/index.tsx b/apps/web/src/components/list-container/index.tsx
index 570d87a4a..1f9e7b06f 100644
--- a/apps/web/src/components/list-container/index.tsx
+++ b/apps/web/src/components/list-container/index.tsx
@@ -38,7 +38,7 @@ import {
isGroupHeader
} from "@notesnook/core";
import { VirtualizedList } from "../virtualized-list";
-import { Virtualizer } from "@tanstack/react-virtual";
+import { ScrollToOptions, Virtualizer } from "@tanstack/react-virtual";
import { useResolvedItem } from "./resolved-item";
type ListContainerProps = {
@@ -138,64 +138,18 @@ function ListContainer(props: ListContainerProps) {
onFocus: () => onFocus(index),
onMouseDown: (e) => onMouseDown(e.nativeEvent, index)
})}
- renderItem={function ItemRenderer({ index }) {
- const resolvedItem = useResolvedItem({ index, items });
- // console.log("Rendering:", index);
- if (!resolvedItem)
- return
;
-
- return (
- <>
- {resolvedItem.group && group ? (
- {
- let endIndex;
- for (
- let i = index + 1;
- i < props.items.ids.length;
- ++i
- ) {
- if (typeof props.items.ids[i] === "object") {
- endIndex = i;
- break;
- }
- }
- setSelectedItems([
- ...selectionStore.get().selectedItems,
- ...props.items.ids.slice(
- index,
- endIndex || props.items.ids.length
- )
- ]);
- }}
- groups={async () =>
- items.groups ? items.groups() : []
- }
- onJump={(index) => {
- listRef.current?.scrollToIndex(index, {
- align: "center",
- behavior: "auto"
- });
- setFocusedGroupIndex(index);
- }}
- />
- ) : null}
-
- >
- );
+ context={{
+ items,
+ group,
+ refresh,
+ focusedGroupIndex,
+ selectItems: setSelectedItems,
+ scrollToIndex: listRef.current?.scrollToIndex,
+ focusGroup: setFocusedGroupIndex,
+ context,
+ compact
}}
+ renderItem={ItemRenderer}
/>
>
@@ -227,6 +181,85 @@ function ListContainer(props: ListContainerProps) {
}
export default ListContainer;
+type ListContext = {
+ items: VirtualizedGrouping- ;
+ group: GroupingKey | undefined;
+ refresh: () => void;
+ focusedGroupIndex: number;
+ selectItems: (items: any) => void;
+ scrollToIndex?: (
+ index: number,
+ options?: ScrollToOptions | undefined
+ ) => void;
+ focusGroup: (index: number) => void;
+ context?: Context;
+ compact?: boolean;
+};
+function ItemRenderer({
+ index,
+ context
+}: {
+ index: number;
+ context: ListContext;
+}) {
+ const {
+ items,
+ group,
+ refresh,
+ focusedGroupIndex,
+ focusGroup,
+ selectItems,
+ scrollToIndex,
+ context: itemContext,
+ compact
+ } = context;
+ const resolvedItem = useResolvedItem({ index, items });
+ if (!resolvedItem) return ;
+
+ return (
+ <>
+ {resolvedItem.group && group ? (
+ {
+ let endIndex;
+ for (let i = index + 1; i < items.ids.length; ++i) {
+ if (typeof items.ids[i] === "object") {
+ endIndex = i;
+ break;
+ }
+ }
+ selectItems([
+ ...selectionStore.get().selectedItems,
+ ...items.ids.slice(index, endIndex || items.ids.length)
+ ]);
+ }}
+ groups={async () => (items.groups ? items.groups() : [])}
+ onJump={(index) => {
+ scrollToIndex?.(index, {
+ align: "center",
+ behavior: "auto"
+ });
+ focusGroup(index);
+ }}
+ />
+ ) : null}
+
+ >
+ );
+}
+
/**
* Scroll the element at the specified index into view and
* wait until it renders into the DOM. This function keeps
diff --git a/apps/web/src/components/list-container/resolved-item.tsx b/apps/web/src/components/list-container/resolved-item.tsx
index 17b5b0901..949d4747c 100644
--- a/apps/web/src/components/list-container/resolved-item.tsx
+++ b/apps/web/src/components/list-container/resolved-item.tsx
@@ -52,7 +52,7 @@ export function ResolvedItem(
[index, items]
);
- if (result.status !== "fulfilled" || !result.value) return null;
+ if (result.status === "rejected" || !result.value) return null;
if (result.value.item.type !== type) return null;
return <>{children(result.value)}>;
@@ -67,7 +67,7 @@ export function useResolvedItem(
[index, items]
);
- if (result.status !== "fulfilled" || !result.value) return null;
+ if (result.status === "rejected" || !result.value) return null;
return result.value;
}
diff --git a/apps/web/src/components/virtualized-list/index.tsx b/apps/web/src/components/virtualized-list/index.tsx
index 242ca0947..8188ce7b8 100644
--- a/apps/web/src/components/virtualized-list/index.tsx
+++ b/apps/web/src/components/virtualized-list/index.tsx
@@ -21,7 +21,7 @@ import { Virtualizer, useVirtualizer } from "@tanstack/react-virtual";
import { Box, BoxProps } from "@theme-ui/components";
import React, { useRef } from "react";
-export type VirtualizedListProps = {
+export type VirtualizedListProps = {
virtualizerRef?: React.MutableRefObject<
Virtualizer | undefined
>;
@@ -30,13 +30,18 @@ export type VirtualizedListProps = {
estimatedSize: number;
getItemKey: (index: number, items: T[]) => string;
scrollElement?: Element | null;
+ context?: C;
itemWrapperProps?: (item: T, index: number) => BoxProps;
- renderItem: (props: { item: T; index: number }) => JSX.Element | null;
+ renderItem: (props: {
+ item: T;
+ index: number;
+ context: C;
+ }) => JSX.Element | null;
scrollMargin?: number;
itemGap?: number;
overscan?: number;
} & BoxProps;
-export function VirtualizedList(props: VirtualizedListProps) {
+export function VirtualizedList(props: VirtualizedListProps) {
const {
items,
getItemKey,
@@ -49,6 +54,7 @@ export function VirtualizedList(props: VirtualizedListProps) {
itemWrapperProps,
itemGap,
overscan = 5,
+ context,
...containerProps
} = props;
const containerRef = useRef(null);
@@ -99,7 +105,12 @@ export function VirtualizedList(props: VirtualizedListProps) {
}px)`
}}
>
-
+
))}
diff --git a/apps/web/src/hooks/use-promise.ts b/apps/web/src/hooks/use-promise.ts
index 039e3615c..7f6f8693a 100644
--- a/apps/web/src/hooks/use-promise.ts
+++ b/apps/web/src/hooks/use-promise.ts
@@ -20,11 +20,12 @@ along with this program. If not, see .
import { DependencyList, useEffect, useState } from "react";
export type PromiseResult =
- | PromisePendingResult
+ | PromisePendingResult
| (PromiseSettledResult & { refresh: () => void });
-export interface PromisePendingResult {
+export interface PromisePendingResult {
status: "pending";
+ value?: T;
}
/**
@@ -62,7 +63,10 @@ export default function usePromise(
useEffect(function effect() {
if (result.status !== "pending") {
- setResult({ status: "pending" });
+ setResult((s) => ({
+ ...s,
+ status: "pending"
+ }));
}
const controller = new AbortController();