@rapidmx/web-client 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/apps/admin/domains/[uid].tsx +3 -2
  2. package/apps/shared/appearance/AppearanceForm.tsx +9 -1
  3. package/apps/shared/calendar/bookingPlugin.ts +100 -0
  4. package/apps/shared/calendar/calendarLiveUpdates.ts +27 -0
  5. package/apps/shared/components/admin/layout/AdminShell.tsx +37 -5
  6. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +3 -1
  7. package/apps/shared/components/admin/settings/PluginsManager.tsx +1545 -1491
  8. package/apps/shared/components/calendar/AppointmentQuickForm.tsx +327 -0
  9. package/apps/shared/components/calendar/DescriptionEditor.tsx +274 -0
  10. package/apps/shared/components/calendar/EventDescriptionView.tsx +70 -0
  11. package/apps/shared/components/calendar/EventDetails.tsx +401 -0
  12. package/apps/shared/components/calendar/EventEditor.tsx +640 -0
  13. package/apps/shared/components/calendar/EventExpandedForm.tsx +210 -0
  14. package/apps/shared/components/calendar/EventFormParts.tsx +622 -0
  15. package/apps/shared/components/calendar/EventModal.tsx +126 -862
  16. package/apps/shared/components/calendar/EventQuickForm.tsx +116 -0
  17. package/apps/shared/components/calendar/EventShell.tsx +202 -0
  18. package/apps/shared/components/calendar/FindATime.tsx +379 -0
  19. package/apps/shared/components/calendar/LazyDescriptionEditor.tsx +70 -0
  20. package/apps/shared/components/calendar/MonthView.tsx +15 -3
  21. package/apps/shared/components/calendar/QuickCreateFaces.tsx +87 -0
  22. package/apps/shared/components/calendar/QuickCreateTabs.tsx +81 -0
  23. package/apps/shared/components/calendar/QuickFaceFrame.tsx +81 -0
  24. package/apps/shared/components/calendar/RecurrenceEditor.tsx +10 -5
  25. package/apps/shared/components/calendar/RequestChangeForm.tsx +271 -0
  26. package/apps/shared/components/calendar/SplitDayView.tsx +6 -5
  27. package/apps/shared/components/calendar/TaskQuickForm.tsx +289 -0
  28. package/apps/shared/components/calendar/TimeGridView.tsx +8 -6
  29. package/apps/shared/components/calendar/eventDialogFields.ts +86 -0
  30. package/apps/shared/components/calendar/eventForm.ts +108 -0
  31. package/apps/shared/components/calendar/eventFormat.ts +183 -0
  32. package/apps/shared/components/calendar/findTimeGrid.ts +90 -0
  33. package/apps/shared/components/calendar/swipeNavigation.ts +14 -0
  34. package/apps/shared/components/layout/UserMenu.tsx +80 -28
  35. package/apps/shared/components/mail/ConversationList.tsx +100 -48
  36. package/apps/shared/components/mail/ConversationThreadPane.tsx +490 -486
  37. package/apps/shared/components/mail/InviteCard.tsx +387 -0
  38. package/apps/shared/components/mail/MessageDetailPane.tsx +24 -2
  39. package/apps/shared/components/mail/SwipeRow.tsx +120 -0
  40. package/apps/shared/components/mail/compose/ComposeWindow.tsx +7 -3
  41. package/apps/shared/components/mail/invite/InviteRowChip.tsx +104 -0
  42. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +271 -0
  43. package/apps/shared/components/mail/invite/InviteTimeline.tsx +200 -0
  44. package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +109 -0
  45. package/apps/shared/components/mail/invite/inviteFormat.ts +110 -0
  46. package/apps/shared/components/mail/invite/inviteStore.ts +114 -0
  47. package/apps/shared/components/mail/layout/MailShell.tsx +522 -490
  48. package/apps/shared/components/settings/layout/SettingsShell.tsx +1 -0
  49. package/apps/shared/gestures/useEnterSlide.ts +54 -0
  50. package/apps/shared/gestures/useSwipe.ts +114 -0
  51. package/apps/shared/gestures/useSwipeSlide.ts +113 -0
  52. package/apps/shared/gestures/useWheelPaging.ts +107 -0
  53. package/apps/shared/mail/newMailNotifications.ts +171 -183
  54. package/apps/shared/mail/useNewMailNotifications.ts +178 -178
  55. package/apps/shared/notifications/preferences.ts +36 -0
  56. package/apps/shared/notifications/store.ts +560 -551
  57. package/apps/www/_routes.ts +1 -0
  58. package/apps/www/calendar/index.tsx +139 -37
  59. package/apps/www/index.tsx +273 -126
  60. package/apps/www/messages/[uid].tsx +31 -4
  61. package/apps/www/settings/profile/index.tsx +248 -0
  62. package/dist/apps/admin/domains/[uid].js +4 -2
  63. package/dist/apps/shared/appearance/AppearanceForm.js +9 -1
  64. package/dist/apps/shared/calendar/bookingPlugin.d.ts +50 -0
  65. package/dist/apps/shared/calendar/bookingPlugin.js +57 -0
  66. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +11 -0
  67. package/dist/apps/shared/calendar/calendarLiveUpdates.js +23 -0
  68. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  69. package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -3
  70. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +3 -1
  71. package/dist/apps/shared/components/admin/settings/PluginsManager.js +40 -6
  72. package/dist/apps/shared/components/calendar/AppointmentQuickForm.d.ts +47 -0
  73. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +135 -0
  74. package/dist/apps/shared/components/calendar/DescriptionEditor.d.ts +26 -0
  75. package/dist/apps/shared/components/calendar/DescriptionEditor.js +192 -0
  76. package/dist/apps/shared/components/calendar/EventDescriptionView.d.ts +14 -0
  77. package/dist/apps/shared/components/calendar/EventDescriptionView.js +39 -0
  78. package/dist/apps/shared/components/calendar/EventDetails.d.ts +33 -0
  79. package/dist/apps/shared/components/calendar/EventDetails.js +137 -0
  80. package/dist/apps/shared/components/calendar/EventEditor.d.ts +59 -0
  81. package/dist/apps/shared/components/calendar/EventEditor.js +549 -0
  82. package/dist/apps/shared/components/calendar/EventExpandedForm.d.ts +14 -0
  83. package/dist/apps/shared/components/calendar/EventExpandedForm.js +44 -0
  84. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +69 -0
  85. package/dist/apps/shared/components/calendar/EventFormParts.js +202 -0
  86. package/dist/apps/shared/components/calendar/EventModal.d.ts +26 -13
  87. package/dist/apps/shared/components/calendar/EventModal.js +57 -455
  88. package/dist/apps/shared/components/calendar/EventQuickForm.d.ts +18 -0
  89. package/dist/apps/shared/components/calendar/EventQuickForm.js +25 -0
  90. package/dist/apps/shared/components/calendar/EventShell.d.ts +64 -0
  91. package/dist/apps/shared/components/calendar/EventShell.js +134 -0
  92. package/dist/apps/shared/components/calendar/FindATime.d.ts +18 -0
  93. package/dist/apps/shared/components/calendar/FindATime.js +190 -0
  94. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.d.ts +8 -0
  95. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.js +44 -0
  96. package/dist/apps/shared/components/calendar/MonthView.d.ts +5 -1
  97. package/dist/apps/shared/components/calendar/MonthView.js +11 -5
  98. package/dist/apps/shared/components/calendar/QuickCreateFaces.d.ts +30 -0
  99. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +44 -0
  100. package/dist/apps/shared/components/calendar/QuickCreateTabs.d.ts +24 -0
  101. package/dist/apps/shared/components/calendar/QuickCreateTabs.js +46 -0
  102. package/dist/apps/shared/components/calendar/QuickFaceFrame.d.ts +25 -0
  103. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +19 -0
  104. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +4 -1
  105. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +2 -2
  106. package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +36 -0
  107. package/dist/apps/shared/components/calendar/RequestChangeForm.js +138 -0
  108. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +3 -2
  109. package/dist/apps/shared/components/calendar/SplitDayView.js +3 -2
  110. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +40 -0
  111. package/dist/apps/shared/components/calendar/TaskQuickForm.js +101 -0
  112. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +4 -2
  113. package/dist/apps/shared/components/calendar/TimeGridView.js +3 -2
  114. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +28 -0
  115. package/dist/apps/shared/components/calendar/eventDialogFields.js +59 -0
  116. package/dist/apps/shared/components/calendar/eventForm.d.ts +98 -0
  117. package/dist/apps/shared/components/calendar/eventForm.js +1 -0
  118. package/dist/apps/shared/components/calendar/eventFormat.d.ts +67 -0
  119. package/dist/apps/shared/components/calendar/eventFormat.js +163 -0
  120. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +30 -0
  121. package/dist/apps/shared/components/calendar/findTimeGrid.js +83 -0
  122. package/dist/apps/shared/components/calendar/swipeNavigation.d.ts +9 -0
  123. package/dist/apps/shared/components/calendar/swipeNavigation.js +8 -0
  124. package/dist/apps/shared/components/layout/UserMenu.d.ts +10 -8
  125. package/dist/apps/shared/components/layout/UserMenu.js +70 -23
  126. package/dist/apps/shared/components/mail/ConversationList.d.ts +12 -1
  127. package/dist/apps/shared/components/mail/ConversationList.js +21 -4
  128. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +4 -1
  129. package/dist/apps/shared/components/mail/InviteCard.d.ts +20 -0
  130. package/dist/apps/shared/components/mail/InviteCard.js +150 -0
  131. package/dist/apps/shared/components/mail/MessageDetailPane.js +13 -2
  132. package/dist/apps/shared/components/mail/SwipeRow.d.ts +22 -0
  133. package/dist/apps/shared/components/mail/SwipeRow.js +71 -0
  134. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +8 -3
  135. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +23 -0
  136. package/dist/apps/shared/components/mail/invite/InviteRowChip.js +46 -0
  137. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +20 -0
  138. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +141 -0
  139. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +27 -0
  140. package/dist/apps/shared/components/mail/invite/InviteTimeline.js +120 -0
  141. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +17 -0
  142. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +45 -0
  143. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +28 -0
  144. package/dist/apps/shared/components/mail/invite/inviteFormat.js +94 -0
  145. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +28 -0
  146. package/dist/apps/shared/components/mail/invite/inviteStore.js +95 -0
  147. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +5 -0
  148. package/dist/apps/shared/components/mail/layout/MailShell.js +14 -3
  149. package/dist/apps/shared/components/settings/layout/SettingsShell.js +1 -0
  150. package/dist/apps/shared/gestures/useEnterSlide.d.ts +14 -0
  151. package/dist/apps/shared/gestures/useEnterSlide.js +47 -0
  152. package/dist/apps/shared/gestures/useSwipe.d.ts +45 -0
  153. package/dist/apps/shared/gestures/useSwipe.js +90 -0
  154. package/dist/apps/shared/gestures/useSwipeSlide.d.ts +40 -0
  155. package/dist/apps/shared/gestures/useSwipeSlide.js +95 -0
  156. package/dist/apps/shared/gestures/useWheelPaging.d.ts +32 -0
  157. package/dist/apps/shared/gestures/useWheelPaging.js +85 -0
  158. package/dist/apps/shared/mail/newMailNotifications.d.ts +3 -8
  159. package/dist/apps/shared/mail/newMailNotifications.js +3 -12
  160. package/dist/apps/shared/mail/useNewMailNotifications.js +3 -2
  161. package/dist/apps/shared/notifications/preferences.d.ts +13 -0
  162. package/dist/apps/shared/notifications/preferences.js +36 -0
  163. package/dist/apps/shared/notifications/store.d.ts +1 -0
  164. package/dist/apps/shared/notifications/store.js +7 -23
  165. package/dist/apps/www/_routes.js +1 -0
  166. package/dist/apps/www/calendar/index.js +76 -6
  167. package/dist/apps/www/index.js +140 -39
  168. package/dist/apps/www/messages/[uid].js +13 -5
  169. package/dist/apps/www/settings/profile/index.d.ts +4 -0
  170. package/dist/apps/www/settings/profile/index.js +124 -0
  171. package/package.json +3 -3
