mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
cleanup
This commit is contained in:
@@ -8,13 +8,10 @@ import {
|
||||
} from "@/features/editor/components/table/types/types.ts";
|
||||
import { ActionIcon, Tooltip } from "@mantine/core";
|
||||
import {
|
||||
IconDownload,
|
||||
IconPaperclip,
|
||||
IconTrash,
|
||||
} from "@tabler/icons-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getFileUrl } from "@/lib/config.ts";
|
||||
import { isInternalFileUrl } from "@docmost/editor-ext";
|
||||
import classes from "../common/toolbar-menu.module.css";
|
||||
|
||||
export function PdfMenu({ editor }: EditorMenuProps) {
|
||||
@@ -40,11 +37,15 @@ export function PdfMenu({ editor }: EditorMenuProps) {
|
||||
|
||||
const shouldShow = useCallback(
|
||||
({ state }: ShouldShowProps) => {
|
||||
if (!state) {
|
||||
if (!state || !editor.isActive("pdf")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return editor.isActive("pdf") && editor.getAttributes("pdf").src;
|
||||
const { selection } = state;
|
||||
const dom = editor.view.nodeDOM(selection.from) as HTMLElement | null;
|
||||
if (!dom) return false;
|
||||
|
||||
return !!dom.querySelector("[data-pdf-error]");
|
||||
},
|
||||
[editor],
|
||||
);
|
||||
@@ -71,15 +72,6 @@ export function PdfMenu({ editor }: EditorMenuProps) {
|
||||
};
|
||||
}, [editor]);
|
||||
|
||||
const handleDownload = useCallback(() => {
|
||||
if (!editorState?.src || !isInternalFileUrl(editorState.src)) return;
|
||||
const url = getFileUrl(editorState.src);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "";
|
||||
a.click();
|
||||
}, [editorState?.src]);
|
||||
|
||||
const handleConvertToAttachment = useCallback(() => {
|
||||
if (!editorState?.src) return;
|
||||
|
||||
@@ -124,17 +116,6 @@ export function PdfMenu({ editor }: EditorMenuProps) {
|
||||
shouldShow={shouldShow}
|
||||
>
|
||||
<div className={classes.toolbar}>
|
||||
<Tooltip position="top" label={t("Download")} withinPortal={false}>
|
||||
<ActionIcon
|
||||
onClick={handleDownload}
|
||||
size="lg"
|
||||
aria-label={t("Download")}
|
||||
variant="subtle"
|
||||
>
|
||||
<IconDownload size={18} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip position="top" label={t("Convert to attachment")} withinPortal={false}>
|
||||
<ActionIcon
|
||||
onClick={handleConvertToAttachment}
|
||||
|
||||
@@ -52,10 +52,32 @@
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.clickOverlay {
|
||||
.hoverMenu {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
cursor: pointer;
|
||||
top: 56px;
|
||||
right: 8px;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
border-radius: 6px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.hoverMenu::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -12px;
|
||||
}
|
||||
|
||||
.hoverMenu:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.pdfResizeWrapper:hover .hoverMenu {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.pdfError {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NodeViewProps, NodeViewWrapper } from "@tiptap/react";
|
||||
import { Group, Loader, Text } from "@mantine/core";
|
||||
import { ActionIcon, Group, Loader, Text, Tooltip } from "@mantine/core";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { getFileUrl } from "@/lib/config.ts";
|
||||
import { ResizableWrapper } from "../common/resizable-wrapper";
|
||||
@@ -7,7 +7,11 @@ import clsx from "clsx";
|
||||
import classes from "./pdf-view.module.css";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { isInternalFileUrl } from "@docmost/editor-ext";
|
||||
import { IconFileTypePdf } from "@tabler/icons-react";
|
||||
import {
|
||||
IconFileTypePdf,
|
||||
IconPaperclip,
|
||||
IconTrash,
|
||||
} from "@tabler/icons-react";
|
||||
|
||||
export default function PdfView(props: NodeViewProps) {
|
||||
const { t } = useTranslation();
|
||||
@@ -34,6 +38,38 @@ export default function PdfView(props: NodeViewProps) {
|
||||
[updateAttributes],
|
||||
);
|
||||
|
||||
const handleConvertToAttachment = useCallback(() => {
|
||||
if (!src) return;
|
||||
const pos = getPos();
|
||||
if (pos === undefined) return;
|
||||
const currentNode = editor.state.doc.nodeAt(pos);
|
||||
if (!currentNode || currentNode.type.name !== "pdf") return;
|
||||
|
||||
editor
|
||||
.chain()
|
||||
.insertContentAt(
|
||||
{ from: pos, to: pos + currentNode.nodeSize },
|
||||
{
|
||||
type: "attachment",
|
||||
attrs: {
|
||||
url: currentNode.attrs.src,
|
||||
name: currentNode.attrs.name,
|
||||
attachmentId: currentNode.attrs.attachmentId,
|
||||
size: currentNode.attrs.size,
|
||||
mime: "application/pdf",
|
||||
},
|
||||
},
|
||||
)
|
||||
.run();
|
||||
}, [editor, src, getPos]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
const pos = getPos();
|
||||
if (pos === undefined) return;
|
||||
editor.commands.setNodeSelection(pos);
|
||||
editor.commands.deleteSelection();
|
||||
}, [editor, getPos]);
|
||||
|
||||
if (!src || !safeSrc) {
|
||||
return (
|
||||
<NodeViewWrapper data-drag-handle>
|
||||
@@ -54,7 +90,7 @@ export default function PdfView(props: NodeViewProps) {
|
||||
if (hasError) {
|
||||
return (
|
||||
<NodeViewWrapper data-drag-handle>
|
||||
<div className={classes.pdfError} onClick={handleSelect}>
|
||||
<div data-pdf-error className={clsx(classes.pdfError, { "ProseMirror-selectednode": selected })} onClick={handleSelect}>
|
||||
<IconFileTypePdf size={32} stroke={1.5} />
|
||||
<Text size="sm" c="dimmed">
|
||||
{t("Failed to load PDF")}
|
||||
@@ -99,7 +135,32 @@ export default function PdfView(props: NodeViewProps) {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{!selected && <div className={classes.clickOverlay} onClick={handleSelect} />}
|
||||
{editor.isEditable && (
|
||||
<div className={classes.hoverMenu}>
|
||||
<Tooltip position="top" label={t("Convert to attachment")} withinPortal>
|
||||
<ActionIcon
|
||||
size="sm"
|
||||
variant="filled"
|
||||
color="dark"
|
||||
onClick={handleConvertToAttachment}
|
||||
aria-label={t("Convert to attachment")}
|
||||
>
|
||||
<IconPaperclip size={14} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Tooltip position="top" label={t("Delete")} withinPortal>
|
||||
<ActionIcon
|
||||
size="sm"
|
||||
variant="filled"
|
||||
color="dark"
|
||||
onClick={handleDelete}
|
||||
aria-label={t("Delete")}
|
||||
>
|
||||
<IconTrash size={14} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</ResizableWrapper>
|
||||
</div>
|
||||
</NodeViewWrapper>
|
||||
|
||||
@@ -427,7 +427,7 @@ const CommandGroups: SlashMenuGroupedItemsType = {
|
||||
editor.chain().focus().deleteRange(range).setDrawio().run(),
|
||||
},
|
||||
{
|
||||
title: "Excalidraw diagram (Whiteboard)",
|
||||
title: "Excalidraw (Whiteboard)",
|
||||
description: "Draw and sketch excalidraw diagrams",
|
||||
searchTerms: ["diagrams", "draw", "sketch", "whiteboard"],
|
||||
icon: IconExcalidraw,
|
||||
|
||||
Reference in New Issue
Block a user