mirror of
https://github.com/zadam/trilium.git
synced 2025-11-11 17:08:58 +01:00
chore(react/type_widgets): port text touchbar (untested)
This commit is contained in:
parent
37d33fb975
commit
3ed399a888
@ -25,6 +25,7 @@ interface ButtonProps {
|
||||
icon?: string;
|
||||
click: () => void;
|
||||
enabled?: boolean;
|
||||
backgroundColor?: string;
|
||||
}
|
||||
|
||||
interface SpacerProps {
|
||||
@ -129,13 +130,14 @@ export function TouchBarSlider({ label, value, minValue, maxValue, onChange }: S
|
||||
return <></>;
|
||||
}
|
||||
|
||||
export function TouchBarButton({ label, icon, click, enabled }: ButtonProps) {
|
||||
export function TouchBarButton({ label, icon, click, enabled, backgroundColor }: ButtonProps) {
|
||||
const api = useContext(TouchBarContext);
|
||||
const item = useMemo(() => {
|
||||
if (!api) return null;
|
||||
return new api.TouchBar.TouchBarButton({
|
||||
label, click, enabled,
|
||||
icon: icon ? buildIcon(api.nativeImage, icon) : undefined
|
||||
icon: icon ? buildIcon(api.nativeImage, icon) : undefined,
|
||||
backgroundColor
|
||||
});
|
||||
}, [ label, icon ]);
|
||||
|
||||
@ -171,6 +173,32 @@ export function TouchBarSegmentedControl({ mode, segments, selectedIndex, onChan
|
||||
return <></>;
|
||||
}
|
||||
|
||||
export function TouchBarGroup({ children }: { children: ComponentChildren }) {
|
||||
const remote = dynamicRequire("@electron/remote") as typeof import("@electron/remote");
|
||||
const items: TouchBarItem[] = [];
|
||||
|
||||
const api: TouchBarContextApi = {
|
||||
TouchBar: remote.TouchBar,
|
||||
nativeImage: remote.nativeImage,
|
||||
addItem: (item) => {
|
||||
items.push(item);
|
||||
}
|
||||
};
|
||||
|
||||
if (api) {
|
||||
const item = new api.TouchBar.TouchBarGroup({
|
||||
items: new api.TouchBar({ items })
|
||||
});
|
||||
api.addItem(item);
|
||||
}
|
||||
|
||||
return <>
|
||||
<TouchBarContext.Provider value={api}>
|
||||
{children}
|
||||
</TouchBarContext.Provider>
|
||||
</>;
|
||||
}
|
||||
|
||||
export function TouchBarSpacer({ size }: SpacerProps) {
|
||||
const api = useContext(TouchBarContext);
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import dialog from "../../../services/dialog";
|
||||
import toast from "../../../services/toast";
|
||||
import utils, { deferred, isMobile } from "../../../services/utils";
|
||||
import utils, { deferred, hasTouchBar, isMobile } from "../../../services/utils";
|
||||
import { useEditorSpacedUpdate, useKeyboardShortcuts, useLegacyImperativeHandlers, useNoteLabel, useTriliumEvent, useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
|
||||
import { TypeWidgetProps } from "../type_widget";
|
||||
import CKEditorWithWatchdog, { CKEditorApi } from "./CKEditorWithWatchdog";
|
||||
@ -14,6 +14,9 @@ import getTemplates, { updateTemplateCache } from "./snippets.js";
|
||||
import appContext from "../../../components/app_context";
|
||||
import link, { parseNavigationStateFromUrl } from "../../../services/link";
|
||||
import note_create from "../../../services/note_create";
|
||||
import TouchBar, { TouchBarButton, TouchBarGroup, TouchBarSegmentedControl } from "../../react/TouchBar";
|
||||
import { RefObject } from "preact";
|
||||
import { buildSelectedBackgroundColor } from "../../../components/touch_bar";
|
||||
|
||||
/**
|
||||
* The editor can operate into two distinct modes:
|
||||
@ -26,6 +29,7 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
|
||||
const [ content, setContent ] = useState<string>();
|
||||
const watchdogRef = useRef<EditorWatchdog>(null);
|
||||
const editorApiRef = useRef<CKEditorApi>(null);
|
||||
const refreshTouchBarRef = useRef<() => void>(null);
|
||||
const [ language ] = useNoteLabel(note, "language");
|
||||
const [ textNoteEditorType ] = useTriliumOption("textNoteEditorType");
|
||||
const [ codeBlockWordWrap ] = useTriliumOptionBool("codeBlockWordWrap");
|
||||
@ -201,9 +205,18 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
|
||||
setupClassicEditor(editor, parentComponent);
|
||||
}
|
||||
|
||||
if (hasTouchBar) {
|
||||
const handler = () => refreshTouchBarRef.current?.();
|
||||
for (const event of [ "bold", "italic", "underline", "paragraph", "heading" ]) {
|
||||
editor.commands.get(event)?.on("change", handler);
|
||||
}
|
||||
}
|
||||
|
||||
initialized.current.resolve();
|
||||
}}
|
||||
/>}
|
||||
|
||||
<EditableTextTouchBar watchdogRef={watchdogRef} refreshTouchBarRef={refreshTouchBarRef} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -304,3 +317,68 @@ function findClassicToolbar(parentComponent: Component): JQuery<HTMLElement> {
|
||||
return $("body").find(".classic-toolbar-widget");
|
||||
}
|
||||
}
|
||||
|
||||
function EditableTextTouchBar({ watchdogRef, refreshTouchBarRef }: { watchdogRef: RefObject<EditorWatchdog | null>, refreshTouchBarRef: RefObject<() => void> }) {
|
||||
const [ headingSelectedIndex, setHeadingSelectedIndex ] = useState<number>();
|
||||
|
||||
function refresh() {
|
||||
let headingSelectedIndex: number | undefined = undefined;
|
||||
const editor = watchdogRef.current?.editor;
|
||||
const headingCommand = editor?.commands.get("heading");
|
||||
const paragraphCommand = editor?.commands.get("paragraph");
|
||||
if (paragraphCommand?.value) {
|
||||
headingSelectedIndex = 0;
|
||||
} else if (headingCommand?.value === "heading2") {
|
||||
headingSelectedIndex = 1;
|
||||
} else if (headingCommand?.value === "heading3") {
|
||||
headingSelectedIndex = 2;
|
||||
}
|
||||
setHeadingSelectedIndex(headingSelectedIndex);
|
||||
}
|
||||
|
||||
useEffect(refresh, []);
|
||||
refreshTouchBarRef.current = refresh;
|
||||
|
||||
return (
|
||||
<TouchBar>
|
||||
<TouchBarSegmentedControl
|
||||
segments={[
|
||||
{ label: "P" },
|
||||
{ label: "H2" },
|
||||
{ label: "H3" }
|
||||
]}
|
||||
onChange={(selectedIndex) => {
|
||||
const editor = watchdogRef.current?.editor;
|
||||
switch (selectedIndex) {
|
||||
case 0:
|
||||
editor?.execute("paragraph")
|
||||
break;
|
||||
case 1:
|
||||
editor?.execute("heading", { value: "heading2" });
|
||||
break;
|
||||
case 2:
|
||||
editor?.execute("heading", { value: "heading3" });
|
||||
break;
|
||||
}
|
||||
}}
|
||||
selectedIndex={headingSelectedIndex}
|
||||
mode="buttons"
|
||||
/>
|
||||
|
||||
<TouchBarGroup>
|
||||
<TouchBarCommandButton watchdogRef={watchdogRef} command="bold" icon="NSTouchBarTextBoldTemplate" />
|
||||
<TouchBarCommandButton watchdogRef={watchdogRef} command="italic" icon="NSTouchBarTextItalicTemplate" />
|
||||
<TouchBarCommandButton watchdogRef={watchdogRef} command="underline" icon="NSTouchBarTextUnderlineTemplate" />
|
||||
</TouchBarGroup>
|
||||
</TouchBar>
|
||||
)
|
||||
}
|
||||
|
||||
function TouchBarCommandButton({ watchdogRef, icon, command }: { watchdogRef: RefObject<EditorWatchdog | null>, icon: string, command: string }) {
|
||||
const editor = watchdogRef.current?.editor;
|
||||
return (<TouchBarButton
|
||||
icon={icon}
|
||||
click={() => editor?.execute(command)}
|
||||
backgroundColor={buildSelectedBackgroundColor(editor?.commands.get(command)?.value as boolean)}
|
||||
/>);
|
||||
}
|
||||
|
||||
@ -32,23 +32,6 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
super.doRender();
|
||||
}
|
||||
|
||||
async initEditor() {
|
||||
this.watchdog.setCreator(async (_, editorConfig) => {
|
||||
// Touch bar integration
|
||||
if (hasTouchBar) {
|
||||
for (const event of [ "bold", "italic", "underline", "paragraph", "heading" ]) {
|
||||
editor.commands.get(event)?.on("change", () => this.triggerCommand("refreshTouchBar"));
|
||||
}
|
||||
}
|
||||
|
||||
return editor;
|
||||
});
|
||||
|
||||
await this.createEditor();
|
||||
}
|
||||
|
||||
show() { }
|
||||
|
||||
getEditor() {
|
||||
return this.watchdog?.editor;
|
||||
}
|
||||
@ -80,64 +63,5 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
await this.reinitialize();
|
||||
}
|
||||
|
||||
buildTouchBarCommand(data: CommandListenerData<"buildTouchBar">) {
|
||||
const { TouchBar, buildIcon } = data;
|
||||
const { TouchBarSegmentedControl, TouchBarGroup, TouchBarButton } = TouchBar;
|
||||
const { editor } = this.watchdog;
|
||||
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const commandButton = (icon: string, command: string) => new TouchBarButton({
|
||||
icon: buildIcon(icon),
|
||||
click: () => editor.execute(command),
|
||||
backgroundColor: buildSelectedBackgroundColor(editor.commands.get(command)?.value as boolean)
|
||||
});
|
||||
|
||||
let headingSelectedIndex: number | undefined = undefined;
|
||||
const headingCommand = editor.commands.get("heading");
|
||||
const paragraphCommand = editor.commands.get("paragraph");
|
||||
if (paragraphCommand?.value) {
|
||||
headingSelectedIndex = 0;
|
||||
} else if (headingCommand?.value === "heading2") {
|
||||
headingSelectedIndex = 1;
|
||||
} else if (headingCommand?.value === "heading3") {
|
||||
headingSelectedIndex = 2;
|
||||
}
|
||||
|
||||
return [
|
||||
new TouchBarSegmentedControl({
|
||||
segments: [
|
||||
{ label: "P" },
|
||||
{ label: "H2" },
|
||||
{ label: "H3" }
|
||||
],
|
||||
change(selectedIndex: number, isSelected: boolean) {
|
||||
switch (selectedIndex) {
|
||||
case 0:
|
||||
editor.execute("paragraph")
|
||||
break;
|
||||
case 1:
|
||||
editor.execute("heading", { value: "heading2" });
|
||||
break;
|
||||
case 2:
|
||||
editor.execute("heading", { value: "heading3" });
|
||||
break;
|
||||
}
|
||||
},
|
||||
selectedIndex: headingSelectedIndex
|
||||
}),
|
||||
new TouchBarGroup({
|
||||
items: new TouchBar({
|
||||
items: [
|
||||
commandButton("NSTouchBarTextBoldTemplate", "bold"),
|
||||
commandButton("NSTouchBarTextItalicTemplate", "italic"),
|
||||
commandButton("NSTouchBarTextUnderlineTemplate", "underline")
|
||||
]
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user