Skip to content

Commit a67becc

Browse files
committed
add draggable audio file
1 parent 201da93 commit a67becc

File tree

3 files changed

+55
-26
lines changed

3 files changed

+55
-26
lines changed

client/src/components/AudioPreview.vue

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<template>
1+
<template>
22
<div class="preview-container">
33
<div class="erase" @click="$emit('delete')" :title="t('app.base.delete_audio')"></div>
44
<div class="audio-container">
5-
<div class="audio-icon">
5+
<div class="audio-icon" v-on:dragstart="onDragStart($event)" :draggable="showPaste">
66
<fa-icon :icon="faMusic" />
77
</div>
88
</div>
@@ -117,6 +117,20 @@
117117
font-size: 2rem;
118118
transition-duration: 0.3s;
119119
120+
&[draggable="true"] {
121+
cursor: move;
122+
/* fallback if grab cursor is unsupported */
123+
cursor: grab;
124+
cursor: -moz-grab;
125+
cursor: -webkit-grab;
126+
127+
&:active {
128+
cursor: grabbing;
129+
cursor: -moz-grabbing;
130+
cursor: -webkit-grabbing;
131+
}
132+
}
133+
120134
&:hover {
121135
background-color: #dee2e6;
122136
border-color: #495057;
@@ -160,7 +174,15 @@ import { convertToHumanReadableFileSize, escapeMarkdownAltText } from "@fumix/fu
160174
import type { PropType } from "vue";
161175
162176
const getMarkdownString = () => {
163-
return `![${escapeMarkdownAltText(props.value.name)}](${props.hash})`;
177+
return `![audio:${escapeMarkdownAltText(props.value.name)}](${props.hash})`;
178+
};
179+
180+
const onDragStart = (event: DragEvent) => {
181+
if (props.showPaste) {
182+
const audioIcon = event.target as HTMLElement;
183+
event.dataTransfer?.setDragImage(audioIcon, 0, 0);
184+
event.dataTransfer?.setData("text/plain", getMarkdownString());
185+
}
164186
};
165187
166188
const props = defineProps({

client/src/views/PostFormView.vue

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -409,24 +409,25 @@ const pasteImageFileToMarkdown = (markdown: string, insertPosition: SupportedIns
409409
form.markdown = insertIntoTextarea(markdown, markdownArea.value as unknown as HTMLTextAreaElement, insertPosition);
410410
};
411411
412-
const removeImageFileFromMarkdown = (file: File) => {
413-
const strToRemove = `![${file.name}](${Object.keys(files).find((key) => files[key] === file)})`.trim();
414-
setTimeout(() => {
415-
// give the preview time to update
416-
form.markdown = form.markdown.split(strToRemove).join("");
417-
}, 0);
418-
};
419-
420412
const pasteFileToMarkdown = (markdown: string, insertPosition: SupportedInsertPositionType = "afterCursor") => {
421413
form.markdown = insertIntoTextarea(markdown, markdownArea.value as unknown as HTMLTextAreaElement, insertPosition);
422414
};
423415
424416
const removeFileFromMarkdown = (file: File) => {
425-
const strToRemove = `![${file.name}](${Object.keys(files).find((key) => files[key] === file)})`.trim();
426-
setTimeout(() => {
427-
// give the preview time to update
428-
form.markdown = form.markdown.split(strToRemove).join("");
429-
}, 0);
417+
const fileHash = Object.keys(files).find((key) => files[key] === file);
418+
if (isImageFile(file)) {
419+
const strToRemove = `![${file.name}](${fileHash})`.trim();
420+
setTimeout(() => {
421+
// give the preview time to update
422+
form.markdown = form.markdown.split(strToRemove).join("");
423+
}, 0);
424+
} else if (isAudioFile(file)) {
425+
const strToRemove = `![audio:${file.name}](${fileHash})`.trim();
426+
setTimeout(() => {
427+
// give the preview time to update
428+
form.markdown = form.markdown.split(strToRemove).join("");
429+
}, 0);
430+
}
430431
};
431432
432433
const isImageFile = (file: File): boolean => {

common/src/markdown-converter-common.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,22 @@ export abstract class MarkdownConverter {
109109
token.escaped = true;
110110
}
111111
},
112-
// renderer: {
113-
// image(href, title, text) {
114-
// // Check if the href is a data URL for an audio file
115-
// if (href && href.startsWith('data:audio/')) {
116-
// return `<audio controls><source src="${href}" type="${href.split(';')[0].split(':')[1]}">Your browser does not support the audio element.</audio>`;
117-
// }
118-
// // Default image rendering
119-
// return `<img src="${href}" alt="${text || ''}" title="${title || ''}">`;
120-
// }
121-
// }
112+
renderer: {
113+
image({ href, title, text }: Tokens.Image) {
114+
// Check if this is an audio file (marked with audio: prefix)
115+
if (text && text.startsWith('audio:')) {
116+
const audioName = text.substring(6); // Remove 'audio:' prefix
117+
// Determine audio type from href if it's a data URL
118+
let audioType = "audio/mpeg"; // default
119+
if (href && href.startsWith('data:audio/')) {
120+
audioType = href.split(';')[0].split(':')[1];
121+
}
122+
return `<audio controls><source src="${href}" type="${audioType}">Your browser does not support the audio element.</audio>`;
123+
}
124+
// Default image rendering
125+
return `<img src="${href}" alt="${text || ''}" title="${title || ''}">`;
126+
}
127+
}
122128
});
123129
marked.use(MarkdownConverter.rendererExtension);
124130
marked.use(

0 commit comments

Comments
 (0)