iachat/app/javascript/dashboard/i18n/locale/en/chatlist.json
Gabriel Jablonski 11e9932e9b
feat(whatsapp): show contact typing and recording indicators via baileys presence (#264)
* feat(whatsapp): show contact typing and recording indicators via baileys presence

Subscribe to WhatsApp presence updates via the baileys-api provider to
display real-time typing and recording indicators in the dashboard.

- Handle presence.update webhook events (composing, recording, paused,
  available) and broadcast via ActionCable
- Add conversation.recording event to ActionCable, webhook, and channel
  listeners for parity with typing_on/typing_off
- Show "typing..." / "recording..." in green text on the chat list,
  replacing the message preview
- Show "X is typing" / "X is recording audio" in the conversation view
- Add presence_subscribe provider config option (default off) to gate
  all subscription calls to the baileys-api
- Subscribe to presence on conversation open and periodically (1 min)
  for the top 10 chat list conversations
- Consolidate contact LID from presence.update jidAlt payload
- Prevent echo-back of contact typing events to the channel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback

- Filter chat list typing indicator to contact-only events
- Add dedupe to presence subscribe bulk calls
- Use strong parameters for conversation_ids
- Remove redundant YAML quotes in swagger webhook enum

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback

- Extract phone from data[:id] when JID is @s.whatsapp.net (fallback
  when jidAlt is absent)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback

- Filter recording users in getTypingUsersText to show correct names
- Add 10s timeout to presence_subscribe HTTP request

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: scope typing timer per user instead of per conversation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: make presence subscribe best-effort with rescue per channel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback

- Add messagePreviewClass to typing preview for consistent padding
- Fix specs to use WebMock assertions instead of instance spying

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:38:11 -03:00

148 lines
3.6 KiB
JSON

{
"CHAT_LIST": {
"LOADING": "Fetching conversations",
"LOAD_MORE_CONVERSATIONS": "Load more conversations",
"EOF": "All conversations loaded 🎉",
"LIST": {
"404": "There are no active conversations in this group."
},
"FAILED_TO_SEND": "Failed to send",
"TAB_HEADING": "Conversations",
"MENTION_HEADING": "Mentions",
"UNATTENDED_HEADING": "Unattended",
"SEARCH": {
"INPUT": "Search for People, Chats, Saved Replies .."
},
"FILTER_ALL": "All",
"ASSIGNEE_TYPE_TABS": {
"me": "Mine",
"unassigned": "Unassigned",
"all": "All"
},
"CHAT_STATUS_FILTER_ITEMS": {
"open": {
"TEXT": "Open"
},
"resolved": {
"TEXT": "Resolved"
},
"pending": {
"TEXT": "Pending"
},
"snoozed": {
"TEXT": "Snoozed"
},
"all": {
"TEXT": "All"
}
},
"VIEW_FILTER": "View",
"SORT_TOOLTIP_LABEL": "Sort conversations",
"CHAT_SORT": {
"STATUS": "Status",
"ORDER_BY": "Order by"
},
"CHAT_TIME_STAMP": {
"CREATED": {
"LATEST": "Created",
"OLDEST": "Created at:"
},
"LAST_ACTIVITY": {
"NOT_ACTIVE": "Last activity:",
"ACTIVE": "Last activity"
}
},
"SORT_ORDER_ITEMS": {
"last_activity_at_asc": {
"TEXT": "Last activity: Oldest first"
},
"last_activity_at_desc": {
"TEXT": "Last activity: Newest first"
},
"created_at_desc": {
"TEXT": "Created at: Newest first"
},
"created_at_asc": {
"TEXT": "Created at: Oldest first"
},
"priority_desc": {
"TEXT": "Priority: Highest first"
},
"priority_asc": {
"TEXT": "Priority: Lowest first"
},
"waiting_since_asc": {
"TEXT": "Pending Response: Longest first"
},
"waiting_since_desc": {
"TEXT": "Pending Response: Shortest first"
},
"priority_desc_created_at_asc": {
"TEXT": "Priority: Highest first, Created: Oldest first"
}
},
"ATTACHMENTS": {
"image": {
"CONTENT": "Picture message"
},
"audio": {
"CONTENT": "Audio message"
},
"video": {
"CONTENT": "Video message"
},
"file": {
"CONTENT": "File Attachment"
},
"location": {
"CONTENT": "Location"
},
"ig_reel": {
"CONTENT": "Instagram Reel"
},
"fallback": {
"CONTENT": "has shared a url"
},
"contact": {
"CONTENT": "Shared contact"
},
"embed": {
"CONTENT": "Embedded content"
}
},
"CHAT_SORT_BY_FILTER": {
"TITLE": "Sort conversation",
"DROPDOWN_TITLE": "Sort by",
"ITEMS": {
"LATEST": {
"NAME": "Last activity at",
"LABEL": "Last activity"
},
"CREATED_AT": {
"NAME": "Created at",
"LABEL": "Created at"
},
"LAST_USER_MESSAGE_AT": {
"NAME": "Last user message at",
"LABEL": "Last message"
}
}
},
"RECEIVED_VIA_EMAIL": "Received via email",
"VIEW_TWEET_IN_TWITTER": "View tweet in Twitter",
"REPLY_TO_TWEET": "Reply to this tweet",
"LINK_TO_STORY": "Go to instagram story",
"SENT": "Sent successfully",
"READ": "Read successfully",
"DELIVERED": "Delivered successfully",
"NO_MESSAGES": "No Messages",
"TYPING": "typing...",
"RECORDING": "recording...",
"NO_CONTENT": "No content available",
"HIDE_QUOTED_TEXT": "Hide Quoted Text",
"SHOW_QUOTED_TEXT": "Show Quoted Text",
"MESSAGE_READ": "Read",
"SENDING": "Sending"
}
}