mirror of
https://github.com/zadam/trilium.git
synced 2025-10-20 15:19:01 +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;
|
||||
}
|
||||
|
||||
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 {
|
||||
reloadFrontendApp,
|
||||
restartDesktopApp,
|
||||
|
@ -3,7 +3,7 @@ import Dropdown from "../react/Dropdown";
|
||||
import { NOTE_TYPES } from "../../services/note_types";
|
||||
import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList";
|
||||
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 { Locale, NoteType, ToggleInParentResponse } from "@triliumnext/commons";
|
||||
import server from "../../services/server";
|
||||
@ -17,10 +17,9 @@ import branches from "../../services/branches";
|
||||
import sync from "../../services/sync";
|
||||
import appContext from "../../components/app_context";
|
||||
import HelpButton from "../react/HelpButton";
|
||||
import { TabContext } from "./ribbon-interface";
|
||||
|
||||
export default function BasicPropertiesTab() {
|
||||
const { note } = useNoteContext();
|
||||
|
||||
export default function BasicPropertiesTab({ note }: TabContext) {
|
||||
return (
|
||||
<div className="basic-properties-widget">
|
||||
<NoteTypeWidget note={note} />
|
||||
|
@ -1,24 +1,21 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { useMemo, useState } from "preact/hooks";
|
||||
import FNote from "../../entities/fnote";
|
||||
import { t } from "../../services/i18n";
|
||||
import { useNoteContext } from "../react/hooks";
|
||||
import "./style.css";
|
||||
import { VNode } from "preact";
|
||||
import BasicPropertiesTab from "./BasicPropertiesTab";
|
||||
|
||||
type TitleFn = string | ((context: TabContext) => string);
|
||||
|
||||
interface TabContext {
|
||||
note: FNote | null | undefined;
|
||||
}
|
||||
|
||||
import { numberObjectsInPlace } from "../../services/utils";
|
||||
import { TabContext } from "./ribbon-interface";
|
||||
interface TabConfiguration {
|
||||
title: TitleFn;
|
||||
title: string | ((context: TabContext) => 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"),
|
||||
icon: "bx bx-text"
|
||||
@ -63,7 +60,8 @@ const TAB_CONFIGURATION: TabConfiguration[] = [
|
||||
// BasicProperties
|
||||
title: t("basic_properties.basic_properties"),
|
||||
icon: "bx bx-slider",
|
||||
content: BasicPropertiesTab
|
||||
content: BasicPropertiesTab,
|
||||
show: ({note}) => !note?.isLaunchBarConfig()
|
||||
},
|
||||
{
|
||||
// OwnedAttributeListWidget
|
||||
@ -94,31 +92,31 @@ const TAB_CONFIGURATION: TabConfiguration[] = [
|
||||
// NoteInfoWidget
|
||||
title: t("note_info_widget.title"),
|
||||
icon: "bx bx-info-circle"
|
||||
},
|
||||
|
||||
];
|
||||
}
|
||||
]);
|
||||
|
||||
export default function Ribbon() {
|
||||
const { note } = useNoteContext();
|
||||
const context: TabContext = { note };
|
||||
const [ activeTab, setActiveTab ] = useState<number | undefined>(8);
|
||||
const activeTabConfiguration = activeTab ? TAB_CONFIGURATION[activeTab] : undefined;
|
||||
const [ activeTabIndex, setActiveTabIndex ] = useState<number | undefined>();
|
||||
const filteredTabs = useMemo(() => TAB_CONFIGURATION.filter(tab => tab.show?.(context)), [ context, note ])
|
||||
const activeTabConfiguration = activeTabIndex ? filteredTabs.find(tab => tab.index === activeTabIndex) : undefined;
|
||||
|
||||
return (
|
||||
<div class="ribbon-container" style={{ contain: "none" }}>
|
||||
<div className="ribbon-top-row">
|
||||
<div className="ribbon-tab-container">
|
||||
{TAB_CONFIGURATION.map(({ title, icon }, i) => (
|
||||
{filteredTabs.map(({ title, icon, index }) => (
|
||||
<RibbonTab
|
||||
icon={icon}
|
||||
title={typeof title === "string" ? title : title(context)}
|
||||
active={i === activeTab}
|
||||
active={index === activeTabIndex}
|
||||
onClick={() => {
|
||||
if (activeTab !== i) {
|
||||
setActiveTab(i);
|
||||
if (activeTabIndex !== index) {
|
||||
setActiveTabIndex(index);
|
||||
} else {
|
||||
// Collapse
|
||||
setActiveTab(undefined);
|
||||
setActiveTabIndex(undefined);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@ -129,7 +127,7 @@ export default function Ribbon() {
|
||||
|
||||
<div className="ribbon-body-container">
|
||||
<div className="ribbon-body">
|
||||
{activeTabConfiguration?.content && activeTabConfiguration.content()}
|
||||
{activeTabConfiguration?.content && activeTabConfiguration.content({ note })}
|
||||
</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