stream-chat-react-native-core 9.4.0-beta.1 → 9.4.0-beta.10

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 (267) hide show
  1. package/lib/commonjs/components/Attachment/Attachment.js +10 -5
  2. package/lib/commonjs/components/Attachment/Attachment.js.map +1 -1
  3. package/lib/commonjs/components/Attachment/Audio/AudioAttachment.js +2 -4
  4. package/lib/commonjs/components/Attachment/Audio/AudioAttachment.js.map +1 -1
  5. package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsActionItems.js +2 -1
  6. package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsActionItems.js.map +1 -1
  7. package/lib/commonjs/components/ChannelList/ChannelList.js +4 -1
  8. package/lib/commonjs/components/ChannelList/ChannelList.js.map +1 -1
  9. package/lib/commonjs/components/ChannelList/hooks/useCreateChannelsContext.js +5 -3
  10. package/lib/commonjs/components/ChannelList/hooks/useCreateChannelsContext.js.map +1 -1
  11. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +5 -3
  12. package/lib/commonjs/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  13. package/lib/commonjs/components/ChannelPreview/ChannelPreview.js +3 -0
  14. package/lib/commonjs/components/ChannelPreview/ChannelPreview.js.map +1 -1
  15. package/lib/commonjs/components/ChannelPreview/ChannelPreviewPinnedStatus.js +30 -0
  16. package/lib/commonjs/components/ChannelPreview/ChannelPreviewPinnedStatus.js.map +1 -0
  17. package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js +8 -3
  18. package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
  19. package/lib/commonjs/components/ChannelPreview/ChannelSwipableWrapper.js +2 -1
  20. package/lib/commonjs/components/ChannelPreview/ChannelSwipableWrapper.js.map +1 -1
  21. package/lib/commonjs/components/ChannelPreview/hooks/index.js +11 -0
  22. package/lib/commonjs/components/ChannelPreview/hooks/index.js.map +1 -1
  23. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js +3 -0
  24. package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -1
  25. package/lib/commonjs/components/ChannelPreview/hooks/useIsChannelPinned.js +11 -0
  26. package/lib/commonjs/components/ChannelPreview/hooks/useIsChannelPinned.js.map +1 -0
  27. package/lib/commonjs/components/Message/Message.js +53 -16
  28. package/lib/commonjs/components/Message/Message.js.map +1 -1
  29. package/lib/commonjs/components/Message/MessageItemView/MessageItemView.js +6 -84
  30. package/lib/commonjs/components/Message/MessageItemView/MessageItemView.js.map +1 -1
  31. package/lib/commonjs/components/MessageInput/MessageComposer.js +8 -29
  32. package/lib/commonjs/components/MessageInput/MessageComposer.js.map +1 -1
  33. package/lib/commonjs/components/MessageMenu/MessageActionList.js +1 -1
  34. package/lib/commonjs/components/Poll/components/CreatePollHeader.js +5 -5
  35. package/lib/commonjs/components/Poll/components/CreatePollHeader.js.map +1 -1
  36. package/lib/commonjs/components/Poll/components/PollButtons.js +25 -56
  37. package/lib/commonjs/components/Poll/components/PollButtons.js.map +1 -1
  38. package/lib/commonjs/components/Poll/components/PollInputDialog.js +9 -11
  39. package/lib/commonjs/components/Poll/components/PollInputDialog.js.map +1 -1
  40. package/lib/commonjs/components/Poll/components/PollModal.js +50 -0
  41. package/lib/commonjs/components/Poll/components/PollModal.js.map +1 -0
  42. package/lib/commonjs/components/Poll/components/PollModalHeader.js +4 -5
  43. package/lib/commonjs/components/Poll/components/PollModalHeader.js.map +1 -1
  44. package/lib/commonjs/components/Poll/components/PollResults/PollResultItem.js +10 -24
  45. package/lib/commonjs/components/Poll/components/PollResults/PollResultItem.js.map +1 -1
  46. package/lib/commonjs/components/Poll/components/index.js +11 -0
  47. package/lib/commonjs/components/Poll/components/index.js.map +1 -1
  48. package/lib/commonjs/components/index.js +11 -0
  49. package/lib/commonjs/components/index.js.map +1 -1
  50. package/lib/commonjs/contexts/channelsContext/ChannelsContext.js.map +1 -1
  51. package/lib/commonjs/contexts/componentsContext/defaultComponents.js +2 -0
  52. package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
  53. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageComposer.js +2 -2
  54. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageComposer.js.map +1 -1
  55. package/lib/commonjs/contexts/themeContext/utils/theme.js +3 -1
  56. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  57. package/lib/commonjs/hooks/actions/useChannelActionItems.js +20 -1
  58. package/lib/commonjs/hooks/actions/useChannelActionItems.js.map +1 -1
  59. package/lib/commonjs/hooks/actions/useChannelActionItemsById.js +3 -1
  60. package/lib/commonjs/hooks/actions/useChannelActionItemsById.js.map +1 -1
  61. package/lib/commonjs/i18n/ar.json +6 -1
  62. package/lib/commonjs/i18n/en.json +5 -0
  63. package/lib/commonjs/i18n/es.json +6 -1
  64. package/lib/commonjs/i18n/fr.json +6 -1
  65. package/lib/commonjs/i18n/he.json +6 -1
  66. package/lib/commonjs/i18n/hi.json +6 -1
  67. package/lib/commonjs/i18n/it.json +6 -1
  68. package/lib/commonjs/i18n/ja.json +6 -1
  69. package/lib/commonjs/i18n/ko.json +6 -1
  70. package/lib/commonjs/i18n/nl.json +6 -1
  71. package/lib/commonjs/i18n/pt-br.json +6 -1
  72. package/lib/commonjs/i18n/ru.json +6 -1
  73. package/lib/commonjs/i18n/tr.json +6 -1
  74. package/lib/commonjs/icons/index.js +12 -0
  75. package/lib/commonjs/icons/index.js.map +1 -1
  76. package/lib/commonjs/version.json +1 -1
  77. package/lib/module/components/Attachment/Attachment.js +10 -5
  78. package/lib/module/components/Attachment/Attachment.js.map +1 -1
  79. package/lib/module/components/Attachment/Audio/AudioAttachment.js +2 -4
  80. package/lib/module/components/Attachment/Audio/AudioAttachment.js.map +1 -1
  81. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsActionItems.js +2 -1
  82. package/lib/module/components/ChannelDetails/hooks/useChannelDetailsActionItems.js.map +1 -1
  83. package/lib/module/components/ChannelList/ChannelList.js +4 -1
  84. package/lib/module/components/ChannelList/ChannelList.js.map +1 -1
  85. package/lib/module/components/ChannelList/hooks/useCreateChannelsContext.js +5 -3
  86. package/lib/module/components/ChannelList/hooks/useCreateChannelsContext.js.map +1 -1
  87. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js +5 -3
  88. package/lib/module/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.js.map +1 -1
  89. package/lib/module/components/ChannelPreview/ChannelPreview.js +3 -0
  90. package/lib/module/components/ChannelPreview/ChannelPreview.js.map +1 -1
  91. package/lib/module/components/ChannelPreview/ChannelPreviewPinnedStatus.js +30 -0
  92. package/lib/module/components/ChannelPreview/ChannelPreviewPinnedStatus.js.map +1 -0
  93. package/lib/module/components/ChannelPreview/ChannelPreviewView.js +8 -3
  94. package/lib/module/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
  95. package/lib/module/components/ChannelPreview/ChannelSwipableWrapper.js +2 -1
  96. package/lib/module/components/ChannelPreview/ChannelSwipableWrapper.js.map +1 -1
  97. package/lib/module/components/ChannelPreview/hooks/index.js +11 -0
  98. package/lib/module/components/ChannelPreview/hooks/index.js.map +1 -1
  99. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js +3 -0
  100. package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -1
  101. package/lib/module/components/ChannelPreview/hooks/useIsChannelPinned.js +11 -0
  102. package/lib/module/components/ChannelPreview/hooks/useIsChannelPinned.js.map +1 -0
  103. package/lib/module/components/Message/Message.js +53 -16
  104. package/lib/module/components/Message/Message.js.map +1 -1
  105. package/lib/module/components/Message/MessageItemView/MessageItemView.js +6 -84
  106. package/lib/module/components/Message/MessageItemView/MessageItemView.js.map +1 -1
  107. package/lib/module/components/MessageInput/MessageComposer.js +8 -29
  108. package/lib/module/components/MessageInput/MessageComposer.js.map +1 -1
  109. package/lib/module/components/MessageMenu/MessageActionList.js +1 -1
  110. package/lib/module/components/Poll/components/CreatePollHeader.js +5 -5
  111. package/lib/module/components/Poll/components/CreatePollHeader.js.map +1 -1
  112. package/lib/module/components/Poll/components/PollButtons.js +25 -56
  113. package/lib/module/components/Poll/components/PollButtons.js.map +1 -1
  114. package/lib/module/components/Poll/components/PollInputDialog.js +9 -11
  115. package/lib/module/components/Poll/components/PollInputDialog.js.map +1 -1
  116. package/lib/module/components/Poll/components/PollModal.js +50 -0
  117. package/lib/module/components/Poll/components/PollModal.js.map +1 -0
  118. package/lib/module/components/Poll/components/PollModalHeader.js +4 -5
  119. package/lib/module/components/Poll/components/PollModalHeader.js.map +1 -1
  120. package/lib/module/components/Poll/components/PollResults/PollResultItem.js +10 -24
  121. package/lib/module/components/Poll/components/PollResults/PollResultItem.js.map +1 -1
  122. package/lib/module/components/Poll/components/index.js +11 -0
  123. package/lib/module/components/Poll/components/index.js.map +1 -1
  124. package/lib/module/components/index.js +11 -0
  125. package/lib/module/components/index.js.map +1 -1
  126. package/lib/module/contexts/channelsContext/ChannelsContext.js.map +1 -1
  127. package/lib/module/contexts/componentsContext/defaultComponents.js +2 -0
  128. package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
  129. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageComposer.js +2 -2
  130. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageComposer.js.map +1 -1
  131. package/lib/module/contexts/themeContext/utils/theme.js +3 -1
  132. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  133. package/lib/module/hooks/actions/useChannelActionItems.js +20 -1
  134. package/lib/module/hooks/actions/useChannelActionItems.js.map +1 -1
  135. package/lib/module/hooks/actions/useChannelActionItemsById.js +3 -1
  136. package/lib/module/hooks/actions/useChannelActionItemsById.js.map +1 -1
  137. package/lib/module/i18n/ar.json +6 -1
  138. package/lib/module/i18n/en.json +5 -0
  139. package/lib/module/i18n/es.json +6 -1
  140. package/lib/module/i18n/fr.json +6 -1
  141. package/lib/module/i18n/he.json +6 -1
  142. package/lib/module/i18n/hi.json +6 -1
  143. package/lib/module/i18n/it.json +6 -1
  144. package/lib/module/i18n/ja.json +6 -1
  145. package/lib/module/i18n/ko.json +6 -1
  146. package/lib/module/i18n/nl.json +6 -1
  147. package/lib/module/i18n/pt-br.json +6 -1
  148. package/lib/module/i18n/ru.json +6 -1
  149. package/lib/module/i18n/tr.json +6 -1
  150. package/lib/module/icons/index.js +12 -0
  151. package/lib/module/icons/index.js.map +1 -1
  152. package/lib/module/version.json +1 -1
  153. package/lib/typescript/components/Attachment/Audio/AudioAttachment.d.ts +1 -0
  154. package/lib/typescript/components/Attachment/Audio/AudioAttachment.d.ts.map +1 -1
  155. package/lib/typescript/components/ChannelList/ChannelList.d.ts +1 -1
  156. package/lib/typescript/components/ChannelList/ChannelList.d.ts.map +1 -1
  157. package/lib/typescript/components/ChannelList/hooks/useCreateChannelsContext.d.ts +1 -1
  158. package/lib/typescript/components/ChannelList/hooks/useCreateChannelsContext.d.ts.map +1 -1
  159. package/lib/typescript/components/ChannelPreview/ChannelPreview.d.ts.map +1 -1
  160. package/lib/typescript/components/ChannelPreview/ChannelPreviewPinnedStatus.d.ts +6 -0
  161. package/lib/typescript/components/ChannelPreview/ChannelPreviewPinnedStatus.d.ts.map +1 -0
  162. package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts +3 -1
  163. package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts.map +1 -1
  164. package/lib/typescript/components/ChannelPreview/ChannelSwipableWrapper.d.ts.map +1 -1
  165. package/lib/typescript/components/ChannelPreview/hooks/index.d.ts +1 -0
  166. package/lib/typescript/components/ChannelPreview/hooks/index.d.ts.map +1 -1
  167. package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts +1 -0
  168. package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts.map +1 -1
  169. package/lib/typescript/components/ChannelPreview/hooks/useIsChannelPinned.d.ts +3 -0
  170. package/lib/typescript/components/ChannelPreview/hooks/useIsChannelPinned.d.ts.map +1 -0
  171. package/lib/typescript/components/Message/Message.d.ts.map +1 -1
  172. package/lib/typescript/components/Message/MessageItemView/MessageItemView.d.ts.map +1 -1
  173. package/lib/typescript/components/MessageInput/MessageComposer.d.ts.map +1 -1
  174. package/lib/typescript/components/Poll/components/CreatePollHeader.d.ts.map +1 -1
  175. package/lib/typescript/components/Poll/components/PollButtons.d.ts.map +1 -1
  176. package/lib/typescript/components/Poll/components/PollModal.d.ts +9 -0
  177. package/lib/typescript/components/Poll/components/PollModal.d.ts.map +1 -0
  178. package/lib/typescript/components/Poll/components/PollResults/PollResultItem.d.ts.map +1 -1
  179. package/lib/typescript/components/Poll/components/index.d.ts +1 -0
  180. package/lib/typescript/components/Poll/components/index.d.ts.map +1 -1
  181. package/lib/typescript/components/index.d.ts +1 -0
  182. package/lib/typescript/components/index.d.ts.map +1 -1
  183. package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts +1 -0
  184. package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts.map +1 -1
  185. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +1 -0
  186. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
  187. package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageComposer.d.ts.map +1 -1
  188. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts +2 -0
  189. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts.map +1 -1
  190. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +2 -0
  191. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  192. package/lib/typescript/hooks/actions/useChannelActionItems.d.ts +35 -2
  193. package/lib/typescript/hooks/actions/useChannelActionItems.d.ts.map +1 -1
  194. package/lib/typescript/hooks/actions/useChannelActionItemsById.d.ts +3 -2
  195. package/lib/typescript/hooks/actions/useChannelActionItemsById.d.ts.map +1 -1
  196. package/lib/typescript/i18n/ar.json +6 -1
  197. package/lib/typescript/i18n/en.json +5 -0
  198. package/lib/typescript/i18n/es.json +6 -1
  199. package/lib/typescript/i18n/fr.json +6 -1
  200. package/lib/typescript/i18n/he.json +6 -1
  201. package/lib/typescript/i18n/hi.json +6 -1
  202. package/lib/typescript/i18n/it.json +6 -1
  203. package/lib/typescript/i18n/ja.json +6 -1
  204. package/lib/typescript/i18n/ko.json +6 -1
  205. package/lib/typescript/i18n/nl.json +6 -1
  206. package/lib/typescript/i18n/pt-br.json +6 -1
  207. package/lib/typescript/i18n/ru.json +6 -1
  208. package/lib/typescript/i18n/tr.json +6 -1
  209. package/lib/typescript/icons/index.d.ts +1 -0
  210. package/lib/typescript/icons/index.d.ts.map +1 -1
  211. package/lib/typescript/utils/i18n/Streami18n.d.ts +5 -0
  212. package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
  213. package/package.json +2 -2
  214. package/src/components/Attachment/Attachment.tsx +15 -6
  215. package/src/components/Attachment/Audio/AudioAttachment.tsx +3 -4
  216. package/src/components/ChannelDetails/__tests__/useChannelDetailsActionItems.test.tsx +6 -2
  217. package/src/components/ChannelDetails/hooks/useChannelDetailsActionItems.ts +1 -1
  218. package/src/components/ChannelList/ChannelList.tsx +3 -0
  219. package/src/components/ChannelList/hooks/useCreateChannelsContext.ts +3 -0
  220. package/src/components/ChannelPreview/ChannelMessagePreviewDeliveryStatus.tsx +3 -2
  221. package/src/components/ChannelPreview/ChannelPreview.tsx +21 -3
  222. package/src/components/ChannelPreview/ChannelPreviewPinnedStatus.tsx +25 -0
  223. package/src/components/ChannelPreview/ChannelPreviewView.tsx +18 -2
  224. package/src/components/ChannelPreview/ChannelSwipableWrapper.tsx +5 -1
  225. package/src/components/ChannelPreview/hooks/__tests__/useIsChannelPinned.test.tsx +35 -0
  226. package/src/components/ChannelPreview/hooks/index.ts +1 -0
  227. package/src/components/ChannelPreview/hooks/useChannelPreviewData.ts +3 -1
  228. package/src/components/ChannelPreview/hooks/useIsChannelPinned.ts +8 -0
  229. package/src/components/Message/Message.tsx +68 -22
  230. package/src/components/Message/MessageItemView/MessageItemView.tsx +5 -116
  231. package/src/components/Message/MessageItemView/__tests__/MessageItemView.test.tsx +22 -13
  232. package/src/components/MessageInput/MessageComposer.tsx +9 -30
  233. package/src/components/MessageMenu/MessageActionList.tsx +1 -1
  234. package/src/components/Poll/components/CreatePollHeader.tsx +12 -5
  235. package/src/components/Poll/components/PollButtons.tsx +14 -38
  236. package/src/components/Poll/components/PollInputDialog.tsx +12 -12
  237. package/src/components/Poll/components/PollModal.tsx +55 -0
  238. package/src/components/Poll/components/PollModalHeader.tsx +4 -5
  239. package/src/components/Poll/components/PollResults/PollResultItem.tsx +6 -18
  240. package/src/components/Poll/components/__tests__/CreatePollHeader.test.tsx +4 -36
  241. package/src/components/Poll/components/__tests__/PollModalHeader.test.tsx +8 -45
  242. package/src/components/Poll/components/index.ts +1 -0
  243. package/src/components/Thread/__tests__/__snapshots__/Thread.test.tsx.snap +5 -5
  244. package/src/components/index.ts +1 -0
  245. package/src/contexts/channelsContext/ChannelsContext.tsx +1 -0
  246. package/src/contexts/componentsContext/defaultComponents.ts +2 -0
  247. package/src/contexts/messageInputContext/hooks/useCreateMessageComposer.ts +10 -4
  248. package/src/contexts/themeContext/utils/theme.ts +4 -0
  249. package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx +137 -14
  250. package/src/hooks/actions/__tests__/useChannelActionItemsById.test.tsx +3 -1
  251. package/src/hooks/actions/useChannelActionItems.tsx +60 -2
  252. package/src/hooks/actions/useChannelActionItemsById.ts +8 -1
  253. package/src/i18n/ar.json +6 -1
  254. package/src/i18n/en.json +5 -0
  255. package/src/i18n/es.json +6 -1
  256. package/src/i18n/fr.json +6 -1
  257. package/src/i18n/he.json +6 -1
  258. package/src/i18n/hi.json +6 -1
  259. package/src/i18n/it.json +6 -1
  260. package/src/i18n/ja.json +6 -1
  261. package/src/i18n/ko.json +6 -1
  262. package/src/i18n/nl.json +6 -1
  263. package/src/i18n/pt-br.json +6 -1
  264. package/src/i18n/ru.json +6 -1
  265. package/src/i18n/tr.json +6 -1
  266. package/src/icons/index.ts +1 -0
  267. package/src/version.json +1 -1
