import { NoteType } from "@triliumnext/commons"; import { useContext, useEffect, useState } from "preact/hooks"; import Component from "../../components/component"; import NoteContext from "../../components/note_context"; import FNote from "../../entities/fnote"; import { t } from "../../services/i18n"; import { downloadFileNote, openNoteExternally } from "../../services/open"; import { openInAppHelpFromUrl } from "../../services/utils"; 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 { ParentComponent } from "../react/react_utils"; import { buildUploadNewFileRevisionListener } from "./FilePropertiesTab"; import { buildUploadNewImageRevisionListener } from "./ImagePropertiesTab"; interface NoteActionsCustomProps { note: FNote; ntxId: string; noteContext: NoteContext; } interface NoteActionsCustomInnerProps extends NoteActionsCustomProps { noteMime: string; noteType: NoteType; isReadOnly: boolean; isDefaultViewMode: boolean; parentComponent: Component; viewType: ViewTypeOptions | null | undefined; } /** * Part of {@link NoteActions} on the new layout, but are rendered with a slight spacing * from the rest of the note items and the buttons differ based on the note type. */ export default function NoteActionsCustom(props: NoteActionsCustomProps) { const { note } = props; const noteType = useNoteProperty(note, "type"); const noteMime = useNoteProperty(note, "mime"); const [ viewType ] = useNoteLabel(note, "viewType"); const parentComponent = useContext(ParentComponent); const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly"); const innerProps: NoteActionsCustomInnerProps | false = !!noteType && !!noteMime && !!parentComponent && { ...props, noteType, noteMime, viewType: viewType as ViewTypeOptions | null | undefined, isDefaultViewMode: props.noteContext.viewScope?.viewMode === "default", parentComponent, isReadOnly }; return (innerProps &&
); } //#region Note type mappings function NoteActionsCustomInner(props: NoteActionsCustomInnerProps) { switch (props.note.type) { case "file": return ; case "image": return ; default: return null; } } function FileActions(props: NoteActionsCustomInnerProps) { return ( <> ); } function ImageActions(props: NoteActionsCustomInnerProps) { return ( <> ); } //#endregion //#region Shared buttons function UploadNewRevisionButton({ note, onChange }: NoteActionsCustomInnerProps & { onChange: (files: FileList | null) => void; }) { return ( ); } function OpenExternallyButton({ note, noteMime }: NoteActionsCustomInnerProps) { return ( openNoteExternally(note.noteId, noteMime)} /> ); } function DownloadFileButton({ note }: NoteActionsCustomInnerProps) { return ( downloadFileNote(note.noteId)} /> ); } //#region Floating buttons function CopyReferenceToClipboardButton({ ntxId, noteType, parentComponent }: NoteActionsCustomInnerProps) { return (["mermaid", "canvas", "mindMap", "image"].includes(noteType) && parentComponent?.triggerEvent("copyImageReferenceToClipboard", { ntxId })} /> ); } function RefreshButton({ note, noteType, isDefaultViewMode, parentComponent, noteContext }: NoteActionsCustomInnerProps) { const isEnabled = (note.noteId === "_backendLog" || noteType === "render") && isDefaultViewMode; return (isEnabled && parentComponent.triggerEvent("refreshData", { ntxId: noteContext.ntxId })} /> ); } function SwitchSplitOrientationButton({ note, isReadOnly, isDefaultViewMode }: NoteActionsCustomInnerProps) { const isShown = note.type === "mermaid" && note.isContentAvailable() && isDefaultViewMode; const [ splitEditorOrientation, setSplitEditorOrientation ] = useTriliumOption("splitEditorOrientation"); const upcomingOrientation = splitEditorOrientation === "horizontal" ? "vertical" : "horizontal"; return isShown && setSplitEditorOrientation(upcomingOrientation)} disabled={isReadOnly} />; } function ToggleReadOnlyButton({ note, viewType, isDefaultViewMode }: NoteActionsCustomInnerProps) { const [ isReadOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly"); const isEnabled = ([ "mermaid", "mindMap", "canvas" ].includes(note.type) || viewType === "geoMap") && note.isContentAvailable() && isDefaultViewMode; return isEnabled && setReadOnly(!isReadOnly)} />; } function RunActiveNoteButton({ noteMime }: NoteActionsCustomInnerProps) { const isEnabled = noteMime.startsWith("application/javascript") || noteMime === "text/x-sqlite;schema=trilium"; return isEnabled && ; } function SaveToNoteButton({ note, noteMime }: NoteActionsCustomInnerProps) { const [ isEnabled, setIsEnabled ] = useState(false); function refresh() { setIsEnabled(noteMime === "text/x-sqlite;schema=trilium" && note.isHiddenCompletely()); } useEffect(refresh, [ note, noteMime ]); useTriliumEvent("entitiesReloaded", ({ loadResults }) => { if (loadResults.getBranchRows().find(b => b.noteId === note.noteId)) { refresh(); } }); return isEnabled && ; } function OpenTriliumApiDocsButton({ noteMime }: NoteActionsCustomInnerProps) { const isEnabled = noteMime.startsWith("application/javascript;env="); return isEnabled && openInAppHelpFromUrl(noteMime.endsWith("frontend") ? "Q2z6av6JZVWm" : "MEtfsqa5VwNi")} />; } //#endregion