mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-05-18 05:05:36 +02:00
editor: various fixes and improvements related to audio widget
This commit is contained in:
@@ -39,8 +39,6 @@ declare module "@tiptap/core" {
|
||||
|
||||
export const AudioNode = Node.create<AudioOptions>({
|
||||
name: "audio",
|
||||
content: "",
|
||||
marks: "",
|
||||
draggable: true,
|
||||
priority: 51,
|
||||
|
||||
@@ -71,7 +69,7 @@ export const AudioNode = Node.create<AudioOptions>({
|
||||
parseHTML() {
|
||||
return [
|
||||
{
|
||||
tag: "audio[data-hash][data-mime^='audio/']"
|
||||
tag: "audio"
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
@@ -28,39 +28,27 @@ import { DesktopOnly } from "../../components/responsive/index.js";
|
||||
import { toBlobURL, revokeBloburl } from "../../utils/downloader.js";
|
||||
import { formatBytes } from "@notesnook/common";
|
||||
|
||||
const SAMPLE_AUDIO = toBlobURL(
|
||||
"data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=",
|
||||
"other",
|
||||
"audio/wav",
|
||||
"sample-audio"
|
||||
);
|
||||
|
||||
export function AudioComponent(props: ReactNodeViewProps<AudioAttachment>) {
|
||||
const { editor, node, selected } = props;
|
||||
const { filename, size, progress, mime, hash } = node.attrs;
|
||||
const elementRef = useRef<HTMLDivElement>();
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [audioSrc, setAudioSrc] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
if (editor.storage?.getAttachmentData && hash) {
|
||||
editor.storage
|
||||
.getAttachmentData({
|
||||
type: "file",
|
||||
hash
|
||||
})
|
||||
.then((data: string | undefined) => {
|
||||
if (data) {
|
||||
const url = toBlobURL(data, "other", mime, hash);
|
||||
if (url) {
|
||||
setAudioSrc(url);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
}, [editor.storage, hash, mime]);
|
||||
const [error, setError] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (audioSrc && hash) {
|
||||
if (hash) {
|
||||
revokeBloburl(hash);
|
||||
}
|
||||
};
|
||||
}, [audioSrc, hash]);
|
||||
}, [hash]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -86,12 +74,13 @@ export function AudioComponent(props: ReactNodeViewProps<AudioAttachment>) {
|
||||
onDragStart={() => setIsDragging(true)}
|
||||
onDragEnd={() => setIsDragging(false)}
|
||||
data-drag-handle
|
||||
data-drag-image
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
mb: audioSrc ? 2 : 0
|
||||
mb: 2
|
||||
}}
|
||||
>
|
||||
<Icon path={Icons.attachment} size={16} />
|
||||
@@ -120,7 +109,9 @@ export function AudioComponent(props: ReactNodeViewProps<AudioAttachment>) {
|
||||
{progress ? `${progress}%` : formatBytes(size, 1)}
|
||||
</Text>
|
||||
</Box>
|
||||
{audioSrc && (
|
||||
{error ? (
|
||||
<Text variant="error">{error}</Text>
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
@@ -130,7 +121,39 @@ export function AudioComponent(props: ReactNodeViewProps<AudioAttachment>) {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<audio controls preload="metadata" src={audioSrc} />
|
||||
<audio
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onDragStart={(e) => e.stopPropagation()}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
controls
|
||||
controlsList="nodownload nofullscreen"
|
||||
src={SAMPLE_AUDIO}
|
||||
onPlay={(e) => {
|
||||
const target = e.currentTarget;
|
||||
if (
|
||||
editor.storage?.getAttachmentData &&
|
||||
hash &&
|
||||
target.src === SAMPLE_AUDIO
|
||||
) {
|
||||
e.preventDefault();
|
||||
editor.storage
|
||||
.getAttachmentData({
|
||||
type: "file",
|
||||
hash
|
||||
})
|
||||
.then((data: string | undefined) => {
|
||||
if (!data) return;
|
||||
const url = toBlobURL(data, "other", mime, hash);
|
||||
if (!url) return;
|
||||
target.src = url;
|
||||
return target.play();
|
||||
})
|
||||
.catch((e) => setError((e as Error).message));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Text as="p">Your browser does not support the audio element.</Text>
|
||||
</audio>
|
||||
</Box>
|
||||
)}
|
||||
<DesktopOnly>
|
||||
|
||||
@@ -23,6 +23,7 @@ import { MoreTools } from "../components/more-tools.js";
|
||||
import { useToolbarLocation } from "../stores/toolbar-store.js";
|
||||
import { findSelectedNode } from "../../utils/prosemirror.js";
|
||||
import { Attachment } from "../../extensions/attachment/index.js";
|
||||
import { Editor } from "../../types.js";
|
||||
|
||||
export function AttachmentSettings(props: ToolProps) {
|
||||
const { editor } = props;
|
||||
@@ -52,9 +53,7 @@ export function DownloadAttachment(props: ToolProps) {
|
||||
title={props.title}
|
||||
toggled={false}
|
||||
onClick={() => {
|
||||
const attachmentNode =
|
||||
findSelectedNode(editor, "attachment") ||
|
||||
findSelectedNode(editor, "image");
|
||||
const attachmentNode = findAttachmentNode(editor);
|
||||
|
||||
const attachment = (attachmentNode?.attrs || {}) as Attachment;
|
||||
editor.storage.downloadAttachment?.(attachment);
|
||||
@@ -65,8 +64,7 @@ export function DownloadAttachment(props: ToolProps) {
|
||||
|
||||
export function PreviewAttachment(props: ToolProps) {
|
||||
const { editor } = props;
|
||||
const attachmentNode =
|
||||
findSelectedNode(editor, "attachment") || findSelectedNode(editor, "image");
|
||||
const attachmentNode = findAttachmentNode(editor);
|
||||
const attachment = (attachmentNode?.attrs || {}) as Attachment;
|
||||
|
||||
if (!editor.isActive("image") && !canPreviewAttachment(attachment))
|
||||
@@ -117,3 +115,11 @@ function canPreviewAttachment(attachment: Attachment) {
|
||||
|
||||
return previewableFileExtensions.indexOf(extension) > -1;
|
||||
}
|
||||
|
||||
function findAttachmentNode(editor: Editor) {
|
||||
return (
|
||||
findSelectedNode(editor, "attachment") ||
|
||||
findSelectedNode(editor, "image") ||
|
||||
findSelectedNode(editor, "audio")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -131,8 +131,9 @@
|
||||
}
|
||||
|
||||
.ProseMirror > div.codeblock-view-content-wrap,
|
||||
.ProseMirror > div.taskList-view-content-wrap,
|
||||
.ProseMirror > div.math-block.math-node {
|
||||
.ProseMirror > div.math-block.math-node,
|
||||
.ProseMirror > div.audio-view-content-wrap,
|
||||
.ProseMirror > div.taskList-view-content-wrap {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user