121 lines
3.2 KiB
Vue
121 lines
3.2 KiB
Vue
<script setup>
|
|
import { computed, onMounted, nextTick } from 'vue';
|
|
import BaseBubble from './Base.vue';
|
|
import Icon from 'next/icon/Icon.vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import maplibregl from 'maplibre-gl';
|
|
|
|
/**
|
|
* @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,
|
|
},
|
|
sender: {
|
|
type: Object,
|
|
default: () => ({}),
|
|
},
|
|
});
|
|
|
|
const { t } = useI18n();
|
|
|
|
const senderName = computed(() => {
|
|
return props.sender.name;
|
|
});
|
|
|
|
const attachment = computed(() => {
|
|
return props.attachments[0];
|
|
});
|
|
|
|
const lat = computed(() => {
|
|
return attachment.value.coordinatesLat;
|
|
});
|
|
const long = computed(() => {
|
|
return attachment.value.coordinatesLong;
|
|
});
|
|
|
|
const title = computed(() => {
|
|
return attachment.value.fallbackTitle;
|
|
});
|
|
|
|
const mapUrl = computed(
|
|
() => `https://maps.google.com/?q=${lat.value},${long.value}`
|
|
);
|
|
|
|
const setupMap = () => {
|
|
const map = new maplibregl.Map({
|
|
style: 'https://tiles.openfreemap.org/styles/positron',
|
|
center: [long.value, lat.value],
|
|
zoom: 9.5,
|
|
container: 'map',
|
|
attributionControl: false,
|
|
dragPan: false,
|
|
dragRotate: false,
|
|
scrollZoom: false,
|
|
touchZoom: false,
|
|
touchRotate: false,
|
|
keyboard: false,
|
|
doubleClickZoom: false,
|
|
});
|
|
|
|
return map;
|
|
};
|
|
|
|
onMounted(async () => {
|
|
await nextTick();
|
|
setupMap();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<BaseBubble class="min-w-64 grid gap-4 overflow-hidden">
|
|
<div id="map" class="max-w-md min-w-64 w-full h-28 -mb-8 z-10" />
|
|
<div class="grid gap-3 px-3 z-20">
|
|
<div class="size-8 rounded-lg bg-[#0D9B8A] grid place-content-center">
|
|
<Icon icon="i-ph-navigation-arrow-fill" class="text-white size-4" />
|
|
</div>
|
|
<div class="truncate text-sm text-n-slate-11">
|
|
<div v-if="senderName" class="text-n-slate-12 text-sm truncate">
|
|
{{
|
|
t('CONVERSATION.SHARED_ATTACHMENT.LOCATION', {
|
|
sender: senderName,
|
|
})
|
|
}}
|
|
</div>
|
|
{{ title }}
|
|
</div>
|
|
</div>
|
|
<div class="px-3 pb-3 w-full">
|
|
<a
|
|
:href="mapUrl"
|
|
target="blank"
|
|
class="w-full block bg-n-solid-3 px-4 py-2 rounded-lg text-sm text-center"
|
|
>
|
|
{{ t('COMPONENTS.LOCATION_BUBBLE.SEE_ON_MAP') }}
|
|
</a>
|
|
</div>
|
|
</BaseBubble>
|
|
</template>
|
|
|
|
<style>
|
|
@import 'maplibre-gl/dist/maplibre-gl.css';
|
|
</style>
|