Commit Graph

221 Commits

Author SHA1 Message Date
Abhinav Raut 703f38fafc quote only messages the contact already saw in email history
Quoted history now leaves out CSAT emails and anything the contact was not part of. Earlier messages load only when the outgoing template or the reply uses PreviousMessages.
2026-10-20 00:00:37 +05:30
Abhinav Raut 114c80a059 add IsIncoming to quoted messages and escape sender fields 2026-10-19 23:34:56 +05:30
Abhinav Raut d3acea74d0 add earlier messages as a variable in the outgoing email template 2026-10-19 23:33:20 +05:30
Sans 9be2894b62 fix: fall back to reference number as email subject for empty-subject conversations
Emails that arrive with no Subject header are stored with an empty subject.
When a reply is sent, some strict SMTP servers reject the message with
"550 Missing subject field". Fall back to the formatted reference number
(e.g. "#CONV-42") so the reply always carries a non-empty subject.

Fixes #701
2026-10-19 21:50:19 +05:30
Abhinav Raut 14d49a7af8 include assignee details in conversation responses
Reuse assignee details in the agent store to avoid separate conversation list lookups.
2026-10-18 19:35:01 +05:30
Abhinav Raut b47e1f53b4 preserve participant tracking while filtering reply notifications 2026-10-18 19:35:01 +05:30
Abhinav Raut 0a13ff5b73 fix reply notifications and repeated agent lookups 2026-10-18 19:35:01 +05:30
Abhinav Raut f85b0c0687 merge latest main into the inbox aliases branch 2026-10-10 03:26:33 +05:30
Abhinav Raut 7df3188a8b Merge remote-tracking branch 'origin/main' into security-review-fixes
# Conflicts:
#	internal/migrations/v2.9.0-rc.9.go
2026-10-10 02:04:38 +05:30
Abhinav Raut 046b744515 fix message loading and unread state races 2026-10-10 01:50:00 +05:30
Abhinav Raut cfeb152a82 allow marking a conversation read without a message id 2026-10-08 00:48:17 +05:30
Abhinav Raut a9fd8616a8 put the alias reply tag on the main address and keep the alias as sender
Alias replies now put the +conv tag on the main address, because many alias forwarders bounce + addresses. From now follows the last address we sent from, and a failed re-verify no longer blocks an alias that was verified before.
2026-10-08 00:37:33 +05:30
Abhinav Raut 723c0e84ba fix notification and conversation read state
Opening a conversation used to mark it read even when the agent never scrolled to the new messages or the tab was in the background. Reply notifications in the bell also stayed unread after the agent read the reply.

Now the browser tells the server which message the agent saw. It only does this when the end of the thread is on screen and the tab has focus. The server moves the agent's last seen time forward to that message and never back.

A reply notification counts as read when the agent's last seen time is at or after the reply. "Mark as unread" marks the old reply notifications read first, so the bell stays the same.

