From 33f75505259362d1a2e23cdcbb70918ced58470c Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Wed, 10 Jun 2026 08:52:34 +0400 Subject: [PATCH 01/57] fix(whatsapp): restrict OGG voice recording to WhatsApp Cloud inboxes (#14692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recording and sending an audio message from a **Twilio WhatsApp** inbox failed silently — Twilio rejected the media with delivery error `63019` ("Media failed to download") and the voice note never reached the customer. This restores audio sending for Twilio WhatsApp (and 360dialog) inboxes. Closes Regression from #14606 ## How to reproduce 1. Open a conversation in a **Twilio WhatsApp** inbox. 2. Record a voice message in the reply box and send it. 3. Before this fix: the message fails to deliver and a `Webhooks::TwilioDeliveryStatusJob` is enqueued with `ErrorCode: 63019`, `ErrorMessage: "Media failed to download"`. 4. After this fix: the audio is recorded as MP3 and delivers normally. ## What changed PR #14606 added WhatsApp **Cloud** voice notes, which require OGG/Opus. It changed `audioRecordFormat` in `ReplyBox.vue` to return OGG for `isAWhatsAppChannel` — but that getter is also `true` for Twilio WhatsApp inboxes. The OGG handling (content-type normalization + the `voice: true` flag) lives only in `WhatsappCloudService`, so Twilio could not download/process the remuxed OGG file. This change scopes OGG to `isAWhatsAppCloudChannel`. Twilio WhatsApp, 360dialog, and Telegram fall back to MP3 exactly as they did before the PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) --- .../dashboard/components/widgets/conversation/ReplyBox.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 17f5559f1..fc93ff2c7 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -375,10 +375,10 @@ export default { return `draft-${this.conversationIdByRoute}-${this.replyType}`; }, audioRecordFormat() { - if (this.isAWhatsAppChannel) { + if (this.isAWhatsAppCloudChannel) { return AUDIO_FORMATS.OGG; } - if (this.isATelegramChannel) { + if (this.isAWhatsAppChannel || this.isATelegramChannel) { return AUDIO_FORMATS.MP3; } if (this.isAPIInbox) { From cabe9bc7332e89656cdd1ec8e30f4134d6b993a9 Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:56:17 +0530 Subject: [PATCH 02/57] fix: populate general settings form on hard reload (#14685) --- .../routes/dashboard/settings/account/Index.vue | 12 +++++++++++- .../settings/account/components/AccountId.vue | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue index 0502ebc1b..55c1e7f03 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/account/Index.vue @@ -94,8 +94,18 @@ export default { return this.getAccount(this.accountId) || {}; }, }, + watch: { + 'currentAccount.id'(id) { + if (id) { + this.initializeAccount(); + } + }, + }, mounted() { - this.initializeAccount(); + // Account already in the store (navigated in): seed immediately. + if (this.currentAccount.id) { + this.initializeAccount(); + } }, methods: { async initializeAccount() { diff --git a/app/javascript/dashboard/routes/dashboard/settings/account/components/AccountId.vue b/app/javascript/dashboard/routes/dashboard/settings/account/components/AccountId.vue index f02efcdc2..941d79fb1 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/account/components/AccountId.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/account/components/AccountId.vue @@ -8,7 +8,7 @@ import SectionLayout from './SectionLayout.vue'; const { t } = useI18n(); const { currentAccount } = useAccount(); -const getAccountId = computed(() => currentAccount.value.id.toString()); +const getAccountId = computed(() => currentAccount.value?.id?.toString());