stream-chat-react-native-core 9.4.0-beta.6 → 9.4.0-beta.7
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.
- package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsActionItems.js +2 -1
- package/lib/commonjs/components/ChannelDetails/hooks/useChannelDetailsActionItems.js.map +1 -1
- package/lib/commonjs/components/ChannelList/ChannelList.js +4 -1
- package/lib/commonjs/components/ChannelList/ChannelList.js.map +1 -1
- package/lib/commonjs/components/ChannelList/hooks/useCreateChannelsContext.js +5 -3
- package/lib/commonjs/components/ChannelList/hooks/useCreateChannelsContext.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreview.js +3 -0
- package/lib/commonjs/components/ChannelPreview/ChannelPreview.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewPinnedStatus.js +30 -0
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewPinnedStatus.js.map +1 -0
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js +8 -3
- package/lib/commonjs/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/ChannelSwipableWrapper.js +2 -1
- package/lib/commonjs/components/ChannelPreview/ChannelSwipableWrapper.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/hooks/index.js +11 -0
- package/lib/commonjs/components/ChannelPreview/hooks/index.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js +3 -0
- package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/hooks/useIsChannelPinned.js +11 -0
- package/lib/commonjs/components/ChannelPreview/hooks/useIsChannelPinned.js.map +1 -0
- package/lib/commonjs/components/index.js +11 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/channelsContext/ChannelsContext.js.map +1 -1
- package/lib/commonjs/contexts/componentsContext/defaultComponents.js +2 -0
- package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +1 -0
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/hooks/actions/useChannelActionItems.js +20 -1
- package/lib/commonjs/hooks/actions/useChannelActionItems.js.map +1 -1
- package/lib/commonjs/hooks/actions/useChannelActionItemsById.js +3 -1
- package/lib/commonjs/hooks/actions/useChannelActionItemsById.js.map +1 -1
- package/lib/commonjs/i18n/ar.json +6 -1
- package/lib/commonjs/i18n/en.json +5 -0
- package/lib/commonjs/i18n/es.json +6 -1
- package/lib/commonjs/i18n/fr.json +6 -1
- package/lib/commonjs/i18n/he.json +6 -1
- package/lib/commonjs/i18n/hi.json +6 -1
- package/lib/commonjs/i18n/it.json +6 -1
- package/lib/commonjs/i18n/ja.json +6 -1
- package/lib/commonjs/i18n/ko.json +6 -1
- package/lib/commonjs/i18n/nl.json +6 -1
- package/lib/commonjs/i18n/pt-br.json +6 -1
- package/lib/commonjs/i18n/ru.json +6 -1
- package/lib/commonjs/i18n/tr.json +6 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/ChannelDetails/hooks/useChannelDetailsActionItems.js +2 -1
- package/lib/module/components/ChannelDetails/hooks/useChannelDetailsActionItems.js.map +1 -1
- package/lib/module/components/ChannelList/ChannelList.js +4 -1
- package/lib/module/components/ChannelList/ChannelList.js.map +1 -1
- package/lib/module/components/ChannelList/hooks/useCreateChannelsContext.js +5 -3
- package/lib/module/components/ChannelList/hooks/useCreateChannelsContext.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreview.js +3 -0
- package/lib/module/components/ChannelPreview/ChannelPreview.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelPreviewPinnedStatus.js +30 -0
- package/lib/module/components/ChannelPreview/ChannelPreviewPinnedStatus.js.map +1 -0
- package/lib/module/components/ChannelPreview/ChannelPreviewView.js +8 -3
- package/lib/module/components/ChannelPreview/ChannelPreviewView.js.map +1 -1
- package/lib/module/components/ChannelPreview/ChannelSwipableWrapper.js +2 -1
- package/lib/module/components/ChannelPreview/ChannelSwipableWrapper.js.map +1 -1
- package/lib/module/components/ChannelPreview/hooks/index.js +11 -0
- package/lib/module/components/ChannelPreview/hooks/index.js.map +1 -1
- package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js +3 -0
- package/lib/module/components/ChannelPreview/hooks/useChannelPreviewData.js.map +1 -1
- package/lib/module/components/ChannelPreview/hooks/useIsChannelPinned.js +11 -0
- package/lib/module/components/ChannelPreview/hooks/useIsChannelPinned.js.map +1 -0
- package/lib/module/components/index.js +11 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/channelsContext/ChannelsContext.js.map +1 -1
- package/lib/module/contexts/componentsContext/defaultComponents.js +2 -0
- package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +1 -0
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/hooks/actions/useChannelActionItems.js +20 -1
- package/lib/module/hooks/actions/useChannelActionItems.js.map +1 -1
- package/lib/module/hooks/actions/useChannelActionItemsById.js +3 -1
- package/lib/module/hooks/actions/useChannelActionItemsById.js.map +1 -1
- package/lib/module/i18n/ar.json +6 -1
- package/lib/module/i18n/en.json +5 -0
- package/lib/module/i18n/es.json +6 -1
- package/lib/module/i18n/fr.json +6 -1
- package/lib/module/i18n/he.json +6 -1
- package/lib/module/i18n/hi.json +6 -1
- package/lib/module/i18n/it.json +6 -1
- package/lib/module/i18n/ja.json +6 -1
- package/lib/module/i18n/ko.json +6 -1
- package/lib/module/i18n/nl.json +6 -1
- package/lib/module/i18n/pt-br.json +6 -1
- package/lib/module/i18n/ru.json +6 -1
- package/lib/module/i18n/tr.json +6 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/ChannelList/ChannelList.d.ts +1 -1
- package/lib/typescript/components/ChannelList/ChannelList.d.ts.map +1 -1
- package/lib/typescript/components/ChannelList/hooks/useCreateChannelsContext.d.ts +1 -1
- package/lib/typescript/components/ChannelList/hooks/useCreateChannelsContext.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreview.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewPinnedStatus.d.ts +6 -0
- package/lib/typescript/components/ChannelPreview/ChannelPreviewPinnedStatus.d.ts.map +1 -0
- package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts +3 -1
- package/lib/typescript/components/ChannelPreview/ChannelPreviewView.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/ChannelSwipableWrapper.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/hooks/index.d.ts +1 -0
- package/lib/typescript/components/ChannelPreview/hooks/index.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts +1 -0
- package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewData.d.ts.map +1 -1
- package/lib/typescript/components/ChannelPreview/hooks/useIsChannelPinned.d.ts +3 -0
- package/lib/typescript/components/ChannelPreview/hooks/useIsChannelPinned.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts +1 -0
- package/lib/typescript/contexts/channelsContext/ChannelsContext.d.ts.map +1 -1
- package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +1 -0
- package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
- package/lib/typescript/contexts/themeContext/ThemeContext.d.ts +1 -0
- package/lib/typescript/contexts/themeContext/ThemeContext.d.ts.map +1 -1
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +1 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
- package/lib/typescript/hooks/actions/useChannelActionItems.d.ts +35 -2
- package/lib/typescript/hooks/actions/useChannelActionItems.d.ts.map +1 -1
- package/lib/typescript/hooks/actions/useChannelActionItemsById.d.ts +3 -2
- package/lib/typescript/hooks/actions/useChannelActionItemsById.d.ts.map +1 -1
- package/lib/typescript/i18n/ar.json +6 -1
- package/lib/typescript/i18n/en.json +5 -0
- package/lib/typescript/i18n/es.json +6 -1
- package/lib/typescript/i18n/fr.json +6 -1
- package/lib/typescript/i18n/he.json +6 -1
- package/lib/typescript/i18n/hi.json +6 -1
- package/lib/typescript/i18n/it.json +6 -1
- package/lib/typescript/i18n/ja.json +6 -1
- package/lib/typescript/i18n/ko.json +6 -1
- package/lib/typescript/i18n/nl.json +6 -1
- package/lib/typescript/i18n/pt-br.json +6 -1
- package/lib/typescript/i18n/ru.json +6 -1
- package/lib/typescript/i18n/tr.json +6 -1
- package/lib/typescript/utils/i18n/Streami18n.d.ts +5 -0
- package/lib/typescript/utils/i18n/Streami18n.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/ChannelDetails/__tests__/useChannelDetailsActionItems.test.tsx +6 -2
- package/src/components/ChannelDetails/hooks/useChannelDetailsActionItems.ts +1 -1
- package/src/components/ChannelList/ChannelList.tsx +3 -0
- package/src/components/ChannelList/hooks/useCreateChannelsContext.ts +3 -0
- package/src/components/ChannelPreview/ChannelPreview.tsx +21 -3
- package/src/components/ChannelPreview/ChannelPreviewPinnedStatus.tsx +25 -0
- package/src/components/ChannelPreview/ChannelPreviewView.tsx +18 -2
- package/src/components/ChannelPreview/ChannelSwipableWrapper.tsx +5 -1
- package/src/components/ChannelPreview/hooks/__tests__/useIsChannelPinned.test.tsx +35 -0
- package/src/components/ChannelPreview/hooks/index.ts +1 -0
- package/src/components/ChannelPreview/hooks/useChannelPreviewData.ts +3 -1
- package/src/components/ChannelPreview/hooks/useIsChannelPinned.ts +8 -0
- package/src/components/index.ts +1 -0
- package/src/contexts/channelsContext/ChannelsContext.tsx +1 -0
- package/src/contexts/componentsContext/defaultComponents.ts +2 -0
- package/src/contexts/themeContext/utils/theme.ts +2 -0
- package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx +137 -14
- package/src/hooks/actions/__tests__/useChannelActionItemsById.test.tsx +3 -1
- package/src/hooks/actions/useChannelActionItems.tsx +60 -2
- package/src/hooks/actions/useChannelActionItemsById.ts +8 -1
- package/src/i18n/ar.json +6 -1
- package/src/i18n/en.json +5 -0
- package/src/i18n/es.json +6 -1
- package/src/i18n/fr.json +6 -1
- package/src/i18n/he.json +6 -1
- package/src/i18n/hi.json +6 -1
- package/src/i18n/it.json +6 -1
- package/src/i18n/ja.json +6 -1
- package/src/i18n/ko.json +6 -1
- package/src/i18n/nl.json +6 -1
- package/src/i18n/pt-br.json +6 -1
- package/src/i18n/ru.json +6 -1
- package/src/i18n/tr.json +6 -1
- package/src/version.json +1 -1
|
@@ -41,6 +41,7 @@ export type ChannelListProps = Partial<
|
|
|
41
41
|
| 'maxUnreadCount'
|
|
42
42
|
| 'numberOfSkeletons'
|
|
43
43
|
| 'mutedStatusPosition'
|
|
44
|
+
| 'pinnedStatusPosition'
|
|
44
45
|
>
|
|
45
46
|
> & {
|
|
46
47
|
/** Optional function to filter channels prior to rendering the list. Do not use any complex logic that would delay the loading of the ChannelList. We recommend using a pure function with array methods like filter/sort/reduce. */
|
|
@@ -252,6 +253,7 @@ export const ChannelList = (props: ChannelListProps) => {
|
|
|
252
253
|
queryChannelsOverride,
|
|
253
254
|
notificationHostId: notificationHostIdProp,
|
|
254
255
|
mutedStatusPosition = 'inlineTitle',
|
|
256
|
+
pinnedStatusPosition = 'inlineTitle',
|
|
255
257
|
swipeActionsEnabled = true,
|
|
256
258
|
} = props;
|
|
257
259
|
|
|
@@ -375,6 +377,7 @@ export const ChannelList = (props: ChannelListProps) => {
|
|
|
375
377
|
}
|
|
376
378
|
},
|
|
377
379
|
mutedStatusPosition,
|
|
380
|
+
pinnedStatusPosition,
|
|
378
381
|
});
|
|
379
382
|
|
|
380
383
|
return (
|
|
@@ -23,6 +23,7 @@ export const useCreateChannelsContext = ({
|
|
|
23
23
|
reloadList,
|
|
24
24
|
setFlatListRef,
|
|
25
25
|
mutedStatusPosition,
|
|
26
|
+
pinnedStatusPosition,
|
|
26
27
|
}: ChannelsContextValue) => {
|
|
27
28
|
const channelValueString = channels
|
|
28
29
|
?.map(
|
|
@@ -56,6 +57,7 @@ export const useCreateChannelsContext = ({
|
|
|
56
57
|
reloadList,
|
|
57
58
|
setFlatListRef,
|
|
58
59
|
mutedStatusPosition,
|
|
60
|
+
pinnedStatusPosition,
|
|
59
61
|
}),
|
|
60
62
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
61
63
|
[
|
|
@@ -69,6 +71,7 @@ export const useCreateChannelsContext = ({
|
|
|
69
71
|
swipeActionsEnabled,
|
|
70
72
|
refreshing,
|
|
71
73
|
mutedStatusPosition,
|
|
74
|
+
pinnedStatusPosition,
|
|
72
75
|
],
|
|
73
76
|
);
|
|
74
77
|
|
|
@@ -30,19 +30,37 @@ export const ChannelPreview = (props: ChannelPreviewProps) => {
|
|
|
30
30
|
|
|
31
31
|
const client = propClient || contextClient;
|
|
32
32
|
|
|
33
|
-
const { muted, unread, lastMessage } = useChannelPreviewData(
|
|
33
|
+
const { muted, pinned, unread, lastMessage } = useChannelPreviewData(
|
|
34
|
+
channel,
|
|
35
|
+
client,
|
|
36
|
+
propForceUpdate,
|
|
37
|
+
);
|
|
34
38
|
|
|
35
39
|
const translatedLastMessage = useTranslatedMessage(lastMessage);
|
|
36
40
|
|
|
37
41
|
const message = translatedLastMessage ? translatedLastMessage : lastMessage;
|
|
38
42
|
|
|
39
43
|
if (!swipeActionsEnabled) {
|
|
40
|
-
return
|
|
44
|
+
return (
|
|
45
|
+
<ChannelPreview
|
|
46
|
+
channel={channel}
|
|
47
|
+
muted={muted}
|
|
48
|
+
pinned={pinned}
|
|
49
|
+
unread={unread}
|
|
50
|
+
lastMessage={message}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
return (
|
|
44
56
|
<ChannelSwipableWrapper channel={channel} getChannelActionItems={getChannelActionItems}>
|
|
45
|
-
<ChannelPreview
|
|
57
|
+
<ChannelPreview
|
|
58
|
+
channel={channel}
|
|
59
|
+
muted={muted}
|
|
60
|
+
pinned={pinned}
|
|
61
|
+
unread={unread}
|
|
62
|
+
lastMessage={message}
|
|
63
|
+
/>
|
|
46
64
|
</ChannelSwipableWrapper>
|
|
47
65
|
);
|
|
48
66
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { useA11yLabel } from '../../a11y/hooks/useA11yLabel';
|
|
4
|
+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
5
|
+
import { Pin } from '../../icons';
|
|
6
|
+
import { CompositeAccessibilityProbe } from '../Accessibility/CompositeAccessibilityProbe';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This UI component displays a pinned indicator for a particular channel.
|
|
10
|
+
*/
|
|
11
|
+
export const ChannelPreviewPinnedStatus = () => {
|
|
12
|
+
const {
|
|
13
|
+
theme: {
|
|
14
|
+
channelPreview: { pinnedStatus },
|
|
15
|
+
semantics,
|
|
16
|
+
},
|
|
17
|
+
} = useTheme();
|
|
18
|
+
const accessibilityLabel = useA11yLabel('a11y/Pinned');
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<CompositeAccessibilityProbe label={accessibilityLabel}>
|
|
22
|
+
<Pin height={20} stroke={semantics.textTertiary} width={20} {...pinnedStatus} />
|
|
23
|
+
</CompositeAccessibilityProbe>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -17,7 +17,10 @@ import { useStableCallback } from '../../hooks';
|
|
|
17
17
|
import { primitives } from '../../theme';
|
|
18
18
|
|
|
19
19
|
export type ChannelPreviewViewPropsWithContext = Pick<ChannelPreviewProps, 'channel'> &
|
|
20
|
-
Pick<
|
|
20
|
+
Pick<
|
|
21
|
+
ChannelsContextValue,
|
|
22
|
+
'maxUnreadCount' | 'onSelect' | 'mutedStatusPosition' | 'pinnedStatusPosition'
|
|
23
|
+
> & {
|
|
21
24
|
/**
|
|
22
25
|
* Formatter function for date of latest message.
|
|
23
26
|
* @param date Message date
|
|
@@ -30,6 +33,8 @@ export type ChannelPreviewViewPropsWithContext = Pick<ChannelPreviewProps, 'chan
|
|
|
30
33
|
formatLatestMessageDate?: (date: Date) => string;
|
|
31
34
|
/** If the channel is muted. */
|
|
32
35
|
muted?: boolean;
|
|
36
|
+
/** If the channel is pinned for the current user. */
|
|
37
|
+
pinned?: boolean;
|
|
33
38
|
/** Number of unread messages on the channel */
|
|
34
39
|
unread?: number;
|
|
35
40
|
lastMessage?: LastMessageType;
|
|
@@ -42,14 +47,17 @@ const ChannelPreviewViewWithContext = (props: ChannelPreviewViewPropsWithContext
|
|
|
42
47
|
maxUnreadCount,
|
|
43
48
|
muted,
|
|
44
49
|
onSelect,
|
|
50
|
+
pinned,
|
|
45
51
|
unread,
|
|
46
52
|
mutedStatusPosition,
|
|
53
|
+
pinnedStatusPosition,
|
|
47
54
|
lastMessage,
|
|
48
55
|
} = props;
|
|
49
56
|
const {
|
|
50
57
|
ChannelPreviewAvatar,
|
|
51
58
|
ChannelPreviewMessage,
|
|
52
59
|
ChannelPreviewMutedStatus,
|
|
60
|
+
ChannelPreviewPinnedStatus,
|
|
53
61
|
ChannelPreviewStatus,
|
|
54
62
|
ChannelPreviewTitle,
|
|
55
63
|
ChannelPreviewUnreadCount,
|
|
@@ -111,6 +119,9 @@ const ChannelPreviewViewWithContext = (props: ChannelPreviewViewPropsWithContext
|
|
|
111
119
|
{muted && mutedStatusPosition === 'inlineTitle' ? (
|
|
112
120
|
<ChannelPreviewMutedStatus />
|
|
113
121
|
) : null}
|
|
122
|
+
{pinned && pinnedStatusPosition === 'inlineTitle' ? (
|
|
123
|
+
<ChannelPreviewPinnedStatus />
|
|
124
|
+
) : null}
|
|
114
125
|
</View>
|
|
115
126
|
|
|
116
127
|
<View style={[styles.statusContainer, statusContainer]}>
|
|
@@ -132,6 +143,9 @@ const ChannelPreviewViewWithContext = (props: ChannelPreviewViewPropsWithContext
|
|
|
132
143
|
{muted && mutedStatusPosition === 'trailingBottom' ? (
|
|
133
144
|
<ChannelPreviewMutedStatus />
|
|
134
145
|
) : null}
|
|
146
|
+
{pinned && pinnedStatusPosition === 'trailingBottom' ? (
|
|
147
|
+
<ChannelPreviewPinnedStatus />
|
|
148
|
+
) : null}
|
|
135
149
|
</View>
|
|
136
150
|
</View>
|
|
137
151
|
</Pressable>
|
|
@@ -151,7 +165,8 @@ const MemoizedChannelPreviewViewWithContext = React.memo(
|
|
|
151
165
|
* from the ChannelPreview component.
|
|
152
166
|
*/
|
|
153
167
|
export const ChannelPreviewView = (props: ChannelPreviewViewProps) => {
|
|
154
|
-
const { forceUpdate, maxUnreadCount, onSelect, mutedStatusPosition } =
|
|
168
|
+
const { forceUpdate, maxUnreadCount, onSelect, mutedStatusPosition, pinnedStatusPosition } =
|
|
169
|
+
useChannelsContext();
|
|
155
170
|
return (
|
|
156
171
|
<MemoizedChannelPreviewViewWithContext
|
|
157
172
|
{...{
|
|
@@ -159,6 +174,7 @@ export const ChannelPreviewView = (props: ChannelPreviewViewProps) => {
|
|
|
159
174
|
maxUnreadCount,
|
|
160
175
|
onSelect,
|
|
161
176
|
mutedStatusPosition,
|
|
177
|
+
pinnedStatusPosition,
|
|
162
178
|
}}
|
|
163
179
|
{...props}
|
|
164
180
|
/>
|
|
@@ -41,7 +41,11 @@ export const ChannelSwipableWrapper = ({
|
|
|
41
41
|
}>) => {
|
|
42
42
|
const { ChannelDetailsBottomSheet: ChannelDetailsBottomSheetComponent } = useComponentsContext();
|
|
43
43
|
const [channelDetailSheetOpen, setChannelDetailSheetOpen] = useState(false);
|
|
44
|
-
const channelActionItems = useChannelActionItems({
|
|
44
|
+
const channelActionItems = useChannelActionItems({
|
|
45
|
+
channel,
|
|
46
|
+
getChannelActionItems,
|
|
47
|
+
surface: 'list',
|
|
48
|
+
});
|
|
45
49
|
const sheetItems = useMemo(
|
|
46
50
|
() => channelActionItems.filter((item) => item.placement !== 'swipe'),
|
|
47
51
|
[channelActionItems],
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-native';
|
|
2
|
+
import { Channel } from 'stream-chat';
|
|
3
|
+
|
|
4
|
+
import { useIsChannelPinned } from '../useIsChannelPinned';
|
|
5
|
+
|
|
6
|
+
describe('useIsChannelPinned', () => {
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
jest.clearAllMocks();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const buildMockChannel = (membership: Record<string, unknown> = {}) =>
|
|
12
|
+
({
|
|
13
|
+
initialized: true,
|
|
14
|
+
on: jest.fn().mockReturnValue({ unsubscribe: jest.fn() }),
|
|
15
|
+
state: { membership },
|
|
16
|
+
}) as unknown as Channel;
|
|
17
|
+
|
|
18
|
+
it('returns false when membership has no pinned_at', () => {
|
|
19
|
+
const channel = buildMockChannel({ pinned_at: null });
|
|
20
|
+
const { result } = renderHook(() => useIsChannelPinned(channel));
|
|
21
|
+
expect(result.current).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('returns true when membership has a pinned_at timestamp', () => {
|
|
25
|
+
const channel = buildMockChannel({ pinned_at: '2026-06-15T08:00:00.000Z' });
|
|
26
|
+
const { result } = renderHook(() => useIsChannelPinned(channel));
|
|
27
|
+
expect(result.current).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('subscribes to member.updated events', () => {
|
|
31
|
+
const channel = buildMockChannel({ pinned_at: null });
|
|
32
|
+
renderHook(() => useIsChannelPinned(channel));
|
|
33
|
+
expect(channel.on).toHaveBeenCalledWith('member.updated', expect.any(Function));
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -4,6 +4,7 @@ import throttle from 'lodash/throttle';
|
|
|
4
4
|
import type { Channel, Event, LocalMessage, MessageResponse, StreamChat } from 'stream-chat';
|
|
5
5
|
|
|
6
6
|
import { useIsChannelMuted } from './useIsChannelMuted';
|
|
7
|
+
import { useIsChannelPinned } from './useIsChannelPinned';
|
|
7
8
|
|
|
8
9
|
import { useChannelsContext } from '../../../contexts';
|
|
9
10
|
import { useStableCallback } from '../../../hooks';
|
|
@@ -39,6 +40,7 @@ export const useChannelPreviewData = (
|
|
|
39
40
|
);
|
|
40
41
|
const [unread, setUnread] = useState(channel.countUnread());
|
|
41
42
|
const { muted } = useIsChannelMuted(channel);
|
|
43
|
+
const pinned = useIsChannelPinned(channel);
|
|
42
44
|
const { forceUpdate: contextForceUpdate } = useChannelsContext();
|
|
43
45
|
const channelListForceUpdate = forceUpdateOverride ?? contextForceUpdate;
|
|
44
46
|
|
|
@@ -170,5 +172,5 @@ export const useChannelPreviewData = (
|
|
|
170
172
|
return () => listeners.forEach((l) => l.unsubscribe());
|
|
171
173
|
}, [channel, refreshUnreadCount, forceUpdate, channelListForceUpdate, setLastMessage]);
|
|
172
174
|
|
|
173
|
-
return { lastMessage, muted, unread };
|
|
175
|
+
return { lastMessage, muted, pinned, unread };
|
|
174
176
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Channel } from 'stream-chat';
|
|
2
|
+
|
|
3
|
+
import { useChannelMembershipState } from '../../../hooks/useChannelMembershipState';
|
|
4
|
+
|
|
5
|
+
export const useIsChannelPinned = (channel: Channel) => {
|
|
6
|
+
const membership = useChannelMembershipState(channel);
|
|
7
|
+
return Boolean(membership?.pinned_at);
|
|
8
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -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,
|
|
@@ -299,6 +299,7 @@ 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;
|
|
@@ -1357,6 +1358,7 @@ export const defaultTheme: Theme = {
|
|
|
1357
1358
|
timeIcon: {},
|
|
1358
1359
|
},
|
|
1359
1360
|
mutedStatus: {},
|
|
1361
|
+
pinnedStatus: {},
|
|
1360
1362
|
lowerRow: {},
|
|
1361
1363
|
title: {},
|
|
1362
1364
|
unreadContainer: {},
|
|
@@ -99,32 +99,45 @@ 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(
|
|
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([
|
|
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([
|
|
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',
|
|
126
138
|
'muteUser',
|
|
127
139
|
'block',
|
|
140
|
+
'pin',
|
|
128
141
|
'leave',
|
|
129
142
|
'deleteChannel',
|
|
130
143
|
]);
|
|
@@ -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(() =>
|
|
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,6 +290,7 @@ 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
|
});
|
|
@@ -277,6 +299,7 @@ describe('getChannelActionItems', () => {
|
|
|
277
299
|
'mute',
|
|
278
300
|
'muteUser',
|
|
279
301
|
'block',
|
|
302
|
+
'pin',
|
|
280
303
|
'leave',
|
|
281
304
|
'deleteChannel',
|
|
282
305
|
]);
|
|
@@ -284,6 +307,7 @@ describe('getChannelActionItems', () => {
|
|
|
284
307
|
channelActions.unmuteChannel,
|
|
285
308
|
channelActions.unmuteUser,
|
|
286
309
|
channelActions.unblockUser,
|
|
310
|
+
channelActions.pin,
|
|
287
311
|
channelActions.leave,
|
|
288
312
|
expect.any(Function),
|
|
289
313
|
]);
|
|
@@ -291,6 +315,7 @@ describe('getChannelActionItems', () => {
|
|
|
291
315
|
'Unmute Chat',
|
|
292
316
|
'Unmute User',
|
|
293
317
|
'Unblock User',
|
|
318
|
+
'Pin Chat',
|
|
294
319
|
'Leave Chat',
|
|
295
320
|
'Delete Chat',
|
|
296
321
|
]);
|
|
@@ -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
|
-
|
|
357
|
-
expect(
|
|
358
|
-
expect(
|
|
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
|
});
|