diff --git a/apps/client/src/widgets/collections/NoteList.css b/apps/client/src/widgets/collections/NoteList.css
index 612d088f4..08fab236c 100644
--- a/apps/client/src/widgets/collections/NoteList.css
+++ b/apps/client/src/widgets/collections/NoteList.css
@@ -15,4 +15,11 @@
.note-list-widget video {
height: 100%;
-}
\ No newline at end of file
+}
+
+/* #region Pagination */
+.note-list-pager span.current-page {
+ text-decoration: underline;
+ font-weight: bold;
+}
+/* #endregion */
\ No newline at end of file
diff --git a/apps/client/src/widgets/collections/legacy/ListView.tsx b/apps/client/src/widgets/collections/legacy/ListView.tsx
index f28f8c2bb..7c061921b 100644
--- a/apps/client/src/widgets/collections/legacy/ListView.tsx
+++ b/apps/client/src/widgets/collections/legacy/ListView.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useMemo, useRef, useState } from "preact/hooks";
+import { Dispatch, StateUpdater, useEffect, useMemo, useRef, useState } from "preact/hooks";
import FNote from "../../../entities/fnote";
import Icon from "../../react/Icon";
import { ViewModeProps } from "../interface";
@@ -7,6 +7,7 @@ import froca from "../../../services/froca";
import NoteLink from "../../react/NoteLink";
import "./ListOrGridView.css";
import content_renderer from "../../../services/content_renderer";
+import { ComponentChildren, VNode } from "preact";
export default function ListView({ note, noteIds }: ViewModeProps) {
const [ isExpanded ] = useNoteLabelBoolean(note, "expanded");
@@ -16,12 +17,12 @@ export default function ListView({ note, noteIds }: ViewModeProps) {
const includedNoteIds = new Set(includedLinks.map((rel) => rel.value));
return noteIds.filter((noteId) => !includedNoteIds.has(noteId) && noteId !== "_hidden");
}, noteIds);
- const { pageNotes } = usePagination(note, filteredNoteIds);
+ const { pageNotes, ...pagination } = usePagination(note, filteredNoteIds);
return (
-
+
{pageNotes?.map(note => (
@@ -29,7 +30,7 @@ export default function ListView({ note, noteIds }: ViewModeProps) {
))}
-
+
);
@@ -97,9 +98,59 @@ function NoteChildren({ note }: { note: FNote}) {
return childNotes?.map(childNote => )
}
-function usePagination(note: FNote, noteIds: string[]) {
+function Pager({ page, pageSize, setPage, pageCount, totalNotes }: Omit) {
+ if (pageCount < 1) return;
+
+ let lastPrinted = false;
+ let children: ComponentChildren[] = [];
+ for (let i = 1; i <= pageCount; i++) {
+ if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(page - i) <= 2) {
+ lastPrinted = true;
+
+ const startIndex = (i - 1) * pageSize + 1;
+ const endIndex = Math.min(totalNotes, i * pageSize);
+
+ if (i !== page) {
+ children.push((
+ setPage(i)}
+ >
+ {i}
+
+ ))
+ } else {
+ // Current page
+ children.push({i})
+ }
+
+ children.push(<>{" "} {" "}>);
+ } else if (lastPrinted) {
+ children.push(<>{"... "} {" "}>);
+ lastPrinted = false;
+ }
+ }
+
+ return (
+
+ )
+}
+
+interface PaginationContext {
+ page: number;
+ setPage: Dispatch>;
+ pageNotes?: FNote[];
+ pageCount: number;
+ pageSize: number;
+ totalNotes: number;
+}
+
+function usePagination(note: FNote, noteIds: string[]): PaginationContext {
const [ page, setPage ] = useState(1);
- const [ pageNotes, setPageNotes ] = useState();
+ const [ pageNotes, setPageNotes ] = useState();
// Parse page size.
const [ pageSize ] = useNoteLabel(note, "pageSize");
@@ -109,17 +160,18 @@ function usePagination(note: FNote, noteIds: string[]) {
// Calculate start/end index.
const startIdx = (page - 1) * normalizedPageSize;
const endIdx = startIdx + normalizedPageSize;
+ const pageCount = Math.ceil(noteIds.length / normalizedPageSize);
// Obtain notes within the range.
- const pageNoteIds = noteIds.slice(startIdx, Math.min(endIdx, noteIds.length));
+ const pageNoteIds = noteIds.slice(startIdx, Math.min(endIdx, noteIds.length));
useEffect(() => {
froca.getNotes(pageNoteIds).then(setPageNotes);
}, [ note, noteIds, page, pageSize ]);
return {
- page,
- setPage,
- pageNotes
- }
+ page, setPage, pageNotes, pageCount,
+ pageSize: normalizedPageSize,
+ totalNotes: noteIds.length
+ };
}
\ 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 b028fbe42..857f1c6f0 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
@@ -45,42 +45,8 @@ class ListOrGridView extends ViewMode<{}> {
}
renderPager() {
- const $pager = this.$noteList.find(".note-list-pager").empty();
- if (!this.page || !this.pageSize) {
- return;
- }
- const pageCount = Math.ceil(this.filteredNoteIds.length / this.pageSize);
- $pager.toggle(pageCount > 1);
-
- let lastPrinted;
-
- for (let i = 1; i <= pageCount; i++) {
- if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(this.page - i) <= 2) {
- lastPrinted = true;
-
- const startIndex = (i - 1) * this.pageSize + 1;
- const endIndex = Math.min(this.filteredNoteIds.length, i * this.pageSize);
-
- $pager.append(
- i === this.page
- ? $("").text(i).css("text-decoration", "underline").css("font-weight", "bold")
- : $('')
- .text(i)
- .attr("title", `Page of ${startIndex} - ${endIndex}`)
- .on("click", () => {
- this.page = i;
- this.renderList();
- }),
- " "
- );
- } else if (lastPrinted) {
- $pager.append("... ");
-
- lastPrinted = false;
- }
- }
// no need to distinguish "note" vs "notes" since in case of one result, there's no paging at all
$pager.append(``);