diff --git a/apps/client/src/widgets/collections/NoteList.tsx b/apps/client/src/widgets/collections/NoteList.tsx
index c4402e8c7..d57c66871 100644
--- a/apps/client/src/widgets/collections/NoteList.tsx
+++ b/apps/client/src/widgets/collections/NoteList.tsx
@@ -1,4 +1,4 @@
-import { allViewTypes, ViewTypeOptions } from "./interface";
+import { allViewTypes, ViewModeProps, ViewTypeOptions } from "./interface";
import { useNoteContext, useNoteLabel, useTriliumEvent } from "../react/hooks";
import FNote from "../../entities/fnote";
import "./NoteList.css";
@@ -13,27 +13,27 @@ export default function NoteList({ }: NoteListProps) {
const { note } = useNoteContext();
const viewType = useNoteViewType(note);
const noteIds = useNoteIds(note, viewType);
- const isEnabled = (!!viewType);
+ const isEnabled = (note && !!viewType);
// Refresh note Ids
- console.log("Got note ids", noteIds);
return (
{isEnabled && (
- {getComponentByViewType(viewType)}
+ {getComponentByViewType(note, noteIds, viewType)}
)}
);
}
-function getComponentByViewType(viewType: ViewTypeOptions) {
- console.log("Got ", viewType);
+function getComponentByViewType(note: FNote, noteIds: string[], viewType: ViewTypeOptions) {
+ const props: ViewModeProps = { note, noteIds };
+
switch (viewType) {
case "list":
- return ;
+ return ;
}
}
@@ -54,12 +54,13 @@ function useNoteIds(note: FNote | null | undefined, viewType: ViewTypeOptions |
const [ noteIds, setNoteIds ] = useState([]);
async function refreshNoteIds() {
- console.log("Refreshed note IDs");
if (!note) {
setNoteIds([]);
} else if (viewType === "list" || viewType === "grid") {
+ console.log("Refreshed note IDs");
setNoteIds(note.getChildNoteIds());
} else {
+ console.log("Refreshed note IDs");
setNoteIds(await note.getSubtreeNoteIds());
}
}
diff --git a/apps/client/src/widgets/collections/interface.ts b/apps/client/src/widgets/collections/interface.ts
index 6d64c2b45..4c3c71e76 100644
--- a/apps/client/src/widgets/collections/interface.ts
+++ b/apps/client/src/widgets/collections/interface.ts
@@ -1,5 +1,14 @@
+import FNote from "../../entities/fnote";
import type { ViewModeArgs } from "../view_widgets/view_mode";
export const allViewTypes = ["list", "grid", "calendar", "table", "geoMap", "board"] as const;
export type ArgsWithoutNoteId = Omit;
export type ViewTypeOptions = typeof allViewTypes[number];
+
+export interface ViewModeProps {
+ note: FNote;
+ /**
+ * We're using noteIds so that it's not necessary to load all notes at once when paging.
+ */
+ noteIds: string[];
+}
diff --git a/apps/client/src/widgets/collections/legacy/ListView.tsx b/apps/client/src/widgets/collections/legacy/ListView.tsx
index 25817b806..550edff60 100644
--- a/apps/client/src/widgets/collections/legacy/ListView.tsx
+++ b/apps/client/src/widgets/collections/legacy/ListView.tsx
@@ -1,14 +1,80 @@
-export default function ListView() {
+import { useEffect, useMemo, useState } from "preact/hooks";
+import FNote from "../../../entities/fnote";
+import Icon from "../../react/Icon";
+import { ViewModeProps } from "../interface";
+import { useNoteLabel, useNoteLabelBoolean } from "../../react/hooks";
+import froca from "../../../services/froca";
+import NoteLink from "../../react/NoteLink";
+
+export default function ListView({ note, noteIds }: ViewModeProps) {
+ const [ isExpanded ] = useNoteLabelBoolean(note, "expanded");
+ const filteredNoteIds = useMemo(() => {
+ // Filters the note IDs for the legacy view to filter out subnotes that are already included in the note content such as images, included notes.
+ const includedLinks = note ? note.getRelations().filter((rel) => rel.name === "imageLink" || rel.name === "includeNoteLink") : [];
+ const includedNoteIds = new Set(includedLinks.map((rel) => rel.value));
+ return noteIds.filter((noteId) => !includedNoteIds.has(noteId) && noteId !== "_hidden");
+ }, noteIds);
+ const { pageNotes } = usePagination(note, filteredNoteIds);
+
return (
- List view goes here.
-
+
+ {pageNotes?.map(note => (
+
+ ))}
+
);
+}
+
+function NoteCard({ note, expand }: { note: FNote, expand?: boolean }) {
+ const isSearch = note.type === "search";
+ const notePath = isSearch
+ ? note.noteId // for search note parent, we want to display a non-search path
+ : `${note.noteId}/${note.noteId}`;
+
+ return (
+
+
+
+
+
+
+ )
+}
+
+function usePagination(note: FNote, noteIds: string[]) {
+ const [ page, setPage ] = useState(1);
+ const [ pageNotes, setPageNotes ] = useState();
+
+ // Parse page size.
+ const [ pageSize ] = useNoteLabel(note, "pageSize");
+ const pageSizeNum = parseInt(pageSize ?? "", 10);
+ const normalizedPageSize = (pageSizeNum && pageSizeNum > 0 ? pageSizeNum : 20);
+
+ // Calculate start/end index.
+ const startIdx = (page - 1) * normalizedPageSize;
+ const endIdx = startIdx + normalizedPageSize;
+
+ // Obtain notes within the range.
+ const pageNoteIds = noteIds.slice(startIdx, Math.min(endIdx, noteIds.length));
+
+ useEffect(() => {
+ froca.getNotes(pageNoteIds).then(setPageNotes);
+ }, [ note, noteIds, page, pageSize ]);
+
+ return {
+ page,
+ setPage,
+ pageNotes
+ }
}
\ No newline at end of file
diff --git a/apps/client/src/widgets/react/Icon.tsx b/apps/client/src/widgets/react/Icon.tsx
index cc7afe812..e047a1762 100644
--- a/apps/client/src/widgets/react/Icon.tsx
+++ b/apps/client/src/widgets/react/Icon.tsx
@@ -1,7 +1,8 @@
interface IconProps {
icon?: string;
+ className?: string;
}
-export default function Icon({ icon }: IconProps) {
- return
+export default function Icon({ icon, className }: IconProps) {
+ return
}
\ No newline at end of file
diff --git a/apps/client/src/widgets/view_widgets/list_or_grid_view.ts b/apps/client/src/widgets/view_widgets/list_or_grid_view.ts
index f68521d5c..e533b3562 100644
--- a/apps/client/src/widgets/view_widgets/list_or_grid_view.ts
+++ b/apps/client/src/widgets/view_widgets/list_or_grid_view.ts
@@ -17,40 +17,10 @@ class ListOrGridView extends ViewMode<{}> {
private showNotePath?: boolean;
private highlightRegex?: RegExp | null;
- /*
- * We're using noteIds so that it's not necessary to load all notes at once when paging
- */
constructor(viewType: ViewTypeOptions, args: ViewModeArgs) {
super(args, viewType);
this.$noteList = $(TPL);
-
-
- args.$parent.append(this.$noteList);
-
- this.page = 1;
- this.pageSize = parseInt(args.parentNote.getLabelValue("pageSize") || "");
-
- if (!this.pageSize || this.pageSize < 1) {
- this.pageSize = 20;
- }
-
this.$noteList.addClass(`${this.viewType}-view`);
-
- this.showNotePath = args.showNotePath;
- }
-
- /** @returns {Set} list of noteIds included (images, included notes) in the parent note and which
- * don't have to be shown in the note list. */
- getIncludedNoteIds() {
- const includedLinks = this.parentNote ? this.parentNote.getRelations().filter((rel) => rel.name === "imageLink" || rel.name === "includeNoteLink") : [];
-
- return new Set(includedLinks.map((rel) => rel.value));
- }
-
- async beforeRender() {
- super.beforeRender();
- const includedNoteIds = this.getIncludedNoteIds();
- this.filteredNoteIds = this.noteIds.filter((noteId) => !includedNoteIds.has(noteId) && noteId !== "_hidden");
}
async renderList() {
@@ -70,20 +40,6 @@ class ListOrGridView extends ViewMode<{}> {
this.$noteList.show();
- const $container = this.$noteList.find(".note-list-container").empty();
-
- const startIdx = (this.page - 1) * this.pageSize;
- const endIdx = startIdx + this.pageSize;
-
- const pageNoteIds = this.filteredNoteIds.slice(startIdx, Math.min(endIdx, this.filteredNoteIds.length));
- const pageNotes = await froca.getNotes(pageNoteIds);
-
- for (const note of pageNotes) {
- const $card = await this.renderNote(note, this.parentNote.isLabelTruthy("expanded"));
-
- $container.append($card);
- }
-
this.renderPager();
return this.$noteList;
@@ -132,25 +88,15 @@ class ListOrGridView extends ViewMode<{}> {
}
async renderNote(note: FNote, expand: boolean = false) {
- const $expander = $('');
-
const { $renderedAttributes } = await attributeRenderer.renderNormalAttributes(note);
- const notePath =
- this.parentNote.type === "search"
- ? note.noteId // for search note parent, we want to display a non-search path
- : `${this.parentNote.noteId}/${note.noteId}`;
const $card = $('')
- .attr("data-note-id", note.noteId)
- .addClass("no-tooltip-preview")
.append(
$('