feat: Improved placeholder and upload handling for videos

This commit is contained in:
Arek Nawo
2026-01-19 20:14:48 +01:00
parent 5bda5623f2
commit 0c5c83a17a
6 changed files with 173 additions and 130 deletions
@@ -205,8 +205,12 @@ const CommandGroups: SlashMenuGroupedItemsType = {
if (input.files?.length) {
const file = input.files[0];
const pos = editor.view.state.selection.from;
uploadVideoAction(file, editor.view, pos, pageId);
}
// Reset the input value to allow uploading the same file again if needed
input.value = "";
};
input.click();
},
@@ -20,7 +20,7 @@ export function VideoMenu({ editor }: EditorMenuProps) {
const editorState = useEditorState({
editor,
selector: ctx => {
selector: (ctx) => {
if (!ctx.editor) {
return null;
}
@@ -43,7 +43,7 @@ export function VideoMenu({ editor }: EditorMenuProps) {
return false;
}
return editor.isActive("video");
return editor.isActive("video") && editor.getAttributes("video").src;
},
[editor],
);
@@ -0,0 +1,15 @@
.videoWrapper {
border-radius: 8px;
@mixin light {
background-color: var(--mantine-color-gray-0);
}
@mixin dark {
background-color: var(--mantine-color-dark-7);
}
}
.video {
display: block;
width: 100%;
border-radius: 8px;
}
@@ -2,11 +2,11 @@ import { NodeViewProps, NodeViewWrapper } from "@tiptap/react";
import { useMemo } from "react";
import { getFileUrl } from "@/lib/config.ts";
import clsx from "clsx";
import classes from "./video-view.module.css";
export default function VideoView(props: NodeViewProps) {
const { node, selected } = props;
const { src, width, align } = node.attrs;
const { src, width, align, aspectRatio } = node.attrs;
const alignClass = useMemo(() => {
if (align === "left") return "alignLeft";
if (align === "right") return "alignRight";
@@ -16,14 +16,26 @@ export default function VideoView(props: NodeViewProps) {
return (
<NodeViewWrapper data-drag-handle>
<video
preload="metadata"
width={width}
controls
src={getFileUrl(src)}
className={clsx(selected ? "ProseMirror-selectednode" : "", alignClass)}
style={{ display: "block" }}
/>
<div
className={clsx(
selected && "ProseMirror-selectednode",
classes.videoWrapper,
alignClass,
)}
style={{
aspectRatio: aspectRatio ? aspectRatio : src ? undefined : "16 / 9",
width,
}}
>
{src && (
<video
className={classes.video}
preload="metadata"
controls
src={getFileUrl(src)}
/>
)}
</div>
</NodeViewWrapper>
);
}