|
3 | 3 | <iframe |
4 | 4 | id="lnbits-chat-embed-iframe" |
5 | 5 | ref="chatIframe" |
| 6 | + class="lnbits-chat-embed-iframe" |
6 | 7 | loading="lazy" |
7 | | - style=" |
8 | | - position: fixed; |
9 | | - right: 24px; |
10 | | - bottom: 24px; |
11 | | - width: 360px; |
12 | | - height: 64px; |
13 | | - border: 0; |
14 | | - border-radius: 12px; |
15 | | - box-shadow: 0 16px 40px rgba(0, 0, 0, 0.35); |
16 | | - z-index: 9999; |
17 | | - transition: height 0.2s ease; |
18 | | - overflow: hidden; |
19 | | - " |
20 | 8 | ></iframe> |
21 | 9 | </div> |
22 | 10 | </template> |
23 | 11 |
|
24 | 12 | <script setup> |
25 | | -import {onMounted, ref} from 'vue' |
| 13 | +import {onBeforeUnmount, onMounted, ref} from 'vue' |
26 | 14 | import {saas} from 'src/boot/saas' |
27 | 15 |
|
28 | 16 | const chatIframe = ref(null) |
| 17 | +const chatUrl = ref('') |
| 18 | +
|
| 19 | +const CHAT_BOTTOM_OFFSET = 24 |
| 20 | +const CHAT_COLLAPSED_HEIGHT = 56 |
| 21 | +const CHAT_EXPANDED_HEIGHT = 520 |
| 22 | +const CHAT_SCROLL_BUFFER = 24 |
| 23 | +
|
| 24 | +function syncChatLayout(isOpen) { |
| 25 | + const iframe = chatIframe.value |
| 26 | + if (!iframe) return |
| 27 | +
|
| 28 | + const iframeHeight = isOpen |
| 29 | + ? CHAT_EXPANDED_HEIGHT |
| 30 | + : CHAT_COLLAPSED_HEIGHT |
| 31 | +
|
| 32 | + iframe.style.height = `${iframeHeight}px` |
| 33 | + document.documentElement.style.setProperty( |
| 34 | + '--chat-embed-safe-space', |
| 35 | + `${iframeHeight + CHAT_BOTTOM_OFFSET + CHAT_SCROLL_BUFFER}px` |
| 36 | + ) |
| 37 | +} |
| 38 | +
|
| 39 | +function handleMessage(event) { |
| 40 | + if (!event.data || event.data.source !== 'lnbits-chat-embed') return |
| 41 | +
|
| 42 | + const iframe = chatIframe.value |
| 43 | + if (!iframe) return |
| 44 | +
|
| 45 | + if (event.data.url && event.data.url !== chatUrl.value) { |
| 46 | + chatUrl.value = event.data.url |
| 47 | + localStorage.setItem('chatUrl', chatUrl.value) |
| 48 | + iframe.src = chatUrl.value |
| 49 | + } |
| 50 | +
|
| 51 | + syncChatLayout(Boolean(event.data.open)) |
| 52 | +} |
29 | 53 |
|
30 | 54 | onMounted(() => { |
31 | 55 | const iframe = chatIframe.value |
32 | 56 | if (!iframe) return |
33 | | - let chatUrl = localStorage.getItem('chatUrl') || saas.chatUrl |
34 | | - iframe.src = chatUrl |
35 | | - const minHeight = 56 |
36 | | - const maxHeight = 520 |
37 | | - window.addEventListener('message', function (event) { |
38 | | - if (!event.data || event.data.source !== 'lnbits-chat-embed') return |
39 | | - if (event.data.url && event.data.url !== chatUrl) { |
40 | | - chatUrl = event.data.url |
41 | | - localStorage.setItem('chatUrl', chatUrl) |
42 | | - iframe.src = chatUrl |
43 | | - } |
44 | | - iframe.style.height = event.data.open ? maxHeight + 'px' : minHeight + 'px' |
45 | | -
|
46 | | - }) |
47 | 57 |
|
| 58 | + chatUrl.value = localStorage.getItem('chatUrl') || saas.chatUrl |
| 59 | + iframe.src = chatUrl.value |
| 60 | + syncChatLayout(false) |
| 61 | + window.addEventListener('message', handleMessage) |
| 62 | +}) |
| 63 | +
|
| 64 | +onBeforeUnmount(() => { |
| 65 | + window.removeEventListener('message', handleMessage) |
| 66 | + document.documentElement.style.removeProperty('--chat-embed-safe-space') |
48 | 67 | }) |
49 | 68 | </script> |
| 69 | + |
| 70 | +<style scoped> |
| 71 | +.lnbits-chat-embed-iframe { |
| 72 | + position: fixed; |
| 73 | + right: 24px; |
| 74 | + bottom: 24px; |
| 75 | + width: 360px; |
| 76 | + height: 56px; |
| 77 | + border: 0; |
| 78 | + border-radius: 12px; |
| 79 | + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.35); |
| 80 | + z-index: 9999; |
| 81 | + transition: height 0.2s ease; |
| 82 | + overflow: hidden; |
| 83 | +} |
| 84 | +</style> |
0 commit comments