Reply emails and pushes wait a little before sending. They are skipped if the agent already read the message or can no longer see the conversation.
2026-10-08 00:33:14 +05:30
Abhinav Raut f6a0a1e5c7 Merge remote-tracking branch 'origin/main' into feat/inbox-aliases
# Conflicts:
#	cmd/conversation.go
#	cmd/inboxes.go
#	cmd/init.go
#	cmd/messages.go
#	cmd/upgrade.go
#	frontend/apps/main/src/api/index.js
#	frontend/apps/main/src/features/admin/inbox/EmailInboxForm.vue
#	frontend/apps/main/src/features/conversation/CreateConversation.vue
#	frontend/apps/main/src/features/conversation/ReplyBox.vue
#	frontend/apps/main/src/views/admin/inbox/EditInbox.vue
#	i18n/en-US.json
#	internal/conversation/message.go
#	internal/inbox/channel/email/email.go
#	internal/inbox/inbox.go
#	internal/inbox/queries.sql
2026-09-29 01:47:13 +05:30
Abhinav Raut ac5921e192 fix security issues found in repository review 2026-09-27 23:11:54 +05:30
Abhinav Raut 0c1dec7456 simplify inbox aliases and tidy the email inbox form
Drop the check that blocked one address on two inboxes and simplify sender
lookup, alias verification and IMAP handling. The inbox form now shows the
connected account first, lines up its fields and shows one hint for unsaved aliases.
2026-09-27 22:54:40 +05:30
Abhinav Raut da13bfb44c Merge remote-tracking branch 'origin/main' into feat/inbox-aliases
# Conflicts:
#	frontend/apps/main/src/features/conversation/ReplyBox.vue
#	frontend/apps/main/src/features/conversation/ReplyBoxContent.vue
#	internal/conversation/conversation.go
#	internal/migrations/v2.9.0.go
2026-09-27 11:11:55 +05:30
Abhinav Raut 9f686ac568 remove redundant translations and semicolons 2026-09-25 02:06:02 +05:30
Abhinav Raut d2e2bcc3b6 Merge remote-tracking branch 'origin/main' into feat-whatsapp 2026-09-23 10:08:30 +05:30
Abhinav Raut 77df872b20 clear the handoff form flag once the form is submitted 2026-09-23 00:44:19 +05:30
Abhinav Raut f6f1bb4ad1 show helpcenter article as is inside the widget. adds new ?embed query param that shows the entire helpcenter in embed mode 2026-09-19 03:58:04 +05:30
Abhinav Raut 28b33a1b56 insert campaign reply messages in the conversation transaction, allow zero cooldown, scope handoff drafts and parent origin 2026-09-18 20:11:54 +05:30
Abhinav Raut da1d8e01a9 count unread messages for new conversations 2026-09-18 16:38:47 +05:30
Abhinav Raut 7d77754b52 improve live chat widget flows
Expand widget conversations with audience-specific forms, AI handoffs, message previews, and help article translations. Keep existing inbox settings compatible and reject invalid live chat configuration.
2026-09-18 16:09:15 +05:30
Abhinav Raut ccba084d4b Merge remote-tracking branch 'origin/main' into libredesk-widget-improvements 2026-09-18 02:54:09 +05:30
Abhinav Raut 9c1e14704f fix campaign reply and poll edge cases, enlarge mobile launcher 2026-09-18 01:05:21 +05:30
Abhinav Raut a41ce679cf merge main into WhatsApp branch 2026-09-17 00:46:54 +05:30
Abhinav Raut 639941eecc fix WhatsApp message order and contact numbers
Normalize stored phone numbers before linking WhatsApp identities. Serialize outbound parts per conversation and inbound messages per sender.
2026-09-17 00:06:09 +05:30
Abhinav Raut 89f58904d2 wip: add widget campaigns, help center in widget and transcript download 2026-09-16 02:11:44 +05:30
Abhinav Raut 6655a9fcb0 fix reply alerts and browser push subscriptions
Send every reply alert while batching email for five minutes. Keep shared browser subscriptions tied to the signed-in agent.
2026-09-16 00:16:12 +05:30
Abhinav Raut ced1a8bee5 add per-agent notification preferences and browser push 2026-09-15 12:31:27 +05:30
Sanielia c60ddbe04d feat(inbox): Implement inbox aliases for sending and receiving 2026-09-03 21:26:56 +02:00
Abhinav Raut 34d418ec86 fix WhatsApp window updates on retries and contact search races 2026-09-03 13:09:00 +05:30
Abhinav Raut 8fd74635a6 Merge remote-tracking branch 'origin/main' into feat-whatsapp
# Conflicts:
#	cmd/conversation.go
#	cmd/media.go
#	cmd/messages.go
#	frontend/apps/main/src/components/sidebar/Sidebar.vue
#	frontend/apps/main/src/constants/emitterEvents.js
#	frontend/apps/main/src/features/conversation/Conversation.vue
#	frontend/apps/main/src/features/conversation/CreateConversation.vue
#	frontend/apps/main/src/features/conversation/ReplyBoxMenuBar.vue
#	frontend/apps/main/src/features/conversation/message/MessageBubble.vue
#	frontend/apps/main/src/stores/conversation.js
#	internal/conversation/models/models.go
#	internal/conversation/queries.sql
#	internal/migrations/v2.9.0.go
#	internal/search/queries.sql
#	internal/user/user.go
2026-09-03 01:37:02 +05:30
Abhinav Raut 2ba716cb58 Merge remote-tracking branch 'origin/main' into pr/sidebar-counts
# Conflicts:
#	frontend/apps/main/src/stores/conversation.js
#	internal/conversation/conversation.go
2026-09-02 00:45:50 +05:30
Abhinav Raut 455f745e08 apply code review fixes to sidebar counts
Refresh badges on new notifications, bulk actions, snooze and unassign. Drop the second count request that fired on every local status change, look up the timezone once per counts request, and move the count base query into queries.sql.
2026-09-02 00:44:42 +05:30
Abhinav Raut 12bb634b0f Merge remote-tracking branch 'origin/main' into shrink-macro-payloads
# Conflicts:
#	frontend/apps/main/src/features/conversation/ReplyBox.vue
#	frontend/apps/main/src/stores/macro.js
#	frontend/apps/main/src/stores/macro.test.js
#	internal/image/image.go
2026-09-02 00:01:42 +05:30
Abhinav Raut 01ec83c7ce fix same-second read receipt and add sent/read tooltips 2026-08-31 01:56:19 +05:30
Emre 409c5bab91 feat(read-indicator): show read indicator for chat messages
This implementation uses already tracked contact_last_seen conversation field and compares the message createdAt value.
It's also confirmed that this field is only updated for live chat conversations so email conversations falls back to the single check mark.

Testing done on the embedded widget and working as expected.