@@ -337,6 +337,7 @@ exports[`Thread should match thread snapshot 1`] = `
337
337
  ],
338
338
  {
339
339
  "paddingHorizontal": 16,
340
+ "paddingVertical": 8,
340
341
  },
341
342
  ]
342
343
  }
@@ -370,7 +371,6 @@ exports[`Thread should match thread snapshot 1`] = `
370
371
  "alignItems": "flex-end",
371
372
  "flexDirection": "row",
372
373
  "gap": 8,
373
- "paddingVertical": 8,
374
374
  "width": "100%",
375
375
  }
376
376
  }
@@ -671,6 +671,7 @@ exports[`Thread should match thread snapshot 1`] = `
671
671
  ],
672
672
  {
673
673
  "paddingHorizontal": 16,
674
+ "paddingVertical": 8,
674
675
  },
675
676
  ]
676
677
  }
@@ -704,7 +705,6 @@ exports[`Thread should match thread snapshot 1`] = `
704
705
  "alignItems": "flex-end",
705
706
  "flexDirection": "row",
706
707
  "gap": 8,
707
- "paddingVertical": 8,
708
708
  "width": "100%",
709
709
  }
710
710
  }
@@ -1039,6 +1039,7 @@ exports[`Thread should match thread snapshot 1`] = `
1039
1039
  ],
1040
1040
  {
1041
1041
  "paddingHorizontal": 16,
1042
+ "paddingVertical": 8,
1042
1043
  },
1043
1044
  ]
1044
1045
  }
@@ -1072,7 +1073,6 @@ exports[`Thread should match thread snapshot 1`] = `
1072
1073
  "alignItems": "flex-end",