@@ -11,6 +11,8 @@ import MailAddress from "./MailAddress.js";
11
11
  import { EncryptedPreview, conversationLooksEncrypted } from "./reading/EncryptedPreview.js";
12
12
  import { ConversationSummary, listConversationMessages } from "@rapidmx/react-shared/mail/conversationsApi.js";
13
13
  import { ROW_FOCUS_CLASS, UnreadBar, UnreadLabel, dateClass, isUnread, rowClass, senderClass, subjectClass } from "./unreadStyle.js";
14
+ import SwipeRow from "./SwipeRow.js";
15
+ import InviteRowChip from "./invite/InviteRowChip.js";
14
16
 
15
17
  export interface ConversationListProps {
16
18
  conversations: ConversationSummary[];
@@ -28,6 +30,8 @@ export interface ConversationListProps {
28
30
  * read, which this list would otherwise keep showing as unread until the thread is collapsed and
29
31
  * expanded again. */
30
32
  messageOverrides?: Record<string, Message>;
33
+ /** Called with one of a conversation's own messages carrying the answer the reader just gave to its meeting request (from that row's RSVP chip), so the caller can keep it. An answer given from the conversation's own (parent) row is kept by this list itself. */
34
+ onMeetingResponded?: (updated: Message) => void;
31
35
  /** Turns each parent row into a checkbox row: select mode here ticks whole conversations, since a
32
36
  * conversation is what this list's rows are. A child row stays a plain "open this message" button - a
33
37
  * mixed conversation/message selection has no sensible bulk semantics (see `MailListToolbar`). */
@@ -35,6 +39,15 @@ export interface ConversationListProps {
35
39
  /** The `conversationId`s currently ticked. */
36
40
  selectedConversationIds?: Set<string>;
37
41
  onToggleSelected?: (conversation: ConversationSummary) => void;
42
+ /**
43
+ * What swiping a parent row does on a phone: right to left archives the conversation (resolving whether it went through), left
44
+ * to right asks where to move it. Absent, or `enabled: false` (a desktop), rows don't follow a finger.
45
+ */
46
+ swipe?: {
47
+ enabled: boolean;
48
+ onArchive: (conversation: ConversationSummary) => Promise<boolean>;
49
+ onMove: (conversation: ConversationSummary) => void;
50
+ };
38
51
  /**
39
52
  * Whether a conversation's own messages read newest first, matching the order sense the rows themselves
40
53
  * are in ("Newest on top"). `listConversationMessages()` always answers oldest first - the order a
@@ -67,15 +80,23 @@ export default function ConversationList({
67
80
  selectedUid,
68
81
  onOpenMessage,
69
82
  messageOverrides,
83
+ onMeetingResponded,
70
84
  selectMode,
71
85
  selectedConversationIds,
72
86
  onToggleSelected,
87
+ swipe,
73
88
  newestFirst,
74
89
  }: ConversationListProps) {
75
90
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
76
91
  const [messagesById, setMessagesById] = useState<Record<string, Message[]>>({});
77
92
  const [loadingIds, setLoadingIds] = useState<Set<string>>(new Set());
78
93
  const [errorsById, setErrorsById] = useState<Record<string, string>>({});
94
+ // The answers given from a row's RSVP chip, by message uid: a row draws them at once, whichever row (the conversation's, or one of its messages) they were given from.
95
+ const [answers, setAnswers] = useState<Record<string, Message["meetingResponse"]>>({});
96
+
97
+ function answered(updated: Message) {
98
+ setAnswers((prev) => ({ ...prev, [updated.uid]: updated.meetingResponse }));
99
+ }
79
100
 
80
101
  function toggle(conversation: ConversationSummary) {
81
102
  const id = conversation.conversationId;
@@ -119,7 +140,8 @@ export default function ConversationList({
119
140
  }
120
141
 
121
142
  return (
122
- <ul>
143
+ // `overflow-x-clip`: the panels a swiped row drags along stand outside its edges (see `SwipeRow`).
144
+ <ul className={swipe?.enabled ? "overflow-x-clip" : undefined}>
123
145
  {conversations.map((conversation) => {
124
146
  const id = conversation.conversationId;
125
147
  const isExpanded = expanded.has(id);
@@ -132,7 +154,11 @@ export default function ConversationList({
132
154
  const ticked = selectedConversationIds?.has(id) ?? false;
133
155
  return (
134
156
  <li key={id}>
135
- <div
157
+ <SwipeRow
158
+ as="div"
159
+ enabled={!!swipe?.enabled && !selectMode}
160
+ onArchive={() => swipe!.onArchive(conversation)}
161
+ onMove={() => swipe!.onMove(conversation)}
136
162
  data-message-uid={conversation.latestMessageUid}
137
163
  data-unread={unread ? "true" : undefined}
138
164
  className={rowClass({ unread, selected: conversation.latestMessageUid === selectedUid || ticked }, "flex items-stretch")}
@@ -163,53 +189,71 @@ export default function ConversationList({
163
189
  <HiChevronRight size={16} aria-hidden="true" />
164
190
  )}
165
191
  </button>
166
- <button
167
- type="button"
168
- data-row-open
169
- onClick={() => onOpenMessage(conversation, conversation.latestMessageUid)}
170
- className={["flex-1 min-w-0 text-left pr-4 py-3", ROW_FOCUS_CLASS].join(" ")}
171
- >
172
- <UnreadLabel unread={unread} />
173
- <div className="flex items-center justify-between gap-2 text-sm">
174
- {/* The first participant in full - name and address - and the rest as a count, with everyone's
175
- address in its tooltip; the latest sender when the summary lists none. */}
176
- <MailAddress
177
- recipient={conversation.participants[0] ?? conversation.latestFrom}
178
- className={["flex-1", senderClass(unread)].join(" ")}
179
- />
180
- {conversation.participants.length > 1 && (
181
- <span className="text-xs text-text-muted shrink-0 font-normal" title={participantList(conversation)}>
182
- +{conversation.participants.length - 1}
183
- <span className="sr-only"> more: {participantList(conversation)}</span>
192
+ {/* The open button and, for a meeting request, its RSVP chip: a button can't hold a button, so the chip is the button's sibling. */}
193
+ <div className="flex-1 min-w-0 flex flex-col">
194
+ <button
195
+ type="button"
196
+ data-row-open
197
+ onClick={() => onOpenMessage(conversation, conversation.latestMessageUid)}
198
+ className={["w-full text-left pr-4 py-3", ROW_FOCUS_CLASS].join(" ")}
199
+ >
200
+ <UnreadLabel unread={unread} />
201
+ <div className="flex items-center justify-between gap-2 text-sm">
202
+ {/* The first participant in full - name and address - and the rest as a count, with everyone's
203
+ address in its tooltip; the latest sender when the summary lists none. */}
204
+ <MailAddress
205
+ recipient={conversation.participants[0] ?? conversation.latestFrom}
206
+ className={["flex-1", senderClass(unread)].join(" ")}
207
+ />
208
+ {conversation.participants.length > 1 && (
209
+ <span className="text-xs text-text-muted shrink-0 font-normal" title={participantList(conversation)}>
210
+ +{conversation.participants.length - 1}
211
+ <span className="sr-only"> more: {participantList(conversation)}</span>
212
+ </span>
213
+ )}
214
+ <span className={["text-xs shrink-0", dateClass(unread)].join(" ")}>
215
+ {new Date(conversation.latestDate).toLocaleDateString()}
184
216
  </span>
185
- )}
186
- <span className={["text-xs shrink-0", dateClass(unread)].join(" ")}>
187
- {new Date(conversation.latestDate).toLocaleDateString()}
188
- </span>
189
- </div>
190
- <div className={["text-sm truncate", subjectClass(unread)].join(" ")}>{conversation.subject || "(no subject)"}</div>
191
- <div className="text-xs text-text-muted truncate font-normal">
192
- {/* An encrypted latest message has no preview (the server never had its plaintext): say so, with a lock, not nothing. */}
193
- {conversationLooksEncrypted(conversation) ? <EncryptedPreview /> : conversation.latestPreview}
194
- </div>
195
- <div className="flex items-center gap-2 mt-1 text-xs text-text-muted font-normal">
196
- {conversation.messageCount > 1 && <span>{conversation.messageCount} messages</span>}
197
- {/* A one-message conversation's unread state is already the row's own
198
- bolding - counting it "1 unread" on every such row is just noise. */}
199
- {unread && conversation.messageCount > 1 && (
200
- <span className="py-0.5 px-2 rounded-pill bg-primary/15 text-primary-dark font-bold">
201
- {conversation.unreadCount} unread
202
- </span>
203
- )}
204
- {conversation.hasAttachments && (
205
- <HiOutlinePaperClip size={13} aria-label="Has attachments" />
206
- )}
207
- {conversation.flagged && (
208
- <HiOutlineFlag size={13} aria-label="Flagged" className="text-danger" />
209
- )}
210
- </div>
211
- </button>
212
- </div>
217
+ </div>
218
+ <div className={["text-sm truncate", subjectClass(unread)].join(" ")}>{conversation.subject || "(no subject)"}</div>
219
+ <div className="text-xs text-text-muted truncate font-normal">
220
+ {/* An encrypted latest message has no preview (the server never had its plaintext): say so, with a lock, not nothing. */}
221
+ {conversationLooksEncrypted(conversation) ? <EncryptedPreview /> : conversation.latestPreview}
222
+ </div>
223
+ <div className="flex items-center gap-2 mt-1 text-xs text-text-muted font-normal">
224
+ {conversation.messageCount > 1 && <span>{conversation.messageCount} messages</span>}
225
+ {/* A one-message conversation's unread state is already the row's own
226
+ bolding - counting it "1 unread" on every such row is just noise. */}
227
+ {unread && conversation.messageCount > 1 && (
228
+ <span className="py-0.5 px-2 rounded-pill bg-primary/15 text-primary-dark font-bold">
229
+ {conversation.unreadCount} unread
230
+ </span>
231
+ )}
232
+ {conversation.hasAttachments && (
233
+ <HiOutlinePaperClip size={13} aria-label="Has attachments" />
234
+ )}
235
+ {conversation.flagged && (
236
+ <HiOutlineFlag size={13} aria-label="Flagged" className="text-danger" />
237
+ )}
238
+ </div>
239
+ </button>
240
+ <InviteRowChip
241
+ message={
242
+ {
243
+ uid: conversation.latestMessageUid,
244
+ meetingMethod: conversation.latestMeetingMethod ?? undefined,
245
+ meetingResponse:
246
+ answers[conversation.latestMessageUid] ??
247
+ messageOverrides?.[conversation.latestMessageUid]?.meetingResponse ??
248
+ conversation.latestMeetingResponse ??
249
+ undefined,
250
+ } as Message
251
+ }
252
+ onResponded={answered}
253
+ className="mr-4"
254
+ />
255
+ </div>
256
+ </SwipeRow>
213
257
  <ul id={panelId} hidden={!isExpanded}>
214
258
  {errorsById[id] && (
215
259
  <li role="alert" className="pl-8 pr-4 py-2 text-xs text-danger border-b border-border">
@@ -259,6 +303,14 @@ export default function ConversationList({
259
303
  )}
260
304
  </div>
261
305
  </button>
306
+ <InviteRowChip
307
+ message={{ ...message, meetingResponse: answers[message.uid] ?? message.meetingResponse }}
308
+ onResponded={(updated) => {
309
+ answered(updated);
310
+ onMeetingResponded?.(updated);
311
+ }}
312
+ className="ml-8 mr-4"
313
+ />
262
314
  </li>
263
315
  );
264
316
  })}