diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 55e40a576..a5a7c037c 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -103,6 +103,7 @@ export default function NoteDetail() { key={type} type={type as ExtendedNoteType} isVisible={activeNoteType === type} + isFullHeight={isFullHeight} props={props} /> })} @@ -114,7 +115,7 @@ export default function NoteDetail() { * Wraps a single note type widget, in order to keep it in the DOM even after the user has switched away to another note type. This allows faster loading of the same note type again. The properties are cached, so that they are updated only * while the widget is visible, to avoid rendering in the background. When not visible, the DOM element is simply hidden. */ -function NoteDetailWrapper({ Element, type, isVisible, props }: { Element: (props: TypeWidgetProps) => VNode, type: ExtendedNoteType, isVisible: boolean, props: TypeWidgetProps }) { +function NoteDetailWrapper({ Element, type, isVisible, isFullHeight, props }: { Element: (props: TypeWidgetProps) => VNode, type: ExtendedNoteType, isVisible: boolean, isFullHeight: boolean, props: TypeWidgetProps }) { const [ cachedProps, setCachedProps ] = useState(props); useEffect(() => { @@ -125,10 +126,15 @@ function NoteDetailWrapper({ Element, type, isVisible, props }: { Element: (prop } }, [ isVisible ]); + const typeMapping = TYPE_MAPPINGS[type]; return ( -
+
{ }
); diff --git a/apps/client/src/widgets/note_types.tsx b/apps/client/src/widgets/note_types.tsx index ec7a3d75f..a8e3086b9 100644 --- a/apps/client/src/widgets/note_types.tsx +++ b/apps/client/src/widgets/note_types.tsx @@ -18,73 +18,117 @@ type NoteTypeView = () => Promise<{ default: TypeWidget } | TypeWidget> | ((prop interface NoteTypeMapping { view: NoteTypeView; + printable?: boolean; + /** The class name to assign to the note type wrapper */ + className: string; } export const TYPE_MAPPINGS: Record = { empty: { view: () => import("./type_widgets/Empty"), + className: "note-detail-empty", + printable: true }, doc: { - view: () => import("./type_widgets/Doc") + view: () => import("./type_widgets/Doc"), + className: "note-detail-doc", + printable: true }, search: { - view: () =>
+ view: () => <>, + className: "note-detail-none", + printable: true }, protectedSession: { - view: () => import("./type_widgets/ProtectedSession") + view: () => import("./type_widgets/ProtectedSession"), + className: "protected-session-password-component" }, book: { - view: () => import("./type_widgets/Book") + view: () => import("./type_widgets/Book"), + className: "note-detail-book", + printable: true, }, contentWidget: { - view: () => import("./type_widgets/ContentWidget") + view: () => import("./type_widgets/ContentWidget"), + className: "note-detail-content-widget", + printable: true }, webView: { - view: () => import("./type_widgets/WebView") + view: () => import("./type_widgets/WebView"), + className: "note-detail-web-view", + printable: true }, file: { - view: () => import("./type_widgets/File") + view: () => import("./type_widgets/File"), + className: "note-detail-file", + printable: true }, image: { - view: () => import("./type_widgets/Image") + view: () => import("./type_widgets/Image"), + className: "note-detail-image", + printable: true }, readOnlyCode: { - view: async () => (await import("./type_widgets/code/Code")).ReadOnlyCode + view: async () => (await import("./type_widgets/code/Code")).ReadOnlyCode, + className: "note-detail-readonly-code", + printable: true }, editableCode: { - view: async () => (await import("./type_widgets/code/Code")).EditableCode + view: async () => (await import("./type_widgets/code/Code")).EditableCode, + className: "note-detail-code", + printable: true }, mermaid: { - view: () => import("./type_widgets/Mermaid") + view: () => import("./type_widgets/Mermaid"), + className: "note-detail-mermaid", + printable: true }, mindMap: { - view: () => import("./type_widgets/MindMap") + view: () => import("./type_widgets/MindMap"), + className: "note-detail-mind-map", + printable: true }, attachmentList: { - view: async () => (await import("./type_widgets/Attachment")).AttachmentList + view: async () => (await import("./type_widgets/Attachment")).AttachmentList, + className: "attachment-list", + printable: true }, attachmentDetail: { - view: async () => (await import("./type_widgets/Attachment")).AttachmentDetail + view: async () => (await import("./type_widgets/Attachment")).AttachmentDetail, + className: "attachment-detail", + printable: true }, readOnlyText: { - view: () => import("./type_widgets/text/ReadOnlyText") + view: () => import("./type_widgets/text/ReadOnlyText"), + className: "note-detail-readonly-text" }, editableText: { - view: () => import("./type_widgets/text/EditableText") + view: () => import("./type_widgets/text/EditableText"), + className: "note-detail-editable-text", + printable: true }, render: { - view: () => import("./type_widgets/Render") + view: () => import("./type_widgets/Render"), + className: "note-detail-render", + printable: true }, canvas: { - view: () => import("./type_widgets/Canvas") + view: () => import("./type_widgets/Canvas"), + className: "note-detail-canvas", + printable: true }, relationMap: { - view: () => import("./type_widgets/relation_map/RelationMap") + view: () => import("./type_widgets/relation_map/RelationMap"), + className: "note-detail-relation-map", + printable: true }, noteMap: { - view: () => import("./type_widgets/NoteMap") + view: () => import("./type_widgets/NoteMap"), + className: "note-detail-note-map", + printable: true }, aiChat: { - view: () => import("./type_widgets/AiChat") + view: () => import("./type_widgets/AiChat"), + className: "ai-chat-widget-container" } }; diff --git a/apps/client/src/widgets/type_widgets/AiChat.tsx b/apps/client/src/widgets/type_widgets/AiChat.tsx index 81da5355d..97e9f9eb5 100644 --- a/apps/client/src/widgets/type_widgets/AiChat.tsx +++ b/apps/client/src/widgets/type_widgets/AiChat.tsx @@ -31,7 +31,6 @@ export default function AiChat({ note, noteContext }: TypeWidgetProps) { return llmChatPanel; }, { noteContext, - containerClassName: "ai-chat-widget-container", containerStyle: { height: "100%" } diff --git a/apps/client/src/widgets/type_widgets/Attachment.tsx b/apps/client/src/widgets/type_widgets/Attachment.tsx index 886b8e892..369844b5f 100644 --- a/apps/client/src/widgets/type_widgets/Attachment.tsx +++ b/apps/client/src/widgets/type_widgets/Attachment.tsx @@ -46,7 +46,7 @@ export function AttachmentList({ note }: TypeWidgetProps) { }); return ( -
+ <>
@@ -58,7 +58,7 @@ export function AttachmentList({ note }: TypeWidgetProps) { )}
-
+ ) } @@ -99,7 +99,7 @@ export function AttachmentDetail({ note, viewScope }: TypeWidgetProps) { }, [ viewScope ]); return ( -
+ <>
{t("attachment_detail.owning_note")}{" "} @@ -122,7 +122,7 @@ export function AttachmentDetail({ note, viewScope }: TypeWidgetProps) { {t("attachment_detail.attachment_deleted")} )}
-
+ ) } diff --git a/apps/client/src/widgets/type_widgets/Book.tsx b/apps/client/src/widgets/type_widgets/Book.tsx index b27dd63d2..83c726d97 100644 --- a/apps/client/src/widgets/type_widgets/Book.tsx +++ b/apps/client/src/widgets/type_widgets/Book.tsx @@ -23,13 +23,9 @@ export default function Book({ note }: TypeWidgetProps) { } }); - return ( -
- {(shouldDisplayNoChildrenWarning && ( - - - - ))} -
+ return (shouldDisplayNoChildrenWarning && + + + ) } diff --git a/apps/client/src/widgets/type_widgets/Canvas.tsx b/apps/client/src/widgets/type_widgets/Canvas.tsx index 90b381e10..bb3b8ecff 100644 --- a/apps/client/src/widgets/type_widgets/Canvas.tsx +++ b/apps/client/src/widgets/type_widgets/Canvas.tsx @@ -60,28 +60,26 @@ export default function Canvas({ note }: TypeWidgetProps) { }, []); return ( -
-
-
- apiRef.current = api} - theme={themeStyle} - viewModeEnabled={isReadOnly || options.is("databaseReadonly")} - zenModeEnabled={false} - isCollaborating={false} - detectScroll={false} - handleKeyboardGlobally={false} - autoFocus={false} - UIOptions={{ - canvasActions: { - saveToActiveFile: false, - export: false - } - }} - onLinkOpen={onLinkOpen} - {...persistence} - /> -
+
+
+ apiRef.current = api} + theme={themeStyle} + viewModeEnabled={isReadOnly || options.is("databaseReadonly")} + zenModeEnabled={false} + isCollaborating={false} + detectScroll={false} + handleKeyboardGlobally={false} + autoFocus={false} + UIOptions={{ + canvasActions: { + saveToActiveFile: false, + export: false + } + }} + onLinkOpen={onLinkOpen} + {...persistence} + />
) diff --git a/apps/client/src/widgets/type_widgets/ContentWidget.tsx b/apps/client/src/widgets/type_widgets/ContentWidget.tsx index c91df0d0b..20d011473 100644 --- a/apps/client/src/widgets/type_widgets/ContentWidget.tsx +++ b/apps/client/src/widgets/type_widgets/ContentWidget.tsx @@ -50,12 +50,10 @@ const CONTENT_WIDGETS: Record -
- {Content - ? - : (t("content_widget.unknown_widget", { id: note.noteId }))} -
+
+ {Content + ? + : (t("content_widget.unknown_widget", { id: note.noteId }))}
) } diff --git a/apps/client/src/widgets/type_widgets/Doc.css b/apps/client/src/widgets/type_widgets/Doc.css index 2f8053ffe..0081da3c7 100644 --- a/apps/client/src/widgets/type_widgets/Doc.css +++ b/apps/client/src/widgets/type_widgets/Doc.css @@ -18,15 +18,15 @@ border: 1px solid var(--main-border-color); } -.note-detail-doc.contextual-help { +.note-detail-doc-content.contextual-help { padding-bottom: 0; } -.note-detail-doc.contextual-help h2, -.note-detail-doc.contextual-help h3, -.note-detail-doc.contextual-help h4, -.note-detail-doc.contextual-help h5, -.note-detail-doc.contextual-help h6 { +.note-detail-doc-content.contextual-help h2, +.note-detail-doc-content.contextual-help h3, +.note-detail-doc-content.contextual-help h4, +.note-detail-doc-content.contextual-help h5, +.note-detail-doc-content.contextual-help h6 { font-size: 1.25rem; background-color: var(--main-background-color); position: sticky; diff --git a/apps/client/src/widgets/type_widgets/Doc.tsx b/apps/client/src/widgets/type_widgets/Doc.tsx index 4d27aa760..f1465571c 100644 --- a/apps/client/src/widgets/type_widgets/Doc.tsx +++ b/apps/client/src/widgets/type_widgets/Doc.tsx @@ -27,12 +27,10 @@ export default function Doc({ note, viewScope, ntxId }: TypeWidgetProps) { }); return ( -
- -
+ ); } diff --git a/apps/client/src/widgets/type_widgets/Empty.tsx b/apps/client/src/widgets/type_widgets/Empty.tsx index f101d95f1..3c0abb11e 100644 --- a/apps/client/src/widgets/type_widgets/Empty.tsx +++ b/apps/client/src/widgets/type_widgets/Empty.tsx @@ -12,10 +12,10 @@ import { TypeWidgetProps } from "./type_widget"; export default function Empty({ }: TypeWidgetProps) { return ( -
+ <> -
+ ) } diff --git a/apps/client/src/widgets/type_widgets/File.tsx b/apps/client/src/widgets/type_widgets/File.tsx index b002f54aa..0c5a79b5a 100644 --- a/apps/client/src/widgets/type_widgets/File.tsx +++ b/apps/client/src/widgets/type_widgets/File.tsx @@ -12,24 +12,17 @@ const TEXT_MAX_NUM_CHARS = 5000; export default function File({ note }: TypeWidgetProps) { const blob = useNoteBlob(note); - let preview: VNode | null = null; if (blob?.content) { - preview = + return } else if (note.mime === "application/pdf") { - preview = + return } else if (note.mime.startsWith("video/")) { - preview = + return } else if (note.mime.startsWith("audio/")) { - preview = + return } else { - preview = + return } - - return ( -
- {preview} -
- ); } function TextPreview({ content }: { content: string }) { diff --git a/apps/client/src/widgets/type_widgets/Image.tsx b/apps/client/src/widgets/type_widgets/Image.tsx index 8381127fb..e9f8738bd 100644 --- a/apps/client/src/widgets/type_widgets/Image.tsx +++ b/apps/client/src/widgets/type_widgets/Image.tsx @@ -41,14 +41,12 @@ export default function Image({ note, ntxId }: TypeWidgetProps) { }); return ( -
-
- -
+
+
) } diff --git a/apps/client/src/widgets/type_widgets/MindMap.tsx b/apps/client/src/widgets/type_widgets/MindMap.tsx index 6f4bb5fe7..542a5152a 100644 --- a/apps/client/src/widgets/type_widgets/MindMap.tsx +++ b/apps/client/src/widgets/type_widgets/MindMap.tsx @@ -7,7 +7,7 @@ import nodeMenu from "@mind-elixir/node-menu"; import "mind-elixir/style"; import "@mind-elixir/node-menu/dist/style.css"; import "./MindMap.css"; -import { useEditorSpacedUpdate, useNoteLabelBoolean, useTriliumEvent, useTriliumEvents, useTriliumOptionBool } from "../react/hooks"; +import { useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOptionBool } from "../react/hooks"; import { refToJQuerySelector } from "../react/react_utils"; import utils from "../../services/utils"; @@ -16,6 +16,7 @@ const NEW_TOPIC_NAME = ""; interface MindElixirProps { apiRef?: RefObject; containerProps?: Omit, "ref">; + containerRef?: RefObject; editable: boolean; content: MindElixirData; onChange?: () => void; @@ -94,23 +95,22 @@ export default function MindMap({ note, ntxId }: TypeWidgetProps) { }, []); return ( -
- spacedUpdate.scheduleUpdate()} - editable={!isReadOnly} - containerProps={{ - className: "mind-map-container", - onKeyDown - }} - /> -
+ spacedUpdate.scheduleUpdate()} + editable={!isReadOnly} + containerProps={{ + className: "mind-map-container", + onKeyDown + }} + /> ) } -function MindElixir({ content, containerProps, apiRef: externalApiRef, onChange, editable }: MindElixirProps) { - const containerRef = useRef(null); +function MindElixir({ content, containerRef: externalContainerRef, containerProps, apiRef: externalApiRef, onChange, editable }: MindElixirProps) { + const containerRef = useSyncedRef(externalContainerRef, null); const apiRef = useRef(null); useEffect(() => { diff --git a/apps/client/src/widgets/type_widgets/NoteMap.tsx b/apps/client/src/widgets/type_widgets/NoteMap.tsx index 55fe8dc4a..7a308151c 100644 --- a/apps/client/src/widgets/type_widgets/NoteMap.tsx +++ b/apps/client/src/widgets/type_widgets/NoteMap.tsx @@ -6,7 +6,7 @@ export default function NoteMap({ note }: TypeWidgetProps) { const containerRef = useRef(null); return ( -
+
); diff --git a/apps/client/src/widgets/type_widgets/ProtectedSession.tsx b/apps/client/src/widgets/type_widgets/ProtectedSession.tsx index 55d5a48b6..b7af4aebc 100644 --- a/apps/client/src/widgets/type_widgets/ProtectedSession.tsx +++ b/apps/client/src/widgets/type_widgets/ProtectedSession.tsx @@ -20,23 +20,21 @@ export default function ProtectedSession() { }, [ passwordRef ]); return ( -
-
- - - - -
+ + +