diff --git a/apps/client/src/widgets/collections/NoteList.css b/apps/client/src/widgets/collections/NoteList.css
new file mode 100644
index 000000000..612d088f4
--- /dev/null
+++ b/apps/client/src/widgets/collections/NoteList.css
@@ -0,0 +1,18 @@
+.note-list-widget {
+ min-height: 0;
+ overflow: auto;
+ contain: none !important;
+}
+
+.note-list-widget .note-list {
+ padding: 10px;
+}
+
+.note-list-widget.full-height,
+.note-list-widget.full-height .note-list-widget-content {
+ height: 100%;
+}
+
+.note-list-widget video {
+ height: 100%;
+}
\ No newline at end of file
diff --git a/apps/client/src/widgets/collections/NoteList.tsx b/apps/client/src/widgets/collections/NoteList.tsx
index e7cb7a588..c4402e8c7 100644
--- a/apps/client/src/widgets/collections/NoteList.tsx
+++ b/apps/client/src/widgets/collections/NoteList.tsx
@@ -1,7 +1,80 @@
+import { allViewTypes, ViewTypeOptions } from "./interface";
+import { useNoteContext, useNoteLabel, useTriliumEvent } from "../react/hooks";
+import FNote from "../../entities/fnote";
+import "./NoteList.css";
+import ListView from "./legacy/ListView";
+import { useEffect, useState } from "preact/hooks";
+
interface NoteListProps {
displayOnlyCollections?: boolean;
}
export default function NoteList({ }: NoteListProps) {
- return
Hi
+ const { note } = useNoteContext();
+ const viewType = useNoteViewType(note);
+ const noteIds = useNoteIds(note, viewType);
+ const isEnabled = (!!viewType);
+
+ // Refresh note Ids
+ console.log("Got note ids", noteIds);
+
+ return (
+
+ {isEnabled && (
+
+ {getComponentByViewType(viewType)}
+
+ )}
+
+ );
+}
+
+function getComponentByViewType(viewType: ViewTypeOptions) {
+ console.log("Got ", viewType);
+ switch (viewType) {
+ case "list":
+ return ;
+ }
+}
+
+function useNoteViewType(note?: FNote | null): ViewTypeOptions | undefined {
+ const [ viewType ] = useNoteLabel(note, "viewType");
+
+ if (!note) {
+ return undefined;
+ } else if (!(allViewTypes as readonly string[]).includes(viewType || "")) {
+ // when not explicitly set, decide based on the note type
+ return note.type === "search" ? "list" : "grid";
+ } else {
+ return viewType as ViewTypeOptions;
+ }
+}
+
+function useNoteIds(note: FNote | null | undefined, viewType: ViewTypeOptions | undefined) {
+ const [ noteIds, setNoteIds ] = useState([]);
+
+ async function refreshNoteIds() {
+ console.log("Refreshed note IDs");
+ if (!note) {
+ setNoteIds([]);
+ } else if (viewType === "list" || viewType === "grid") {
+ setNoteIds(note.getChildNoteIds());
+ } else {
+ setNoteIds(await note.getSubtreeNoteIds());
+ }
+ }
+
+ // Refresh on note switch.
+ useEffect(() => { refreshNoteIds() }, [ note ]);
+
+ // Refresh on alterations to the note subtree.
+ useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
+ if (note && loadResults.getBranchRows().some(branch =>
+ branch.parentNoteId === note.noteId
+ || noteIds.includes(branch.parentNoteId ?? ""))) {
+ refreshNoteIds();
+ }
+ })
+
+ return noteIds;
}
\ No newline at end of file
diff --git a/apps/client/src/widgets/collections/interface.ts b/apps/client/src/widgets/collections/interface.ts
index ea33be446..6d64c2b45 100644
--- a/apps/client/src/widgets/collections/interface.ts
+++ b/apps/client/src/widgets/collections/interface.ts
@@ -1,5 +1,5 @@
import type { ViewModeArgs } from "../view_widgets/view_mode";
-const allViewTypes = ["list", "grid", "calendar", "table", "geoMap", "board"] as const;
+export const allViewTypes = ["list", "grid", "calendar", "table", "geoMap", "board"] as const;
export type ArgsWithoutNoteId = Omit;
export type ViewTypeOptions = typeof allViewTypes[number];
diff --git a/apps/client/src/widgets/collections/legacy/ListOrGridView.css b/apps/client/src/widgets/collections/legacy/ListOrGridView.css
new file mode 100644
index 000000000..73c98a5f2
--- /dev/null
+++ b/apps/client/src/widgets/collections/legacy/ListOrGridView.css
@@ -0,0 +1,138 @@
+.note-list {
+ overflow: hidden;
+ position: relative;
+ height: 100%;
+}
+
+.note-book-card {
+ border-radius: 10px;
+ background-color: var(--accented-background-color);
+ padding: 10px 15px 15px 8px;
+ margin: 5px 5px 5px 5px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0;
+ flex-grow: 1;
+}
+
+.note-book-card:not(.expanded) .note-book-content {
+ display: none !important;
+ padding: 10px
+}
+
+.note-book-card.expanded .note-book-content {
+ display: block;
+ min-height: 0;
+ height: 100%;
+ padding-top: 10px;
+}
+
+.note-book-content .rendered-content {
+ height: 100%;
+}
+
+.note-book-header {
+ border-bottom: 1px solid var(--main-border-color);
+ margin-bottom: 0;
+ padding-bottom: .5rem;
+ word-break: break-all;
+}
+
+/* not-expanded title is limited to one line only */
+.note-book-card:not(.expanded) .note-book-header {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+.note-book-header .rendered-note-attributes {
+ font-size: medium;
+}
+
+.note-book-header .rendered-note-attributes:before {
+ content: "\\00a0\\00a0";
+}
+
+.note-book-header .note-icon {
+ font-size: 100%;
+ display: inline-block;
+ padding-right: 7px;
+ position: relative;
+}
+
+.note-book-card .note-book-card {
+ border: 1px solid var(--main-border-color);
+}
+
+.note-book-content.type-image, .note-book-content.type-file, .note-book-content.type-protectedSession {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ padding: 10px;
+}
+
+.note-book-content.type-image img, .note-book-content.type-canvas svg {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+}
+
+.note-book-card.type-image .note-book-content img,
+.note-book-card.type-text .note-book-content img,
+.note-book-card.type-canvas .note-book-content img {
+ max-width: 100%;
+ max-height: 100%;
+}
+
+.note-book-header {
+ flex-grow: 0;
+}
+
+.note-list-wrapper {
+ height: 100%;
+ overflow: auto;
+}
+
+.note-expander {
+ font-size: x-large;
+ position: relative;
+ top: 3px;
+ cursor: pointer;
+}
+
+.note-list-pager {
+ text-align: center;
+}
+
+/* #region Grid view */
+.note-list.grid-view .note-list-container {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.note-list.grid-view .note-book-card {
+ flex-basis: 300px;
+ border: 1px solid transparent;
+}
+
+.note-list.grid-view .note-expander {
+ display: none;
+}
+
+.note-list.grid-view .note-book-card {
+ max-height: 300px;
+}
+
+.note-list.grid-view .note-book-card img {
+ max-height: 220px;
+ object-fit: contain;
+}
+
+.note-list.grid-view .note-book-card:hover {
+ cursor: pointer;
+ border: 1px solid var(--main-border-color);
+ background: var(--more-accented-background-color);
+}
+/* #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
new file mode 100644
index 000000000..25817b806
--- /dev/null
+++ b/apps/client/src/widgets/collections/legacy/ListView.tsx
@@ -0,0 +1,14 @@
+export default function ListView() {
+ return (
+
+
+ List view goes here.
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/client/src/widgets/collections/note_list.bak b/apps/client/src/widgets/collections/note_list.bak
index 1e14adca2..61fdca46b 100644
--- a/apps/client/src/widgets/collections/note_list.bak
+++ b/apps/client/src/widgets/collections/note_list.bak
@@ -4,32 +4,6 @@ import type FNote from "../../entities/fnote.js";
import type { CommandListener, CommandListenerData, CommandMappings, CommandNames, EventData, EventNames } from "../../components/app_context.js";
import type ViewMode from "../view_widgets/view_mode.js";
-const TPL = /*html*/`
-`;
-
export default class NoteListWidget extends NoteContextAwareWidget {
private $content!: JQuery;
@@ -49,10 +23,6 @@ export default class NoteListWidget extends NoteContextAwareWidget {
}
isEnabled() {
- if (!super.isEnabled()) {
- return false;
- }
-
if (this.displayOnlyCollections && this.note?.type !== "book") {
const viewType = this.note?.getLabelValue("viewType");
if (!viewType || ["grid", "list"].includes(viewType)) {
diff --git a/apps/client/src/widgets/collections/note_list_renderer.ts.bak b/apps/client/src/widgets/collections/note_list_renderer.ts.bak
index 9660883ea..ce7bbc426 100644
--- a/apps/client/src/widgets/collections/note_list_renderer.ts.bak
+++ b/apps/client/src/widgets/collections/note_list_renderer.ts.bak
@@ -17,17 +17,6 @@ export default class NoteListRenderer {
this.viewType = this.#getViewType(args.parentNote);
}
- #getViewType(parentNote: FNote): ViewTypeOptions {
- const viewType = parentNote.getLabelValue("viewType");
-
- if (!(allViewTypes as readonly string[]).includes(viewType || "")) {
- // when not explicitly set, decide based on the note type
- return parentNote.type === "search" ? "list" : "grid";
- } else {
- return viewType as ViewTypeOptions;
- }
- }
-
get isFullHeight() {
switch (this.viewType) {
case "list":
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 9ab58bbbf..f68521d5c 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
@@ -8,156 +8,6 @@ import type FNote from "../../entities/fnote.js";
import ViewMode, { type ViewModeArgs } from "./view_mode.js";
import { ViewTypeOptions } from "../collections/interface.js";
-const TPL = /*html*/`
-`;
-
class ListOrGridView extends ViewMode<{}> {
private $noteList: JQuery;
diff --git a/apps/client/src/widgets/view_widgets/view_mode.ts b/apps/client/src/widgets/view_widgets/view_mode.ts
index 2b7f02c9a..cb7d3a8a8 100644
--- a/apps/client/src/widgets/view_widgets/view_mode.ts
+++ b/apps/client/src/widgets/view_widgets/view_mode.ts
@@ -48,10 +48,6 @@ export default abstract class ViewMode extends Component {
}
async entitiesReloadedEvent(e: EventData<"entitiesReloaded">) {
- if (e.loadResults.getBranchRows().some(branch => branch.parentNoteId === this.parentNote.noteId || this.noteIds.includes(branch.parentNoteId ?? ""))) {
- this.#refreshNoteIds();
- }
-
if (await this.onEntitiesReloaded(e)) {
appContext.triggerEvent("refreshNoteList", { noteId: this.parentNote.noteId });
}
@@ -70,14 +66,4 @@ export default abstract class ViewMode extends Component {
return this._viewStorage;
}
- async #refreshNoteIds() {
- let noteIds: string[];
- if (this.viewType === "list" || this.viewType === "grid") {
- noteIds = this.args.parentNote.getChildNoteIds();
- } else {
- noteIds = await this.args.parentNote.getSubtreeNoteIds();
- }
- this.noteIds = noteIds;
- }
-
}