Skip to content

Commit d9a1c26

Browse files
authored
feat: optional custom domain (#71)
* feat: optional custom domain * fix: business plan too
1 parent e5141f0 commit d9a1c26

4 files changed

Lines changed: 77 additions & 33 deletions

File tree

src/components/cards/ChatCard.vue

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,47 +3,82 @@
33
<iframe
44
id="lnbits-chat-embed-iframe"
55
ref="chatIframe"
6+
class="lnbits-chat-embed-iframe"
67
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-
"
208
></iframe>
219
</div>
2210
</template>
2311

2412
<script setup>
25-
import {onMounted, ref} from 'vue'
13+
import {onBeforeUnmount, onMounted, ref} from 'vue'
2614
import {saas} from 'src/boot/saas'
2715
2816
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+
}
2953
3054
onMounted(() => {
3155
const iframe = chatIframe.value
3256
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-
})
4757
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')
4867
})
4968
</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>

src/components/tables/InstancesTable.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,7 +1469,8 @@ export default defineComponent({
14691469
'<p>This payment plan supports a custom subdomain or a full custom domain. Enter the hostname you want to use for this instance.</p>' +
14701470
'<p>You will need to configure your domain\'s DNS settings. <a href="https://community.lnbits.com/t/custom-domain-names-dns-setup-guide/60" title="LNbits SaaS custom DNS settings" target="_blank">Find out how here.</a></p>',
14711471
label: 'Domain or subdomain',
1472-
hint: 'Examples: my-team or pay.example.com',
1472+
hint: 'Optional. Examples: my-team or pay.example.com',
1473+
optional: true,
14731474
missingMessage: 'Enter a custom domain or subdomain.',
14741475
invalidMessage: 'Use a valid hostname such as my-team or pay.example.com.',
14751476
formatValue: value => this.normalizeDomainValue(value),
@@ -1481,11 +1482,12 @@ export default defineComponent({
14811482
return {
14821483
title: 'Custom subdomain',
14831484
message:
1484-
'<p>This payment plan includes a custom subdomain. Enter the subdomain you want to reserve for this instance.</p>' +
1485+
'<p>This payment plan includes a custom subdomain. Enter the subdomain you want to reserve for this instance.</p>' +
14851486
'<p>You will need to configure your domain\'s DNS settings. <a href="https://community.lnbits.com/t/custom-domain-names-dns-setup-guide/60" title="LNbits SaaS custom DNS settings" target="_blank">Find out how here.</a></p>',
14861487
label: 'Subdomain',
1487-
hint: 'Example: my-team.lnbits.com',
1488+
hint: 'Optional. Example: my-team.lnbits.com',
14881489
suffix: '.lnbits.com',
1490+
optional: true,
14891491
missingMessage: 'Enter a custom subdomain.',
14901492
invalidMessage: 'Use only letters, numbers, and hyphens for the subdomain.',
14911493
formatValue: value => {
@@ -2588,7 +2590,7 @@ export default defineComponent({
25882590
}
25892591
25902592
if (!this.normalizedPlanDomain) {
2591-
return config.missingMessage
2593+
return config.optional ? '' : config.missingMessage
25922594
}
25932595
25942596
if (!config.isValid(this.normalizedPlanDomain)) {

src/css/app.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
--surface-glass: rgba(255, 255, 255, 0.08);
1010
--surface-glass-strong: rgba(255, 255, 255, 0.12);
1111
--stroke-glass: rgba(255, 255, 255, 0.16);
12+
--chat-embed-safe-space: 0px;
1213
}
1314

1415
body {
@@ -545,6 +546,12 @@ pre {
545546
background: transparent;
546547
}
547548

549+
@media (min-width: 600px) {
550+
.app-shell__page-container {
551+
padding-bottom: var(--chat-embed-safe-space);
552+
}
553+
}
554+
548555
.body--dark .app-shell .q-header {
549556
background: linear-gradient(120deg, rgba(12, 7, 20, 0.88), rgba(22, 10, 36, 0.7));
550557
backdrop-filter: blur(14px);

src/layouts/MainLayout.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
</q-list>
104104
</q-drawer>
105105

106-
<q-page-container>
106+
<q-page-container class="app-shell__page-container">
107107
<router-view />
108108
</q-page-container>
109109
</q-layout>

0 commit comments

Comments
 (0)