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; - } - }