mirror of
https://github.com/zadam/trilium.git
synced 2025-10-21 07:38:53 +02:00
chore(react/ribbon): bring back tab filtering
This commit is contained in:
parent
bf0213907e
commit
b99d01ad7b
@ -788,6 +788,22 @@ export function arrayEqual<T>(a: T[], b: T[]) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Indexed<T extends object> = T & { index: number };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an object array, alters every object in the array to have an index field assigned to it.
|
||||||
|
*
|
||||||
|
* @param items the objects to be numbered.
|
||||||
|
* @returns the same object for convenience, with the type changed to indicate the new index field.
|
||||||
|
*/
|
||||||
|
export function numberObjectsInPlace<T extends object>(items: T[]): Indexed<T>[] {
|
||||||
|
let index = 0;
|
||||||
|
for (const item of items) {
|
||||||
|
(item as Indexed<T>).index = index++;
|
||||||
|
}
|
||||||
|
return items as Indexed<T>[];
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
reloadFrontendApp,
|
reloadFrontendApp,
|
||||||
restartDesktopApp,
|
restartDesktopApp,
|
||||||
|
@ -3,7 +3,7 @@ import Dropdown from "../react/Dropdown";
|
|||||||
import { NOTE_TYPES } from "../../services/note_types";
|
import { NOTE_TYPES } from "../../services/note_types";
|
||||||
import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
|
import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
|
||||||
import { getAvailableLocales, t } from "../../services/i18n";
|
import { getAvailableLocales, t } from "../../services/i18n";
|
||||||
import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption, useTriliumOptionBeta, useTriliumOptionJson } from "../react/hooks";
|
import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEventBeta, useTriliumOption, useTriliumOptionBeta, useTriliumOptionJson } from "../react/hooks";
|
||||||
import mime_types from "../../services/mime_types";
|
import mime_types from "../../services/mime_types";
|
||||||
import { Locale, NoteType, ToggleInParentResponse } from "@triliumnext/commons";
|
import { Locale, NoteType, ToggleInParentResponse } from "@triliumnext/commons";
|
||||||
import server from "../../services/server";
|
import server from "../../services/server";
|
||||||
@ -17,10 +17,9 @@ import branches from "../../services/branches";
|
|||||||
import sync from "../../services/sync";
|
import sync from "../../services/sync";
|
||||||
import appContext from "../../components/app_context";
|
import appContext from "../../components/app_context";
|
||||||
import HelpButton from "../react/HelpButton";
|
import HelpButton from "../react/HelpButton";
|
||||||
|
import { TabContext } from "./ribbon-interface";
|
||||||
|
|
||||||
export default function BasicPropertiesTab() {
|
export default function BasicPropertiesTab({ note }: TabContext) {
|
||||||
const { note } = useNoteContext();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="basic-properties-widget">
|
<div className="basic-properties-widget">
|
||||||
<NoteTypeWidget note={note} />
|
<NoteTypeWidget note={note} />
|
||||||
|
@ -1,24 +1,21 @@
|
|||||||
import { useState } from "preact/hooks";
|
import { useMemo, useState } from "preact/hooks";
|
||||||
import FNote from "../../entities/fnote";
|
import FNote from "../../entities/fnote";
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
import { useNoteContext } from "../react/hooks";
|
import { useNoteContext } from "../react/hooks";
|
||||||
import "./style.css";
|
import "./style.css";
|
||||||
import { VNode } from "preact";
|
import { VNode } from "preact";
|
||||||
import BasicPropertiesTab from "./BasicPropertiesTab";
|
import BasicPropertiesTab from "./BasicPropertiesTab";
|
||||||
|
import { numberObjectsInPlace } from "../../services/utils";
|
||||||
type TitleFn = string | ((context: TabContext) => string);
|
import { TabContext } from "./ribbon-interface";
|
||||||
|
|
||||||
interface TabContext {
|
|
||||||
note: FNote | null | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TabConfiguration {
|
interface TabConfiguration {
|
||||||
title: TitleFn;
|
title: string | ((context: TabContext) => string);
|
||||||
icon: string;
|
icon: string;
|
||||||
content?: () => VNode;
|
// TODO: Mark as required after porting them all.
|
||||||
|
content?: (context: TabContext) => VNode;
|
||||||
|
show?: (context: TabContext) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TAB_CONFIGURATION: TabConfiguration[] = [
|
const TAB_CONFIGURATION = numberObjectsInPlace<TabConfiguration>([
|
||||||
{
|
{
|
||||||
title: t("classic_editor_toolbar.title"),
|
title: t("classic_editor_toolbar.title"),
|
||||||
icon: "bx bx-text"
|
icon: "bx bx-text"
|
||||||
@ -63,7 +60,8 @@ const TAB_CONFIGURATION: TabConfiguration[] = [
|
|||||||
// BasicProperties
|
// BasicProperties
|
||||||
title: t("basic_properties.basic_properties"),
|
title: t("basic_properties.basic_properties"),
|
||||||
icon: "bx bx-slider",
|
icon: "bx bx-slider",
|
||||||
content: BasicPropertiesTab
|
content: BasicPropertiesTab,
|
||||||
|
show: ({note}) => !note?.isLaunchBarConfig()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// OwnedAttributeListWidget
|
// OwnedAttributeListWidget
|
||||||
@ -94,31 +92,31 @@ const TAB_CONFIGURATION: TabConfiguration[] = [
|
|||||||
// NoteInfoWidget
|
// NoteInfoWidget
|
||||||
title: t("note_info_widget.title"),
|
title: t("note_info_widget.title"),
|
||||||
icon: "bx bx-info-circle"
|
icon: "bx bx-info-circle"
|
||||||
},
|
}
|
||||||
|
]);
|
||||||
];
|
|
||||||
|
|
||||||
export default function Ribbon() {
|
export default function Ribbon() {
|
||||||
const { note } = useNoteContext();
|
const { note } = useNoteContext();
|
||||||
const context: TabContext = { note };
|
const context: TabContext = { note };
|
||||||
const [ activeTab, setActiveTab ] = useState<number | undefined>(8);
|
const [ activeTabIndex, setActiveTabIndex ] = useState<number | undefined>();
|
||||||
const activeTabConfiguration = activeTab ? TAB_CONFIGURATION[activeTab] : undefined;
|
const filteredTabs = useMemo(() => TAB_CONFIGURATION.filter(tab => tab.show?.(context)), [ context, note ])
|
||||||
|
const activeTabConfiguration = activeTabIndex ? filteredTabs.find(tab => tab.index === activeTabIndex) : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="ribbon-container" style={{ contain: "none" }}>
|
<div class="ribbon-container" style={{ contain: "none" }}>
|
||||||
<div className="ribbon-top-row">
|
<div className="ribbon-top-row">
|
||||||
<div className="ribbon-tab-container">
|
<div className="ribbon-tab-container">
|
||||||
{TAB_CONFIGURATION.map(({ title, icon }, i) => (
|
{filteredTabs.map(({ title, icon, index }) => (
|
||||||
<RibbonTab
|
<RibbonTab
|
||||||
icon={icon}
|
icon={icon}
|
||||||
title={typeof title === "string" ? title : title(context)}
|
title={typeof title === "string" ? title : title(context)}
|
||||||
active={i === activeTab}
|
active={index === activeTabIndex}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (activeTab !== i) {
|
if (activeTabIndex !== index) {
|
||||||
setActiveTab(i);
|
setActiveTabIndex(index);
|
||||||
} else {
|
} else {
|
||||||
// Collapse
|
// Collapse
|
||||||
setActiveTab(undefined);
|
setActiveTabIndex(undefined);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -129,7 +127,7 @@ export default function Ribbon() {
|
|||||||
|
|
||||||
<div className="ribbon-body-container">
|
<div className="ribbon-body-container">
|
||||||
<div className="ribbon-body">
|
<div className="ribbon-body">
|
||||||
{activeTabConfiguration?.content && activeTabConfiguration.content()}
|
{activeTabConfiguration?.content && activeTabConfiguration.content({ note })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
5
apps/client/src/widgets/ribbon/ribbon-interface.ts
Normal file
5
apps/client/src/widgets/ribbon/ribbon-interface.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import FNote from "../../entities/fnote";
|
||||||
|
|
||||||
|
export interface TabContext {
|
||||||
|
note: FNote | null | undefined;
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
import { t } from "../services/i18n.js";
|
|
||||||
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
|
||||||
|
|
||||||
export default class SwitchWidget extends NoteContextAwareWidget {
|
|
||||||
|
|
||||||
doRender() {
|
|
||||||
this.$widget = $(TPL);
|
|
||||||
this.$switchButton = this.$widget.find(".switch-button");
|
|
||||||
|
|
||||||
this.$switchToggle = this.$widget.find(".switch-toggle");
|
|
||||||
this.$switchName = this.$widget.find(".switch-name");
|
|
||||||
this.$helpButton = this.$widget.find(".switch-help-button");
|
|
||||||
}
|
|
||||||
|
|
||||||
switchOff() {}
|
|
||||||
switchOn() {}
|
|
||||||
|
|
||||||
/** Gets or sets whether the switch is toggled. */
|
|
||||||
get isToggled() {
|
|
||||||
return this.currentState;
|
|
||||||
}
|
|
||||||
|
|
||||||
set isToggled(state) {
|
|
||||||
this.currentState = !!state;
|
|
||||||
|
|
||||||
this.$switchButton.toggleClass("on", this.currentState);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets or sets whether the switch is enabled. */
|
|
||||||
get canToggle() {
|
|
||||||
return !this.$switchButton.hasClass("disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
set canToggle(isEnabled) {
|
|
||||||
if (isEnabled) {
|
|
||||||
this.isToggled = this.currentState; // Reapply the correct tooltip
|
|
||||||
} else {
|
|
||||||
this.$switchButton.attr("title", this.disabledTooltip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user