- handoff form no longer overwrites a JWT contact's name, email or phone.
The CRM resyncs those on every exchange, so the edit reverted anyway.
Visitors still get their submitted values saved.
- search queries dropped the cs and cp table aliases. Any saved view
filtering on conversation_statuses.name returned a 500.
- status and priority never showed as selected in the search filters.
The combobox compares strings, the store gives numbers.
- widget logout left the previous visitor's pre chat draft on screen.
- an auto hidden campaign preview was suppressed forever instead of for
the session.
- switching campaigns in the admin preview did not close the open panel.
The watcher only saw null and non null, so it now keys on campaign id.
- the Help tab blanked out when featured_ids came back as null.
- copilot panel spinner stuck when no conversation was open.
- help center theme toggle was hidden when there were no nav links and
one locale.
- help center dark mode leaked into the article panel inside the widget.
Livechat:
- Add a live widget preview that renders in the inbox settings help rail.
- Warn when the primary or header colors are too close to the background.
- Require gradient/image background values and notice banner text when enabled.
- Show a default launcher logo in the widget when none is set, matching the preview.
- Drop the Beta badge from the livechat channel.
General settings:
- Add "set agents away on login". Agents log in as away and must go online manually.
- Add "show subject in conversation list" toggle.
Other:
- Add a keyboard shortcuts dialog from the user menu.
- Show a "snoozed until" badge on snoozed conversations.
- Contact search now matches emails partially instead of exact.
- Give outgoing message bubbles a secondary background.
- The new-conversation flow can start a WhatsApp thread. handleCreateConversation branches on the inbox channel, resolves or creates the contact by wa_id, and queues an approved template as the first message.
- The 24h customer window is now per contact, not per thread. It is the latest inbound across the contact's threads on that inbox (a MAX computed on read), so a freshly created thread can send free text when the customer messaged any thread within 24h. get-conversation returns contact_last_inbound_at for the composer.
- Contact search also matches phone_number now, backed by a trigram index. ContactResult.email is nullable so phone-only contacts no longer break the scan.
- WhatsApp inbound stores the full wa_id as the contact phone when none is set, and the old heuristic dial-code split is removed. The wa_id digit normalizer now lives in stringutil and is shared.
- Open-thread routing orders by last public interaction instead of last_message_at, so private notes no longer affect it.
Before this feature the only way to create a conversation was by adding inbox and sending an email.
Agents first search contacts by email, see a dropdown select an existing contact or fill a new email for new contact.
The backend creates contact if it does not exist, creates a conversation, sends a reply to the conversation.
Optinally assigns conversation to a user / team.
fix: Replies to emails create a new conversation instead of attaching to the previous one.
Was not happening in gmail, as gmail was sending the references headers in all replies and I missed this completely. So when libredesk searches a conversation by references headers it worked!
Instead the right way is to generate the outgoing email message id and saving it in DB. This commit fixes that.
There could be more backup strategies like putting reference number in the subject but that can be explored later.
chore: new role `conversatons:write` that enables the create conversations feature for an agent.
chore: migrations for v0.4.0.