Merge branch 'main' into main

This commit is contained in:
Xen0r 2025-12-18 09:36:55 +01:00 committed by GitHub
commit 28da93fc65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 1563 additions and 356 deletions

View File

@ -1,14 +1,14 @@
import Component from "./component.js";
import appContext, { type CommandData, type CommandListenerData } from "./app_context.js";
import dateNoteService from "../services/date_notes.js";
import treeService from "../services/tree.js";
import openService from "../services/open.js";
import protectedSessionService from "../services/protected_session.js";
import options from "../services/options.js";
import froca from "../services/froca.js";
import utils, { openInReusableSplit } from "../services/utils.js";
import toastService from "../services/toast.js";
import noteCreateService from "../services/note_create.js";
import openService from "../services/open.js";
import options from "../services/options.js";
import protectedSessionService from "../services/protected_session.js";
import toastService from "../services/toast.js";
import treeService from "../services/tree.js";
import utils, { openInReusableSplit } from "../services/utils.js";
import appContext, { type CommandListenerData } from "./app_context.js";
import Component from "./component.js";
export default class RootCommandExecutor extends Component {
editReadOnlyNoteCommand() {
@ -193,10 +193,13 @@ export default class RootCommandExecutor extends Component {
appContext.triggerEvent("zenModeChanged", { isEnabled });
}
async toggleRibbonTabNoteMapCommand() {
async toggleRibbonTabNoteMapCommand(data: CommandListenerData<"toggleRibbonTabNoteMap">) {
const { isExperimentalFeatureEnabled } = await import("../services/experimental_features.js");
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
if (!isNewLayout) return;
if (!isNewLayout) {
this.triggerEvent("toggleRibbonTabNoteMap", data);
return;
}
const activeContext = appContext.tabManager.getActiveContext();
if (!activeContext?.notePath) return;
@ -272,7 +275,7 @@ export default class RootCommandExecutor extends Component {
}
catch (e) {
console.error("Error creating AI Chat note:", e);
toastService.showError("Failed to create AI Chat note: " + (e as Error).message);
toastService.showError(`Failed to create AI Chat note: ${(e as Error).message}`);
}
}
}

View File

@ -1,17 +1,17 @@
import server from "../services/server.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import cssClassManager from "../services/css_class_manager.js";
import type { Froca } from "../services/froca-interface.js";
import type FAttachment from "./fattachment.js";
import type { default as FAttribute, AttributeType } from "./fattribute.js";
import utils from "../services/utils.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import search from "../services/search.js";
import server from "../services/server.js";
import utils from "../services/utils.js";
import type FAttachment from "./fattachment.js";
import type { AttributeType,default as FAttribute } from "./fattribute.js";
const LABEL = "label";
const RELATION = "relation";
const NOTE_TYPE_ICONS = {
export const NOTE_TYPE_ICONS = {
file: "bx bx-file",
image: "bx bx-image",
code: "bx bx-code",
@ -268,13 +268,12 @@ export default class FNote {
}
}
return results;
} else {
return this.children;
}
return this.children;
}
async getSubtreeNoteIds(includeArchived = false) {
let noteIds: (string | string[])[] = [];
const noteIds: (string | string[])[] = [];
for (const child of await this.getChildNotes()) {
if (child.isArchived && !includeArchived) continue;
@ -471,9 +470,8 @@ export default class FNote {
return a.isHidden ? 1 : -1;
} else if (a.isSearch !== b.isSearch) {
return a.isSearch ? 1 : -1;
} else {
return a.notePath.length - b.notePath.length;
}
return a.notePath.length - b.notePath.length;
});
return notePaths;
@ -597,14 +595,12 @@ export default class FNote {
} else if (this.type === "text") {
if (this.isFolder()) {
return "bx bx-folder";
} else {
return "bx bx-note";
}
return "bx bx-note";
} else if (this.type === "code" && this.mime.startsWith("text/x-sql")) {
return "bx bx-data";
} else {
return NOTE_TYPE_ICONS[this.type];
}
return NOTE_TYPE_ICONS[this.type];
}
getColorClass() {
@ -617,7 +613,7 @@ export default class FNote {
}
getFilteredChildBranches() {
let childBranches = this.getChildBranches();
const childBranches = this.getChildBranches();
if (!childBranches) {
console.error(`No children for '${this.noteId}'. This shouldn't happen.`);
@ -811,9 +807,9 @@ export default class FNote {
return this.getLabelValue(nameWithPrefix.substring(1));
} else if (nameWithPrefix.startsWith("~")) {
return this.getRelationValue(nameWithPrefix.substring(1));
} else {
return this.getLabelValue(nameWithPrefix);
}
return this.getLabelValue(nameWithPrefix);
}
/**
@ -878,10 +874,10 @@ export default class FNote {
promotedAttrs.sort((a, b) => {
if (a.noteId === b.noteId) {
return a.position < b.position ? -1 : 1;
} else {
// inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761
return a.noteId < b.noteId ? -1 : 1;
}
// inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761
return a.noteId < b.noteId ? -1 : 1;
});
return promotedAttrs;

View File

@ -20,11 +20,19 @@ export type ExperimentalFeatureId = typeof experimentalFeatures[number]["id"];
let enabledFeatures: Set<ExperimentalFeatureId> | null = null;
export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId): boolean {
if (featureId === "new-layout") {
return options.is("newLayout");
}
return getEnabledFeatures().has(featureId);
}
export function getEnabledExperimentalFeatureIds() {
return getEnabledFeatures().values();
const values = [ ...getEnabledFeatures().values() ];
if (options.is("newLayout")) {
values.push("new-layout");
}
return values;
}
export async function toggleExperimentalFeature(featureId: ExperimentalFeatureId, enable: boolean) {

View File

@ -717,12 +717,17 @@ table.promoted-attributes-in-tooltip th {
.tooltip {
font-size: var(--main-font-size) !important;
z-index: calc(var(--ck-z-panel) - 1) !important;
white-space: pre-wrap;
}
.tooltip.tooltip-top {
z-index: 32767 !important;
}
.pre-wrap-text {
white-space: pre-wrap;
}
.bs-tooltip-bottom .tooltip-arrow::before {
border-bottom-color: var(--main-border-color) !important;
}

View File

@ -22,7 +22,7 @@
--ck-color-button-on-background: transparent;
--ck-color-button-on-hover-background: var(--hover-item-background-color);
--ck-color-button-default-active-background: var(--hover-item-background-color);
--ck-color-split-button-hover-background: var(--ck-editor-toolbar-dropdown-button-open-background);
--ck-focus-ring: 1px solid transparent;
@ -77,7 +77,7 @@
visibility: collapse;
}
/*
/*
* Dropdowns
*/
@ -85,7 +85,7 @@
:root .ck.ck-dropdown__panel,
:root .ck-balloon-panel {
--ck-editor-popup-padding: 4px;
--ck-color-panel-background: var(--menu-background-color);
--ck-color-panel-border: var(--ck-editor-popup-border-color);
@ -487,7 +487,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
.ck.ck-labeled-field-view > .ck.ck-labeled-field-view__input-wrapper > label.ck.ck-label {
/* Move the label above the text box regardless of the text box state */
transform: translate(0, calc(-.2em - var(--ck-input-label-height))) !important;
padding-inline-start: 0 !important;
background: transparent;
font-size: .85em;
@ -518,7 +518,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
*/
/*
* Code Blocks
* Code Blocks
*/
.attachment-content-wrapper pre,
@ -526,10 +526,14 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
.ck-mermaid__editing-view {
border: 0;
border-radius: 6px;
box-shadow: var(--code-block-box-shadow);
box-shadow: var(--code-block-box-shadow);
margin-top: 2px !important;
}
.attachment-content-wrapper pre {
border-radius: var(--dropdown-border-radius);
}
:root .ck-content pre:has(> code) {
padding: 0;
}
@ -542,7 +546,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
* for single-line code blocks */
--copy-button-margin-size: calc((1em * 1.5 + var(--padding-size) * 2 - var(--icon-button-size)) / 2);
/* Where: Line height
* Font size
*/
@ -690,4 +694,4 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
.note-list-widget {
outline: 0 !important;
}
}

View File

@ -2109,6 +2109,9 @@
"background_effects_title": "Background effects are now stable",
"background_effects_message": "On Windows devices, background effects are now fully stable. The background effects adds a touch of color to the user interface by blurring the background behind it. This technique is also used in other applications such as Windows Explorer.",
"background_effects_button": "Enable background effects",
"new_layout_title": "New layout",
"new_layout_message": "Weve introduced a modernized layout for Trilium. The ribbon has been removed and seamlessly integrated into the main interface, with a new status bar and expandable sections (such as promoted attributes) taking over key functions.\n\nThe new layout is enabled by default, and can be temporarily disabled via Options → Appearance.",
"new_layout_button": "More info",
"dismiss": "Dismiss"
},
"settings": {
@ -2116,7 +2119,10 @@
},
"settings_appearance": {
"related_code_blocks": "Color scheme for code blocks in text notes",
"related_code_notes": "Color scheme for code notes"
"related_code_notes": "Color scheme for code notes",
"ui": "User interface",
"ui_old_layout": "Old layout",
"ui_new_layout": "New layout"
},
"units": {
"percentage": "%"

View File

@ -1,7 +1,7 @@
import "./global_menu.css";
import { KeyboardActionNames } from "@triliumnext/commons";
import { ComponentChildren } from "preact";
import { ComponentChildren, RefObject } from "preact";
import { useContext, useEffect, useRef, useState } from "preact/hooks";
import { CommandNames } from "../../components/app_context";
@ -30,13 +30,15 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout:
const parentComponent = useContext(ParentComponent);
const { isUpdateAvailable, latestVersion } = useTriliumUpdateStatus();
const isMobileLocal = isMobile();
const logoRef = useRef<SVGSVGElement>(null);
useStaticTooltip(logoRef);
return (
<Dropdown
className="global-menu"
buttonClassName={`global-menu-button ${isHorizontalLayout ? "bx bx-menu" : ""}`} noSelectButtonStyle iconAction hideToggleArrow
text={<>
{isVerticalLayout && <VerticalLayoutIcon />}
{isVerticalLayout && <VerticalLayoutIcon logoRef={logoRef} />}
{isUpdateAvailable && <div class="global-menu-button-update-available">
<span className="bx bxs-down-arrow-alt global-menu-button-update-available-button" title={t("update_available.update_available")} />
</div>}
@ -135,9 +137,9 @@ function SwitchToOptions() {
return;
} else if (!isMobile()) {
return <MenuItem command="switchToMobileVersion" icon="bx bx-mobile" text={t("global_menu.switch_to_mobile_version")} />;
}
}
return <MenuItem command="switchToDesktopVersion" icon="bx bx-desktop" text={t("global_menu.switch_to_desktop_version")} />;
}
function MenuItem({ icon, text, title, command, disabled, active }: MenuItemProps<KeyboardActionNames | CommandNames | (() => void)>) {
@ -159,10 +161,7 @@ function KeyboardActionMenuItem({ text, command, ...props }: MenuItemProps<Keybo
/>;
}
function VerticalLayoutIcon() {
const logoRef = useRef<SVGSVGElement>(null);
useStaticTooltip(logoRef);
export function VerticalLayoutIcon({ logoRef }: { logoRef?: RefObject<SVGSVGElement> }) {
return (
<svg ref={logoRef} viewBox="0 0 256 256" title={t("global_menu.menu")}>
<g>

View File

@ -1,11 +1,12 @@
import { useMemo, useState } from "preact/hooks";
import { t } from "../../services/i18n";
import Button from "../react/Button";
import Modal from "../react/Modal";
import { dismissCallToAction, getCallToActions } from "./call_to_action_definitions";
import { t } from "../../services/i18n";
export default function CallToActionDialog() {
const activeCallToActions = useMemo(() => getCallToActions(), []);
const activeCallToActions = useMemo(() => getCallToActions(), []);
const [ activeIndex, setActiveIndex ] = useState(0);
const [ shown, setShown ] = useState(true);
const activeItem = activeCallToActions[activeIndex];
@ -36,11 +37,11 @@ export default function CallToActionDialog() {
await dismissCallToAction(activeItem.id);
await button.onClick();
goToNext();
}}/>
}}/>
)}
</>}
>
<p>{activeItem.message}</p>
<p className="pre-wrap-text">{activeItem.message}</p>
</Modal>
)
);
}

View File