Fixes #434
2026-08-28 13:19:10 -04:00
Abhinav Raut 387071117d cut memory spikes from uploads, i18n and the hourly time trigger
Heap profiles on a large install showed three hot spots: image uploads
decoded the full bitmap twice, every i18n request rebuilt the language
pack, and the hourly time trigger loaded all conversations from the
last 30 days into one slice.
2026-08-28 17:06:08 +05:30
Abhinav Raut 18514cd021 search and paginate agents, teams, tags and macros instead of loading them all at boot 2026-08-28 01:43:59 +05:30
Amberger Moritz d12c4446a6 feat: show open conversation counts in the inbox sidebar
Adds badges with the number of open conversations next to My inbox,
Mentions, Unassigned, All and each personal or shared view. "Open" means
a conversation whose status category is open, so snoozed and resolved
conversations are not counted.

Backend:
- GET /api/v1/conversations/sidebar-counts returns the counts, gated by
  the conversations:read permission. Each individual count is additionally
  gated server-side by the permission for that list, so an agent never
  receives a number for a list they cannot open.
- View counts are unioned into a single statement, so the number of views
  does not drive the number of queries.
- The list-type conditions shared by the conversation list and count
  queries are extracted into appendListTypeConditions, so both stay in
  sync on what each list type means.
- An empty team list now renders as IN (NULL) instead of the invalid
  IN (), which an agent holding a team permission without a team hit.
- The feature can be turned off via app.sidebar_counts_enabled, which
  defaults to enabled when the setting is missing.

Frontend:
- Counts refresh when switching inboxes, after the agent's own status or
  assignee changes, and from new_conversation and status-carrying
  conversation_update websocket events.
- Refreshes are throttled and share a short TTL, so bursts of incoming
  conversations collapse into a single request. Re-enabling the feature
  bypasses the TTL, because being disabled leaves a zeroed result cached.

Refs #466

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 16:58:30 +02:00
Abhinav Raut fd4a37ff76 add WhatsApp channel tests and bug fixes 2026-08-25 18:29:16 +05:30
Abhinav Raut b7c2ef93ee Merge remote-tracking branch 'origin/main' into feat-whatsapp
# Conflicts:
#	cmd/main.go
#	frontend/apps/main/src/features/conversation/Conversation.vue
#	frontend/apps/main/src/features/conversation/CreateConversation.vue
#	frontend/apps/main/src/features/conversation/list/ConversationListItem.vue
2026-08-23 03:00:22 +05:30
Abhinav Raut 364d11aa7f stop duplicate key errors when adding conversation participants 2026-08-21 12:13:17 +05:30
Abhinav Raut 51621254d8 broadcast the remaining sla fields when a policy is applied 2026-08-21 02:59:53 +05:30
Abhinav Raut 6fa5d66b6b recompute conversation SLA deadline when next response is settled
Marking a next-response SLA event met or breached never updated
conversations.next_sla_deadline_at, so the conversation kept sorting as if
the reply was still due. Reopening a resolved conversation had the same
problem in reverse: the column stays NULL even though its deadlines are
live again.
2026-08-21 02:01:04 +05:30
Abhinav Raut 3568aa18c6 restrict private note deletion to the note author or an admin 2026-08-19 14:35:32 +05:30
Abhinav Raut defc6535b9 send whatsapp attachments as one message per file
Meta accepts only one media per message and sends one status webhook per
message id, so a reply with 3 files is now sent as 3 requests from the reply
box instead of one message that half-succeeded. Drops the partial-send
tracking, markers and retry-attachments button that existed to paper over it.
2026-08-16 22:51:05 +05:30
Abhinav Raut 92a1ef8150 Merge branch 'help-center' into feat-whatsapp
# Conflicts:
#	cmd/conversation.go
#	cmd/upgrade.go
#	frontend/apps/main/src/api/index.js
#	frontend/apps/main/src/constants/emitterEvents.js
#	frontend/apps/main/src/features/contact/ContactForm.vue
#	frontend/apps/main/src/features/conversation/Conversation.vue
#	frontend/apps/main/src/features/conversation/CreateConversation.vue
#	frontend/apps/main/src/features/conversation/ReplyBox.vue
#	frontend/apps/main/src/features/conversation/ReplyBoxMenuBar.vue
#	frontend/apps/main/src/features/conversation/list/ConversationListItem.vue
#	frontend/apps/main/src/features/conversation/message/MessageBubble.vue
#	frontend/apps/main/src/features/conversation/message/attachment/BubbleAttachmentItem.vue
#	frontend/apps/main/src/features/conversation/sidebar/ConversationSideBarContact.vue
#	frontend/apps/main/src/views/admin/inbox/NewInbox.vue
#	frontend/shared-ui/constants/countries.js
#	go.mod
#	internal/search/models/models.go
#	internal/stringutil/stringutil.go
#	internal/user/queries.sql
2026-07-25 14:34:00 +05:30