mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			85 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script setup>
 | |
| import { ref, computed } from 'vue';
 | |
| import BaseBubble from './Base.vue';
 | |
| import Icon from 'next/icon/Icon.vue';
 | |
| import { useSnakeCase } from 'dashboard/composables/useTransformKeys';
 | |
| import { useMessageContext } from 'next/message/provider.js';
 | |
| import GalleryView from 'dashboard/components/widgets/conversation/components/GalleryView.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
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * @typedef {Object} Props
 | |
|  * @property {Attachment[]} [attachments=[]] - The attachments associated with the message
 | |
|  */
 | |
| 
 | |
| const props = defineProps({
 | |
|   attachments: {
 | |
|     type: Array,
 | |
|     required: true,
 | |
|   },
 | |
| });
 | |
| const emit = defineEmits(['error']);
 | |
| const hasError = ref(false);
 | |
| const showGallery = ref(false);
 | |
| const { filteredCurrentChatAttachments } = useMessageContext();
 | |
| 
 | |
| const handleError = () => {
 | |
|   hasError.value = true;
 | |
|   emit('error');
 | |
| };
 | |
| 
 | |
| const attachment = computed(() => {
 | |
|   return props.attachments[0];
 | |
| });
 | |
| 
 | |
| const isReel = computed(() => {
 | |
|   return attachment.value.fileType === ATTACHMENT_TYPES.IG_REEL;
 | |
| });
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <BaseBubble
 | |
|     class="overflow-hidden relative group border-[4px] border-n-weak"
 | |
|     data-bubble-name="video"
 | |
|     @click="showGallery = true"
 | |
|   >
 | |
|     <div
 | |
|       v-if="isReel"
 | |
|       class="absolute p-2 flex items-start justify-end size-12 bg-gradient-to-bl from-n-alpha-black1 to-transparent right-0"
 | |
|     >
 | |
|       <Icon icon="i-lucide-instagram" class="text-white" />
 | |
|     </div>
 | |
|     <video
 | |
|       controls
 | |
|       :src="attachment.dataUrl"
 | |
|       :class="{
 | |
|         'max-w-48': isReel,
 | |
|         'max-w-full': !isReel,
 | |
|       }"
 | |
|       @error="handleError"
 | |
|     />
 | |
|   </BaseBubble>
 | |
|   <GalleryView
 | |
|     v-if="showGallery"
 | |
|     v-model:show="showGallery"
 | |
|     :attachment="useSnakeCase(attachment)"
 | |
|     :all-attachments="filteredCurrentChatAttachments"
 | |
|     @error="onError"
 | |
|     @close="() => (showGallery = false)"
 | |
|   />
 | |
| </template>
 | 