@ -1,6 +1,7 @@
import utils from "../../services/utils";
import options from "../../services/options";
import appContext from "../../components/app_context";
import { t } from "../../services/i18n";
import options from "../../services/options";
import utils from "../../services/utils";
/**
* A "call-to-action" is an interactive message for the user, generally to present new features.
@ -46,18 +47,15 @@ function isNextTheme() {
const CALL_TO_ACTIONS: CallToAction[] = [
{
id: "next_theme",
title: t("call_to_action.next_theme_title"),
message: t("call_to_action.next_theme_message"),
enabled: () => !isNextTheme(),
id: "new_layout",
title: t("call_to_action.new_layout_title"),
message: t("call_to_action.new_layout_message"),
enabled: () => true,
buttons: [
{
text: t("call_to_action.next_theme_button"),
async onClick() {
await options.save("theme", "next");
await options.save("backgroundEffects", "true");
utils.reloadFrontendApp("call-to-action");
}
text: t("call_to_action.new_layout_button"),
onClick: () => appContext.tabManager.openInNewTab("_help_IjZS7iK5EXtb", "_help", true)
}
]
},
@ -75,6 +73,22 @@ const CALL_TO_ACTIONS: CallToAction[] = [
}
}
]
},
{
id: "next_theme",
title: t("call_to_action.next_theme_title"),
message: t("call_to_action.next_theme_message"),
enabled: () => !isNextTheme(),
buttons: [
{
text: t("call_to_action.next_theme_button"),
async onClick() {
await options.save("theme", "next");
await options.save("backgroundEffects", "true");
utils.reloadFrontendApp("call-to-action");
}
}
]
}
];

View File

@ -7,7 +7,6 @@
}
.inline-title {
margin-top: 2px; /* Allow space for the focus outline */
max-width: var(--max-content-width);
container-type: inline-size;
padding-inline-start: 24px;
@ -111,7 +110,7 @@ body.prefers-centered-content .inline-title {
.note-type-switcher {
--badge-radius: 12px;
position: relative;
top: 5px;
padding: .25em 0;
@ -121,7 +120,7 @@ body.prefers-centered-content .inline-title {
min-width: 0;
gap: 5px;
min-height: 35px;
>* {
flex-shrink: 0;
animation: note-type-switcher-intro 200ms ease-in;

View File

@ -328,20 +328,19 @@ function EditedNotes() {
function EditedNotesContent({ note }: { note: FNote }) {
const editedNotes = useEditedNotes(note);
return (
<>
{editedNotes?.map(editedNote => (
<SimpleBadge
key={editedNote.noteId}
title={(
<NoteLink
notePath={editedNote.noteId}
showNoteIcon
/>
)}
/>
))}
</>
);
return (editedNotes !== undefined &&
(editedNotes.length > 0 ? editedNotes?.map(editedNote => (
<SimpleBadge
key={editedNote.noteId}
title={(
<NoteLink
notePath={editedNote.noteId}
showNoteIcon
/>
)}
/>
)) : (
<div className="no-edited-notes-found">{t("edited_notes.no_edited_notes_found")}</div>
)));
}
//#endregion

View File

@ -22,11 +22,10 @@ export default function NoteBadges() {
function ReadOnlyBadge() {
const { note, noteContext } = useNoteContext();
const { isReadOnly, enableEditing } = useIsNoteReadOnly(note, noteContext);
const { isReadOnly, enableEditing, temporarilyEditable } = useIsNoteReadOnly(note, noteContext);
const isExplicitReadOnly = note?.isLabelTruthy("readOnly");
const isTemporarilyEditable = noteContext?.ntxId !== "_popup-editor" && noteContext?.viewScope?.readOnlyTemporarilyDisabled;
if (isTemporarilyEditable) {
if (temporarilyEditable) {
return <Badge
icon="bx bx-lock-open-alt"
text={t("breadcrumb_badges.read_only_temporarily_disabled")}

View File

@ -1,7 +1,7 @@
import "./NoteTitleActions.css";
import clsx from "clsx";
import { useEffect, useState } from "preact/hooks";
import { useEffect, useRef, useState } from "preact/hooks";
import NoteContext from "../../components/note_context";
import FNote from "../../entities/fnote";
@ -10,7 +10,7 @@ import CollectionProperties from "../note_bars/CollectionProperties";
import { checkFullHeight, getExtendedWidgetType } from "../NoteDetail";
import { PromotedAttributesContent, usePromotedAttributeData } from "../PromotedAttributes";
import Collapsible, { ExternallyControlledCollapsible } from "../react/Collapsible";
import { useNoteContext, useNoteProperty } from "../react/hooks";
import { useNoteContext, useNoteProperty, useTriliumEvent } from "../react/hooks";
import SearchDefinitionTab from "../ribbon/SearchDefinitionTab";
export default function NoteTitleActions() {
@ -57,6 +57,9 @@ function PromotedAttributes({ note, componentId, noteContext }: {
});
}, [ note, noteContext ]);
// Keyboard shortcut.
useTriliumEvent("toggleRibbonTabPromotedAttributes", () => setExpanded(!expanded));
if (!cells?.length) return false;
return (note && (
<ExternallyControlledCollapsible

View File

@ -1,6 +1,6 @@
import "./StatusBar.css";
import { Locale } from "@triliumnext/commons";
import { KeyboardActionNames, Locale } from "@triliumnext/commons";
import { Dropdown as BootstrapDropdown } from "bootstrap";
import clsx from "clsx";
import { type ComponentChildren } from "preact";
@ -9,7 +9,7 @@ import { useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
import { CommandNames } from "../../components/app_context";
import NoteContext from "../../components/note_context";
import FNote from "../../entities/fnote";
import FNote, { NOTE_TYPE_ICONS } from "../../entities/fnote";
import attributes from "../../services/attributes";
import { t } from "../../services/i18n";
import { ViewScope } from "../../services/link";
@ -216,14 +216,19 @@ interface NoteInfoContext extends StatusBarContext {
setSimilarNotesShown: (value: boolean) => void;
}
export function NoteInfoBadge({ note, setSimilarNotesShown }: NoteInfoContext) {
export function NoteInfoBadge({ note, similarNotesShown, setSimilarNotesShown }: NoteInfoContext) {
const dropdownRef = useRef<BootstrapDropdown>(null);
const { metadata, ...sizeProps } = useNoteMetadata(note);
const [ originalFileName ] = useNoteLabel(note, "originalFileName");
const currentNoteType = useNoteProperty(note, "type");
const currentNoteTypeData = useMemo(() => NOTE_TYPES.find(t => t.type === currentNoteType), [ currentNoteType ]);
const noteType = useNoteProperty(note, "type");
const noteTypeMapping = useMemo(() => NOTE_TYPES.find(t => t.type === noteType), [ noteType ]);
const enabled = note && noteType && noteTypeMapping;
return (note && currentNoteTypeData &&
// Keyboard shortcut.
useTriliumEvent("toggleRibbonTabNoteInfo", () => enabled && dropdownRef.current?.show());
useTriliumEvent("toggleRibbonTabSimilarNotes", () => setSimilarNotesShown(!similarNotesShown));
return (enabled &&
<StatusBarDropdown
icon="bx bx-info-circle"
title={t("status_bar.note_info_title")}
@ -235,7 +240,7 @@ export function NoteInfoBadge({ note, setSimilarNotesShown }: NoteInfoContext) {
{originalFileName && <NoteInfoValue text={t("file_properties.original_file_name")} value={originalFileName} />}
<NoteInfoValue text={t("note_info_widget.created")} value={formatDateTime(metadata?.dateCreated)} />
<NoteInfoValue text={t("note_info_widget.modified")} value={formatDateTime(metadata?.dateModified)} />
<NoteInfoValue text={t("note_info_widget.type")} value={<><Icon icon={`bx ${currentNoteTypeData.icon}`}/>{" "}{currentNoteTypeData?.title}</>} />
<NoteInfoValue text={t("note_info_widget.type")} value={<><Icon icon={`bx ${noteTypeMapping.icon ?? NOTE_TYPE_ICONS[noteType]}`}/>{" "}{noteTypeMapping?.title}</>} />
{note.mime && <NoteInfoValue text={t("note_info_widget.mime")} value={note.mime} />}
<NoteInfoValue text={t("note_info_widget.note_id")} value={<code>{note.noteId}</code>} />
<NoteInfoValue text={t("note_info_widget.note_size")} title={t("note_info_widget.note_size_info")} value={<NoteSizeWidget {...sizeProps} />} />
@ -349,6 +354,10 @@ function AttributesPane({ note, noteContext, attributesShown, setAttributesShown
// Show on keyboard shortcuts.
useTriliumEvents([ "addNewLabel", "addNewRelation" ], () => setAttributesShown(true));
useTriliumEvents([ "toggleRibbonTabOwnedAttributes", "toggleRibbonTabInheritedAttributes" ], () => setAttributesShown(!attributesShown));
// Auto-focus the owned attributes.
useEffect(() => api.current?.focus(), [ attributesShown ]);
// Interaction with the attribute editor.
useLegacyImperativeHandlers(useMemo(() => ({
@ -373,12 +382,18 @@ function AttributesPane({ note, noteContext, attributesShown, setAttributesShown
//#region Note paths
function NotePaths({ note, hoistedNoteId, notePath }: StatusBarContext) {
const dropdownRef = useRef<BootstrapDropdown>(null);
const sortedNotePaths = useSortedNotePaths(note, hoistedNoteId);
const count = sortedNotePaths?.length ?? 0;
const enabled = count > 1;
return (count > 1 &&
// Keyboard shortcut.
useTriliumEvent("toggleRibbonTabNotePaths", () => enabled && dropdownRef.current?.show());
return (enabled &&
<StatusBarDropdown
title={t("status_bar.note_paths_title")}
dropdownRef={dropdownRef}
dropdownContainerClassName="dropdown-note-paths"
icon="bx bx-directions"
text={t("status_bar.note_paths", { count })}

View File

@ -1,7 +1,7 @@
import "./CollectionProperties.css";
import { t } from "i18next";
import { useContext } from "preact/hooks";
import { useContext, useRef } from "preact/hooks";
import { Fragment } from "preact/jsx-runtime";
import FNote from "../../entities/fnote";
@ -12,7 +12,7 @@ import ActionButton from "../react/ActionButton";
import Dropdown from "../react/Dropdown";
import { FormDropdownDivider, FormDropdownSubmenu, FormListItem, FormListToggleableItem } from "../react/FormList";
import FormTextBox from "../react/FormTextBox";
import { useNoteLabel, useNoteLabelBoolean, useNoteLabelWithDefault } from "../react/hooks";
import { useNoteLabel, useNoteLabelBoolean, useNoteLabelWithDefault, useTriliumEvent } from "../react/hooks";
import Icon from "../react/Icon";
import { ParentComponent } from "../react/react_utils";
import { bookPropertiesConfig, BookProperty, ButtonProperty, CheckBoxProperty, ComboBoxItem, ComboBoxProperty, NumberProperty, SplitButtonProperty } from "../ribbon/collection-properties-config";
@ -42,8 +42,15 @@ export default function CollectionProperties({ note }: { note: FNote }) {
}
function ViewTypeSwitcher({ viewType, setViewType }: { viewType: ViewTypeOptions, setViewType: (newValue: ViewTypeOptions) => void }) {
// Keyboard shortcut
const dropdownContainerRef = useRef<HTMLDivElement>(null);
useTriliumEvent("toggleRibbonTabBookProperties", () => {
dropdownContainerRef.current?.querySelector("button")?.focus();
});
return (
<Dropdown
dropdownContainerRef={dropdownContainerRef}
text={<>
<Icon icon={ICON_MAPPINGS[viewType]} />&nbsp;
{VIEW_TYPE_MAPPINGS[viewType]}

View File

@ -2,13 +2,13 @@ import "./FormList.css";
import { Dropdown as BootstrapDropdown, Tooltip } from "bootstrap";
import clsx from "clsx";
import { ComponentChildren } from "preact";
import { ComponentChildren, RefObject } from "preact";
import { type CSSProperties,useEffect, useMemo, useRef, useState } from "preact/compat";
import { CommandNames } from "../../components/app_context";
import { handleRightToLeftPlacement, isMobile, openInAppHelpFromUrl } from "../../services/utils";
import FormToggle from "./FormToggle";
import { useStaticTooltip } from "./hooks";
import { useStaticTooltip, useSyncedRef } from "./hooks";
import Icon from "./Icon";
interface FormListOpts {
@ -97,6 +97,7 @@ interface FormListItemOpts {
className?: string;
rtl?: boolean;
postContent?: ComponentChildren;
itemRef?: RefObject<HTMLLIElement>;
}
const TOOLTIP_CONFIG: Partial<Tooltip.Options> = {
@ -104,8 +105,8 @@ const TOOLTIP_CONFIG: Partial<Tooltip.Options> = {
fallbackPlacements: [ handleRightToLeftPlacement("right") ]
};
export function FormListItem({ className, icon, value, title, active, disabled, checked, container, onClick, selected, rtl, triggerCommand, description, ...contentProps }: FormListItemOpts) {
const itemRef = useRef<HTMLLIElement>(null);
export function FormListItem({ className, icon, value, title, active, disabled, checked, container, onClick, selected, rtl, triggerCommand, description, itemRef: externalItemRef, ...contentProps }: FormListItemOpts) {
const itemRef = useSyncedRef<HTMLLIElement>(externalItemRef, null);
if (checked) {
icon = "bx bx-check";

View File

@ -933,11 +933,13 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N
const [ isReadOnly, setIsReadOnly ] = useState<boolean | undefined>(undefined);
const [ readOnlyAttr ] = useNoteLabelBoolean(note, "readOnly");
const [ autoReadOnlyDisabledAttr ] = useNoteLabelBoolean(note, "autoReadOnlyDisabled");
const [ temporarilyEditable, setTemporarilyEditable ] = useState(false);
const enableEditing = useCallback((enabled = true) => {
if (noteContext?.viewScope) {
noteContext.viewScope.readOnlyTemporarilyDisabled = enabled;
appContext.triggerEvent("readOnlyTemporarilyDisabled", {noteContext});
setTemporarilyEditable(enabled);
}
}, [noteContext]);
@ -945,6 +947,7 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N
if (note && noteContext) {
isNoteReadOnly(note, noteContext).then((readOnly) => {
setIsReadOnly(readOnly);
setTemporarilyEditable(false);
});
}
}, [ note, noteContext, noteContext?.viewScope, readOnlyAttr, autoReadOnlyDisabledAttr ]);
@ -952,10 +955,11 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N
useTriliumEvent("readOnlyTemporarilyDisabled", ({noteContext: eventNoteContext}) => {
if (noteContext?.ntxId === eventNoteContext.ntxId) {
setIsReadOnly(!noteContext.viewScope?.readOnlyTemporarilyDisabled);
setTemporarilyEditable(true);
}
});
return { isReadOnly, enableEditing };
return { isReadOnly, enableEditing, temporarilyEditable };
}
async function isNoteReadOnly(note: FNote, noteContext: NoteContext) {

View File

@ -49,6 +49,21 @@ export function FixedFormattingToolbar() {
const renderState = useRenderState(noteContext, note);
const [ toolbarToRender, setToolbarToRender ] = useState<HTMLElement | null | undefined>();
// Keyboard shortcut.
const lastFocusedElement = useRef<Element>(null);
useTriliumEvent("toggleRibbonTabClassicEditor", () => {
if (!toolbarToRender) return;
if (!toolbarToRender.contains(document.activeElement)) {
// Focus to the fixed formatting toolbar.
lastFocusedElement.current = document.activeElement;
toolbarToRender.querySelector<HTMLButtonElement>(".ck-toolbar__items button")?.focus();
} else {
// Focus back to the last selection.
(lastFocusedElement.current as HTMLElement)?.focus();
lastFocusedElement.current = null;
}
});
// Populate the cache with the toolbar of every note context.
useTriliumEvent("textEditorRefreshed", ({ ntxId: eventNtxId, editor }) => {
if (!eventNtxId) return;

View File

@ -1,5 +1,7 @@
import { ConvertToAttachmentResponse } from "@triliumnext/commons";
import { useContext } from "preact/hooks";
import { Dropdown as BootstrapDropdown } from "bootstrap";
import { RefObject } from "preact";
import { useContext, useEffect, useRef } from "preact/hooks";
import appContext, { CommandNames } from "../../components/app_context";
import Component from "../../components/component";
@ -20,7 +22,7 @@ import MovePaneButton from "../buttons/move_pane_button";
import ActionButton from "../react/ActionButton";
import Dropdown from "../react/Dropdown";
import { FormDropdownDivider, FormDropdownSubmenu, FormListHeader, FormListItem, FormListToggleableItem } from "../react/FormList";
import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumOption } from "../react/hooks";
import { useIsNoteReadOnly, useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent, useTriliumOption } from "../react/hooks";
import { ParentComponent } from "../react/react_utils";
import { NoteTypeDropdownContent, useNoteBookmarkState, useShareState } from "./BasicPropertiesTab";
import NoteActionsCustom from "./NoteActionsCustom";
@ -59,7 +61,10 @@ function RevisionsButton({ note }: { note: FNote }) {
);
}
type ItemToFocus = "basic-properties";
function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: NoteContext }) {
const dropdownRef = useRef<BootstrapDropdown>(null);
const parentComponent = useContext(ParentComponent);
const noteType = useNoteProperty(note, "type") ?? "";
const [viewType] = useNoteLabel(note, "viewType");
@ -77,14 +82,25 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
const [syncServerHost] = useTriliumOption("syncServerHost");
const { isReadOnly, enableEditing } = useIsNoteReadOnly(note, noteContext);
const isNormalViewMode = noteContext?.viewScope?.viewMode === "default";
const itemToFocusRef = useRef<ItemToFocus>(null);
// Keyboard shortcuts.
useTriliumEvent("toggleRibbonTabBasicProperties", () => {
if (!isNewLayout) return;
itemToFocusRef.current = "basic-properties";
dropdownRef.current?.toggle();
});
return (
<Dropdown
dropdownRef={dropdownRef}
buttonClassName={ isNewLayout ? "bx bx-dots-horizontal-rounded" : "bx bx-dots-vertical-rounded" }
className="note-actions"
hideToggleArrow
noSelectButtonStyle
iconAction>
iconAction
onHidden={() => itemToFocusRef.current = null }
>
{isReadOnly && <>
<CommandItem icon="bx bx-pencil" text={t("read-only-info.edit-note")}
@ -99,7 +115,7 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
<FormDropdownDivider />
{isNewLayout && isNormalViewMode && !isHelpPage && <>
<NoteBasicProperties note={note} />
<NoteBasicProperties note={note} focus={itemToFocusRef} />
<FormDropdownDivider />
</>}
@ -148,12 +164,22 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
);
}
function NoteBasicProperties({ note }: { note: FNote }) {
function NoteBasicProperties({ note, focus }: {
note: FNote;
focus: RefObject<ItemToFocus>;
}) {
const itemToFocusRef = useRef<HTMLLIElement>(null);
const [ isBookmarked, setIsBookmarked ] = useNoteBookmarkState(note);
const [ isShared, switchShareState ] = useShareState(note);
const [ isTemplate, setIsTemplate ] = useNoteLabelBoolean(note, "template");
const isProtected = useNoteProperty(note, "isProtected");
useEffect(() => {
if (focus.current === "basic-properties") {
itemToFocusRef.current?.focus();
}
}, [ focus ]);
return <>
<FormListToggleableItem
icon="bx bx-share-alt"
@ -161,6 +187,7 @@ function NoteBasicProperties({ note }: { note: FNote }) {
currentValue={isShared} onChange={switchShareState}
helpPage="R9pX4DGra2Vt"
disabled={["root", "_share", "_hidden"].includes(note?.noteId ?? "") || note?.noteId.startsWith("_options")}
itemRef={itemToFocusRef}
/>
<FormListToggleableItem
icon="bx bx-lock-alt"

View File

@ -1,5 +1,5 @@
import { NoteType } from "@triliumnext/commons";
import { useContext, useEffect, useState } from "preact/hooks";
import { useContext, useEffect, useRef, useState } from "preact/hooks";
import Component from "../../components/component";
import NoteContext from "../../components/note_context";
@ -12,7 +12,7 @@ import { ViewTypeOptions } from "../collections/interface";
import { buildSaveSqlToNoteHandler } from "../FloatingButtonsDefinitions";
import ActionButton from "../react/ActionButton";
import { FormFileUploadActionButton } from "../react/FormFileUpload";
import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent, useTriliumOption } from "../react/hooks";
import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
import { ParentComponent } from "../react/react_utils";
import { buildUploadNewFileRevisionListener } from "./FilePropertiesTab";
import { buildUploadNewImageRevisionListener } from "./ImagePropertiesTab";
@ -38,6 +38,7 @@ interface NoteActionsCustomInnerProps extends NoteActionsCustomProps {
*/
export default function NoteActionsCustom(props: NoteActionsCustomProps) {
const { note } = props;
const containerRef = useRef<HTMLDivElement>(null);
const noteType = useNoteProperty(note, "type");
const noteMime = useNoteProperty(note, "mime");
const [ viewType ] = useNoteLabel(note, "viewType");
@ -53,8 +54,15 @@ export default function NoteActionsCustom(props: NoteActionsCustomProps) {
isReadOnly
};
useTriliumEvents([ "toggleRibbonTabFileProperties", "toggleRibbonTabImageProperties" ], () => {
(containerRef.current?.firstElementChild as HTMLElement)?.focus();
});
return (innerProps &&
<div className="note-actions-custom">
<div
ref={containerRef}
className="note-actions-custom"
>
<AddChildButton {...innerProps} />
<RunActiveNoteButton {...innerProps } />
<OpenTriliumApiDocsButton {...innerProps} />

View File

@ -1,25 +1,26 @@
import { MutableRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "preact/hooks";
import { AttributeEditor as CKEditorAttributeEditor, MentionFeed, ModelElement, ModelNode, ModelPosition } from "@triliumnext/ckeditor5";
import { AttributeType } from "@triliumnext/commons";
import { MutableRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "preact/hooks";
import type { CommandData, FilteredCommandNames } from "../../../components/app_context";
import FAttribute from "../../../entities/fattribute";
import FNote from "../../../entities/fnote";
import contextMenu from "../../../menus/context_menu";
import attribute_parser, { Attribute } from "../../../services/attribute_parser";
import attribute_renderer from "../../../services/attribute_renderer";
import attributes from "../../../services/attributes";
import froca from "../../../services/froca";
import { t } from "../../../services/i18n";
import server from "../../../services/server";
import link from "../../../services/link";
import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete";
import note_create from "../../../services/note_create";
import server from "../../../services/server";
import { isIMEComposing } from "../../../services/shortcuts";
import { escapeQuotes, getErrorMessage } from "../../../services/utils";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
import ActionButton from "../../react/ActionButton";
import CKEditor, { CKEditorApi } from "../../react/CKEditor";
import { useLegacyImperativeHandlers, useLegacyWidget, useTooltip, useTriliumEvent, useTriliumOption } from "../../react/hooks";
import FAttribute from "../../../entities/fattribute";
import attribute_renderer from "../../../services/attribute_renderer";
import FNote from "../../../entities/fnote";
import AttributeDetailWidget from "../../attribute_widgets/attribute_detail";
import attribute_parser, { Attribute } from "../../../services/attribute_parser";
import ActionButton from "../../react/ActionButton";
import { escapeQuotes, getErrorMessage } from "../../../services/utils";
import link from "../../../services/link";
import { isIMEComposing } from "../../../services/shortcuts";
import froca from "../../../services/froca";
import contextMenu from "../../../menus/context_menu";
import type { CommandData, FilteredCommandNames } from "../../../components/app_context";
import { AttributeType } from "@triliumnext/commons";
import attributes from "../../../services/attributes";
import note_create from "../../../services/note_create";
type AttributeCommandNames = FilteredCommandNames<CommandData>;
@ -52,7 +53,7 @@ const mentionSetup: MentionFeed[] = [
return names.map((name) => {
return {
id: `#${name}`,
name: name
name
};
});
},
@ -66,7 +67,7 @@ const mentionSetup: MentionFeed[] = [
return names.map((name) => {
return {
id: `~${name}`,
name: name
name
};
});
},
@ -85,9 +86,10 @@ interface AttributeEditorProps {
}
export interface AttributeEditorImperativeHandlers {
save: () => Promise<void>;
refresh: () => void;
renderOwnedAttributes: (ownedAttributes: FAttribute[]) => Promise<void>;
save(): Promise<void>;
refresh(): void;
focus(): void;
renderOwnedAttributes(ownedAttributes: FAttribute[]): Promise<void>;
}
export default function AttributeEditor({ api, note, componentId, notePath, ntxId, hidden }: AttributeEditorProps) {
@ -124,7 +126,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
// attrs are not resorted if position changes after the initial load
ownedAttributes.sort((a, b) => a.position - b.position);
let htmlAttrs = ("<p>" + (await attribute_renderer.renderAttributes(ownedAttributes, true)).html() + "</p>");
let htmlAttrs = (`<p>${(await attribute_renderer.renderAttributes(ownedAttributes, true)).html()}</p>`);
if (saved) {
lastSavedContent.current = htmlAttrs;
@ -162,7 +164,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
wrapperRef.current.style.opacity = "0";
setTimeout(() => {
if (wrapperRef.current) {
wrapperRef.current.style.opacity = "1"
wrapperRef.current.style.opacity = "1";
}
}, 100);
}
@ -252,7 +254,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
if (notePath) {
result = await note_create.createNoteWithTypePrompt(notePath, {
activate: false,
title: title
title
});
}
@ -274,7 +276,8 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
useImperativeHandle(api, () => ({
save,
refresh,
renderOwnedAttributes: (attributes) => renderOwnedAttributes(attributes as FAttribute[], false)
renderOwnedAttributes: (attributes) => renderOwnedAttributes(attributes as FAttribute[], false),
focus: () => editorRef.current?.focus()
}), [ save, refresh, renderOwnedAttributes ]);
return (
@ -404,7 +407,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
{attributeDetailWidgetEl}
</>
)
);
}
function getPreprocessedData(currentValue: string) {

View File

@ -22,12 +22,13 @@
margin-bottom: 20px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.attachment-title {
font-size: 1.1rem;
margin: 0;
a {
color: inherit !important;
}
@ -72,8 +73,8 @@
.attachment-detail-wrapper.list-view {
border-radius: 12px;
background-color: var(--card-background-color);
padding: 0 6px;
background-color: var(--card-background-color);
padding: 6px 6px 0 6px;
box-shadow: var(--card-box-shadow);
}
@ -126,15 +127,6 @@
/* #endregion */
/* #region Attachment actions */
.attachment-actions {
width: 35px;
height: 35px;
}
.attachment-actions .select-button {
position: relative;
top: 3px;
}
.attachment-actions .dropdown-menu {
width: 20em;
@ -152,4 +144,4 @@
background-color: transparent !important;
pointer-events: none; /* makes it unclickable */
}
/* #endregion */
/* #endregion */

View File

@ -0,0 +1,114 @@
.old-layout-illustration {
width: 170px;
height: 130px;
border: 1px solid var(--main-border-color);
border-radius: 6px;
display: flex;
background: var(--root-background);
overflow: hidden;
.launcher-pane {
width: 10%;
background: var(--launcher-pane-vert-background-color);
display: flex;
flex-direction: column;
align-items: center;
padding: 1px 0;
svg {
margin-top: 1px;
margin-bottom: 5px;
}
.bx {
margin: 4px 0;
font-size: 12px;
opacity: 0.5;
}
}
.tree {
width: 20%;
font-size: 4px;
padding: 12px 5px;
overflow: hidden;
flex-shrink: 0;
filter: blur(1px);
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
}
.main {
display: flex;
flex-direction: column;
flex-grow: 1;
font-size: 8px;
.tab-bar {
height: 10px;
flex-shrink: 0;
}
.content {
background-color: var(--main-background-color);
flex-grow: 1;
border-top-left-radius: 6px;
display: flex;
flex-direction: column;
min-height: 0;
.title-bar {
display: flex;
align-items: center;
font-size: 14px;
padding: 5px;
.title {
flex-grow: 1;
}
}
.ribbon {
padding: 0 5px;
.bx {
font-size: 10px;
}
.ribbon-header {
display: flex;
}
.ribbon-body {
height: 20px;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 6px;
margin: 1px 0;
}
}
.content-inner {
font-size: 6px;
overflow: hidden;
padding: 5px;
opacity: 0.5;
filter: blur(1px);
}
.status-bar {
background-color: var(--left-pane-background-color);
flex-shrink: 0;
padding: 0 2px;
display: flex;
&> .status-bar-breadcrumb {
flex-grow: 1;
}
}
}
}
}

View File

@ -1,18 +1,24 @@
import "./appearance.css";
import { FontFamily, OptionNames } from "@triliumnext/commons";
import { useEffect, useState } from "preact/hooks";
import { t } from "../../../services/i18n";
import { isElectron, isMobile, reloadFrontendApp, restartDesktopApp } from "../../../services/utils";
import Column from "../../react/Column";
import FormRadioGroup from "../../react/FormRadioGroup";
import FormSelect, { FormSelectWithGroups } from "../../react/FormSelect";
import { useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
import OptionsSection from "./components/OptionsSection";
import server from "../../../services/server";
import { isElectron, isMobile, reloadFrontendApp, restartDesktopApp } from "../../../services/utils";
import { VerticalLayoutIcon } from "../../buttons/global_menu";
import Button from "../../react/Button";
import Column from "../../react/Column";
import FormCheckbox from "../../react/FormCheckbox";
import FormGroup from "../../react/FormGroup";
import { FontFamily, OptionNames } from "@triliumnext/commons";
import FormTextBox, { FormTextBoxWithUnit } from "../../react/FormTextBox";
import FormRadioGroup from "../../react/FormRadioGroup";
import FormSelect, { FormSelectWithGroups } from "../../react/FormSelect";
import FormText from "../../react/FormText";
import Button from "../../react/Button";
import FormTextBox, { FormTextBoxWithUnit } from "../../react/FormTextBox";
import { useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
import Icon from "../../react/Icon";
import OptionsSection from "./components/OptionsSection";
import RadioWithIllustration from "./components/RadioWithIllustration";
import RelatedSettings from "./components/RelatedSettings";
const MIN_CONTENT_WIDTH = 640;
@ -30,7 +36,7 @@ const BUILTIN_THEMES: Theme[] = [
{ val: "auto", title: t("theme.auto_theme") },
{ val: "light", title: t("theme.light_theme") },
{ val: "dark", title: t("theme.dark_theme") }
]
];
interface FontFamilyEntry {
value: FontFamily;
@ -84,6 +90,7 @@ export default function AppearanceSettings() {
return (
<div>
{!isMobile() && <LayoutSwitcher />}
{!isMobile() && <LayoutOrientation />}
<ApplicationTheme />
{overrideThemeFonts === "true" && <Fonts />}
@ -102,7 +109,99 @@ export default function AppearanceSettings() {
}
]} />
</div>
)
);
}
function LayoutSwitcher() {
const [ newLayout, setNewLayout ] = useTriliumOptionBool("newLayout");
return (
<OptionsSection title={t("settings_appearance.ui")}>
<RadioWithIllustration
currentValue={newLayout ? "new-layout" : "old-layout"}
onChange={async newValue => {
await setNewLayout(newValue === "new-layout");
reloadFrontendApp();
}}
values={[
{ key: "old-layout", text: t("settings_appearance.ui_old_layout"), illustration: <LayoutIllustration /> },
{ key: "new-layout", text: t("settings_appearance.ui_new_layout"), illustration: <LayoutIllustration isNewLayout /> }
]}
/>
</OptionsSection>
);
}
function LayoutIllustration({ isNewLayout }: { isNewLayout?: boolean }) {
return (
<div className="old-layout-illustration">
<div className="launcher-pane">
<VerticalLayoutIcon />
<Icon icon="bx bx-send" />
<Icon icon="bx bx-file-blank" />
<Icon icon="bx bx-search" />
</div>
<div className="tree">
<ul>
<li>Options</li>
<ul>
<li>Appearance</li>
<li>Shortcuts</li>
<li>Text Notes</li>
<li>Code Notes</li>
<li>Images</li>
</ul>
</ul>
</div>
<div className="main">
<div className="tab-bar" />
<div className="content">
<div className="title-bar">
<Icon icon="bx bx-note" />
<span className="title">Title</span>
<Icon icon="bx bx-dock-right" />
</div>
{!isNewLayout && <div className="ribbon">
<div className="ribbon-header">
<Icon icon="bx bx-slider" />
<Icon icon="bx bx-list-check" />
<Icon icon="bx bx-list-plus" />
<Icon icon="bx bx-collection" />
</div>
<div className="ribbon-body" />
</div>}
{isNewLayout && <div className="note-title-actions">
<Icon icon="bx bx-chevron-down" />{" "}Promoted attributes
</div>}
<div className="content-inner">
This is a "demo" document packaged with Trilium to showcase some of its features and also give you some ideas on how you might structure your notes. You can play with it, and modify the note content and tree structure as you wish.
</div>
{isNewLayout && <div className="status-bar">
<div className="status-bar-breadcrumb">
<Icon icon="bx bx-home" />
<Icon icon="bx bx-chevron-right" />
Note
<Icon icon="bx bx-chevron-right" />
Note
</div>
<div className="status-bar-actions">
<Icon icon="bx bx-list-check" />
<Icon icon="bx bx-info-circle" />
</div>
</div>}
</div>
</div>
</div>
);
}
function LayoutOrientation() {
@ -141,7 +240,7 @@ function ApplicationTheme() {
setThemes([
...BUILTIN_THEMES,
...userThemes
])
]);
});
}, []);
@ -162,7 +261,7 @@ function ApplicationTheme() {
</FormGroup>
</div>
</OptionsSection>
)
);
}
function Fonts() {
@ -245,7 +344,7 @@ function ElectronIntegration() {
<Button text={t("electron_integration.restart-app-button")} onClick={restartDesktopApp} />
</OptionsSection>
)
);
}
function Performance() {
@ -271,7 +370,7 @@ function Performance() {
{isElectron() && <SmoothScrollEnabledOption />}
</OptionsSection>
</OptionsSection>;
}
function SmoothScrollEnabledOption() {
@ -280,7 +379,7 @@ function SmoothScrollEnabledOption() {
return <FormCheckbox
label={`${t("ui-performance.enable-smooth-scroll")} ${t("ui-performance.app-restart-required")}`}
currentValue={smoothScrollEnabled} onChange={setSmoothScrollEnabled}
/>
/>;
}
function MaxContentWidth() {
@ -302,10 +401,10 @@ function MaxContentWidth() {
</Column>
<FormCheckbox label={t("max_content_width.centerContent")}
currentValue={centerContent}
onChange={setCenterContent} />
currentValue={centerContent}
onChange={setCenterContent} />
</OptionsSection>
)
);
}
function RibbonOptions() {
@ -318,5 +417,5 @@ function RibbonOptions() {
currentValue={editedNotesOpenInRibbon} onChange={setEditedNotesOpenInRibbon}
/>
</OptionsSection>
)
);
}

View File

@ -8,6 +8,7 @@
.option-row > label {
width: 40%;
margin-bottom: 0 !important;
flex-shrink: 0;
}
.option-row > select,
@ -26,4 +27,4 @@
.option-row.centered {
justify-content: center;
}
}

View File

@ -0,0 +1,28 @@
.options-section .radio-with-illustration {
list-style-type: none;
margin-bottom: 0;
padding: 0;
display: flex;
gap: 1.5em;
justify-content: center;
figure {
figcaption {
margin-top: 0.25em;
text-align: center;
}
margin-bottom: 0;
&> .illustration {
border-radius: 6px;
padding: 3px;
cursor: pointer;
}
}
&> .selected figure > .illustration {
outline: 3px solid var(--input-focus-outline-color);
}
}

View File

@ -0,0 +1,38 @@
import "./RadioWithIllustration.css";
import clsx from "clsx";
import { ComponentChild } from "preact";
interface RadioWithIllustrationProps {
values: {
key: string;
text: string;
illustration: ComponentChild;
}[];
currentValue: string;
onChange(newValue: string): void;
}
export default function RadioWithIllustration({ currentValue, onChange, values }: RadioWithIllustrationProps) {
return (
<ul className="radio-with-illustration">
{values.map(value => (
<li
key={value.key}
className={clsx(value.key === currentValue && "selected")}
>
<figure>
<div
className="illustration"
role="button"
onClick={() => onChange(value.key)}
>
{value.illustration}
</div>
<figcaption>{value.text}</figcaption>
</figure>
</li>
))}
</ul>
);
}

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,218 @@
<p>The <em>New layout</em> is a series of UI/UX changes that were introduced
in v0.101.0 that heavily change both existing UI elements, as well as adding
some new ones. The goal of this new layout is to modernize the application
and to make it more intuitive but at the same time to reduce clutter.</p>
<h2>Newly introduced features</h2>
<h3>Status bar</h3>
<p>At the bottom of the window there is a new bar called the <em>Status bar</em>.
This bar houses multiple items such as the Breadcrumb navigation and information
and settings about the current note, such as the <a href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_veGu4faJErEM">content language</a> and&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/_help_zEY4DaJG4YT5">Attributes</a>.</p>
<p>For more information, consult the <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/IjZS7iK5EXtb/_help_AlJ73vBCjWDw">dedicated page</a>.</p>
<figure
class="image">
<img style="aspect-ratio:1150/27;" src="4_New Layout_image.png"
width="1150" height="27">
</figure>
<h3>Inline title</h3>
<p>In previous versions of Trilium, the title bar was fixed at all times.
In the new layout, there is both a fixed title bar and one that scrolls
with the text. The newly introduced title is called the <em>Inline title</em> and
it displays the title in a larger font, while also displaying additional
information such as the creation and the modification date.</p>
<p>Whenever the title is scrolled past, the fixed title is shown instead.</p>
<p>This only affects&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_iPIMuisry3hd">Text</a>&nbsp;and&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_6f9hih2hXXZk">Code</a>&nbsp;notes. Note types that take the entirety of the screen such
as&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_grjYqerjn243">Canvas</a>&nbsp;will
always have only the fixed title bar.</p>
<p>Depending on the note type, the inline title will also present some more
interactive options such as being able to switch the note type (see below).</p>
<figure
class="image">
<img style="aspect-ratio:899/122;" src="New Layout_image.png"
width="899" height="122">
<figcaption>The <em>Inline title</em>, which is displayed at the top of the note and
can be scrolled past.</figcaption>
</figure>
<figure class="image">
<img style="aspect-ratio:910/104;" src="3_New Layout_image.png"
width="910" height="104">
<figcaption>The fixed title bar. The title only appears after scrolling past the <em>Inline title</em>.</figcaption>
</figure>
<h3>New note type switcher</h3>
<p>When a new&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_iPIMuisry3hd">Text</a>&nbsp;or&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_6f9hih2hXXZk">Code</a>&nbsp;note is created, a note type switcher will appear below
the <em>Inline title</em>. Apart from changing the note type, it's also
possible to apply a <a href="#root/pOsGYCXsbNQG/tC7s2alapj8V/_help_KC1HB96bqqHX">template</a>.</p>
<p>The switcher will disappear as soon as a text is entered.</p>
<p>
<img src="5_New Layout_image.png" width="735" height="143">
</p>
<h3>Note badges</h3>
<p>Note badges appear near the fixed note title and indicate important information
about the note such as whether it is read-only. Some of the badges are
also interactive.</p>
<figure class="image">
<img style="aspect-ratio:910/49;" src="2_New Layout_image.png"
width="910" height="49">
</figure>
<p>The following badges are available:</p>
<ul>
<li data-list-item-id="e681fff45ecdebbf3a5c6fc8398b4e8b1"><strong>Read-only badge</strong>, which will be shown if the note is not
editable due to either automatic read-only or manual read-only. Clicking
on the badge will temporarily edit the note (similar to the Edit <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_XpOYSgsLkTJy">floating button</a>).</li>
<li
data-list-item-id="ee8bd349f3feb3df5069b31345e627985"><strong>Share badge</strong>, which will indicate that the current note
is shared. The badge will also indicate if the share is on the local network
(for the desktop application without&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/Otzi9La2YAUX/_help_cbkrhQjrkKrh">Synchronization</a>&nbsp;set
up) or publicly accessible (for the server).&nbsp;</li>
<li data-list-item-id="e8f5a122ba42c453bf36eb4f0064d570d"><strong>Web clip badge</strong>, which will indicate if the note was clipped
using the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/Otzi9La2YAUX/_help_MtPxeAWVAzMg">Web Clipper</a>.
The badge acts as a link, so it can be clicked on to navigate to the page
or right clicked for more options.</li>
<li data-list-item-id="e4f52532a9ae7b5ff88cc081da81049ad"><strong>Execute badge</strong>, for <a href="#root/pOsGYCXsbNQG/_help_CdNpE2pqjmI6">scripts</a> or
<a
href="#root/pOsGYCXsbNQG/tC7s2alapj8V/wX4HbRucYSDD/oyIAJ9PvvwHX/_help_YKWqdJhzi2VY">saved SQL queries</a>which have an execute button or a description.</li>
</ul>
<p>Some of these badges replace the dedicated panels at the top of the note.</p>
<h3>Collapsible sections</h3>
<figure class="image">
<img style="aspect-ratio:496/265;" src="1_New Layout_image.png"
width="496" height="265">
</figure>
<p>The following sections have been made collapsible:</p>
<ul>
<li class="ck-list-marker-italic" data-list-item-id="e1e7527a923c6adc4b25a81c836aa54bb"><em>Promoted Attributes</em>
<ul>
<li data-list-item-id="e81342adbccbbbe0c186887eb0c96f6c7">For full-height notes such as&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_grjYqerjn243">Canvas</a>,
the promoted attributes are collapsed by default to make room.</li>
<li
data-list-item-id="e6c14c0f102892bc42cc6f503d901b1f0">The keyboard shortcut previously used to trigger the promoted attributes
ribbon tab (which was no longer working) has been repurposed to toggle
the promoted attributes instead.</li>
</ul>
</li>
<li data-list-item-id="e11bfe716c8b0b09f68d9c7cc99c93e03"><em>Edited Notes</em>, which appears for&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/tC7s2alapj8V/5668rwcirq1t/_help_l0tKav7yLHGF">Day Notes</a>&nbsp;is
now shown underneath the title.
<ul>
<li data-list-item-id="e24a6e624c699432c4d812b34f25a137a">Whether the section is collapsed or not depends on the choice in&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_4TIF1oA4VQRO">Options</a>&nbsp;→ Appearance.</li>
</ul>
</li>
<li data-list-item-id="e16420a44b06dbe4810f6ab5087bb7f09"><em>Search Properties</em>, which appears for the full&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/wArbEsdSae6g/_help_eIg8jdvaoNNd">Search</a>&nbsp;and&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_m523cpzocqaD">Saved Search</a>.</li>
</ul>
<h2>Changing to the existing layout</h2>
<h3>Removal of the ribbon</h3>
<p>The most significant change is the removal of the ribbon. All the actions
and options from the ribbon were integrated in other places in the application.</p>
<p>Here's how all the different tabs that were once part of the ribbon are
now available in the new layout:</p>
<ul>
<li data-list-item-id="e23a8f5ef92bc84b978897596a0f311d5">“Formatting toolbar” was relocated to the top of the page.
<ul>
<li data-list-item-id="eaff03a54c5d839b1cf491b873e4ac417">Instead of having one per split, now there is a single formatting toolbar
per tab. This allows more space for the toolbar items.</li>
</ul>
</li>
<li data-list-item-id="e55efa7b7fa563c7a792952d0a00f69c7">“Owned attributes” and “Inherited attributes” were merged and moved to
the status bar region (displayed one above the other).</li>
<li data-list-item-id="eaf2afbfe470834eca4dc7269b7310964">“Basic Properties” were integrated in the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_8YBEPzcpUgxw">Note buttons</a>&nbsp;menu.
<ul>
<li data-list-item-id="e44ec78344d9a6c8966b0c9c68ae79d79">The only exception here is the Language combo box which can now be found
in the status bar (top-right of the screen).</li>
</ul>
</li>
<li data-list-item-id="ea5cf9c168f3291f8247ce89924472c33">“File” and “Image” tabs
<ul>
<li data-list-item-id="e32291890baede8270361747c20724271">The buttons were moved to the right of the note title, as dedicated entries
in&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_8YBEPzcpUgxw">Note buttons</a>.</li>
<li
data-list-item-id="e4e0b374eeaa3d5cee3ec10c2f0f51e1c">The info section has been merged into the <em>Note info </em>section of
the status bar.</li>
</ul>
</li>
<li data-list-item-id="ea542c02972f94d40cd87ed5f971db880">Edited notes
<ul>
<li data-list-item-id="e628eec12558a51865f1b4f14e9f3fec8">Moved underneath the title, displayed under a collapsible area and the
notes are represented as badges/chips.</li>
<li data-list-item-id="ed819af0e25679551eb56d66bd81cf431">Whether the section is expanded or collapsed depends on the “Edited Notes
ribbon tab will automatically open on day notes” setting from Options →
Appearance.</li>
</ul>
</li>
<li data-list-item-id="eb5f31f734338d9f6ada1329849ac9652">Search definition tab
<ul>
<li data-list-item-id="ee00a5cb8f4d7920a236fb95f34d93dbf">Moved underneath the title under a collapsible area.</li>
<li data-list-item-id="e310963b6aafce5d8e75fd65810087d0b">Expanded by default for new searches, collapsed for saved searches.</li>
</ul>
</li>
<li data-list-item-id="e7713cf206015ff83cdc8569fe22301a4">The Note map is now available in the Note actions menu.
<ul>
<li data-list-item-id="e507702eef9a13e0fc6b88da4e8b4b280">Instead of opening into a panel in the ribbon, the note map now opens
in a side split (similar to the in-app help).</li>
</ul>
</li>
<li data-list-item-id="e36fac289364571fe38384d913a9b82f6">“Note info” tab was moved to a small (i) icon in the status bar.</li>
<li
data-list-item-id="ec77db0f7e17da59142a53738bd6e5dde">“Similar notes” tab
<ul>
<li data-list-item-id="e82f29a4705ba7ef67cfa7871d09d55ec">Moved to the status bar, by going to the “Note info” section and pressing
the button to show similar notes.</li>
<li data-list-item-id="e4824fa59a2e7b078c235fdf191809693">Displayed as a fixed panel, similar to the attributes.</li>
</ul>
</li>
<li data-list-item-id="e51662a87308396697ebe51f8dad842f9">The Collection properties tab were relocated under the note title and
grouped into:
<ul>
<li data-list-item-id="e5355d95afa06871493dd0633eeb21342">A combo box to quickly switch between views.</li>
<li data-list-item-id="eebd3911c5dd2fc770534ae8fc7d2b47e">Individual settings for the current view in a submenu.</li>
</ul>
</li>
<li data-list-item-id="eae9dae6a2a5b74aaea84d818d1334fc9">Some smaller ribbon tabs were converted to badges that appear near the
note title in the breadcrumb section:
<ul>
<li data-list-item-id="ea7f24c544b22fda5ef7d513410454738">Original URL indicator for clipped web pages (<code spellcheck="false">#pageUrl</code>).</li>
<li
data-list-item-id="e43d835ca69e35e71203f64efd2fd12c2">SQL and script execute buttons.</li>
</ul>
</li>
</ul>
<aside class="admonition note">
<p>The ribbon keyboard shortcuts (e.g. <code spellcheck="false">toggleRibbonTabClassicEditor</code>)
have been repurposed to work on the new layout, where they will toggle
the appropriate panel.</p>
</aside>
<h3>Removal of the floating buttons</h3>
<p>Most of the buttons were relocated to the right of the note title, in
the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_8YBEPzcpUgxw">Note buttons</a>&nbsp;area,
with the exception of:</p>
<ul>
<li data-list-item-id="ec0623b0ce81f563d1c58d0d17de7c517">The Edit button is displayed near the note title, as a badge.</li>
<li
data-list-item-id="e0f1d6b12f8ebaf09d070aa9c86850726"><em>Backlinks</em> is displayed in the status bar. When clicked, the same
list of backlinks is displayed.</li>
<li data-list-item-id="e9693ac78b6cb054e6e492e464abd7c16">Relation map zoom buttons are now part of the relation map itself.</li>
<li
data-list-item-id="e4f2e79a6ea41e31ffe58e6c25a75216a">Export image to PNG/SVG are now in the Note actions menu, in the <em>Export as image</em> option.</li>
</ul>
<h2>How to toggle the new layout</h2>
<p>Starting with v0.101.0, this new layout is enabled by default. It is possible
to fall back to the old layout by going to&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_4TIF1oA4VQRO">Options</a>&nbsp;
Appearance and selecting <em>Old layout</em>.</p>
<aside class="admonition important">
<p>Since a new layout was introduced, this becomes the standard one. The <em>Old layout</em> is
considered deprecated and will not receive new features (for example, the
breadcrumb) as we focus on the new one. At some point the old layout will
be removed entirely, as maintaining two layouts with major differences
creates a maintenance burden.</p>
</aside>

View File

@ -0,0 +1,55 @@
<figure class="image">
<img style="aspect-ratio:1150/27;" src="Breadcrumb_image.png"
width="1150" height="27">
</figure>
<p>The breadcrumb allows quickly viewing the note hierarchy of the current
note and navigating through it.</p>
<p>It is part of the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/IjZS7iK5EXtb/_help_AlJ73vBCjWDw">Status bar</a>,
displayed in the bottom-left of the screen.</p>
<h2>Layout and Interaction</h2>
<ul>
<li data-list-item-id="eeca71aa25c6fc24ccea32b3fd91c7d03">If a note or workspace is hoisted, a badge will appear on the left-most
side.
<ul>
<li data-list-item-id="e0c5e4b89d1a4f0fccfd64fd5a5c401de">Clicking on the badge will un-hoist the note/workspace.</li>
</ul>
</li>
<li data-list-item-id="e3f4bcf3d23cc23094991e4b982fab65d">The left-most icon represents the root note, or the hoisted note or workspace.
<ul>
<li data-list-item-id="e0acc69822ac800e00f15286d69150011">Clicking the icon will jump to the root note.</li>
<li data-list-item-id="ea7ad114455b8e77f527cab5064b24f62">Right clicking the icon will display a menu that allows opening the note
in a new tab, split, etc.</li>
</ul>
</li>
<li data-list-item-id="e1e81c0cc1c8ca8ae94e3861e2e7ba104">Each segment shows the title of a note in the current note hierarchy.
<ul>
<li data-list-item-id="e42e1001c318c8b55ec25d44649f116f6">Clicking the icon will jump to that note.</li>
<li data-list-item-id="ebd05c3d7be7f994f229d48131ccd79bb">Right clicking will open a menu with multiple options such as opening
the note in a different tab/split/window, hoisting, moving/cloning the
note, duplicating as well as changing the color of the note.</li>
</ul>
</li>
<li data-list-item-id="ed8111f04712d97db418a8ba507cf1cf4">Clicking the arrow next to each segment will reveal the child notes of
the segment on the left.
<ul>
<li data-list-item-id="e9689b35aa5224f861cf61e63fc3abd96">Clicking on an icon will navigate to that particular note.</li>
<li data-list-item-id="ea008f6126b2d2dc03e9795fa89a8fe0c">It's also possible to create a new child note from here.</li>
<li data-list-item-id="e5d56879e41e3eba28d89999ac208cf63">The menu can optionally hide the archived notes.</li>
</ul>
</li>
<li data-list-item-id="ed65ebfd673ab4cc6eb2e2a227f0caa95">If the current note is deep within a hierarchy, the segments will collapse
into a […] button in order not to occupy too much space.
<ul>
<li data-list-item-id="e3081db77d1acea4568da8d69d199171b">Clicking this button will display each collapsed entry as a menu item.
Clicking on it will navigate to that particular note.</li>
</ul>
</li>
<li data-list-item-id="e17205300d9c0018d65cf0f0fc92343bf">Right clicking on an empty space to the right of the breadcrumb (before
the other status bar items) will reveal another menu that allows:
<ul>
<li data-list-item-id="e80899972041248ee12d26fb7065772a3">Toggling whether archived notes are displayed in the breadcrumb and in
the note tree.</li>
<li data-list-item-id="ef692f737f9df3df6d77b180ade9ecd45">Copying the current note path to clipboard.</li>
</ul>
</li>
</ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,53 @@
<p>The status bar displays information about the current note and allows
changing settings related to it such as configuring the language or attributes.</p>
<h2>Layout and interaction</h2>
<p>On the left side, the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/IjZS7iK5EXtb/_help_I6p2a06hdnL6">Breadcrumb</a>&nbsp;is
displayed which indicates the current note as well as its parent notes
and allows for quick navigation throughout the hierarchy.</p>
<p>On the right side, specific sections will show depending on the type of
the current note.</p>
<ol>
<li data-list-item-id="ef3e251512bf6573cca80079d8efd08ec">For code notes, the language mode of the note is indicated (e.g. JavaScript,
plain text), as well as allowing easy switching to another mode.</li>
<li
data-list-item-id="eb5c80ff8ad9e92fd95cae059af10f1b9">For text notes, the content language is displayed and can be changed,
thus configuring the spell-check and the right-to-left support.
<ol>
<li data-list-item-id="eb8a685a73d822de440eacbf53b361d80">Note that this applies to the entire note and not the selection, unlike
some text editors.</li>
</ol>
</li>
<li data-list-item-id="eec1c0804323b8b841538dd493654e6ac">If a note is placed in multiple places in the tree (cloned), the number
of the note paths will be displayed.
<ol>
<li data-list-item-id="e5975fc63b51ceaee4639a4185025c912">Clicking it will reveal the full list of note paths and a button to place
it somewhere else.</li>
</ol>
</li>
<li data-list-item-id="e9644f8d1759a085172efe05ca9de454e">If a note has attachments, their number will be displayed.
<ol>
<li data-list-item-id="e1f84e230de4009fc971a999330eee2d2">Clicking on it will reveal the list of attachments in a new tab.</li>
</ol>
</li>
<li data-list-item-id="eae7faacee8099500ffeed87bcd10d48c">If a note is linked from other text notes (backlinks), the number of backlinks
will be displayed.
<ol>
<li data-list-item-id="e23765b409994cae53cc3085abdb8c6f4">Clicking on it will show the list of notes that link to this note, as
well as an excerpt of where the note is referenced.</li>
</ol>
</li>
</ol>
<p>Regardless of note type, the following items will always be displayed
if there is a note:</p>
<ol>
<li data-list-item-id="eeba7911e7138db1df76d76712b360b45">Note info, which displays:
<ol>
<li data-list-item-id="ea184596335824cc6cdf737949ee4be0e">The creation/modification date of the note.</li>
<li data-list-item-id="e785134c29b68229dd42afab43413cd70">The type and MIME of the note.</li>
<li data-list-item-id="e06b3ee88bd4ae7da4182e3747264223e">The note ID.</li>
<li data-list-item-id="e896b429faa3a7b9e4ddff8abb2ff0795">An estimation of the note size of the note itself and its children.</li>
<li
data-list-item-id="e2749abcfbc46d6d8cab5b7f0b3fbb161">A button to show Similar notes.</li>
</ol>
</li>
</ol>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -3,10 +3,15 @@
<img src="Note buttons_image.png">
</p>
<ul>
<li>The Note Revisions button displays the&nbsp;<a href="#root/_help_vZWERwf8U3nx">Note Revisions</a>&nbsp;for
<li data-list-item-id="e9bebdee3f029e4352aaa066ccc75f3cc">The Note Revisions button displays the&nbsp;<a href="#root/_help_vZWERwf8U3nx">Note Revisions</a>&nbsp;for
that particular note.</li>
<li>The contextual menu offers commands for the note or its subtree, such
<li data-list-item-id="ed4fd4715e47307a0808ccb0481660303">The contextual menu offers commands for the note or its subtree, such
as import, export, viewing the&nbsp;<a href="#root/_help_4FahAwuGTAwC">Note source code</a>&nbsp;or&nbsp;
<a
href="#root/_help_0vhv7lsOLy82">Attachments</a>.</li>
</ul>
</ul>
<p>On the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_IjZS7iK5EXtb">New Layout</a>,
the button area is populated by some more buttons that are specific to
the current note. For example, for Image and&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/_help_W8vYD3Q1zjCR">File</a>&nbsp;notes,
the download and copy buttons were relocated there.</p>

View File

@ -7,98 +7,94 @@
adjusted.</p>
<h2>How it works</h2>
<p>When first creating a collection of <em>Board</em> type, a few subnotes
will be created, each having a <code spellcheck="false">#status</code> label
set. The board then groups each note by the value of the status attribute.</p>
will be created, each having a <code>#status</code> label set. The board
then groups each note by the value of the status attribute.</p>
<p>Notes are displayed recursively, so even the child notes of the child
notes will be displayed. However, unlike the&nbsp;<a class="reference-link"
href="#root/_help_2FvYrpmOXm29">Table</a>, the notes are not displayed in a hierarchy.</p>
<h2>Interaction</h2>
<h3>Working with columns</h3>
<ul>
<li data-list-item-id="eed75fe2d70ba712457da18d13b91fa16">Create a new column by pressing <em>Add Column</em> near the last column.
<li>Create a new column by pressing <em>Add Column</em> near the last column.
<ul>
<li data-list-item-id="ef2cf2654ff26b4f04aabe7aea447ba04">Once pressed, a text box will be displayed to set the name of the column.
<li>Once pressed, a text box will be displayed to set the name of the column.
Press <kbd>Enter</kbd> to confirm, or <kbd>Escape</kbd> to dismiss.</li>
</ul>
</li>
<li data-list-item-id="ecf404437de7a7126ec6e74428386c644">To reorder a column, simply hold the mouse over the title and drag it
<li>To reorder a column, simply hold the mouse over the title and drag it
to the desired position.</li>
<li data-list-item-id="ebe673a03d3e54db84bad22ac06caf1bc">To delete a column, right click on its title and select <em>Delete column</em>.</li>
<li
data-list-item-id="e7c4c69d4c1ef862d13c886c29fccc0e2">To rename a column, click on the note title.
<li>To delete a column, right click on its title and select <em>Delete column</em>.</li>
<li>To rename a column, click on the note title.
<ul>
<li data-list-item-id="ea8ee1c0d6783c0c64fde427a7334f703">Press Enter to confirm.</li>
<li data-list-item-id="e85724e2b224df1670b08a418e560b05d">Upon renaming a column, the corresponding status attribute of all its
<li>Press Enter to confirm.</li>
<li>Upon renaming a column, the corresponding status attribute of all its
notes will be changed in bulk.</li>
</ul>
</li>
<li data-list-item-id="e2836e9a5f492795750c949f1f060f548">If there are many columns, use the mouse wheel to scroll.</li>
</li>
<li>If there are many columns, use the mouse wheel to scroll.</li>
</ul>
<h3>Working with notes</h3>
<ul>
<li data-list-item-id="efb7df180d7edb7e6c070bcfee5aa6595">Create a new note in any column by pressing <em>New item</em>
<li>Create a new note in any column by pressing <em>New item</em>
<ul>
<li data-list-item-id="e1cba0534a1bd351bad9a8eab629a2267">Enter the name of the note and press <kbd>Enter</kbd> or click away. To
<li>Enter the name of the note and press <kbd>Enter</kbd> or click away. To
dismiss the creation of a new note, simply press <kbd>Escape</kbd> or leave
the name empty.</li>
<li data-list-item-id="ecd0181ef17ca7eea5c4f5864472bb4b3">Once created, the new note will have an attribute (<code spellcheck="false">status</code> label
<li>Once created, the new note will have an attribute (<code>status</code> label
by default) set to the name of the column.</li>
</ul>
</li>
<li data-list-item-id="ee23b9bd9fedee464cb70079e80379b12">To open the note, simply click on it.</li>
<li data-list-item-id="ef6b267a604ab3dedcce739bda9928c36">To change the title of the note directly from the board, hover the mouse
<li>To open the note, simply click on it.</li>
<li>To change the title of the note directly from the board, hover the mouse
over its card and press the edit button on the right.</li>
<li data-list-item-id="ebbe903cc36e703cf676e988a5b58d950">To change the state of a note, simply drag a note from one column to the
<li>To change the state of a note, simply drag a note from one column to the
other to change its state.</li>
<li data-list-item-id="e41960c677e9041fcf07692b44e70b5af">The order of the notes in each column corresponds to their position in
<li>The order of the notes in each column corresponds to their position in
the tree.
<ul>
<li data-list-item-id="e0868bc9825cdef09da3fc03e873c47d7">It's possible to reorder notes simply by dragging them to the desired
<li>It's possible to reorder notes simply by dragging them to the desired
position within the same columns.</li>
<li data-list-item-id="e0706409ea69226ec62e3364d85001697">It's also possible to drag notes across columns, at the desired position.</li>
<li>It's also possible to drag notes across columns, at the desired position.</li>
</ul>
</li>
<li data-list-item-id="e5ad1e7155fc0100222f460ef9feb6b41">For more options, right click on a note to display a context menu with
<li>For more options, right click on a note to display a context menu with
the following options:
<ul>
<li data-list-item-id="e1ce2217942aaa4c6b78b8c76a7f38dbb">Open the note in a new tab/split/window or quick edit.</li>
<li data-list-item-id="e707e47f9eede68e4546eb6b8a83e8a17">Move the note to any column.</li>
<li data-list-item-id="e3125b7d4859803621bad3d679339dab9">Insert a new note above/below the current one.</li>
<li data-list-item-id="ea16c75aba80bbcb50b3dd416cec09753">Archive/unarchive the current note.</li>
<li data-list-item-id="e5ea20c999a4f17c69ed4094d24a706f3">Delete the current note.</li>
<li>Open the note in a new tab/split/window or quick edit.</li>
<li>Move the note to any column.</li>
<li>Insert a new note above/below the current one.</li>
<li>Archive/unarchive the current note.</li>
<li>Delete the current note.</li>
</ul>
</li>
<li data-list-item-id="e568d17582bdddc191dfe89bb9aca89d5">If there are many notes within the column, move the mouse over the column
<li>If there are many notes within the column, move the mouse over the column
and use the mouse wheel to scroll.</li>
</ul>
<h3>Working with the note tree</h3>
<p>It's also possible to add items on the board using the&nbsp;<a class="reference-link"
href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>.</p>
<ol>
<li data-list-item-id="e921887a37d6dba75eb00782ac7c7e118">Select the desired note in the&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>.</li>
<li
data-list-item-id="efeec7811e055ff6465ed839bbba2f776">Hold the mouse on the note and drag it to the to the desired column.</li>
<li>Select the desired note in the&nbsp;<a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a>.</li>
<li>Hold the mouse on the note and drag it to the to the desired column.</li>
</ol>
<p>This works for:</p>
<ul>
<li data-list-item-id="e31561dca83d4b9598775e33d9c4a8396">Notes that are not children of the board, case in which a <a href="#root/_help_IakOLONlIfGI">clone</a> will
<li>Notes that are not children of the board, case in which a <a href="#root/_help_IakOLONlIfGI">clone</a> will
be created.</li>
<li data-list-item-id="e74f3978f78cb119c8ae4b0ec167f8683">Notes that are children of the board, but not yet assigned on the board.</li>
<li
data-list-item-id="e581a876b974f0e5f0381651496400d48">Notes that are children of the board, case in which they will be moved
<li>Notes that are children of the board, but not yet assigned on the board.</li>
<li>Notes that are children of the board, case in which they will be moved
to the new column.</li>
</ul>
<h3>Keyboard interaction</h3>
<p>The board view has mild support for keyboard-based navigation:</p>
<ul>
<li data-list-item-id="e956369914e25568591f1d3dda5ae970e">Use <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> to navigate between
<li>Use <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> to navigate between
column titles, notes and the “New item” button for each of the columns,
in sequential order.</li>
<li data-list-item-id="e5211444d02da23ac54a370bc1cced494">To rename a column or a note, press <kbd>F2</kbd> while it is focused.</li>
<li
data-list-item-id="e11a91b88f8a12237ef40ab9c32d9f8f8">To open a specific note or create a new item, press <kbd>Enter</kbd> while
<li>To rename a column or a note, press <kbd>F2</kbd> while it is focused.</li>
<li>To open a specific note or create a new item, press <kbd>Enter</kbd> while
it is focused.</li>
<li data-list-item-id="e34aabe77a5bce273c353c2400da91cee">To dismiss a rename of a note or a column, press <kbd>Escape</kbd>.</li>
<li>To dismiss a rename of a note or a column, press <kbd>Escape</kbd>.</li>
</ul>
<h2>Configuration</h2>
<h3>Displaying custom attributes</h3>
@ -112,37 +108,33 @@
href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a>). The easiest way to
add these is:</p>
<ol>
<li data-list-item-id="e63c976202ef9f633570f685d391b5e50">Go to board note.</li>
<li data-list-item-id="ea821edb6d448b1bde26f9d756b4b0fec">In the ribbon select <em>Owned Attributes</em> → plus button → <em>Add new label/relation definition</em>.</li>
<li
data-list-item-id="e94dd8b134591fe71e2dcea3506247df6">Configure the attribute as desired.</li>
<li data-list-item-id="ea08e72fd3555837459105e19c12c1e33">Check <em>Inheritable</em> to make it applicable to child notes automatically.</li>
<li>Go to board note.</li>
<li>In the ribbon select <em>Owned Attributes</em> → plus button → <em>Add new label/relation definition</em>.</li>
<li>Configure the attribute as desired.</li>
<li>Check <em>Inheritable</em> to make it applicable to child notes automatically.</li>
</ol>
<p>After creating the attribute, click on a note and fill in the promoted
attributes which should then reflect inside the board.</p>
<p>Of note:</p>
<ul>
<li data-list-item-id="eb9e8b5e12e3dc2f5410bc10ba091d552">Both promoted and non-promoted attribute definitions are supported. The
<li>Both promoted and non-promoted attribute definitions are supported. The
only difference is that non-promoted attributes don't have an “Alias” for
assigning a custom name.</li>
<li data-list-item-id="ee41e79b02872367b2c5f2c4f88c3da41">Both “Single value” and “Multi value” attributes are supported. In case
<li>Both “Single value” and “Multi value” attributes are supported. In case
of multi-value, a badge is displayed for every instance of the attribute.</li>
<li
data-list-item-id="eb4d6fdbc5f52e70263706b3f51d929e3">All label types are supported, including dates, booleans and URLs.</li>
<li
data-list-item-id="ec141a7d5aca14f33f58abb3fdb1ab2e3">Relation attributes are also supported as well, showing a link with the
target note title and icon.</li>
<li data-list-item-id="ef13f98f321ca5b0b0ea881966e7a8ce9">Currently, it's not possible to adjust which promoted attributes are displayed,
since all promoted attributes will be displayed (except the <code spellcheck="false">board:groupBy</code> one).
There are plans to improve upon this being able to hide promoted attributes
individually.</li>
<li>All label types are supported, including dates, booleans and URLs.</li>
<li>Relation attributes are also supported as well, showing a link with the
target note title and icon.</li>
<li>Currently, it's not possible to adjust which promoted attributes are displayed,
since all promoted attributes will be displayed (except the <code>board:groupBy</code> one).
There are plans to improve upon this being able to hide promoted attributes
individually.</li>
</ul>
<h3>Grouping by another label</h3>
<p>By default, the label used to group the notes is <code spellcheck="false">#status</code>.
It is possible to use a different label if needed by defining a label named
<code
spellcheck="false">#board:groupBy</code>with the value being the attribute to use (with or
without <code spellcheck="false">#</code> attribute prefix).</p>
<p>By default, the label used to group the notes is <code>#status</code>.
It is possible to use a different label if needed by defining a label named <code>#board:groupBy</code> with
the value being the attribute to use (with or without <code>#</code> attribute
prefix).</p>
<h3>Grouping by relations</h3>
<figure class="image image-style-align-right">
<img style="aspect-ratio:535/245;" src="1_Kanban Board_image.png"
@ -151,35 +143,35 @@
<p>A more advanced use-case is grouping by <a href="#root/_help_Cq5X6iKQop6R">Relations</a>.</p>
<p>During this mode:</p>
<ul>
<li data-list-item-id="e8b12352beeecdc5fbba7ab2cc8c17ebf">The columns represent the <em>target notes</em> of a relation.</li>
<li data-list-item-id="e93e74a0b91864714971460d4f0c70d7c">When creating a new column, a note is selected instead of a column name.</li>
<li
data-list-item-id="ef5f8b62aea5f50ce16fd0eb7ec2da8a9">The column icon will match the target note.</li>
<li data-list-item-id="e1a406b952707601c17f59b79b428fcc4">Moving notes between columns will change its relation.</li>
<li data-list-item-id="e26ad186c049342b5071dbd7e288c34a5">Renaming an existing column will change the target note of all the notes
in that column.</li>
<li>The columns represent the <em>target notes</em> of a relation.</li>
<li>When creating a new column, a note is selected instead of a column name.</li>
<li>The column icon will match the target note.</li>
<li>Moving notes between columns will change its relation.</li>
<li>Renaming an existing column will change the target note of all the notes
in that column.</li>
</ul>
<p>Using relations instead of labels has some benefits:</p>
<ul>
<li data-list-item-id="e023fc2ef6ec6e976dc81d3e2b0fd0c46">The status/grouping of the notes is visible outside the Kanban board,
<li>The status/grouping of the notes is visible outside the Kanban board,
for example on the&nbsp;<a class="reference-link" href="#root/_help_bdUJEHsAPYQR">Note Map</a>.</li>
<li
data-list-item-id="e3b0b352a62b78f4ec2cf335e054f1cac">Columns can have icons.</li>
<li data-list-item-id="e5646f801237c13c7ddd600eecffea714">Renaming columns is less intensive since it simply involves changing the
note title of the target note instead of having to do a bulk rename.</li>
<li>Columns can have icons.</li>
<li>Renaming columns is less intensive since it simply involves changing the
note title of the target note instead of having to do a bulk rename.</li>
</ul>
<p>To do so:</p>
<ol>
<li data-list-item-id="ecd59797f1fe062de6118a1020034f761">First, create a Kanban board from scratch and not a template:</li>
<li
data-list-item-id="ea3e28bea94fae0e37b0319a1e2c0f48c">Assign <code spellcheck="false">#viewType=board #hidePromotedAttributes</code> to
emulate the default template.</li>
<li data-list-item-id="e063e32f35af1b206b060779666db84e5">Set <code spellcheck="false">#board:groupBy</code> to the name of a relation
to group by, <strong>including the</strong> <code spellcheck="false">~</code> <strong>prefix</strong> (e.g.
<code
spellcheck="false">~status</code>).</li>
<li data-list-item-id="e079874488794f7fa65ea90c7aa6a71a9">
<p>Optionally, use&nbsp;<a class="reference-link" href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a>&nbsp;for
easy status change within the note:</p><pre><code class="language-text-x-trilium-auto">#relation:status(inheritable)="promoted,alias=Status,single"</code></pre>
</li>
<li>
<p>First, create a Kanban board from scratch and not a template:</p>
</li>
<li>
<p>Assign <code>#viewType=board #hidePromotedAttributes</code> to emulate the
default template.</p>
</li>
<li>
<p>Set <code>#board:groupBy</code> to the name of a relation to group by, <strong>including the</strong> <code>~</code> <strong>prefix</strong> (e.g. <code>~status</code>).</p>
</li>
<li>
<p>Optionally, use&nbsp;<a class="reference-link" href="#root/_help_OFXdgB2nNk1F">Promoted Attributes</a>&nbsp;for
easy status change within the note:</p><pre><code class="language-text-x-trilium-auto">#relation:status(inheritable)="promoted,alias=Status,single"</code></pre>
</li>
</ol>

View File

@ -3,81 +3,93 @@
of brevity, beta versions are skipped and the features gathered to the
nearest stable version.</p>
<ul>
<li>v0.97.0:
<li data-list-item-id="ef19f93f07430e9fca2b18faeccdb8541">v0.101.0:
<ul>
<li>Books are now&nbsp;<a class="reference-link" href="#root/_help_GTwFsgaA0lCt">Collections</a>.</li>
<li><a class="reference-link" href="#root/_help_2FvYrpmOXm29">Table View</a>&nbsp;is
<li data-list-item-id="e966cf04b1d3e2d4c25a0804e1300fce1">A&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_IjZS7iK5EXtb">New Layout</a>&nbsp;has
been introduced, making significant modifications to the UI/UX such as
integrating the ribbon and the floating buttons into other UI elements
and introducing new functionality such as the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/IjZS7iK5EXtb/_help_I6p2a06hdnL6">Breadcrumb</a>.</li>
</ul>
</li>
<li data-list-item-id="e5e5a3e380946c4a9c20c195c4c2a67aa">v0.97.0:
<ul>
<li data-list-item-id="ebbabd91a31cefad600f9158e0d8ed8a6">Books are now&nbsp;<a class="reference-link" href="#root/_help_GTwFsgaA0lCt">Collections</a>.</li>
<li
data-list-item-id="e5d450d9e3671fcaaddf7de7d4189cce9"><a class="reference-link" href="#root/_help_2FvYrpmOXm29">Table</a>&nbsp;is
a new collection type displaying notes and attributes in an editable grid.</li>
<li><a class="reference-link" href="#root/_help_ZjLYv08Rp3qC">Quick edit</a>&nbsp;is
introduced, adding a new way to edit notes in a popup instead of opening
a new tab. It also integrates well with&nbsp;<a class="reference-link"
href="#root/_help_GTwFsgaA0lCt">Collections</a>.</li>
<li
data-list-item-id="ec1854c492a549ddaf435991b6600932f"><a class="reference-link" href="#root/_help_ZjLYv08Rp3qC">Quick edit</a>&nbsp;is
introduced, adding a new way to edit notes in a popup instead of opening
a new tab. It also integrates well with&nbsp;<a class="reference-link"
href="#root/_help_GTwFsgaA0lCt">Collections</a>.</li>
</ul>
</li>
<li>v0.96.0:
<ul>
<li><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;gain
premium features thanks to a collaboration with the CKEditor team:
<ul>
<li><a class="reference-link" href="#root/_help_ZlN4nump6EbW">Slash Commands</a>
</li>
<li><a class="reference-link" href="#root/_help_pwc194wlRzcH">Text Snippets</a>
</li>
</ul>
</li>
</li>
<li data-list-item-id="e669f8c64a650e888f7ab9ad44811b3fe">v0.96.0:
<ul>
<li data-list-item-id="e9edc8470eceb197a762ea99a56990b04"><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;gain
premium features thanks to a collaboration with the CKEditor team:
<ul>
<li data-list-item-id="eed1f858832c5484cc05c5206af7deb8c"><a class="reference-link" href="#root/_help_ZlN4nump6EbW">Slash Commands</a>
</li>
<li data-list-item-id="e423ca44abcf1c492bca3326c68a4dd02"><a class="reference-link" href="#root/_help_pwc194wlRzcH">Text Snippets</a>
</li>
</ul>
</li>
</ul>
</li>
<li data-list-item-id="edd5bb4ebdcbc1b78eab317432920681e">v0.95.0:
<ul>
<li data-list-item-id="e96ab356645dc2872d00ef26303c3c243">A more friendly theme was introduced for&nbsp;<a class="reference-link"
href="#root/_help_R9pX4DGra2Vt">Sharing</a>, with search, expandable tree, night
mode and more.</li>
</ul>
</li>
<li data-list-item-id="eb0db41819961cceb421d0080ebe393a0">v0.94.0:
<ul>
<li data-list-item-id="ef5d455dc8f704ff4ed8dbaa643680b4f">Added integration with&nbsp;<a class="reference-link" href="#root/_help_LMAv4Uy3Wk6J">[missing note]</a>&nbsp;(using
self-hosted LLMs such as Ollama or industry standards such as ChatGPT).</li>
</ul>
</li>
<li data-list-item-id="eb02f63d990d33fb68e5c5ef4cb4d98bc">v0.92.5:
<ul>
<li data-list-item-id="eb7667b18dbb62602cb808e66391dc419">Windows binaries are now signed.</li>
<li data-list-item-id="eb2eb9833623a29c74170e96c8354fb58"><a class="reference-link" href="#root/_help_7DAiwaf8Z7Rz">Multi-Factor Authentication</a>&nbsp;was
introduced.</li>
</ul>
</li>
<li data-list-item-id="e72d4cc6c767dc3d84b26a106ec7c68b5">v0.92.4:
<ul>
<li data-list-item-id="ee1f5a03462a47645dbb59199872e1872">macOS binaries are now signed.</li>
<li data-list-item-id="eae09e921f976e97d897d36c907dec049"><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes
can now have adjustable&nbsp;<a class="reference-link" href="#root/_help_veGu4faJErEM">Content language &amp; Right-to-left support</a>.</li>
<li
data-list-item-id="e12e70f61de823364911a9312f5a531e3"><a class="reference-link" href="#root/_help_NRnIZmSMc5sj">Printing &amp; Exporting as PDF</a>
</li>
<li data-list-item-id="e4dc6fa7783021624c2c792eed2a8d444"><a class="reference-link" href="#root/_help_rC3pL2aptaRE">Zen mode</a>
</li>
<li data-list-item-id="e089e6f72a09ee8fe6d12a9c5a774aa78"><a class="reference-link" href="#root/_help_xWbu3jpNWapp">Calendar</a>, allowing
notes to be displayed in a monthly grid based on start and end dates.</li>
</ul>
</li>
<li>v0.95.0:
<ul>
<li>A more friendly theme was introduced for&nbsp;<a class="reference-link"
href="#root/_help_R9pX4DGra2Vt">Sharing</a>, with search, expandable tree, night
mode and more.</li>
</li>
<li data-list-item-id="e5acf0fb776a98a6f22fc1e7d8baa1239">v0.91.5:
<ul>
<li data-list-item-id="eff56df616edfcfbacd72082aa8400caa">Significant improvements for mobile.</li>
<li data-list-item-id="e60bb9702a5cadd5806140a188716ec8e"><a class="reference-link" href="#root/_help_AgjCISero73a">Footnotes</a>&nbsp;are
now supported in&nbsp;<a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes.</li>
<li
data-list-item-id="e9214e1433aa79a600f283168945fd4ba">Mermaid diagrams can now be inserted inline within&nbsp;<a class="reference-link"
href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes.</li>
<li data-list-item-id="e0369b6c1b97c47dcb47a0f46a003c8ed">The TriliumNext theme is introduced, bringing a more modern design to
the application.</li>
<li data-list-item-id="ef5ee87f813b6d7b4ac89f6f3b9e72964"><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map</a>, displaying
notes as markers on a geographical map for easy trip planning.</li>
</ul>
</li>
<li>v0.94.0:
<ul>
<li>Added integration with&nbsp;<a class="reference-link" href="#root/_help_LMAv4Uy3Wk6J">AI</a>&nbsp;(using
self-hosted LLMs such as Ollama or industry standards such as ChatGPT).</li>
</ul>
</li>
<li>v0.92.5:
<ul>
<li>Windows binaries are now signed.</li>
<li><a class="reference-link" href="#root/_help_7DAiwaf8Z7Rz">Multi-Factor Authentication</a>&nbsp;was
introduced.</li>
</ul>
</li>
<li>v0.92.4:
<ul>
<li>macOS binaries are now signed.</li>
<li><a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes
can now have adjustable&nbsp;<a class="reference-link" href="#root/_help_veGu4faJErEM">Content language &amp; Right-to-left support</a>.</li>
<li><a class="reference-link" href="#root/_help_NRnIZmSMc5sj">Export as PDF</a>
</li>
<li><a class="reference-link" href="#root/_help_rC3pL2aptaRE">Zen mode</a>
</li>
<li><a class="reference-link" href="#root/_help_xWbu3jpNWapp">Calendar View</a>,
allowing notes to be displayed in a monthly grid based on start and end
dates.</li>
</ul>
</li>
<li>v0.91.5:
<ul>
<li>Significant improvements for mobile.</li>
<li><a class="reference-link" href="#root/_help_AgjCISero73a">Footnotes</a>&nbsp;are
now supported in&nbsp;<a class="reference-link" href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes.</li>
<li>Mermaid diagrams can now be inserted inline within&nbsp;<a class="reference-link"
href="#root/_help_iPIMuisry3hd">Text</a>&nbsp;notes.</li>
<li>The TriliumNext theme is introduced, bringing a more modern design to
the application.</li>
<li><a class="reference-link" href="#root/_help_81SGnPGMk7Xc">Geo Map View</a>,
displaying notes as markers on a geographical map for easy trip planning.</li>
</ul>
</li>
<li>v0.90.8:
<ul>
<li>A new note type was introduced:&nbsp;<a class="reference-link" href="#root/_help_gBbsAeiuUxI5">Mind Map</a>
</li>
</ul>
</li>
</li>
<li data-list-item-id="ec24ee9c5a93cac613b12ed9632dbd5d1">v0.90.8:
<ul>
<li data-list-item-id="eef68f9a9f5de860bbf95fb520aa499e3">A new note type was introduced:&nbsp;<a class="reference-link" href="#root/_help_gBbsAeiuUxI5">Mind Map</a>
</li>
</ul>
</li>
</ul>

View File

@ -1,13 +1,14 @@
"use strict";
import optionService from "../../services/options.js";
import log from "../../services/log.js";
import searchService from "../../services/search/services/search.js";
import ValidationError from "../../errors/validation_error.js";
import type { Request } from "express";
import { changeLanguage, getLocales } from "../../services/i18n.js";
import type { OptionNames } from "@triliumnext/commons";
import type { Request } from "express";
import ValidationError from "../../errors/validation_error.js";
import config from "../../services/config.js";
import { changeLanguage, getLocales } from "../../services/i18n.js";
import log from "../../services/log.js";
import optionService from "../../services/options.js";
import searchService from "../../services/search/services/search.js";
interface UserTheme {
val: string; // value of the theme, used in the URL
@ -100,6 +101,7 @@ const ALLOWED_OPTIONS = new Set<OptionNames>([
"splitEditorOrientation",
"seenCallToActions",
"experimentalFeatures",
"newLayout",
// AI/LLM integration options
"aiEnabled",

View File

@ -1,10 +1,11 @@
import optionService from "./options.js";
import { type KeyboardShortcutWithRequiredActionName, type OptionMap, type OptionNames, SANITIZER_DEFAULT_ALLOWED_TAGS } from "@triliumnext/commons";
import appInfo from "./app_info.js";
import { randomSecureToken, isWindows } from "./utils.js";
import log from "./log.js";
import dateUtils from "./date_utils.js";
import keyboardActions from "./keyboard_actions.js";
import { SANITIZER_DEFAULT_ALLOWED_TAGS, type KeyboardShortcutWithRequiredActionName, type OptionMap, type OptionNames } from "@triliumnext/commons";
import log from "./log.js";
import optionService from "./options.js";
import { isWindows,randomSecureToken } from "./utils.js";
function initDocumentOptions() {
optionService.createOption("documentId", randomSecureToken(16), false);
@ -156,6 +157,7 @@ const defaultOptions: DefaultOption[] = [
{ name: "shadowsEnabled", value: "true", isSynced: false },
{ name: "backdropEffectsEnabled", value: "true", isSynced: false },
{ name: "smoothScrollEnabled", value: "true", isSynced: false },
{ name: "newLayout", value: "true", isSynced: true },
// Internationalization
{ name: "locale", value: "en", isSynced: true },
@ -171,9 +173,9 @@ const defaultOptions: DefaultOption[] = [
value: (optionsMap) => {
if (optionsMap.theme === "light") {
return "default:stackoverflow-light";
} else {
return "default:stackoverflow-dark";
}
return "default:stackoverflow-dark";
},
isSynced: false
},

View File

@ -1,5 +1,5 @@
# Documentation
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/lONK7oKNhIgu/Documentation_image.png" width="205" height="162">
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/Y3urZDbSOH6u/Documentation_image.png" width="205" height="162">
* The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing <kbd>F1</kbd>.
* The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers.

View File

@ -237,6 +237,20 @@
"value": "feature-highlights",
"isInheritable": false,
"position": 170
},
{
"type": "relation",
"name": "internalLink",
"value": "IjZS7iK5EXtb",
"isInheritable": false,
"position": 180
},
{
"type": "relation",
"name": "internalLink",
"value": "I6p2a06hdnL6",
"isInheritable": false,
"position": 190
}
],
"format": "markdown",
@ -2851,6 +2865,20 @@
"value": "note-buttons",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "IjZS7iK5EXtb",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "W8vYD3Q1zjCR",
"isInheritable": false,
"position": 80
}
],
"format": "markdown",
@ -3436,6 +3464,286 @@
"dataFileName": "Note Tooltip_image.png"
}
]
},
{
"isClone": false,
"noteId": "IjZS7iK5EXtb",
"notePath": [
"pOsGYCXsbNQG",
"gh7bpGYxajRS",
"Vc8PjrjAGuOp",
"IjZS7iK5EXtb"
],
"title": "New Layout",
"notePosition": 220,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "iconClass",
"value": "bx bx-layout",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "4TIF1oA4VQRO",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "iPIMuisry3hd",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "6f9hih2hXXZk",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "KC1HB96bqqHX",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "8YBEPzcpUgxw",
"isInheritable": false,
"position": 80
},
{
"type": "relation",
"name": "internalLink",
"value": "grjYqerjn243",
"isInheritable": false,
"position": 90
},
{
"type": "relation",
"name": "internalLink",
"value": "XpOYSgsLkTJy",
"isInheritable": false,
"position": 100
},
{
"type": "relation",
"name": "internalLink",
"value": "cbkrhQjrkKrh",
"isInheritable": false,
"position": 110
},
{
"type": "relation",
"name": "internalLink",
"value": "MtPxeAWVAzMg",
"isInheritable": false,
"position": 120
},
{
"type": "relation",
"name": "internalLink",
"value": "CdNpE2pqjmI6",
"isInheritable": false,
"position": 140
},
{
"type": "relation",
"name": "internalLink",
"value": "YKWqdJhzi2VY",
"isInheritable": false,
"position": 150
},
{
"type": "relation",
"name": "internalLink",
"value": "veGu4faJErEM",
"isInheritable": false,
"position": 160
},
{
"type": "relation",
"name": "internalLink",
"value": "zEY4DaJG4YT5",
"isInheritable": false,
"position": 170
},
{
"type": "relation",
"name": "internalLink",
"value": "AlJ73vBCjWDw",
"isInheritable": false,
"position": 180
},
{
"type": "relation",
"name": "internalLink",
"value": "l0tKav7yLHGF",
"isInheritable": false,
"position": 190
},
{
"type": "relation",
"name": "internalLink",
"value": "eIg8jdvaoNNd",
"isInheritable": false,
"position": 200
},
{
"type": "relation",
"name": "internalLink",
"value": "m523cpzocqaD",
"isInheritable": false,
"position": 210
}
],
"format": "markdown",
"dataFileName": "New Layout.md",
"attachments": [
{
"attachmentId": "3DFGaMiTTHQ1",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "New Layout_image.png"
},
{
"attachmentId": "6iN5nrmdwG6z",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "1_New Layout_image.png"
},
{
"attachmentId": "KvNAEoJjRhyr",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "2_New Layout_image.png"
},
{
"attachmentId": "lEKxf6dYMG6u",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "3_New Layout_image.png"
},
{
"attachmentId": "SYOTVGCyx749",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "4_New Layout_image.png"
},
{
"attachmentId": "wCwzwfGspejR",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "5_New Layout_image.png"
}
],
"dirFileName": "New Layout",
"children": [
{
"isClone": false,
"noteId": "I6p2a06hdnL6",
"notePath": [
"pOsGYCXsbNQG",
"gh7bpGYxajRS",
"Vc8PjrjAGuOp",
"IjZS7iK5EXtb",
"I6p2a06hdnL6"
],
"title": "Breadcrumb",
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "AlJ73vBCjWDw",
"isInheritable": false,
"position": 30
},
{
"type": "label",
"name": "iconClass",
"value": "bx bx-chevron-right",
"isInheritable": false,
"position": 40
}
],
"format": "markdown",
"dataFileName": "Breadcrumb.md",
"attachments": [
{
"attachmentId": "CjYmaJD0L1D4",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "Breadcrumb_image.png"
}
]
},
{
"isClone": false,
"noteId": "AlJ73vBCjWDw",
"notePath": [
"pOsGYCXsbNQG",
"gh7bpGYxajRS",
"Vc8PjrjAGuOp",
"IjZS7iK5EXtb",
"AlJ73vBCjWDw"
],
"title": "Status bar",
"notePosition": 20,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "I6p2a06hdnL6",
"isInheritable": false,
"position": 30
},
{
"type": "label",
"name": "iconClass",
"value": "bx bx-dock-bottom",
"isInheritable": false,
"position": 40
}
],
"format": "markdown",
"dataFileName": "Status bar.md",
"attachments": []
}
]
}
]
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,114 @@
# New Layout
The _New layout_ is a series of UI/UX changes that were introduced in v0.101.0 that heavily change both existing UI elements, as well as adding some new ones. The goal of this new layout is to modernize the application and to make it more intuitive but at the same time to reduce clutter.
## Newly introduced features
### Status bar
At the bottom of the window there is a new bar called the _Status bar_. This bar houses multiple items such as the Breadcrumb navigation and information and settings about the current note, such as the [content language](../../Note%20Types/Text/Content%20language%20%26%20Right-to-le.md) and <a class="reference-link" href="../../Advanced%20Usage/Attributes.md">Attributes</a>.
For more information, consult the [dedicated page](New%20Layout/Status%20bar.md).
<figure class="image"><img style="aspect-ratio:1150/27;" src="4_New Layout_image.png" width="1150" height="27"></figure>
### Inline title
In previous versions of Trilium, the title bar was fixed at all times. In the new layout, there is both a fixed title bar and one that scrolls with the text. The newly introduced title is called the _Inline title_ and it displays the title in a larger font, while also displaying additional information such as the creation and the modification date.
Whenever the title is scrolled past, the fixed title is shown instead.
This only affects <a class="reference-link" href="../../Note%20Types/Text.md">Text</a> and <a class="reference-link" href="../../Note%20Types/Code.md">Code</a> notes. Note types that take the entirety of the screen such as <a class="reference-link" href="../../Note%20Types/Canvas.md">Canvas</a> will always have only the fixed title bar.
Depending on the note type, the inline title will also present some more interactive options such as being able to switch the note type (see below).
<figure class="image"><img style="aspect-ratio:899/122;" src="New Layout_image.png" width="899" height="122"><figcaption>The <em>Inline title</em>, which is displayed at the top of the note and can be scrolled past.</figcaption></figure><figure class="image"><img style="aspect-ratio:910/104;" src="3_New Layout_image.png" width="910" height="104"><figcaption>The fixed title bar. The title only appears after scrolling past the <em>Inline title</em>.</figcaption></figure>
### New note type switcher
When a new <a class="reference-link" href="../../Note%20Types/Text.md">Text</a> or <a class="reference-link" href="../../Note%20Types/Code.md">Code</a> note is created, a note type switcher will appear below the _Inline title_. Apart from changing the note type, it's also possible to apply a [template](../../Advanced%20Usage/Templates.md).
The switcher will disappear as soon as a text is entered.
<img src="5_New Layout_image.png" width="735" height="143">
### Note badges
Note badges appear near the fixed note title and indicate important information about the note such as whether it is read-only. Some of the badges are also interactive.
<figure class="image"><img style="aspect-ratio:910/49;" src="2_New Layout_image.png" width="910" height="49"></figure>
The following badges are available:
* **Read-only badge**, which will be shown if the note is not editable due to either automatic read-only or manual read-only. Clicking on the badge will temporarily edit the note (similar to the Edit [floating button](Floating%20buttons.md)).
* **Share badge**, which will indicate that the current note is shared. The badge will also indicate if the share is on the local network (for the desktop application without <a class="reference-link" href="../../Installation%20%26%20Setup/Synchronization.md">Synchronization</a> set up) or publicly accessible (for the server).
* **Web clip badge**, which will indicate if the note was clipped using the <a class="reference-link" href="../../Installation%20%26%20Setup/Web%20Clipper.md">Web Clipper</a>. The badge acts as a link, so it can be clicked on to navigate to the page or right clicked for more options.
* **Execute badge**, for [scripts](../../Scripting.md) or [saved SQL queries](../../Advanced%20Usage/Database/Manually%20altering%20the%20database/SQL%20Console.md) which have an execute button or a description.
Some of these badges replace the dedicated panels at the top of the note.
### Collapsible sections
<figure class="image"><img style="aspect-ratio:496/265;" src="1_New Layout_image.png" width="496" height="265"></figure>
The following sections have been made collapsible:
* _Promoted Attributes_
* For full-height notes such as <a class="reference-link" href="../../Note%20Types/Canvas.md">Canvas</a>, the promoted attributes are collapsed by default to make room.
* The keyboard shortcut previously used to trigger the promoted attributes ribbon tab (which was no longer working) has been repurposed to toggle the promoted attributes instead.
* _Edited Notes_, which appears for <a class="reference-link" href="../../Advanced%20Usage/Advanced%20Showcases/Day%20Notes.md">Day Notes</a> is now shown underneath the title.
* Whether the section is collapsed or not depends on the choice in <a class="reference-link" href="Options.md">Options</a> → Appearance.
* _Search Properties_, which appears for the full <a class="reference-link" href="../Navigation/Search.md">Search</a> and <a class="reference-link" href="../../Note%20Types/Saved%20Search.md">Saved Search</a>.
## Changing to the existing layout
### Removal of the ribbon
The most significant change is the removal of the ribbon. All the actions and options from the ribbon were integrated in other places in the application.
Here's how all the different tabs that were once part of the ribbon are now available in the new layout:
* “Formatting toolbar” was relocated to the top of the page.
* Instead of having one per split, now there is a single formatting toolbar per tab. This allows more space for the toolbar items.
* “Owned attributes” and “Inherited attributes” were merged and moved to the status bar region (displayed one above the other).
* “Basic Properties” were integrated in the <a class="reference-link" href="Note%20buttons.md">Note buttons</a> menu.
* The only exception here is the Language combo box which can now be found in the status bar (top-right of the screen).
* “File” and “Image” tabs
* The buttons were moved to the right of the note title, as dedicated entries in <a class="reference-link" href="Note%20buttons.md">Note buttons</a>.
* The info section has been merged into the _Note info_ section of the status bar.
* Edited notes
* Moved underneath the title, displayed under a collapsible area and the notes are represented as badges/chips.
* Whether the section is expanded or collapsed depends on the “Edited Notes ribbon tab will automatically open on day notes” setting from Options → Appearance.
* Search definition tab
* Moved underneath the title under a collapsible area.
* Expanded by default for new searches, collapsed for saved searches.
* The Note map is now available in the Note actions menu.
* Instead of opening into a panel in the ribbon, the note map now opens in a side split (similar to the in-app help).
* “Note info” tab was moved to a small (i) icon in the status bar.
* “Similar notes” tab
* Moved to the status bar, by going to the “Note info” section and pressing the button to show similar notes.
* Displayed as a fixed panel, similar to the attributes.
* The Collection properties tab were relocated under the note title and grouped into:
* A combo box to quickly switch between views.
* Individual settings for the current view in a submenu.
* Some smaller ribbon tabs were converted to badges that appear near the note title in the breadcrumb section:
* Original URL indicator for clipped web pages (`#pageUrl`).
* SQL and script execute buttons.
> [!NOTE]
> The ribbon keyboard shortcuts (e.g. `toggleRibbonTabClassicEditor`) have been repurposed to work on the new layout, where they will toggle the appropriate panel.
### Removal of the floating buttons
Most of the buttons were relocated to the right of the note title, in the <a class="reference-link" href="Note%20buttons.md">Note buttons</a> area, with the exception of:
* The Edit button is displayed near the note title, as a badge.
* _Backlinks_ is displayed in the status bar. When clicked, the same list of backlinks is displayed.
* Relation map zoom buttons are now part of the relation map itself.
* Export image to PNG/SVG are now in the Note actions menu, in the _Export as image_ option.
## How to toggle the new layout
Starting with v0.101.0, this new layout is enabled by default. It is possible to fall back to the old layout by going to <a class="reference-link" href="Options.md">Options</a> → Appearance and selecting _Old layout_.
> [!IMPORTANT]
> Since a new layout was introduced, this becomes the standard one. The _Old layout_ is considered deprecated and will not receive new features (for example, the breadcrumb) as we focus on the new one. At some point the old layout will be removed entirely, as maintaining two layouts with major differences creates a maintenance burden.

View File

@ -0,0 +1,26 @@
# Breadcrumb
<figure class="image"><img style="aspect-ratio:1150/27;" src="Breadcrumb_image.png" width="1150" height="27"></figure>
The breadcrumb allows quickly viewing the note hierarchy of the current note and navigating through it.
It is part of the <a class="reference-link" href="Status%20bar.md">Status bar</a>, displayed in the bottom-left of the screen.
## Layout and Interaction
* If a note or workspace is hoisted, a badge will appear on the left-most side.
* Clicking on the badge will un-hoist the note/workspace.
* The left-most icon represents the root note, or the hoisted note or workspace.
* Clicking the icon will jump to the root note.
* Right clicking the icon will display a menu that allows opening the note in a new tab, split, etc.
* Each segment shows the title of a note in the current note hierarchy.
* Clicking the icon will jump to that note.
* Right clicking will open a menu with multiple options such as opening the note in a different tab/split/window, hoisting, moving/cloning the note, duplicating as well as changing the color of the note.
* Clicking the arrow next to each segment will reveal the child notes of the segment on the left.
* Clicking on an icon will navigate to that particular note.
* It's also possible to create a new child note from here.
* The menu can optionally hide the archived notes.
* If the current note is deep within a hierarchy, the segments will collapse into a \[…\] button in order not to occupy too much space.
* Clicking this button will display each collapsed entry as a menu item. Clicking on it will navigate to that particular note.
* Right clicking on an empty space to the right of the breadcrumb (before the other status bar items) will reveal another menu that allows:
* Toggling whether archived notes are displayed in the breadcrumb and in the note tree.
* Copying the current note path to clipboard.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,27 @@
# Status bar
The status bar displays information about the current note and allows changing settings related to it such as configuring the language or attributes.
## Layout and interaction
On the left side, the <a class="reference-link" href="Breadcrumb.md">Breadcrumb</a> is displayed which indicates the current note as well as its parent notes and allows for quick navigation throughout the hierarchy.
On the right side, specific sections will show depending on the type of the current note.
1. For code notes, the language mode of the note is indicated (e.g. JavaScript, plain text), as well as allowing easy switching to another mode.
2. For text notes, the content language is displayed and can be changed, thus configuring the spell-check and the right-to-left support.
1. Note that this applies to the entire note and not the selection, unlike some text editors.
3. If a note is placed in multiple places in the tree (cloned), the number of the note paths will be displayed.
1. Clicking it will reveal the full list of note paths and a button to place it somewhere else.
4. If a note has attachments, their number will be displayed.
1. Clicking on it will reveal the list of attachments in a new tab.
5. If a note is linked from other text notes (backlinks), the number of backlinks will be displayed.
1. Clicking on it will show the list of notes that link to this note, as well as an excerpt of where the note is referenced.
Regardless of note type, the following items will always be displayed if there is a note:
1. Note info, which displays:
1. The creation/modification date of the note.
2. The type and MIME of the note.
3. The note ID.
4. An estimation of the note size of the note itself and its children.
5. A button to show Similar notes.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@ -2,4 +2,6 @@
To the right of the [Ribbon](Ribbon.md) there are a few more buttons: ![](Note%20buttons_image.png)
* The Note Revisions button displays the [Note Revisions](../Notes/Note%20Revisions.md) for that particular note.
* The contextual menu offers commands for the note or its subtree, such as import, export, viewing the [Note source code](../../Advanced%20Usage/Note%20source.md) or [Attachments](../Notes/Attachments.md).
* The contextual menu offers commands for the note or its subtree, such as import, export, viewing the [Note source code](../../Advanced%20Usage/Note%20source.md) or [Attachments](../Notes/Attachments.md).
On the <a class="reference-link" href="New%20Layout.md">New Layout</a>, the button area is populated by some more buttons that are specific to the current note. For example, for Image and <a class="reference-link" href="../../Note%20Types/File.md">File</a> notes, the download and copy buttons were relocated there.

View File

@ -1,9 +1,11 @@
# Feature Highlights
This section presents the most important changes by version. For a full set of changes, please consult the change log of each release. For purposes of brevity, beta versions are skipped and the features gathered to the nearest stable version.
* v0.101.0:
* A <a class="reference-link" href="Basic%20Concepts%20and%20Features/UI%20Elements/New%20Layout.md">New Layout</a> has been introduced, making significant modifications to the UI/UX such as integrating the ribbon and the floating buttons into other UI elements and introducing new functionality such as the <a class="reference-link" href="Basic%20Concepts%20and%20Features/UI%20Elements/New%20Layout/Breadcrumb.md">Breadcrumb</a>.
* v0.97.0:
* Books are now <a class="reference-link" href="Collections.md">Collections</a>.
* <a class="reference-link" href="Collections/Table.md">Table View</a> is a new collection type displaying notes and attributes in an editable grid.
* <a class="reference-link" href="Collections/Table.md">Table</a> is a new collection type displaying notes and attributes in an editable grid.
* <a class="reference-link" href="Basic%20Concepts%20and%20Features/Navigation/Quick%20edit.md">Quick edit</a> is introduced, adding a new way to edit notes in a popup instead of opening a new tab. It also integrates well with <a class="reference-link" href="Collections.md">Collections</a>.
* v0.96.0:
* <a class="reference-link" href="Note%20Types/Text.md">Text</a> gain premium features thanks to a collaboration with the CKEditor team:
@ -12,21 +14,21 @@ This section presents the most important changes by version. For a full set of c
* v0.95.0:
* A more friendly theme was introduced for <a class="reference-link" href="Advanced%20Usage/Sharing.md">Sharing</a>, with search, expandable tree, night mode and more.
* v0.94.0:
* Added integration with <a class="reference-link" href="#root/LMAv4Uy3Wk6J">AI</a> (using self-hosted LLMs such as Ollama or industry standards such as ChatGPT).
* Added integration with <a class="reference-link" href="#root/LMAv4Uy3Wk6J">[missing note]</a> (using self-hosted LLMs such as Ollama or industry standards such as ChatGPT).
* v0.92.5:
* Windows binaries are now signed.
* <a class="reference-link" href="Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md">Multi-Factor Authentication</a> was introduced.
* v0.92.4:
* macOS binaries are now signed.
* <a class="reference-link" href="Note%20Types/Text.md">Text</a> notes can now have adjustable <a class="reference-link" href="Note%20Types/Text/Content%20language%20%26%20Right-to-le.md">Content language &amp; Right-to-left support</a>.
* <a class="reference-link" href="Basic%20Concepts%20and%20Features/Notes/Printing%20%26%20Exporting%20as%20PDF.md">Export as PDF</a>
* <a class="reference-link" href="Basic%20Concepts%20and%20Features/Notes/Printing%20%26%20Exporting%20as%20PDF.md">Printing &amp; Exporting as PDF</a>
* <a class="reference-link" href="Basic%20Concepts%20and%20Features/Zen%20mode.md">Zen mode</a>
* <a class="reference-link" href="Collections/Calendar.md">Calendar View</a>, allowing notes to be displayed in a monthly grid based on start and end dates.
* <a class="reference-link" href="Collections/Calendar.md">Calendar</a>, allowing notes to be displayed in a monthly grid based on start and end dates.
* v0.91.5:
* Significant improvements for mobile.
* <a class="reference-link" href="Note%20Types/Text/Footnotes.md">Footnotes</a> are now supported in <a class="reference-link" href="Note%20Types/Text.md">Text</a> notes.
* Mermaid diagrams can now be inserted inline within <a class="reference-link" href="Note%20Types/Text.md">Text</a> notes.
* The TriliumNext theme is introduced, bringing a more modern design to the application.
* <a class="reference-link" href="Collections/Geo%20Map.md">Geo Map View</a>, displaying notes as markers on a geographical map for easy trip planning.
* <a class="reference-link" href="Collections/Geo%20Map.md">Geo Map</a>, displaying notes as markers on a geographical map for easy trip planning.
* v0.90.8:
* A new note type was introduced: <a class="reference-link" href="Note%20Types/Mind%20Map.md">Mind Map</a>

View File

@ -131,6 +131,7 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActi
/** Whether keyboard auto-completion for editing commands is triggered when typing `/`. */
textNoteSlashCommandsEnabled: boolean;
backgroundEffects: boolean;
newLayout: boolean;
// Share settings
redirectBareDomain: boolean;