mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 12:08:01 +00:00
fix: Audio attachment issues (#9260)
* fix: Audio attachment issues * chore: Style fix * chore: Minor fix * chore: Minor fix * chore: Review fixes
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="preview-item__wrap flex overflow-auto max-h-[12.5rem]">
|
<div class="flex overflow-auto max-h-[12.5rem]">
|
||||||
<div
|
<div
|
||||||
v-for="(attachment, index) in attachments"
|
v-for="(attachment, index) in nonRecordedAudioAttachments"
|
||||||
:key="attachment.id"
|
:key="attachment.id"
|
||||||
class="preview-item flex items-center p-1 bg-slate-50 dark:bg-slate-800 gap-1 rounded-md w-[15rem] mb-1"
|
class="preview-item flex items-center p-1 bg-slate-50 dark:bg-slate-800 gap-1 rounded-md w-[15rem] mb-1"
|
||||||
>
|
>
|
||||||
<div class="max-w-[4rem] flex-shrink-0 w-6 flex items-center">
|
<div class="max-w-[4rem] flex-shrink-0 w-6 flex items-center">
|
||||||
<img
|
<img
|
||||||
v-if="isTypeImage(attachment.resource)"
|
v-if="isTypeImage(attachment.resource)"
|
||||||
class="image-thumb"
|
class="object-cover w-6 h-6 rounded-sm"
|
||||||
:src="attachment.thumb"
|
:src="attachment.thumb"
|
||||||
/>
|
/>
|
||||||
<span v-else class="w-6 h-6 text-lg relative -top-px text-left">
|
<span v-else class="relative w-6 h-6 text-lg text-left -top-px">
|
||||||
📄
|
📄
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -23,73 +23,62 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-[30%] justify-center">
|
<div class="w-[30%] justify-center">
|
||||||
<span
|
<span class="overflow-hidden text-xs text-ellipsis whitespace-nowrap">
|
||||||
class="item overflow-hidden text-xs text-ellipsis whitespace-nowrap"
|
|
||||||
>
|
|
||||||
{{ formatFileSize(attachment.resource) }}
|
{{ formatFileSize(attachment.resource) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<woot-button
|
<woot-button
|
||||||
v-if="!isTypeAudio(attachment.resource)"
|
class="!w-6 !h-6 text-sm rounded-md hover:bg-slate-50 dark:hover:bg-slate-800 clear secondary"
|
||||||
class="remove--attachment clear secondary"
|
|
||||||
icon="dismiss"
|
icon="dismiss"
|
||||||
@click="() => onRemoveAttachment(index)"
|
@click="onRemoveAttachment(index)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
import { formatBytes } from 'shared/helpers/FileHelper';
|
import { formatBytes } from 'shared/helpers/FileHelper';
|
||||||
export default {
|
|
||||||
props: {
|
const props = defineProps({
|
||||||
attachments: {
|
attachments: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
|
||||||
removeAttachment: {
|
|
||||||
type: Function,
|
|
||||||
default: () => {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onRemoveAttachment(index) {
|
|
||||||
this.removeAttachment(index);
|
|
||||||
},
|
|
||||||
formatFileSize(file) {
|
|
||||||
const size = file.byte_size || file.size;
|
|
||||||
return formatBytes(size, 0);
|
|
||||||
},
|
|
||||||
isTypeImage(file) {
|
|
||||||
const type = file.content_type || file.type;
|
|
||||||
return type.includes('image');
|
|
||||||
},
|
|
||||||
isTypeAudio(file) {
|
|
||||||
const type = file.content_type || file.type;
|
|
||||||
return type.includes('audio');
|
|
||||||
},
|
|
||||||
fileName(file) {
|
|
||||||
return file.filename || file.name;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(['remove-attachment']);
|
||||||
|
|
||||||
|
const nonRecordedAudioAttachments = computed(() => {
|
||||||
|
return props.attachments.filter(attachment => !attachment?.isRecordedAudio);
|
||||||
|
});
|
||||||
|
|
||||||
|
const recordedAudioAttachments = computed(() =>
|
||||||
|
props.attachments.filter(attachment => attachment.isRecordedAudio)
|
||||||
|
);
|
||||||
|
|
||||||
|
const onRemoveAttachment = itemIndex => {
|
||||||
|
emits(
|
||||||
|
'remove-attachment',
|
||||||
|
nonRecordedAudioAttachments.value
|
||||||
|
.filter((_, index) => index !== itemIndex)
|
||||||
|
.concat(recordedAudioAttachments.value)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatFileSize = file => {
|
||||||
|
const size = file.byte_size || file.size;
|
||||||
|
return formatBytes(size, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isTypeImage = file => {
|
||||||
|
const type = file.content_type || file.type;
|
||||||
|
return type.includes('image');
|
||||||
|
};
|
||||||
|
|
||||||
|
const fileName = file => {
|
||||||
|
return file.filename || file.name;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.image-thumb {
|
|
||||||
@apply w-6 h-6 object-cover rounded-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-name-wrap,
|
|
||||||
.file-size-wrap {
|
|
||||||
@apply flex items-center py-0 px-1;
|
|
||||||
|
|
||||||
> .item {
|
|
||||||
@apply m-0 overflow-hidden text-xs font-medium;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.remove--attachment {
|
|
||||||
@apply w-6 h-6 rounded-md text-sm cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -231,7 +231,18 @@ export default {
|
|||||||
@apply bg-transparent max-h-60 min-h-[3rem] pt-4 px-0 pb-0 resize-none;
|
@apply bg-transparent max-h-60 min-h-[3rem] pt-4 px-0 pb-0 resize-none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.video-js .vjs-control-bar {
|
// Added to override the default text and bg style to support dark and light mode.
|
||||||
background-color: transparent;
|
.video-js .vjs-control-bar,
|
||||||
|
.vjs-record.video-js .vjs-control.vjs-record-indicator:before {
|
||||||
|
@apply text-slate-600 dark:text-slate-200 bg-transparent dark:bg-transparent;
|
||||||
|
}
|
||||||
|
// Added to fix div overlays the screen and takes over the button clicks
|
||||||
|
// https://github.com/collab-project/videojs-record/issues/688
|
||||||
|
// https://github.com/collab-project/videojs-record/pull/709
|
||||||
|
.vjs-record.video-js .vjs-control.vjs-record-indicator.vjs-hidden,
|
||||||
|
.vjs-record.video-js .vjs-control.vjs-record-indicator,
|
||||||
|
.vjs-record.video-js .vjs-control.vjs-record-indicator:before,
|
||||||
|
.vjs-record.video-js .vjs-control.vjs-record-indicator:after {
|
||||||
|
@apply pointer-events-none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
<attachment-preview
|
<attachment-preview
|
||||||
class="flex-col mt-4"
|
class="flex-col mt-4"
|
||||||
:attachments="attachedFiles"
|
:attachments="attachedFiles"
|
||||||
:remove-attachment="removeAttachment"
|
@remove-attachment="removeAttachment"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<message-signature-missing-alert
|
<message-signature-missing-alert
|
||||||
@@ -937,6 +937,13 @@ export default {
|
|||||||
this.bccEmails = '';
|
this.bccEmails = '';
|
||||||
this.toEmails = '';
|
this.toEmails = '';
|
||||||
},
|
},
|
||||||
|
clearRecorder() {
|
||||||
|
this.isRecordingAudio = false;
|
||||||
|
// Only clear the recorded audio when we click toggle button.
|
||||||
|
this.attachedFiles = this.attachedFiles.filter(
|
||||||
|
file => !file?.isRecordedAudio
|
||||||
|
);
|
||||||
|
},
|
||||||
toggleEmojiPicker() {
|
toggleEmojiPicker() {
|
||||||
this.showEmojiPicker = !this.showEmojiPicker;
|
this.showEmojiPicker = !this.showEmojiPicker;
|
||||||
},
|
},
|
||||||
@@ -944,8 +951,7 @@ export default {
|
|||||||
this.isRecordingAudio = !this.isRecordingAudio;
|
this.isRecordingAudio = !this.isRecordingAudio;
|
||||||
this.isRecorderAudioStopped = !this.isRecordingAudio;
|
this.isRecorderAudioStopped = !this.isRecordingAudio;
|
||||||
if (!this.isRecordingAudio) {
|
if (!this.isRecordingAudio) {
|
||||||
this.clearMessage();
|
this.clearRecorder();
|
||||||
this.clearEmailField();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleAudioRecorderPlayPause() {
|
toggleAudioRecorderPlayPause() {
|
||||||
@@ -989,7 +995,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFinishRecorder(file) {
|
onFinishRecorder(file) {
|
||||||
return file && this.onFileUpload(file);
|
// Added a new key isRecordedAudio to the file to find it's and recorded audio
|
||||||
|
// Because to filter and show only non recorded audio and other attachments
|
||||||
|
const autoRecordedFile = {
|
||||||
|
...file,
|
||||||
|
isRecordedAudio: true,
|
||||||
|
};
|
||||||
|
return file && this.onFileUpload(autoRecordedFile);
|
||||||
},
|
},
|
||||||
toggleTyping(status) {
|
toggleTyping(status) {
|
||||||
const conversationId = this.currentChat.id;
|
const conversationId = this.currentChat.id;
|
||||||
@@ -1015,13 +1027,12 @@ export default {
|
|||||||
isPrivate: this.isPrivate,
|
isPrivate: this.isPrivate,
|
||||||
thumb: reader.result,
|
thumb: reader.result,
|
||||||
blobSignedId: blob ? blob.signed_id : undefined,
|
blobSignedId: blob ? blob.signed_id : undefined,
|
||||||
|
isRecordedAudio: file?.isRecordedAudio || false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
removeAttachment(itemIndex) {
|
removeAttachment(attachments) {
|
||||||
this.attachedFiles = this.attachedFiles.filter(
|
this.attachedFiles = attachments;
|
||||||
(item, index) => itemIndex !== index
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
setReplyToInPayload(payload) {
|
setReplyToInPayload(payload) {
|
||||||
if (this.inReplyTo?.id) {
|
if (this.inReplyTo?.id) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
@error="onImgError"
|
@error="onImgError"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
/>
|
/>
|
||||||
<audio v-else-if="isAudio" controls class="skip-context-menu">
|
<audio v-else-if="isAudio" controls class="skip-context-menu mb-0.5">
|
||||||
<source :src="`${dataUrl}?t=${Date.now()}`" />
|
<source :src="`${dataUrl}?t=${Date.now()}`" />
|
||||||
</audio>
|
</audio>
|
||||||
<gallery-view
|
<gallery-view
|
||||||
|
|||||||
Reference in New Issue
Block a user