@planningcenter/chat-react-native 3.2.0-rc.2 → 3.2.0-rc.3
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/build/components/conversations/conversations.d.ts +3 -6
- package/build/components/conversations/conversations.d.ts.map +1 -1
- package/build/components/conversations/conversations.js +3 -10
- package/build/components/conversations/conversations.js.map +1 -1
- package/build/contexts/conversations_context.d.ts +14 -0
- package/build/contexts/conversations_context.d.ts.map +1 -0
- package/build/contexts/conversations_context.js +47 -0
- package/build/contexts/conversations_context.js.map +1 -0
- package/build/hooks/use_conversations.d.ts +6 -32
- package/build/hooks/use_conversations.d.ts.map +1 -1
- package/build/hooks/use_conversations.js +15 -14
- package/build/hooks/use_conversations.js.map +1 -1
- package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
- package/build/screens/conversations/conversations_screen.js +5 -12
- package/build/screens/conversations/conversations_screen.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversations/conversations.tsx +16 -26
- package/src/contexts/conversations_context.tsx +79 -0
- package/src/hooks/use_conversations.ts +34 -16
- package/src/screens/conversations/conversations_screen.tsx +5 -18
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
interface ConversationsProps extends Partial<Omit<ConversationRequestArgs, 'group'>> {
|
|
5
|
-
chat_group_graph_id?: string;
|
|
6
|
-
ListHeaderComponent?: ListHeaderComponent;
|
|
2
|
+
interface ConversationsProps {
|
|
3
|
+
ListHeaderComponent?: React.ComponentType<any> | React.ReactElement<any, string | React.JSXElementConstructor<any>> | null | undefined;
|
|
7
4
|
}
|
|
8
|
-
export declare const Conversations: ({ ListHeaderComponent
|
|
5
|
+
export declare const Conversations: ({ ListHeaderComponent }: ConversationsProps) => React.JSX.Element;
|
|
9
6
|
export {};
|
|
10
7
|
//# sourceMappingURL=conversations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../src/components/conversations/conversations.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"conversations.d.ts","sourceRoot":"","sources":["../../../src/components/conversations/conversations.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,UAAU,kBAAkB;IAC1B,mBAAmB,CAAC,EAChB,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GACxB,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,GAClE,IAAI,GACJ,SAAS,CAAA;CACd;AAED,eAAO,MAAM,aAAa,4BAA6B,kBAAkB,sBA0CxE,CAAA"}
|
|
@@ -2,22 +2,15 @@ import { useNavigation } from '@react-navigation/native';
|
|
|
2
2
|
import { FlashList } from '@shopify/flash-list';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { StyleSheet, View } from 'react-native';
|
|
5
|
+
import { useConversationsContext } from '../../contexts/conversations_context';
|
|
5
6
|
import { useTheme } from '../../hooks';
|
|
6
|
-
import { useConversationsJoltEvents } from '../../hooks/use_conversation_jolt_events';
|
|
7
|
-
import { useConversations } from '../../hooks/use_conversations';
|
|
8
7
|
import { Text } from '../display';
|
|
9
8
|
import { ConversationPreview } from './conversation_preview';
|
|
10
9
|
import { ConversationActionsProvider } from '../../contexts/swipeable_active_conversation';
|
|
11
|
-
export const Conversations = ({ ListHeaderComponent
|
|
10
|
+
export const Conversations = ({ ListHeaderComponent }) => {
|
|
12
11
|
const styles = useStyles();
|
|
13
|
-
const { conversations, fetchNextPage, refetch, isRefetching, isFetched } =
|
|
14
|
-
filter,
|
|
15
|
-
group: chat_group_graph_id,
|
|
16
|
-
gids,
|
|
17
|
-
group_source_app_name,
|
|
18
|
-
});
|
|
12
|
+
const { conversations, fetchNextPage, refetch, isRefetching, isFetched, args: { chat_group_graph_id }, } = useConversationsContext();
|
|
19
13
|
const navigation = useNavigation();
|
|
20
|
-
useConversationsJoltEvents();
|
|
21
14
|
const showBadges = !chat_group_graph_id;
|
|
22
15
|
return (<ConversationActionsProvider>
|
|
23
16
|
<View style={styles.container}>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../../src/components/conversations/conversations.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../../src/components/conversations/conversations.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAA;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAA;AAU1F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,mBAAmB,EAAsB,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,MAAM,EACJ,aAAa,EACb,aAAa,EACb,OAAO,EACP,YAAY,EACZ,SAAS,EACT,IAAI,EAAE,EAAE,mBAAmB,EAAE,GAC9B,GAAG,uBAAuB,EAAE,CAAA;IAC7B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAElC,MAAM,UAAU,GAAG,CAAC,mBAAmB,CAAA;IAEvC,OAAO,CACL,CAAC,2BAA2B,CAC1B;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;QAAA,CAAC,SAAS,CACR,IAAI,CAAC,CAAC,aAAa,CAAC,CACpB,iBAAiB,CAAC,CAAC,EAAE,CAAC,CACtB,qBAAqB,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAC/C,SAAS,CAAC,CAAC,OAAO,CAAC,CACnB,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,YAAY,CAAC,CACvC,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,CACzC,kBAAkB,CAAC,CACjB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;cAAA,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,sBAAsB,EAAE,IAAI,CACxD;YAAA,EAAE,IAAI,CACR,CAAC,CACD,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CACxB,CAAC,mBAAmB,CAClB,YAAY,CAAC,CAAC,IAAI,CAAC,CACnB,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CACjF,UAAU,CAAC,CAAC,UAAU,CAAC,EACvB,CACH,CAAC,CACF,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,EAExC;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,2BAA2B,CAAC,CAC/B,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;QACtB,gBAAgB,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE;QACzC,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,mBAAmB,EAAE;QAC/C,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;YACxB,UAAU,EAAE,QAAQ;YACpB,eAAe,EAAE,EAAE;SACpB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport { FlashList } from '@shopify/flash-list'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { useConversationsContext } from '../../contexts/conversations_context'\nimport { useTheme } from '../../hooks'\nimport { Text } from '../display'\nimport { ConversationPreview } from './conversation_preview'\nimport { ConversationActionsProvider } from '../../contexts/swipeable_active_conversation'\n\ninterface ConversationsProps {\n ListHeaderComponent?:\n | React.ComponentType<any>\n | React.ReactElement<any, string | React.JSXElementConstructor<any>>\n | null\n | undefined\n}\n\nexport const Conversations = ({ ListHeaderComponent }: ConversationsProps) => {\n const styles = useStyles()\n\n const {\n conversations,\n fetchNextPage,\n refetch,\n isRefetching,\n isFetched,\n args: { chat_group_graph_id },\n } = useConversationsContext()\n const navigation = useNavigation()\n\n const showBadges = !chat_group_graph_id\n\n return (\n <ConversationActionsProvider>\n <View style={styles.container}>\n <FlashList\n data={conversations}\n estimatedItemSize={97}\n contentContainerStyle={styles.contentContainer}\n onRefresh={refetch}\n refreshing={!isFetched && isRefetching}\n ListHeaderComponent={ListHeaderComponent}\n ListEmptyComponent={\n <View style={styles.listEmpty}>\n <Text variant=\"secondary\">No conversations found</Text>\n </View>\n }\n renderItem={({ item }) => (\n <ConversationPreview\n conversation={item}\n onPress={() => navigation.navigate('Conversation', { conversation_id: item.id })}\n showBadges={showBadges}\n />\n )}\n onEndReached={() => fetchNextPage()}\n />\n </View>\n </ConversationActionsProvider>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: { flex: 1 },\n contentContainer: { paddingVertical: 16 },\n listItem: { color: colors.fillColorNeutral020 },\n listEmpty: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n paddingVertical: 16,\n },\n })\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { ConversationFiltersParams } from '../screens/conversation_filters/screen_props';
|
|
3
|
+
import { UseConversationsValue } from '../hooks/use_conversations';
|
|
4
|
+
interface ConversationsContextValue extends UseConversationsValue {
|
|
5
|
+
activeConversationId?: number;
|
|
6
|
+
setActiveConversationId: (_id: number) => void;
|
|
7
|
+
args: ConversationFiltersParams;
|
|
8
|
+
}
|
|
9
|
+
export declare const ConversationsContextProvider: ({ children, args, }: PropsWithChildren<{
|
|
10
|
+
args: ConversationFiltersParams;
|
|
11
|
+
}>) => React.JSX.Element;
|
|
12
|
+
export declare const useConversationsContext: () => ConversationsContextValue;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=conversations_context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversations_context.d.ts","sourceRoot":"","sources":["../../src/contexts/conversations_context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAiB,iBAAiB,EAAiC,MAAM,OAAO,CAAA;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,8CAA8C,CAAA;AACxF,OAAO,EAAoB,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AASpF,UAAU,yBAA0B,SAAQ,qBAAqB;IAC/D,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,uBAAuB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9C,IAAI,EAAE,yBAAyB,CAAA;CAChC;AAqBD,eAAO,MAAM,4BAA4B,wBAGtC,iBAAiB,CAAC;IAAE,IAAI,EAAE,yBAAyB,CAAA;CAAE,CAAC,sBA6BxD,CAAA;AAUD,eAAO,MAAM,uBAAuB,iCAAyC,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { createContext, useContext, useMemo, useState } from 'react';
|
|
2
|
+
import { useConversations } from '../hooks/use_conversations';
|
|
3
|
+
import { useConversationsJoltEvents } from '../hooks/use_conversation_jolt_events';
|
|
4
|
+
const defaultQueryValue = {
|
|
5
|
+
conversations: [],
|
|
6
|
+
refetch: () => Promise.resolve(null),
|
|
7
|
+
error: null,
|
|
8
|
+
isError: false,
|
|
9
|
+
fetchNextPage,
|
|
10
|
+
hasNextPage: false,
|
|
11
|
+
isFetching: false,
|
|
12
|
+
isFetched: false,
|
|
13
|
+
isRefetching: false,
|
|
14
|
+
};
|
|
15
|
+
const ConversationsContext = createContext({
|
|
16
|
+
args: {},
|
|
17
|
+
activeConversationId: undefined,
|
|
18
|
+
setActiveConversationId: () => { },
|
|
19
|
+
...defaultQueryValue,
|
|
20
|
+
});
|
|
21
|
+
export const ConversationsContextProvider = ({ children, args, }) => {
|
|
22
|
+
const [activeConversationId, setActiveConversationId] = useState();
|
|
23
|
+
const { chat_group_graph_id, group_source_app_name } = args;
|
|
24
|
+
const filter = useMemo(() => {
|
|
25
|
+
if (chat_group_graph_id) {
|
|
26
|
+
return 'group';
|
|
27
|
+
}
|
|
28
|
+
else if (group_source_app_name) {
|
|
29
|
+
return 'group_source_app_name';
|
|
30
|
+
}
|
|
31
|
+
return 'mine_or_not_empty';
|
|
32
|
+
}, [chat_group_graph_id, group_source_app_name]);
|
|
33
|
+
const query = useConversations({ group: chat_group_graph_id, group_source_app_name, filter });
|
|
34
|
+
const value = useMemo(() => ({
|
|
35
|
+
args,
|
|
36
|
+
activeConversationId,
|
|
37
|
+
setActiveConversationId,
|
|
38
|
+
...query,
|
|
39
|
+
}), [args, activeConversationId, query]);
|
|
40
|
+
useConversationsJoltEvents();
|
|
41
|
+
return <ConversationsContext.Provider value={value}>{children}</ConversationsContext.Provider>;
|
|
42
|
+
};
|
|
43
|
+
function fetchNextPage(_options) {
|
|
44
|
+
throw new Error('Function not implemented.');
|
|
45
|
+
}
|
|
46
|
+
export const useConversationsContext = () => useContext(ConversationsContext);
|
|
47
|
+
//# sourceMappingURL=conversations_context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversations_context.js","sourceRoot":"","sources":["../../src/contexts/conversations_context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAqB,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE9F,OAAO,EAAE,gBAAgB,EAAyB,MAAM,4BAA4B,CAAA;AAOpF,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAQlF,MAAM,iBAAiB,GAA0B;IAC/C,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IACpC,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,KAAK;IACd,aAAa;IACb,WAAW,EAAE,KAAK;IAClB,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,KAAK;IAChB,YAAY,EAAE,KAAK;CACpB,CAAA;AAED,MAAM,oBAAoB,GAAG,aAAa,CAA4B;IACpE,IAAI,EAAE,EAAE;IACR,oBAAoB,EAAE,SAAS;IAC/B,uBAAuB,EAAE,GAAG,EAAE,GAAE,CAAC;IACjC,GAAG,iBAAiB;CACrB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,EAC3C,QAAQ,EACR,IAAI,GACmD,EAAE,EAAE;IAC3D,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,QAAQ,EAAsB,CAAA;IACtF,MAAM,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,GAAG,IAAI,CAAA;IAE3D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1B,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,OAAO,CAAA;QAChB,CAAC;aAAM,IAAI,qBAAqB,EAAE,CAAC;YACjC,OAAO,uBAAuB,CAAA;QAChC,CAAC;QAED,OAAO,mBAAmB,CAAA;IAC5B,CAAC,EAAE,CAAC,mBAAmB,EAAE,qBAAqB,CAAC,CAAC,CAAA;IAEhD,MAAM,KAAK,GAAG,gBAAgB,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,EAAE,CAAC,CAAA;IAE7F,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,IAAI;QACJ,oBAAoB;QACpB,uBAAuB;QACvB,GAAG,KAAK;KACT,CAAC,EACF,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,CAAC,CACpC,CAAA;IAED,0BAA0B,EAAE,CAAA;IAE5B,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAChG,CAAC,CAAA;AAED,SAAS,aAAa,CACpB,QAA+B;IAI/B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;AAC9C,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAA","sourcesContent":["import React, { createContext, PropsWithChildren, useContext, useMemo, useState } from 'react'\nimport { ConversationFiltersParams } from '../screens/conversation_filters/screen_props'\nimport { useConversations, UseConversationsValue } from '../hooks/use_conversations'\nimport {\n FetchNextPageOptions,\n InfiniteQueryObserverResult,\n InfiniteData,\n} from '@tanstack/react-query'\nimport { ApiCollection, ConversationResource } from '../types'\nimport { useConversationsJoltEvents } from '../hooks/use_conversation_jolt_events'\n\ninterface ConversationsContextValue extends UseConversationsValue {\n activeConversationId?: number\n setActiveConversationId: (_id: number) => void\n args: ConversationFiltersParams\n}\n\nconst defaultQueryValue: UseConversationsValue = {\n conversations: [],\n refetch: () => Promise.resolve(null),\n error: null,\n isError: false,\n fetchNextPage,\n hasNextPage: false,\n isFetching: false,\n isFetched: false,\n isRefetching: false,\n}\n\nconst ConversationsContext = createContext<ConversationsContextValue>({\n args: {},\n activeConversationId: undefined,\n setActiveConversationId: () => {},\n ...defaultQueryValue,\n})\n\nexport const ConversationsContextProvider = ({\n children,\n args,\n}: PropsWithChildren<{ args: ConversationFiltersParams }>) => {\n const [activeConversationId, setActiveConversationId] = useState<number | undefined>()\n const { chat_group_graph_id, group_source_app_name } = args\n\n const filter = useMemo(() => {\n if (chat_group_graph_id) {\n return 'group'\n } else if (group_source_app_name) {\n return 'group_source_app_name'\n }\n\n return 'mine_or_not_empty'\n }, [chat_group_graph_id, group_source_app_name])\n\n const query = useConversations({ group: chat_group_graph_id, group_source_app_name, filter })\n\n const value = useMemo(\n () => ({\n args,\n activeConversationId,\n setActiveConversationId,\n ...query,\n }),\n [args, activeConversationId, query]\n )\n\n useConversationsJoltEvents()\n\n return <ConversationsContext.Provider value={value}>{children}</ConversationsContext.Provider>\n}\n\nfunction fetchNextPage(\n _options?: FetchNextPageOptions\n): Promise<\n InfiniteQueryObserverResult<InfiniteData<ApiCollection<ConversationResource>, unknown>, Response>\n> {\n throw new Error('Function not implemented.')\n}\n\nexport const useConversationsContext = () => useContext(ConversationsContext)\n"]}
|
|
@@ -1,36 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InfiniteData, UseSuspenseInfiniteQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { ApiCollection, ConversationResource } from '../types';
|
|
2
3
|
import { ConversationRequestArgs } from '../utils/request/conversation';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
isError: boolean;
|
|
6
|
-
isPending: false;
|
|
7
|
-
isLoading: false;
|
|
8
|
-
isLoadingError: false;
|
|
9
|
-
isRefetchError: boolean;
|
|
10
|
-
isSuccess: boolean;
|
|
11
|
-
status: "error" | "success";
|
|
12
|
-
dataUpdatedAt: number;
|
|
13
|
-
errorUpdatedAt: number;
|
|
14
|
-
failureCount: number;
|
|
15
|
-
failureReason: Response | null;
|
|
16
|
-
errorUpdateCount: number;
|
|
17
|
-
isFetched: boolean;
|
|
18
|
-
isFetchedAfterMount: boolean;
|
|
19
|
-
isFetching: boolean;
|
|
20
|
-
isInitialLoading: boolean;
|
|
21
|
-
isPaused: boolean;
|
|
22
|
-
isRefetching: boolean;
|
|
23
|
-
isStale: boolean;
|
|
24
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../types").ApiCollection<ConversationResource>, unknown>, Response>>;
|
|
25
|
-
fetchStatus: import("@tanstack/query-core").FetchStatus;
|
|
26
|
-
fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../types").ApiCollection<ConversationResource>, unknown>, Response>>;
|
|
27
|
-
fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../types").ApiCollection<ConversationResource>, unknown>, Response>>;
|
|
28
|
-
hasNextPage: boolean;
|
|
29
|
-
hasPreviousPage: boolean;
|
|
30
|
-
isFetchNextPageError: boolean;
|
|
31
|
-
isFetchingNextPage: boolean;
|
|
32
|
-
isFetchPreviousPageError: boolean;
|
|
33
|
-
isFetchingPreviousPage: boolean;
|
|
4
|
+
export type ConversationPaginationResult = UseSuspenseInfiniteQueryResult<InfiniteData<ApiCollection<ConversationResource>, unknown>, Response>;
|
|
5
|
+
export type UseConversationsValue = Pick<ConversationPaginationResult, 'isFetching' | 'isError' | 'error' | 'fetchNextPage' | 'hasNextPage' | 'isFetched' | 'isRefetching'> & {
|
|
34
6
|
conversations: ConversationResource[];
|
|
7
|
+
refetch: () => Promise<any>;
|
|
35
8
|
};
|
|
9
|
+
export declare function useConversations(args?: Partial<ConversationRequestArgs>): UseConversationsValue;
|
|
36
10
|
//# sourceMappingURL=use_conversations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_conversations.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use_conversations.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAA;AAEpF,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC9D,OAAO,EAAE,uBAAuB,EAA+B,MAAM,+BAA+B,CAAA;AAGpG,MAAM,MAAM,4BAA4B,GAAG,8BAA8B,CACvE,YAAY,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC,EAC1D,QAAQ,CACT,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,4BAA4B,EAC1B,YAAY,GACZ,SAAS,GACT,OAAO,GACP,eAAe,GACf,aAAa,GACb,WAAW,GACX,cAAc,CACjB,GAAG;IACF,aAAa,EAAE,oBAAoB,EAAE,CAAA;IACrC,OAAO,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;CAC5B,CAAA;AAED,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,qBAAqB,CAO/F"}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import { useSuspensePaginator } from './use_suspense_api';
|
|
3
2
|
import { getConversationsRequestArgs } from '../utils/request/conversation';
|
|
3
|
+
import { useSuspensePaginator } from './use_suspense_api';
|
|
4
4
|
export function useConversations(args) {
|
|
5
5
|
const requestArgs = getConversationsRequestArgs(args);
|
|
6
6
|
const { data, ...rest } = useSuspensePaginator(requestArgs);
|
|
7
|
-
const conversations = useMemo(() => data.sort(
|
|
8
|
-
const dateA = a.lastMessageCreatedAt || a.createdAt;
|
|
9
|
-
const dateB = b.lastMessageCreatedAt || b.createdAt;
|
|
10
|
-
if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt)
|
|
11
|
-
return 1;
|
|
12
|
-
if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt)
|
|
13
|
-
return -1;
|
|
14
|
-
if (dateB > dateA)
|
|
15
|
-
return 1;
|
|
16
|
-
if (dateB < dateA)
|
|
17
|
-
return -1;
|
|
18
|
-
return 0;
|
|
19
|
-
}), [data]);
|
|
7
|
+
const conversations = useMemo(() => data.sort(sortByLastMessage), [data]);
|
|
20
8
|
return { conversations, ...rest };
|
|
21
9
|
}
|
|
10
|
+
function sortByLastMessage(a, b) {
|
|
11
|
+
const dateA = a.lastMessageCreatedAt || a.createdAt;
|
|
12
|
+
const dateB = b.lastMessageCreatedAt || b.createdAt;
|
|
13
|
+
if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt)
|
|
14
|
+
return 1;
|
|
15
|
+
if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt)
|
|
16
|
+
return -1;
|
|
17
|
+
if (dateB > dateA)
|
|
18
|
+
return 1;
|
|
19
|
+
if (dateB < dateA)
|
|
20
|
+
return -1;
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
22
23
|
//# sourceMappingURL=use_conversations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_conversations.js","sourceRoot":"","sources":["../../src/hooks/use_conversations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use_conversations.js","sourceRoot":"","sources":["../../src/hooks/use_conversations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B,OAAO,EAA2B,2BAA2B,EAAE,MAAM,+BAA+B,CAAA;AACpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAqBzD,MAAM,UAAU,gBAAgB,CAAC,IAAuC;IACtE,MAAM,WAAW,GAAG,2BAA2B,CAAC,IAAI,CAAC,CAAA;IACrD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,oBAAoB,CAAuB,WAAW,CAAC,CAAA;IAEjF,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEzE,OAAO,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,CAAA;AACnC,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAuB,EAAE,CAAuB;IACzE,MAAM,KAAK,GAAG,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC,SAAS,CAAA;IACnD,MAAM,KAAK,GAAG,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC,SAAS,CAAA;IACnD,IAAI,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC,CAAC,oBAAoB;QAAE,OAAO,CAAC,CAAA;IAC/D,IAAI,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC,oBAAoB;QAAE,OAAO,CAAC,CAAC,CAAA;IAChE,IAAI,KAAK,GAAG,KAAK;QAAE,OAAO,CAAC,CAAA;IAC3B,IAAI,KAAK,GAAG,KAAK;QAAE,OAAO,CAAC,CAAC,CAAA;IAC5B,OAAO,CAAC,CAAA;AACV,CAAC","sourcesContent":["import { InfiniteData, UseSuspenseInfiniteQueryResult } from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { ApiCollection, ConversationResource } from '../types'\nimport { ConversationRequestArgs, getConversationsRequestArgs } from '../utils/request/conversation'\nimport { useSuspensePaginator } from './use_suspense_api'\n\nexport type ConversationPaginationResult = UseSuspenseInfiniteQueryResult<\n InfiniteData<ApiCollection<ConversationResource>, unknown>,\n Response\n>\n\nexport type UseConversationsValue = Pick<\n ConversationPaginationResult,\n | 'isFetching'\n | 'isError'\n | 'error'\n | 'fetchNextPage'\n | 'hasNextPage'\n | 'isFetched'\n | 'isRefetching'\n> & {\n conversations: ConversationResource[]\n refetch: () => Promise<any>\n}\n\nexport function useConversations(args?: Partial<ConversationRequestArgs>): UseConversationsValue {\n const requestArgs = getConversationsRequestArgs(args)\n const { data, ...rest } = useSuspensePaginator<ConversationResource>(requestArgs)\n\n const conversations = useMemo(() => data.sort(sortByLastMessage), [data])\n\n return { conversations, ...rest }\n}\n\nfunction sortByLastMessage(a: ConversationResource, b: ConversationResource): number {\n const dateA = a.lastMessageCreatedAt || a.createdAt\n const dateB = b.lastMessageCreatedAt || b.createdAt\n if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt) return 1\n if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt) return -1\n if (dateB > dateA) return 1\n if (dateB < dateA) return -1\n return 0\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations_screen.d.ts","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAC3E,OAAO,
|
|
1
|
+
{"version":3,"file":"conversations_screen.d.ts","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,MAAM,OAAO,CAAA;AAMzB,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAA;AAG9D,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAC,CAAA;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBAiBrE"}
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native';
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react';
|
|
3
3
|
import { StyleSheet, View } from 'react-native';
|
|
4
4
|
import { Conversations } from '../../components';
|
|
5
5
|
import { ActionButton } from '../../components/display/action_button';
|
|
6
|
+
import { ConversationsContextProvider } from '../../contexts/conversations_context';
|
|
6
7
|
import { useCanCreateConversations } from '../../hooks';
|
|
7
8
|
import { ListHeaderComponent } from './components/list_header_component';
|
|
8
9
|
export function ConversationsScreen({ route }) {
|
|
9
10
|
const navigation = useNavigation();
|
|
10
11
|
const canCreateConversations = useCanCreateConversations();
|
|
11
12
|
const styles = useStyles();
|
|
12
|
-
const { chat_group_graph_id, group_source_app_name } = route.params || {};
|
|
13
|
-
const filter = useMemo(() => {
|
|
14
|
-
if (chat_group_graph_id) {
|
|
15
|
-
return 'group';
|
|
16
|
-
}
|
|
17
|
-
else if (group_source_app_name) {
|
|
18
|
-
return 'group_source_app_name';
|
|
19
|
-
}
|
|
20
|
-
return 'mine_or_not_empty';
|
|
21
|
-
}, [chat_group_graph_id, group_source_app_name]);
|
|
22
13
|
return (<View style={styles.container}>
|
|
23
|
-
<
|
|
14
|
+
<ConversationsContextProvider args={route.params}>
|
|
15
|
+
<Conversations ListHeaderComponent={ListHeaderComponent}/>
|
|
16
|
+
</ConversationsContextProvider>
|
|
24
17
|
<ActionButton visible={canCreateConversations} title="New conversation" onPress={() => navigation.navigate('Create')}/>
|
|
25
18
|
</View>);
|
|
26
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations_screen.js","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"conversations_screen.js","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AACrE,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAA;AACnF,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AAQxE,MAAM,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAA2B;IACpE,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,sBAAsB,GAAG,yBAAyB,EAAE,CAAA;IAC1D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAC/C;QAAA,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,EAC1D;MAAA,EAAE,4BAA4B,CAC9B;MAAA,CAAC,YAAY,CACX,OAAO,CAAC,CAAC,sBAAsB,CAAC,CAChC,KAAK,CAAC,kBAAkB,CACxB,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAEjD;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;SACzB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Conversations } from '../../components'\nimport { ActionButton } from '../../components/display/action_button'\nimport { ConversationsContextProvider } from '../../contexts/conversations_context'\nimport { useCanCreateConversations } from '../../hooks'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { ListHeaderComponent } from './components/list_header_component'\n\nexport type ConversationScreenProps = StaticScreenProps<{\n title?: string\n chat_group_graph_id?: GraphId\n group_source_app_name?: string\n}>\n\nexport function ConversationsScreen({ route }: ConversationScreenProps) {\n const navigation = useNavigation()\n const canCreateConversations = useCanCreateConversations()\n const styles = useStyles()\n\n return (\n <View style={styles.container}>\n <ConversationsContextProvider args={route.params}>\n <Conversations ListHeaderComponent={ListHeaderComponent} />\n </ConversationsContextProvider>\n <ActionButton\n visible={canCreateConversations}\n title=\"New conversation\"\n onPress={() => navigation.navigate('Create')}\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n })\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.2.0-rc.
|
|
3
|
+
"version": "3.2.0-rc.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"prettier": "^3.4.2",
|
|
55
55
|
"typescript": "<5.6.0"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "ed621d6faf57a029b665e2f624d3860a58620002"
|
|
58
58
|
}
|
|
@@ -2,43 +2,33 @@ import { useNavigation } from '@react-navigation/native'
|
|
|
2
2
|
import { FlashList } from '@shopify/flash-list'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { StyleSheet, View } from 'react-native'
|
|
5
|
+
import { useConversationsContext } from '../../contexts/conversations_context'
|
|
5
6
|
import { useTheme } from '../../hooks'
|
|
6
|
-
import { useConversationsJoltEvents } from '../../hooks/use_conversation_jolt_events'
|
|
7
|
-
import { useConversations } from '../../hooks/use_conversations'
|
|
8
7
|
import { Text } from '../display'
|
|
9
|
-
import { ConversationRequestArgs } from '../../utils/request/conversation'
|
|
10
8
|
import { ConversationPreview } from './conversation_preview'
|
|
11
9
|
import { ConversationActionsProvider } from '../../contexts/swipeable_active_conversation'
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
chat_group_graph_id?: string
|
|
20
|
-
ListHeaderComponent?: ListHeaderComponent
|
|
11
|
+
interface ConversationsProps {
|
|
12
|
+
ListHeaderComponent?:
|
|
13
|
+
| React.ComponentType<any>
|
|
14
|
+
| React.ReactElement<any, string | React.JSXElementConstructor<any>>
|
|
15
|
+
| null
|
|
16
|
+
| undefined
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
export const Conversations = ({
|
|
24
|
-
ListHeaderComponent,
|
|
25
|
-
filter,
|
|
26
|
-
chat_group_graph_id,
|
|
27
|
-
gids,
|
|
28
|
-
group_source_app_name,
|
|
29
|
-
}: ConversationsProps) => {
|
|
19
|
+
export const Conversations = ({ ListHeaderComponent }: ConversationsProps) => {
|
|
30
20
|
const styles = useStyles()
|
|
31
21
|
|
|
32
|
-
const {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
const {
|
|
23
|
+
conversations,
|
|
24
|
+
fetchNextPage,
|
|
25
|
+
refetch,
|
|
26
|
+
isRefetching,
|
|
27
|
+
isFetched,
|
|
28
|
+
args: { chat_group_graph_id },
|
|
29
|
+
} = useConversationsContext()
|
|
38
30
|
const navigation = useNavigation()
|
|
39
31
|
|
|
40
|
-
useConversationsJoltEvents()
|
|
41
|
-
|
|
42
32
|
const showBadges = !chat_group_graph_id
|
|
43
33
|
|
|
44
34
|
return (
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, { createContext, PropsWithChildren, useContext, useMemo, useState } from 'react'
|
|
2
|
+
import { ConversationFiltersParams } from '../screens/conversation_filters/screen_props'
|
|
3
|
+
import { useConversations, UseConversationsValue } from '../hooks/use_conversations'
|
|
4
|
+
import {
|
|
5
|
+
FetchNextPageOptions,
|
|
6
|
+
InfiniteQueryObserverResult,
|
|
7
|
+
InfiniteData,
|
|
8
|
+
} from '@tanstack/react-query'
|
|
9
|
+
import { ApiCollection, ConversationResource } from '../types'
|
|
10
|
+
import { useConversationsJoltEvents } from '../hooks/use_conversation_jolt_events'
|
|
11
|
+
|
|
12
|
+
interface ConversationsContextValue extends UseConversationsValue {
|
|
13
|
+
activeConversationId?: number
|
|
14
|
+
setActiveConversationId: (_id: number) => void
|
|
15
|
+
args: ConversationFiltersParams
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const defaultQueryValue: UseConversationsValue = {
|
|
19
|
+
conversations: [],
|
|
20
|
+
refetch: () => Promise.resolve(null),
|
|
21
|
+
error: null,
|
|
22
|
+
isError: false,
|
|
23
|
+
fetchNextPage,
|
|
24
|
+
hasNextPage: false,
|
|
25
|
+
isFetching: false,
|
|
26
|
+
isFetched: false,
|
|
27
|
+
isRefetching: false,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const ConversationsContext = createContext<ConversationsContextValue>({
|
|
31
|
+
args: {},
|
|
32
|
+
activeConversationId: undefined,
|
|
33
|
+
setActiveConversationId: () => {},
|
|
34
|
+
...defaultQueryValue,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
export const ConversationsContextProvider = ({
|
|
38
|
+
children,
|
|
39
|
+
args,
|
|
40
|
+
}: PropsWithChildren<{ args: ConversationFiltersParams }>) => {
|
|
41
|
+
const [activeConversationId, setActiveConversationId] = useState<number | undefined>()
|
|
42
|
+
const { chat_group_graph_id, group_source_app_name } = args
|
|
43
|
+
|
|
44
|
+
const filter = useMemo(() => {
|
|
45
|
+
if (chat_group_graph_id) {
|
|
46
|
+
return 'group'
|
|
47
|
+
} else if (group_source_app_name) {
|
|
48
|
+
return 'group_source_app_name'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return 'mine_or_not_empty'
|
|
52
|
+
}, [chat_group_graph_id, group_source_app_name])
|
|
53
|
+
|
|
54
|
+
const query = useConversations({ group: chat_group_graph_id, group_source_app_name, filter })
|
|
55
|
+
|
|
56
|
+
const value = useMemo(
|
|
57
|
+
() => ({
|
|
58
|
+
args,
|
|
59
|
+
activeConversationId,
|
|
60
|
+
setActiveConversationId,
|
|
61
|
+
...query,
|
|
62
|
+
}),
|
|
63
|
+
[args, activeConversationId, query]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
useConversationsJoltEvents()
|
|
67
|
+
|
|
68
|
+
return <ConversationsContext.Provider value={value}>{children}</ConversationsContext.Provider>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function fetchNextPage(
|
|
72
|
+
_options?: FetchNextPageOptions
|
|
73
|
+
): Promise<
|
|
74
|
+
InfiniteQueryObserverResult<InfiniteData<ApiCollection<ConversationResource>, unknown>, Response>
|
|
75
|
+
> {
|
|
76
|
+
throw new Error('Function not implemented.')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const useConversationsContext = () => useContext(ConversationsContext)
|
|
@@ -1,25 +1,43 @@
|
|
|
1
|
+
import { InfiniteData, UseSuspenseInfiniteQueryResult } from '@tanstack/react-query'
|
|
1
2
|
import { useMemo } from 'react'
|
|
2
|
-
import { ConversationResource } from '../types'
|
|
3
|
-
import { useSuspensePaginator } from './use_suspense_api'
|
|
3
|
+
import { ApiCollection, ConversationResource } from '../types'
|
|
4
4
|
import { ConversationRequestArgs, getConversationsRequestArgs } from '../utils/request/conversation'
|
|
5
|
+
import { useSuspensePaginator } from './use_suspense_api'
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
+
export type ConversationPaginationResult = UseSuspenseInfiniteQueryResult<
|
|
8
|
+
InfiniteData<ApiCollection<ConversationResource>, unknown>,
|
|
9
|
+
Response
|
|
10
|
+
>
|
|
11
|
+
|
|
12
|
+
export type UseConversationsValue = Pick<
|
|
13
|
+
ConversationPaginationResult,
|
|
14
|
+
| 'isFetching'
|
|
15
|
+
| 'isError'
|
|
16
|
+
| 'error'
|
|
17
|
+
| 'fetchNextPage'
|
|
18
|
+
| 'hasNextPage'
|
|
19
|
+
| 'isFetched'
|
|
20
|
+
| 'isRefetching'
|
|
21
|
+
> & {
|
|
22
|
+
conversations: ConversationResource[]
|
|
23
|
+
refetch: () => Promise<any>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function useConversations(args?: Partial<ConversationRequestArgs>): UseConversationsValue {
|
|
7
27
|
const requestArgs = getConversationsRequestArgs(args)
|
|
8
28
|
const { data, ...rest } = useSuspensePaginator<ConversationResource>(requestArgs)
|
|
9
29
|
|
|
10
|
-
const conversations = useMemo(
|
|
11
|
-
() =>
|
|
12
|
-
data.sort((a, b) => {
|
|
13
|
-
const dateA = a.lastMessageCreatedAt || a.createdAt
|
|
14
|
-
const dateB = b.lastMessageCreatedAt || b.createdAt
|
|
15
|
-
if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt) return 1
|
|
16
|
-
if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt) return -1
|
|
17
|
-
if (dateB > dateA) return 1
|
|
18
|
-
if (dateB < dateA) return -1
|
|
19
|
-
return 0
|
|
20
|
-
}),
|
|
21
|
-
[data]
|
|
22
|
-
)
|
|
30
|
+
const conversations = useMemo(() => data.sort(sortByLastMessage), [data])
|
|
23
31
|
|
|
24
32
|
return { conversations, ...rest }
|
|
25
33
|
}
|
|
34
|
+
|
|
35
|
+
function sortByLastMessage(a: ConversationResource, b: ConversationResource): number {
|
|
36
|
+
const dateA = a.lastMessageCreatedAt || a.createdAt
|
|
37
|
+
const dateB = b.lastMessageCreatedAt || b.createdAt
|
|
38
|
+
if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt) return 1
|
|
39
|
+
if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt) return -1
|
|
40
|
+
if (dateB > dateA) return 1
|
|
41
|
+
if (dateB < dateA) return -1
|
|
42
|
+
return 0
|
|
43
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
|
|
2
|
-
import React
|
|
2
|
+
import React from 'react'
|
|
3
3
|
import { StyleSheet, View } from 'react-native'
|
|
4
4
|
import { Conversations } from '../../components'
|
|
5
5
|
import { ActionButton } from '../../components/display/action_button'
|
|
6
|
+
import { ConversationsContextProvider } from '../../contexts/conversations_context'
|
|
6
7
|
import { useCanCreateConversations } from '../../hooks'
|
|
7
8
|
import { GraphId } from '../../types/resources/group_resource'
|
|
8
9
|
import { ListHeaderComponent } from './components/list_header_component'
|
|
@@ -17,26 +18,12 @@ export function ConversationsScreen({ route }: ConversationScreenProps) {
|
|
|
17
18
|
const navigation = useNavigation()
|
|
18
19
|
const canCreateConversations = useCanCreateConversations()
|
|
19
20
|
const styles = useStyles()
|
|
20
|
-
const { chat_group_graph_id, group_source_app_name } = route.params || {}
|
|
21
|
-
|
|
22
|
-
const filter = useMemo(() => {
|
|
23
|
-
if (chat_group_graph_id) {
|
|
24
|
-
return 'group'
|
|
25
|
-
} else if (group_source_app_name) {
|
|
26
|
-
return 'group_source_app_name'
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return 'mine_or_not_empty'
|
|
30
|
-
}, [chat_group_graph_id, group_source_app_name])
|
|
31
21
|
|
|
32
22
|
return (
|
|
33
23
|
<View style={styles.container}>
|
|
34
|
-
<
|
|
35
|
-
ListHeaderComponent={ListHeaderComponent}
|
|
36
|
-
|
|
37
|
-
group_source_app_name={group_source_app_name}
|
|
38
|
-
filter={filter}
|
|
39
|
-
/>
|
|
24
|
+
<ConversationsContextProvider args={route.params}>
|
|
25
|
+
<Conversations ListHeaderComponent={ListHeaderComponent} />
|
|
26
|
+
</ConversationsContextProvider>
|
|
40
27
|
<ActionButton
|
|
41
28
|
visible={canCreateConversations}
|
|
42
29
|
title="New conversation"
|