Skip to content

Commit 3286514

Browse files
committed
feat: upload and display video
1 parent 9f17b4f commit 3286514

File tree

25 files changed

+272
-7
lines changed

25 files changed

+272
-7
lines changed

src/app/src/components/content/ContentEditorTipTap.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { tiptapToMDC } from '../../utils/tiptap/tiptapToMdc'
1919
import { getStandardToolbarItems, getStandardSuggestionItems, standardNuxtUIComponents, computeStandardDragActions, removeLastEmptyParagraph } from '../../utils/tiptap/editor'
2020
import { Element } from '../../utils/tiptap/extensions/element'
2121
import { ImagePicker } from '../../utils/tiptap/extensions/image-picker'
22+
import { VideoPicker } from '../../utils/tiptap/extensions/video-picker'
23+
import { Video } from '../../utils/tiptap/extensions/video'
2224
import { Slot } from '../../utils/tiptap/extensions/slot'
2325
import { Frontmatter } from '../../utils/tiptap/extensions/frontmatter'
2426
import { CodeBlock } from '../../utils/tiptap/extensions/code-block'
@@ -116,6 +118,12 @@ const customHandlers = computed(() => ({
116118
isActive: (editor: Editor) => editor.isActive('image-picker'),
117119
isDisabled: undefined,
118120
},
121+
video: {
122+
canExecute: (editor: Editor) => editor.can().insertContent({ type: 'video-picker' }),
123+
execute: (editor: Editor) => editor.chain().focus().insertContent({ type: 'video-picker' }),
124+
isActive: (editor: Editor) => editor.isActive('video-picker'),
125+
isDisabled: undefined,
126+
},
119127
...Object.fromEntries(
120128
componentItems.value.map(item => [
121129
item.kind,
@@ -173,6 +181,8 @@ const toolbarItems = computed(() => getStandardToolbarItems(t))
173181
:extensions="[
174182
Frontmatter,
175183
ImagePicker,
184+
VideoPicker,
185+
Video,
176186
Element,
177187
InlineElement,
178188
Slot,

src/app/src/components/shared/ModalMediaPicker.vue

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
11
<script setup lang="ts">
22
import { computed } from 'vue'
33
import { useStudio } from '../../composables/useStudio'
4-
import { isImageFile } from '../../utils/file'
4+
import { isImageFile, isVideoFile } from '../../utils/file'
55
import { Image } from '@unpic/vue'
66
import type { TreeItem } from '../../types'
77
import { StudioFeature } from '../../types'
88
99
const { mediaTree, context } = useStudio()
1010
11-
defineProps<{ open: boolean }>()
11+
const props = defineProps<{ open: boolean, type: 'image' | 'video' }>()
1212
1313
const emit = defineEmits<{
1414
select: [image: TreeItem]
1515
cancel: []
1616
}>()
1717
18+
const isValidFileType = (item: TreeItem) => {
19+
if (props.type === 'image') {
20+
return isImageFile(item.fsPath)
21+
}
22+
if (props.type === 'video') {
23+
return isVideoFile(item.fsPath)
24+
}
25+
return false
26+
}
27+
1828
const imageFiles = computed(() => {
1929
const images: TreeItem[] = []
2030
2131
const collectImages = (items: TreeItem[]) => {
2232
for (const item of items) {
23-
if (item.type === 'file' && isImageFile(item.fsPath)) {
33+
if (item.type === 'file' && isValidFileType(item)) {
2434
images.push(item)
2535
}
2636
if (item.children) {

src/app/src/components/tiptap/extension/TiptapExtensionImagePicker.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const handleCancel = () => {
5151
:open="isOpen"
5252
@select="handleImageSelect"
5353
@cancel="handleCancel"
54+
type="image"
5455
/>
5556
</NodeViewWrapper>
5657
</template>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<NodeViewWrapper as="div">
3+
<div
4+
:contenteditable="false"
5+
class="relative group rounded-md overflow-hidden"
6+
:ui="{ body: { padding: '' } }"
7+
>
8+
<video
9+
:src="props.src"
10+
controls
11+
class="my-0 w-full"
12+
/>
13+
</div>
14+
<NodeViewContent as="span" />
15+
</NodeViewWrapper>
16+
</template>
17+
18+
<script setup lang="ts">
19+
import { computed } from 'vue'
20+
import { nodeViewProps, NodeViewWrapper, NodeViewContent } from '@tiptap/vue-3'
21+
22+
const nodeProps = defineProps(nodeViewProps)
23+
24+
const props = computed(() => nodeProps.node.attrs?.props || {})
25+
</script>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<script setup lang="ts">
2+
import type { NodeViewProps } from '@tiptap/vue-3'
3+
import { NodeViewWrapper } from '@tiptap/vue-3'
4+
import { ref } from 'vue'
5+
import type { TreeItem } from '../../../types'
6+
import ModalMediaPicker from '../../shared/ModalMediaPicker.vue'
7+
8+
const props = defineProps<NodeViewProps>()
9+
10+
const isOpen = ref(true)
11+
12+
const handleImageSelect = (image: TreeItem) => {
13+
const pos = props.getPos()
14+
15+
if (typeof pos === 'number') {
16+
props.editor
17+
.chain()
18+
.focus()
19+
.deleteRange({ from: pos, to: pos + 1 })
20+
.insertContent({
21+
type: 'video',
22+
attrs: {
23+
src: image.routePath,
24+
props: {
25+
src: image.routePath,
26+
},
27+
},
28+
})
29+
.run()
30+
}
31+
32+
isOpen.value = false
33+
}
34+
35+
const handleCancel = () => {
36+
const pos = props.getPos()
37+
38+
if (typeof pos === 'number') {
39+
props.editor
40+
.chain()
41+
.focus()
42+
.deleteRange({ from: pos, to: pos + 1 })
43+
.run()
44+
}
45+
46+
isOpen.value = false
47+
}
48+
</script>
49+
50+
<template>
51+
<NodeViewWrapper>
52+
<ModalMediaPicker
53+
:open="isOpen"
54+
@select="handleImageSelect"
55+
@cancel="handleCancel"
56+
type="video"
57+
/>
58+
</NodeViewWrapper>
59+
</template>

src/app/src/locales/bg.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
"paragraph": "Параграф",
220220
"insert": "Вмъкване",
221221
"image": "Изображение",
222+
"video": "Видео",
222223
"horizontalRule": "Хоризонтална линия"
223224
},
224225
"drag": {

src/app/src/locales/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
"paragraph": "Absatz",
220220
"insert": "Einfügen",
221221
"image": "Bild",
222+
"video": "Video",
222223
"horizontalRule": "Horizontale Linie"
223224
},
224225
"drag": {

src/app/src/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
"paragraph": "Paragraph",
220220
"insert": "Insert",
221221
"image": "Image",
222+
"video": "Video",
222223
"horizontalRule": "Horizontal Rule"
223224
},
224225
"drag": {

src/app/src/locales/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
"paragraph": "Párrafo",
220220
"insert": "Insertar",
221221
"image": "Imagen",
222+
"video": "Video",
222223
"horizontalRule": "Regla horizontal"
223224
},
224225
"drag": {

src/app/src/locales/fa.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
"paragraph": "پاراگراف",
220220
"insert": "درج",
221221
"image": "تصویر",
222+
"video": "ویدیو",
222223
"horizontalRule": "خط افقی"
223224
},
224225
"drag": {

0 commit comments

Comments
 (0)