feat(note_bars): view type switcher

This commit is contained in:
Elian Doran 2025-12-11 18:53:48 +02:00
parent 0856d3dbdf
commit 0eed72b888
No known key found for this signature in database
4 changed files with 67 additions and 65 deletions

View File

@ -1,46 +1,13 @@
import { type ComponentChild } from "preact";
import { formatDateTime } from "../utils/formatters";
import { useNoteContext, useStaticTooltip } from "./react/hooks";
import { joinElements } from "./react/react_utils";
import { useNoteMetadata } from "./ribbon/NoteInfoTab";
import { Trans } from "react-i18next";
import { useRef } from "preact/hooks";
import CollectionProperties from "./note_bars/CollectionProperties";
import { useNoteContext, useNoteProperty } from "./react/hooks";
export default function NoteTitleDetails() {
const { note, noteContext } = useNoteContext();
const isHiddenNote = note?.noteId.startsWith("_");
const isDefaultView = noteContext?.viewScope?.viewMode === "default";
const { note } = useNoteContext();
const noteType = useNoteProperty(note, "type");
const items: ComponentChild[] = [].filter(item => !!item);
return items.length && (
return (
<div className="title-details">
{joinElements(items, " • ")}
{note && noteType === "book" && <CollectionProperties note={note} />}
</div>
);
}
function TextWithValue({ i18nKey, value, valueTooltip }: {
i18nKey: string;
value: string;
valueTooltip: string;
}) {
const listItemRef = useRef<HTMLLIElement>(null);
useStaticTooltip(listItemRef, {
selector: "span.value",
title: valueTooltip,
popperConfig: { placement: "bottom" }
});
return (
<li ref={listItemRef}>
<Trans
i18nKey={i18nKey}
components={{
Value: <span className="value">{value}</span> as React.ReactElement
}}
/>
</li>
);
}

View File

@ -0,0 +1,29 @@
import FNote from "../../entities/fnote";
import { ViewTypeOptions } from "../collections/interface";
import Dropdown from "../react/Dropdown";
import { FormListItem } from "../react/FormList";
import { useViewType, VIEW_TYPE_MAPPINGS } from "../ribbon/CollectionPropertiesTab";
export default function CollectionProperties({ note }: { note: FNote }) {
return (
<ViewTypeSwitcher note={note} />
);
}
function ViewTypeSwitcher({ note }: { note: FNote }) {
const [ viewType, setViewType ] = useViewType(note);
return (
<Dropdown
text={VIEW_TYPE_MAPPINGS[viewType as ViewTypeOptions ?? "grid"]}
>
{Object.entries(VIEW_TYPE_MAPPINGS).map(([ key, label ]) => (
<FormListItem
key={key}
onClick={() => setViewType(key)}
checked={viewType === key}
>{label}</FormListItem>
))}
</Dropdown>
);
}

View File

@ -89,8 +89,7 @@ body.experimental-feature-new-layout {
}
.title-details {
margin-bottom: 0.2em;
opacity: 0.65;
padding-bottom: 0.2em;
font-size: 0.8em;
}
}

View File

@ -12,9 +12,9 @@ import FormCheckbox from "../react/FormCheckbox";
import FormTextBox from "../react/FormTextBox";
import { ComponentChildren } from "preact";
import { ViewTypeOptions } from "../collections/interface";
import { FormDropdownDivider, FormListItem } from "../react/FormList";
import { isExperimentalFeatureEnabled } from "../../services/experimental_features";
const VIEW_TYPE_MAPPINGS: Record<ViewTypeOptions, string> = {
export const VIEW_TYPE_MAPPINGS: Record<ViewTypeOptions, string> = {
grid: t("book_properties.grid"),
list: t("book_properties.list"),
calendar: t("book_properties.calendar"),
@ -24,24 +24,31 @@ const VIEW_TYPE_MAPPINGS: Record<ViewTypeOptions, string> = {
presentation: t("book_properties.presentation")
};
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
export default function CollectionPropertiesTab({ note }: TabContext) {
const [ viewType, setViewType ] = useNoteLabel(note, "viewType");
const defaultViewType = (note?.type === "search" ? "list" : "grid");
const viewTypeWithDefault = (viewType ?? defaultViewType) as ViewTypeOptions;
const properties = bookPropertiesConfig[viewTypeWithDefault].properties;
const [viewType, setViewType] = useViewType(note);
const properties = bookPropertiesConfig[viewType].properties;
return (
<div className="book-properties-widget">
{note && (
<>
<CollectionTypeSwitcher viewType={viewTypeWithDefault} setViewType={setViewType} />
<BookProperties viewType={viewTypeWithDefault} note={note} properties={properties} />
{!isNewLayout && <CollectionTypeSwitcher viewType={viewType} setViewType={setViewType} />}
<BookProperties viewType={viewType} note={note} properties={properties} />
</>
)}
</div>
);
}
export function useViewType(note: FNote | null | undefined) {
const [ viewType, setViewType ] = useNoteLabel(note, "viewType");
const defaultViewType = (note?.type === "search" ? "list" : "grid");
const viewTypeWithDefault = (viewType ?? defaultViewType) as ViewTypeOptions;
return [ viewTypeWithDefault, setViewType ] as const;
}
function CollectionTypeSwitcher({ viewType, setViewType }: { viewType: string, setViewType: (newValue: string) => void }) {
const collectionTypes = useMemo(() => mapToKeyValueArray(VIEW_TYPE_MAPPINGS), []);