1073
1074
  "flexDirection": "row",
1074
1075
  "gap": 8,
1075
- "paddingVertical": 8,
1076
1076
  "width": "100%",
1077
1077
  }
1078
1078
  }
@@ -1365,7 +1365,9 @@ exports[`Thread should match thread snapshot 1`] = `
1365
1365
  [
1366
1366
  undefined,
1367
1367
  {
1368
+ "marginBottom": 12,
1368
1369
  "paddingHorizontal": 16,
1370
+ "paddingVertical": 8,
1369
1371
  },
1370
1372
  ]
1371
1373
  }
@@ -1399,8 +1401,6 @@ exports[`Thread should match thread snapshot 1`] = `
1399
1401
  "alignItems": "flex-end",
1400
1402
  "flexDirection": "row",
1401
1403
  "gap": 8,
1402
- "marginBottom": 12,
1403
- "paddingVertical": 8,
1404
1404
  "width": "100%",
1405
1405
  }
1406
1406
  }
@@ -56,6 +56,7 @@ export * from './ChannelPreview/ChannelPreview';
56
56
  export * from './ChannelPreview/ChannelPreviewMessage';
57
57
  export * from './ChannelPreview/ChannelPreviewView';
58
58
  export * from './ChannelPreview/ChannelPreviewMutedStatus';
