feat: add attachment only component
This commit is contained in:
@@ -17,6 +17,7 @@ import ActivityBubble from './bubbles/Activity.vue';
|
||||
import ImageBubble from './bubbles/Image.vue';
|
||||
import FileBubble from './bubbles/File.vue';
|
||||
import AudioBubble from './bubbles/Audio.vue';
|
||||
import AttachmentsBubble from './bubbles/Attachments.vue';
|
||||
|
||||
import MessageError from './MessageError.vue';
|
||||
import MessageMeta from './MessageMeta.vue';
|
||||
@@ -219,6 +220,10 @@ const componentToRender = computed(() => {
|
||||
if (fileType === ATTACHMENT_TYPES.AUDIO) return AudioBubble;
|
||||
}
|
||||
|
||||
if (props.attachments.length > 1 && !props.content) {
|
||||
return AttachmentsBubble;
|
||||
}
|
||||
|
||||
return TextBubble;
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
import BaseBubble from 'next/message/bubbles/Base.vue';
|
||||
import ImageChip from 'next/message/chips/Image.vue';
|
||||
import VideoChip from 'next/message/chips/Video.vue';
|
||||
import AudioChip from 'next/message/chips/Audio.vue';
|
||||
import FileChip from 'next/message/chips/File.vue';
|
||||
|
||||
import { ATTACHMENT_TYPES } from '../constants';
|
||||
/**
|
||||
* @typedef {Object} Attachment
|
||||
* @property {number} id - Unique identifier for the attachment
|
||||
* @property {number} messageId - ID of the associated message
|
||||
* @property {'image'|'audio'|'video'|'file'|'location'|'fallback'|'share'|'story_mention'|'contact'|'ig_reel'} fileType - Type of the attachment (file or image)
|
||||
* @property {number} accountId - ID of the associated account
|
||||
* @property {string|null} extension - File extension
|
||||
* @property {string} dataUrl - URL to access the full attachment data
|
||||
* @property {string} thumbUrl - URL to access the thumbnail version
|
||||
* @property {number} fileSize - Size of the file in bytes
|
||||
* @property {number|null} width - Width of the image if applicable
|
||||
* @property {number|null} height - Height of the image if applicable
|
||||
*/
|
||||
const props = defineProps({
|
||||
attachments: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const mediaAttachments = computed(() => {
|
||||
const allowedTypes = [ATTACHMENT_TYPES.IMAGE, ATTACHMENT_TYPES.VIDEO];
|
||||
const mediaTypes = props.attachments.filter(attachment =>
|
||||
allowedTypes.includes(attachment.fileType)
|
||||
);
|
||||
|
||||
return mediaTypes.sort(
|
||||
(a, b) =>
|
||||
allowedTypes.indexOf(a.fileType) - allowedTypes.indexOf(b.fileType)
|
||||
);
|
||||
});
|
||||
|
||||
const recordings = computed(() => {
|
||||
return props.attachments.filter(
|
||||
attachment => attachment.fileType === ATTACHMENT_TYPES.AUDIO
|
||||
);
|
||||
});
|
||||
|
||||
const files = computed(() => {
|
||||
return props.attachments.filter(
|
||||
attachment => attachment.fileType === ATTACHMENT_TYPES.FILE
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BaseBubble class="grid gap-2 bg-transparent">
|
||||
<div v-if="mediaAttachments.length" class="flex gap-1">
|
||||
<template v-for="attachment in mediaAttachments" :key="attachment.id">
|
||||
<ImageChip
|
||||
v-if="attachment.fileType === ATTACHMENT_TYPES.IMAGE"
|
||||
:attachment="attachment"
|
||||
/>
|
||||
<VideoChip
|
||||
v-else-if="attachment.fileType === ATTACHMENT_TYPES.VIDEO"
|
||||
:attachment="attachment"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="recordings.length" class="flex flex-wrap gap-1">
|
||||
<AudioChip
|
||||
v-for="attachment in recordings"
|
||||
:key="attachment.id"
|
||||
class="bg-n-alpha-3 dark:bg-n-alpha-2 text-n-slate-12"
|
||||
:attachment="attachment"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="files.length" class="flex flex-wrap gap-1">
|
||||
<FileChip
|
||||
v-for="attachment in files"
|
||||
:key="attachment.id"
|
||||
:attachment="attachment"
|
||||
/>
|
||||
</div>
|
||||
</BaseBubble>
|
||||
</template>
|
||||
@@ -70,9 +70,9 @@ const files = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BaseBubble class="p-3 space-y-[10px]">
|
||||
<BaseBubble class="p-3 grid gap-3">
|
||||
<span v-if="content" v-html="formattedContent" />
|
||||
<div v-if="mediaAttachments.length" class="flex gap-[10px]">
|
||||
<div v-if="mediaAttachments.length" class="flex gap-2">
|
||||
<template v-for="attachment in mediaAttachments" :key="attachment.id">
|
||||
<ImageChip
|
||||
v-if="attachment.fileType === ATTACHMENT_TYPES.IMAGE"
|
||||
@@ -84,7 +84,7 @@ const files = computed(() => {
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="recordings.length" class="flex flex-wrap gap-[10px]">
|
||||
<div v-if="recordings.length" class="flex flex-wrap gap-2">
|
||||
<AudioChip
|
||||
v-for="attachment in recordings"
|
||||
:key="attachment.id"
|
||||
@@ -92,7 +92,7 @@ const files = computed(() => {
|
||||
:attachment="attachment"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="files.length" class="flex flex-wrap gap-[10px]">
|
||||
<div v-if="files.length" class="flex flex-wrap gap-2">
|
||||
<FileChip
|
||||
v-for="attachment in files"
|
||||
:key="attachment.id"
|
||||
|
||||
@@ -1212,27 +1212,31 @@ export default camelcaseKeys(
|
||||
},
|
||||
{
|
||||
id: 5323,
|
||||
content: null,
|
||||
content: 'These are all the files you requested',
|
||||
inbox_id: 486,
|
||||
echo_id: '9f7432284767',
|
||||
conversation_id: 1016,
|
||||
message_type: 1,
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
status: 'sent',
|
||||
content_attributes: {},
|
||||
created_at: 1732795624,
|
||||
private: false,
|
||||
source_id: null,
|
||||
sender_type: 'Contact',
|
||||
sender_id: 599,
|
||||
sender: {
|
||||
id: 1,
|
||||
name: 'John',
|
||||
available_name: 'John',
|
||||
avatar_url:
|
||||
'http://localhost:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaDBLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--4e625d80e7ef2dc41354392bc214832fbe640840/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2RTNKbGMybDZaVjkwYjE5bWFXeHNXd2RwQWZvdyIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--ebe60765d222d11ade39165eae49cc4b2de18d89/picologo.png',
|
||||
type: 'user',
|
||||
availability_status: 'offline',
|
||||
thumbnail:
|
||||
'http://localhost:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaDBLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--4e625d80e7ef2dc41354392bc214832fbe640840/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2RTNKbGMybDZaVjkwYjE5bWFXeHNXd2RwQWZvdyIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--ebe60765d222d11ade39165eae49cc4b2de18d89/picologo.png',
|
||||
additional_attributes: {
|
||||
created_at_ip: '::1',
|
||||
},
|
||||
custom_attributes: {},
|
||||
email: 'anthony@example.com',
|
||||
id: 599,
|
||||
identifier: null,
|
||||
name: 'anthony',
|
||||
phone_number: null,
|
||||
thumbnail: '',
|
||||
type: 'contact',
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
@@ -1263,6 +1267,93 @@ export default camelcaseKeys(
|
||||
width: null,
|
||||
height: null,
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
message_id: 5323,
|
||||
file_type: 'file',
|
||||
account_id: 2,
|
||||
extension: null,
|
||||
data_url:
|
||||
'http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXdLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aa5f4c3a2a034b6e68800d4787d369254ab1eb4/multi.zip',
|
||||
thumb_url:
|
||||
'http://localhost:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXdLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aa5f4c3a2a034b6e68800d4787d369254ab1eb4/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBPZ2h3Ym1jNkUzSmxjMmw2WlY5MGIxOW1hV3hzV3dkcEFmb3ciLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--328463286cffa0d7d9a36a3a30bfa1daed3a5ee6/multi.webp',
|
||||
file_size: 58696,
|
||||
width: null,
|
||||
height: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 5323,
|
||||
content: null,
|
||||
inbox_id: 486,
|
||||
echo_id: '9f7432284767',
|
||||
conversation_id: 1016,
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
status: 'sent',
|
||||
content_attributes: {},
|
||||
created_at: 1732795624,
|
||||
private: false,
|
||||
source_id: null,
|
||||
sender_type: 'Contact',
|
||||
sender_id: 599,
|
||||
sender: {
|
||||
additional_attributes: {
|
||||
created_at_ip: '::1',
|
||||
},
|
||||
custom_attributes: {},
|
||||
email: 'anthony@example.com',
|
||||
id: 599,
|
||||
identifier: null,
|
||||
name: 'anthony',
|
||||
phone_number: null,
|
||||
thumbnail: '',
|
||||
type: 'contact',
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
id: 27,
|
||||
message_id: 5323,
|
||||
file_type: 'image',
|
||||
account_id: 2,
|
||||
extension: null,
|
||||
data_url:
|
||||
'http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXNLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--08dfc1dcfd6733fe82ad318036e8f5926f2d7634/scrubbing.webp',
|
||||
thumb_url:
|
||||
'http://localhost:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXNLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--08dfc1dcfd6733fe82ad318036e8f5926f2d7634/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBPZ2h3Ym1jNkUzSmxjMmw2WlY5MGIxOW1hV3hzV3dkcEFmb3ciLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--328463286cffa0d7d9a36a3a30bfa1daed3a5ee6/scrubbing.webp',
|
||||
file_size: 26126,
|
||||
width: null,
|
||||
height: null,
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
message_id: 5323,
|
||||
file_type: 'image',
|
||||
account_id: 2,
|
||||
extension: null,
|
||||
data_url:
|
||||
'http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXdLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aa5f4c3a2a034b6e68800d4787d369254ab1eb4/multi.webp',
|
||||
thumb_url:
|
||||
'http://localhost:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXdLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aa5f4c3a2a034b6e68800d4787d369254ab1eb4/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBPZ2h3Ym1jNkUzSmxjMmw2WlY5MGIxOW1hV3hzV3dkcEFmb3ciLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--328463286cffa0d7d9a36a3a30bfa1daed3a5ee6/multi.webp',
|
||||
file_size: 58696,
|
||||
width: null,
|
||||
height: null,
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
message_id: 5323,
|
||||
file_type: 'file',
|
||||
account_id: 2,
|
||||
extension: null,
|
||||
data_url:
|
||||
'http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXdLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aa5f4c3a2a034b6e68800d4787d369254ab1eb4/list-with-all-data.csv',
|
||||
thumb_url:
|
||||
'http://localhost:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBaXdLIiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aa5f4c3a2a034b6e68800d4787d369254ab1eb4/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBPZ2h3Ym1jNkUzSmxjMmw2WlY5MGIxOW1hV3hzV3dkcEFmb3ciLCJleHAiOm51bGwsInB1ciI6InZhcmlhdGlvbiJ9fQ==--328463286cffa0d7d9a36a3a30bfa1daed3a5ee6/multi.webp',
|
||||
file_size: 58696,
|
||||
width: null,
|
||||
height: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user