59
+ export * from './ChannelPreview/ChannelPreviewPinnedStatus';
59
60
  export * from './ChannelPreview/ChannelLastMessagePreview';
60
61
  export * from './ChannelPreview/ChannelPreviewStatus';
61
62
  export * from './ChannelPreview/ChannelPreviewTitle';
@@ -118,6 +118,7 @@ export type ChannelsContextValue = {
118
118
  swipeActionsEnabled?: boolean;
119
119
 
120
120
  mutedStatusPosition?: 'trailingBottom' | 'inlineTitle';
121
+ pinnedStatusPosition?: 'trailingBottom' | 'inlineTitle';
121
122
  };
122
123
 
123
124
  export const ChannelsContext = React.createContext(
@@ -53,6 +53,7 @@ import { ChannelLastMessagePreview } from '../../components/ChannelPreview/Chann
53
53
  import { ChannelMessagePreviewDeliveryStatus } from '../../components/ChannelPreview/ChannelMessagePreviewDeliveryStatus';
54
54
  import { ChannelPreviewMessage } from '../../components/ChannelPreview/ChannelPreviewMessage';
55
55
  import { ChannelPreviewMutedStatus } from '../../components/ChannelPreview/ChannelPreviewMutedStatus';
56
+ import { ChannelPreviewPinnedStatus } from '../../components/ChannelPreview/ChannelPreviewPinnedStatus';
56
57
  import { ChannelPreviewStatus } from '../../components/ChannelPreview/ChannelPreviewStatus';
57
58
  import { ChannelPreviewTitle } from '../../components/ChannelPreview/ChannelPreviewTitle';
58
59
  import { ChannelPreviewTypingIndicator } from '../../components/ChannelPreview/ChannelPreviewTypingIndicator';
@@ -271,6 +272,7 @@ const components = {
271
272
  ChannelPreviewMessage,
272
273
  ChannelPreviewMessageDeliveryStatus: ChannelMessagePreviewDeliveryStatus,
273
274
  ChannelPreviewMutedStatus,
275
+ ChannelPreviewPinnedStatus,
274
276
  ChannelPreviewStatus,
275
277
  ChannelPreviewTitle,
276
278
  ChannelPreviewTypingIndicator,
@@ -1,12 +1,10 @@
1
1
  import { useEffect, useMemo } from 'react';
2
2
 
3
- import { FixedSizeQueueCache, MessageComposer } from 'stream-chat';
3
+ import { MessageComposer } from 'stream-chat';
4
4
 
5
5
  import { useChatContext } from '../../chatContext/ChatContext';
6
6
  import { MessageComposerContextValue } from '../../messageComposerContext/MessageComposerContext';
7
7
 
8
- const queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);
9
-
10
8
  export const useCreateMessageComposer = ({
11
9
  editing: editedMessage,
12
10
  thread: parentMessage,
@@ -14,6 +12,7 @@ export const useCreateMessageComposer = ({
14
12
  channel,
15
13
  }: Pick<MessageComposerContextValue, 'channel' | 'threadInstance' | 'thread' | 'editing'>) => {
16
14
  const { client } = useChatContext();
15
+ const { messageComposerCache: queueCache } = client;
17
16
 
18
17
  const cachedEditedMessage = useMemo(() => {
19
18
  if (!editedMessage) return undefined;
@@ -69,7 +68,14 @@ export const useCreateMessageComposer = ({
69
68
  } else {
70
69
  return channel.messageComposer;
71
70
  }
72
- }, [cachedEditedMessage, cachedParentMessage, channel, client, threadInstance]);
71
+ }, [
72
+ cachedEditedMessage,
73
+ cachedParentMessage,
74
+ channel.messageComposer,
75
+ client,
76
+ queueCache,
77
+ threadInstance,
78
+ ]);
73
79
 
74
80
  if (
75
81
  (['legacy_thread', 'message'] as MessageComposer['contextType'][]).includes(
@@ -299,12 +299,14 @@ export type Theme = {
299
299
  contentContainer: ViewStyle;
300
300
  date: TextStyle;
301
301
  mutedStatus: IconProps;
302
+ pinnedStatus: IconProps;
302
303
  messageDeliveryStatus: {
303
304
  container: ViewStyle;
304
305
  text: TextStyle;
305
306
  checkAllIcon: IconProps;
306
307
  checkIcon: IconProps;
307
308
  timeIcon: IconProps;
309
+ username: TextStyle;
308
310
  };
309
311
  lowerRow: ViewStyle;
310
312
  title: TextStyle;
@@ -1355,8 +1357,10 @@ export const defaultTheme: Theme = {
1355
1357
  checkAllIcon: {},
1356
1358
  checkIcon: {},
1357
1359
  timeIcon: {},
1360
+ username: {},
1358
1361
  },
1359
1362
  mutedStatus: {},
1363
+ pinnedStatus: {},
1360
1364
  lowerRow: {},
1361
1365
  title: {},
1362
1366
  unreadContainer: {},
@@ -99,30 +99,43 @@ describe('useChannelActionItems', () => {
99
99
  });
100
100
 
101
101
  it('returns default channel action items', () => {
102
- const { result } = renderHook(() => useChannelActionItems({ channel }));
102
+ const { result } = renderHook(() => useChannelActionItems({ channel, surface: 'list' }));
103
103
 
104
- expect(result.current).toHaveLength(3);
104
+ expect(result.current).toHaveLength(4);
105
105
  expect(result.current.map((item) => item.action)).toEqual([
106
106
  channelActions.muteChannel,
107
+ channelActions.pin,
107
108
  channelActions.leave,
108
109
  expect.any(Function),
109
110
  ]);
110
- expect(result.current.map((item) => item.id)).toEqual(['mute', 'leave', 'deleteChannel']);
111
+ expect(result.current.map((item) => item.id)).toEqual([
112
+ 'mute',
113
+ 'pin',
114
+ 'leave',
115
+ 'deleteChannel',
116
+ ]);
111
117
  expect(result.current.map((item) => item.type)).toEqual([
118
+ 'standard',
112
119
  'standard',
113
120
  'destructive',
114
121
  'destructive',
115
122
  ]);
116
- expect(result.current.map((item) => item.placement)).toEqual(['swipe', 'sheet', 'sheet']);
123
+ expect(result.current.map((item) => item.placement)).toEqual([
124
+ 'swipe',
125
+ 'sheet',
126
+ 'sheet',
127
+ 'sheet',
128
+ ]);
117
129
  });
118
130
 
119
131
  it('returns muteUser only in direct chats', () => {
120
132
  jest.spyOn(useIsDirectChatModule, 'useIsDirectChat').mockReturnValue(true);
121
133
 
122
- const { result } = renderHook(() => useChannelActionItems({ channel }));
134
+ const { result } = renderHook(() => useChannelActionItems({ channel, surface: 'list' }));
123
135
 
124
136
  expect(result.current.map((item) => item.id)).toEqual([
125
137
  'mute',
138
+ 'pin',
126
139
  'muteUser',
127
140
  'block',
128
141
  'leave',
@@ -143,7 +156,7 @@ describe('useChannelActionItems', () => {
143
156
  });
144
157
  jest.spyOn(useMutedUsersModule, 'useMutedUsers').mockReturnValue([] as Mute[]);
145
158
 
146
- const { result } = renderHook(() => useChannelActionItems({ channel }));
159
+ const { result } = renderHook(() => useChannelActionItems({ channel, surface: 'list' }));
147
160
 
148
161
  const muteItem = result.current.find((item) => item.id === 'mute');
149
162
  const muteUserItem = result.current.find((item) => item.id === 'muteUser');
@@ -152,7 +165,7 @@ describe('useChannelActionItems', () => {
152
165
  });
153
166
 
154
167
  it('forwards options from item.action to the underlying channel action', async () => {
155
- const { result } = renderHook(() => useChannelActionItems({ channel }));
168
+ const { result } = renderHook(() => useChannelActionItems({ channel, surface: 'list' }));
156
169
 
157
170
  const muteItem = result.current.find((item) => item.id === 'mute');
158
171
  expect(muteItem).toBeDefined();
@@ -165,7 +178,7 @@ describe('useChannelActionItems', () => {
165
178
  it('marks block as destructive when user is not blocked', () => {
166
179
  jest.spyOn(useIsDirectChatModule, 'useIsDirectChat').mockReturnValue(true);
167
180
 
168
- const { result } = renderHook(() => useChannelActionItems({ channel }));
181
+ const { result } = renderHook(() => useChannelActionItems({ channel, surface: 'list' }));
169
182
 
170
183
  const blockItem = result.current.find((item) => item.id === 'block');
171
184
  expect(blockItem?.type).toBe('destructive');
@@ -175,7 +188,9 @@ describe('useChannelActionItems', () => {
175
188
  jest.spyOn(useIsDirectChatModule, 'useIsDirectChat').mockReturnValue(true);
176
189
  const blockedChannel = createChannelMock({ blockedUserIds: ['other-user-id'] });
177
190
 
178
- const { result } = renderHook(() => useChannelActionItems({ channel: blockedChannel }));
191
+ const { result } = renderHook(() =>
192
+ useChannelActionItems({ channel: blockedChannel, surface: 'list' }),
193
+ );
179
194
 
180
195
  const blockItem = result.current.find((item) => item.id === 'block');
181
196
  expect(blockItem?.type).toBe('standard');
@@ -190,6 +205,7 @@ describe('useChannelActionItems', () => {
190
205
  useChannelActionItems({
191
206
  channel,
192
207
  getChannelActionItems: customGetChannelActionItems,
208
+ surface: 'list',
193
209
  }),
194
210
  );
195
211
 
@@ -202,6 +218,7 @@ describe('useChannelActionItems', () => {
202
218
  isBlocked: undefined,
203
219
  isDirectChat: false,
204
220
  isPinned: false,
221
+ surface: 'list',
205
222
  t: expect.any(Function),
206
223
  userMuteActive: false,
207
224
  },
@@ -228,6 +245,7 @@ describe('getChannelActionItems', () => {
228
245
  isBlocked: undefined,
229
246
  isDirectChat: false,
230
247
  isPinned: false,
248
+ surface: 'list',
231
249
  t: ((value: string) => value) as TranslationContextValue['t'],
232
250
  userMuteActive: false,
233
251
  });
@@ -240,6 +258,7 @@ describe('getChannelActionItems', () => {
240
258
  isBlocked: undefined,
241
259
  isDirectChat: false,
242
260
  isPinned: false,
261
+ surface: 'list',
243
262
  t: ((value: string) => value) as TranslationContextValue['t'],
244
263
  userMuteActive: false,
245
264
  },
@@ -248,11 +267,13 @@ describe('getChannelActionItems', () => {
248
267
 
249
268
  expect(actionItems.map((item) => item.action)).toEqual([
250
269
  channelActions.muteChannel,
270
+ channelActions.pin,
251
271
  channelActions.leave,
252
272
  expect.any(Function),
253
273
  ]);
254
- expect(actionItems.map((item) => item.id)).toEqual(['mute', 'leave', 'deleteChannel']);
274
+ expect(actionItems.map((item) => item.id)).toEqual(['mute', 'pin', 'leave', 'deleteChannel']);
255
275
  expect(actionItems.map((item) => item.type)).toEqual([
276
+ 'standard',
256
277
  'standard',
257
278
  'destructive',
258
279
  'destructive',
@@ -269,12 +290,14 @@ describe('getChannelActionItems', () => {
269
290
  isBlocked: true,
270
291
  isDirectChat: true,
271
292
  isPinned: false,
293
+ surface: 'list',
272
294
  t: ((value: string) => value) as TranslationContextValue['t'],
273
295
  userMuteActive: true,
274
296
  });
275
297
 
276
298
  expect(actionItems.map((item) => item.id)).toEqual([
277
299
  'mute',
300
+ 'pin',
278
301
  'muteUser',
279
302
  'block',
280
303
  'leave',
@@ -282,6 +305,7 @@ describe('getChannelActionItems', () => {
282
305
  ]);
283
306
  expect(actionItems.map((item) => item.action)).toEqual([
284
307
  channelActions.unmuteChannel,
308
+ channelActions.pin,
285
309
  channelActions.unmuteUser,
286
310
  channelActions.unblockUser,
287
311
  channelActions.leave,
@@ -289,6 +313,7 @@ describe('getChannelActionItems', () => {
289
313
  ]);
290
314
  expect(actionItems.map((item) => item.label)).toEqual([
291
315
  'Unmute Chat',
316
+ 'Pin Chat',
292
317
  'Unmute User',
293
318
  'Unblock User',
294
319
  'Leave Chat',
@@ -300,6 +325,7 @@ describe('getChannelActionItems', () => {
300
325
  'sheet',
301
326
  'sheet',
302
327
  'sheet',
328
+ 'sheet',
303
329
  ]);
304
330
  });
305
331
 
@@ -312,6 +338,7 @@ describe('getChannelActionItems', () => {
312
338
  isBlocked: undefined,
313
339
  isDirectChat: false,
314
340
  isPinned: false,
341
+ surface: 'list',
315
342
  t: ((value: string) => value) as TranslationContextValue['t'],
316
343
  userMuteActive: false,
317
344
  });
@@ -328,11 +355,12 @@ describe('getChannelActionItems', () => {
328
355
  isBlocked: undefined,
329
356
  isDirectChat: false,
330
357
  isPinned: false,
358
+ surface: 'list',
331
359
  t: ((value: string) => value) as TranslationContextValue['t'],
332
360
  userMuteActive: false,
333
361
  });
334
362
 
335
- expect(actionItems.map((item) => item.id)).toEqual(['mute', 'leave']);
363
+ expect(actionItems.map((item) => item.id)).toEqual(['mute', 'pin', 'leave']);
336
364
  });
337
365
 
338
366
  it('uses group mute variants for labels and placements', () => {
@@ -345,6 +373,7 @@ describe('getChannelActionItems', () => {
345
373
  isBlocked: undefined,
346
374
  isDirectChat: false,
347
375
  isPinned: false,
376
+ surface: 'list',
348
377
  t: ((value: string) => value) as TranslationContextValue['t'],
349
378
  userMuteActive: false,
350
379
  });
@@ -353,9 +382,101 @@ describe('getChannelActionItems', () => {
353
382
  expect(actionItems[0].label).toBe('Unmute Group');
354
383
  expect(actionItems[0].placement).toBe('swipe');
355
384
 
356
- expect(actionItems[1].action).toBe(channelActions.leave);
357
- expect(actionItems[1].label).toBe('Leave Group');
358
- expect(actionItems[1].placement).toBe('sheet');
385
+ const leaveItem = actionItems.find((item) => item.id === 'leave');
386
+ expect(leaveItem?.action).toBe(channelActions.leave);
387
+ expect(leaveItem?.label).toBe('Leave Group');
388
+ expect(leaveItem?.placement).toBe('sheet');
389
+ });
390
+
391
+ it('pin item toggles to unpin when channel is pinned', () => {
392
+ const channelActions = createChannelActions();
393
+ const actionItems = buildDefaultChannelActionItems({
394
+ actions: channelActions,
395
+ channel,
396
+ channelMuteActive: false,
397
+ isArchived: false,
398
+ isBlocked: undefined,
399
+ isDirectChat: false,
400
+ isPinned: true,
401
+ surface: 'list',
402
+ t: ((value: string) => value) as TranslationContextValue['t'],
403
+ userMuteActive: false,
404
+ });
405
+
406
+ const pinItem = actionItems.find((item) => item.id === 'pin');
407
+ expect(pinItem?.action).toBe(channelActions.unpin);
408
+ expect(pinItem?.label).toBe('Unpin Group');
409
+ expect(pinItem?.placement).toBe('sheet');
410
+ });
411
+
412
+ it('pin item uses direct-chat label variant', () => {
413
+ const channelActions = createChannelActions();
414
+ const actionItems = buildDefaultChannelActionItems({
415
+ actions: channelActions,
416
+ channel,
417
+ channelMuteActive: false,
418
+ isArchived: false,
419
+ isBlocked: undefined,
420
+ isDirectChat: true,
421
+ isPinned: false,
422
+ surface: 'list',
423
+ t: ((value: string) => value) as TranslationContextValue['t'],
424
+ userMuteActive: false,
425
+ });
426
+
427
+ const pinItem = actionItems.find((item) => item.id === 'pin');
428
+ expect(pinItem?.action).toBe(channelActions.pin);
429
+ expect(pinItem?.label).toBe('Pin Chat');
430
+ });
431
+
432
+ it('omits the pin item when building for the details surface', () => {
433
+ const actionItems = buildDefaultChannelActionItems({
434
+ actions: createChannelActions(),
435
+ channel,
436
+ channelMuteActive: false,
437
+ isArchived: false,
438
+ isBlocked: undefined,
439
+ isDirectChat: false,
440
+ isPinned: false,
441
+ surface: 'details',
442
+ t: ((value: string) => value) as TranslationContextValue['t'],
443
+ userMuteActive: false,
444
+ });
445
+
446
+ expect(actionItems.map((item) => item.id)).not.toContain('pin');
447
+ });
448
+
449
+ it('includes the pin item when building for the list surface', () => {
450
+ const actionItems = buildDefaultChannelActionItems({
451
+ actions: createChannelActions(),
452
+ channel,
453
+ channelMuteActive: false,
454
+ isArchived: false,
455
+ isBlocked: undefined,
456
+ isDirectChat: false,
457
+ isPinned: false,
458
+ surface: 'list',
459
+ t: ((value: string) => value) as TranslationContextValue['t'],
460
+ userMuteActive: false,
461
+ });
462
+
463
+ expect(actionItems.map((item) => item.id)).toContain('pin');
464
+ });
465
+
466
+ it('applies no surface-specific filtering when surface is omitted', () => {
467
+ const actionItems = buildDefaultChannelActionItems({
468
+ actions: createChannelActions(),
469
+ channel,
470
+ channelMuteActive: false,
471
+ isArchived: false,
472
+ isBlocked: undefined,
473
+ isDirectChat: false,
474
+ isPinned: false,
475
+ t: ((value: string) => value) as TranslationContextValue['t'],
476
+ userMuteActive: false,
477
+ });
478
+
479
+ expect(actionItems.map((item) => item.id)).toEqual(['mute', 'pin', 'leave', 'deleteChannel']);
359
480
  });
360
481
 
361
482
  it('mute and muteUser reflect their respective active states independently', () => {
@@ -368,6 +489,7 @@ describe('getChannelActionItems', () => {
368
489
  isBlocked: undefined,
369
490
  isDirectChat: true,
370
491
  isPinned: false,
492
+ surface: 'list',
371
493
  t: ((value: string) => value) as TranslationContextValue['t'],
372
494
  userMuteActive: true,
373
495
  });
@@ -393,6 +515,7 @@ describe('getChannelActionItems', () => {
393
515
  isBlocked: undefined,
394
516
  isDirectChat: false,
395
517
  isPinned: false,
518
+ surface: 'list',
396
519
  t: ((value: string) => value) as TranslationContextValue['t'],
397
520
  userMuteActive: false,
398
521
  });
@@ -41,7 +41,7 @@ describe('useChannelActionItemsById', () => {
41
41
  .spyOn(useChannelActionItemsModule, 'useChannelActionItems')
42
42
  .mockReturnValue(channelActionItems);
43
43
 
44
- const { result } = renderHook(() => useChannelActionItemsById({ channel }));
44
+ const { result } = renderHook(() => useChannelActionItemsById({ channel, surface: 'list' }));
45
45
 
46
46
  expect(result.current.pin).toBe(channelActionItems[0]);
47
47
  expect(result.current.deleteChannel).toBe(channelActionItems[1]);
@@ -59,12 +59,14 @@ describe('useChannelActionItemsById', () => {
59
59
  useChannelActionItemsById({
60
60
  channel,
61
61
  getChannelActionItems,
62
+ surface: 'list',
62
63
  }),
63
64
  );
64
65
 
65
66
  expect(useChannelActionItemsSpy).toHaveBeenCalledWith({
66
67
  channel,
67
68
  getChannelActionItems,
69
+ surface: 'list',
68
70
  });
69
71
  });
70
72
  });
@@ -15,18 +15,50 @@ import { useIsChannelMuted } from '../../components/ChannelPreview/hooks/useIsCh
15
15
  import { useUserMuteActive } from '../../components/Message/hooks/useUserMuteActive';
16
16
  import { useTheme, useTranslationContext } from '../../contexts';
17
17
  import type { TranslationContextValue } from '../../contexts/translationContext/TranslationContext';
18
- import { IconProps, Mute, BlockUser, Delete, Sound } from '../../icons';
18
+ import { IconProps, Mute, BlockUser, Delete, Pin, Sound, Unpin } from '../../icons';
19
19
  import { ArrowBoxLeft } from '../../icons/leave';
20
20
  import { useChannelMembershipState } from '../useChannelMembershipState';
21
21
  import { useIsDirectChat } from '../useIsDirectChat';
22
22
  import { useStateStore } from '../useStateStore';
23
23
 
24
24
  export type ChannelActionItem = ActionItem<
25
- 'mute' | 'muteUser' | 'block' | 'leave' | 'deleteChannel' | string
25
+ 'mute' | 'muteUser' | 'block' | 'leave' | 'deleteChannel' | 'pin' | string
26
26
  > & {
27
+ /**
28
+ * Per item routing **within a channel preview interaction** (swipe row vs
29
+ * the sheet that opens from it). Only meaningful when the items are consumed
30
+ * from `<ChannelSwipableWrapper>`:
31
+ *
32
+ * - `'swipe'`: shown only in the swipe-row chips.
33
+ * - `'sheet'`: shown only in the swipe-triggered options sheet.
34
+ * - `'both'`: shown in both swipe row and sheet.
35
+ *
36
+ * The standalone Channel Details screen does **not** filter by `placement` -
37
+ * use {@link ChannelActionSurface} (`surface`) instead to vary items between
38
+ * the channel list and the Channel Details screen.
39
+ */
27
40
  placement: 'both' | 'sheet' | 'swipe';
28
41
  };
29
42
 
43
+ /**
44
+ * Identifies which top level UI surface is requesting channel action items.
45
+ * Passed verbatim into {@link ChannelActionItemsParams} so the default builder
46
+ * and any integrator supplied `getChannelActionItems` can branch on it - i.e.
47
+ * to drop or relabel an item on a specific surface or to provide an entirely
48
+ * different builder per surface.
49
+ *
50
+ * - `'list'`: anything driven by a ChannelList interaction, the swipe row
51
+ * chips on a channel preview and the bottom sheet that opens from them.
52
+ * Subrouting between the swipe row and the sheet is handled by the per item
53
+ * {@link ChannelActionItem.placement} field.
54
+ * - `'details'`: items for the standalone Channel Details screen.
55
+ *
56
+ * `surface` operates at the call site level (which UI is asking). It is
57
+ * optional and when omitted, the default builder applies no surface specific
58
+ * filtering and returns every item it would otherwise produce.
59
+ */
60
+ export type ChannelActionSurface = 'list' | 'details';
61
+
30
62
  export type ChannelActionItemsParams = {
31
63
  actions: ChannelActions;
32
64
  channel: Channel;
@@ -35,6 +67,7 @@ export type ChannelActionItemsParams = {
35
67
  isBlocked: boolean | undefined;
36
68
  isDirectChat: boolean;
37
69
  isPinned: boolean;
70
+ surface?: ChannelActionSurface;
38
71
  t: TranslationContextValue['t'];
39
72
  userMuteActive: boolean;
40
73
  };
@@ -67,10 +100,14 @@ export const buildDefaultChannelActionItems: BuildDefaultChannelActionItems = (
67
100
  unmuteUser,
68
101
  blockUser,
69
102
  unblockUser,
103
+ pin,
104
+ unpin,
70
105
  },
71
106
  channelMuteActive,
72
107
  isBlocked,
73
108
  isDirectChat,
109
+ isPinned,
110
+ surface,
74
111
  userMuteActive,
75
112
  t,
76
113
  channel,
@@ -105,6 +142,23 @@ export const buildDefaultChannelActionItems: BuildDefaultChannelActionItems = (
105
142
  },
106
143
  ];
107
144
 
145
+ if (surface !== 'details') {
146
+ actionItems.push({
147
+ action: isPinned ? unpin : pin,
148
+ Icon: (props) => <ChannelActionsIcon Icon={isPinned ? Unpin : Pin} {...props} />,
149
+ id: 'pin',
150
+ label: isDirectChat
151
+ ? isPinned
152
+ ? t('Unpin Chat')
153
+ : t('Pin Chat')
154
+ : isPinned
155
+ ? t('Unpin Group')
156
+ : t('Pin Group'),
157
+ placement: 'sheet',
158
+ type: 'standard',
159
+ });
160
+ }
161
+
108
162
  if (isDirectChat) {
109
163
  actionItems.push({
110
164
  action: userMuteActive ? unmuteUser : muteUser,
@@ -186,6 +240,7 @@ export const getChannelActionItems: GetChannelActionItems = ({ defaultItems }) =
186
240
 
187
241
  type UseChannelActionItemsParams = {
188
242
  channel: Channel;
243
+ surface?: ChannelActionSurface;
189
244
  getChannelActionItems?: GetChannelActionItems;
190
245
  };
191
246
 
@@ -194,6 +249,7 @@ const blockedUsersStateSelector = (state: BlockedUsersState) =>
194
249
 
195
250
  export const useChannelActionItems = ({
196
251
  channel,
252
+ surface,
197
253
  getChannelActionItems: getChannelActionItemsProp = getChannelActionItems,
198
254
  }: UseChannelActionItemsParams) => {
199
255
  const { t } = useTranslationContext();
@@ -225,6 +281,7 @@ export const useChannelActionItems = ({
225
281
  isBlocked,
226
282
  isDirectChat,
227
283
  isPinned,
284
+ surface,
228
285
  t,
229
286
  userMuteActive,
230
287
  }),
@@ -236,6 +293,7 @@ export const useChannelActionItems = ({
236
293
  isBlocked,
237
294
  isDirectChat,
238
295
  isPinned,
296
+ surface,
239
297
  t,
240
298
  userMuteActive,
241
299
  ],
@@ -2,23 +2,30 @@ import { useMemo } from 'react';
2
2
 
3
3
  import type { Channel } from 'stream-chat';
4
4
 
5
- import type { ChannelActionItem, GetChannelActionItems } from './useChannelActionItems';
5
+ import type {
6
+ ChannelActionItem,
7
+ ChannelActionSurface,
8
+ GetChannelActionItems,
9
+ } from './useChannelActionItems';
6
10
  import { useChannelActionItems } from './useChannelActionItems';
7
11
 
8
12
  export type ChannelActionItemsById = Partial<Record<ChannelActionItem['id'], ChannelActionItem>>;
9
13
 
10
14
  type UseChannelActionItemsByIdParams = {
11
15
  channel: Channel;
16
+ surface?: ChannelActionSurface;
12
17
  getChannelActionItems?: GetChannelActionItems;
13
18
  };
14
19
 
15
20
  export const useChannelActionItemsById = ({
16
21
  channel,
22
+ surface,
17
23
  getChannelActionItems,
18
24
  }: UseChannelActionItemsByIdParams) => {
19
25
  const channelActionItems = useChannelActionItems({
20
26
  channel,
21
27
  getChannelActionItems,
28
+ surface,
22
29
  });
23
30
 
24
31
  return useMemo(