@planningcenter/chat-react-native 3.35.0-rc.1 → 3.35.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/contexts/conversation_context.d.ts +6 -1
- package/build/contexts/conversation_context.d.ts.map +1 -1
- package/build/contexts/conversation_context.js +13 -3
- package/build/contexts/conversation_context.js.map +1 -1
- package/build/hooks/use_conversation_messages.d.ts +13 -6
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +56 -7
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_features.d.ts +1 -0
- package/build/hooks/use_features.d.ts.map +1 -1
- package/build/hooks/use_features.js +1 -0
- package/build/hooks/use_features.js.map +1 -1
- package/build/hooks/use_suspense_api.d.ts +1 -0
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +1 -1
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +1 -19
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +11 -100
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/utils/conversation_messages.d.ts +10 -0
- package/build/utils/conversation_messages.d.ts.map +1 -0
- package/build/utils/conversation_messages.js +22 -0
- package/build/utils/conversation_messages.js.map +1 -0
- package/build/utils/group_messages.d.ts +21 -0
- package/build/utils/group_messages.d.ts.map +1 -0
- package/build/utils/group_messages.js +123 -0
- package/build/utils/group_messages.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/hooks/use_conversation_messages.test.tsx +109 -0
- package/src/contexts/conversation_context.tsx +28 -2
- package/src/hooks/use_conversation_messages.ts +105 -21
- package/src/hooks/use_features.ts +1 -0
- package/src/hooks/use_suspense_api.ts +1 -1
- package/src/screens/conversation_screen.tsx +14 -131
- package/src/utils/__tests__/conversation_messages.test.ts +105 -0
- package/src/utils/__tests__/group_messages.test.ts +143 -0
- package/src/utils/conversation_messages.ts +37 -0
- package/src/utils/group_messages.ts +177 -0
- package/src/__tests__/hooks/use_conversation_messages.ts +0 -55
|
@@ -2,12 +2,17 @@ import React, { PropsWithChildren } from 'react';
|
|
|
2
2
|
interface ConversationContextValue {
|
|
3
3
|
conversationId: number;
|
|
4
4
|
currentPageReplyRootId: string | null;
|
|
5
|
+
initialMessageId: string | null;
|
|
6
|
+
setInitialMessageId: (id: string | null) => void;
|
|
7
|
+
initialMessageIdIsAnchor: boolean;
|
|
5
8
|
}
|
|
6
9
|
interface ConversationContextProviderProps extends PropsWithChildren {
|
|
7
10
|
conversationId: number;
|
|
8
11
|
currentPageReplyRootId: string | null;
|
|
12
|
+
initialMessageId?: string | null;
|
|
13
|
+
initialMessageIdIsAnchor?: boolean;
|
|
9
14
|
}
|
|
10
|
-
export declare const ConversationContextProvider: ({ children, conversationId, currentPageReplyRootId, }: ConversationContextProviderProps) => React.JSX.Element;
|
|
15
|
+
export declare const ConversationContextProvider: ({ children, conversationId, currentPageReplyRootId, initialMessageId: initialMessageIdProp, initialMessageIdIsAnchor, }: ConversationContextProviderProps) => React.JSX.Element;
|
|
11
16
|
export declare const useConversationContext: () => ConversationContextValue;
|
|
12
17
|
export {};
|
|
13
18
|
//# sourceMappingURL=conversation_context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_context.d.ts","sourceRoot":"","sources":["../../src/contexts/conversation_context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"conversation_context.d.ts","sourceRoot":"","sources":["../../src/contexts/conversation_context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAEZ,iBAAiB,EAKlB,MAAM,OAAO,CAAA;AAEd,UAAU,wBAAwB;IAChC,cAAc,EAAE,MAAM,CAAA;IACtB,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,wBAAwB,EAAE,OAAO,CAAA;CAClC;AAED,UAAU,gCAAiC,SAAQ,iBAAiB;IAClE,cAAc,EAAE,MAAM,CAAA;IACtB,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,wBAAwB,CAAC,EAAE,OAAO,CAAA;CACnC;AAUD,eAAO,MAAM,2BAA2B,GAAI,yHAMzC,gCAAgC,sBAmBlC,CAAA;AAED,eAAO,MAAM,sBAAsB,gCAAwC,CAAA"}
|
|
@@ -1,13 +1,23 @@
|
|
|
1
|
-
import React, { createContext, useContext, useMemo } from 'react';
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo, useState, } from 'react';
|
|
2
2
|
const ConversationContext = createContext({
|
|
3
3
|
conversationId: 0,
|
|
4
4
|
currentPageReplyRootId: null,
|
|
5
|
+
initialMessageId: null,
|
|
6
|
+
setInitialMessageId: () => { },
|
|
7
|
+
initialMessageIdIsAnchor: false,
|
|
5
8
|
});
|
|
6
|
-
export const ConversationContextProvider = ({ children, conversationId, currentPageReplyRootId, }) => {
|
|
9
|
+
export const ConversationContextProvider = ({ children, conversationId, currentPageReplyRootId, initialMessageId: initialMessageIdProp = null, initialMessageIdIsAnchor = false, }) => {
|
|
10
|
+
const [initialMessageId, setInitialMessageId] = useState(initialMessageIdProp);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
setInitialMessageId(initialMessageIdProp);
|
|
13
|
+
}, [initialMessageIdProp]);
|
|
7
14
|
const value = useMemo(() => ({
|
|
8
15
|
conversationId,
|
|
9
16
|
currentPageReplyRootId,
|
|
10
|
-
|
|
17
|
+
initialMessageId,
|
|
18
|
+
setInitialMessageId,
|
|
19
|
+
initialMessageIdIsAnchor,
|
|
20
|
+
}), [conversationId, currentPageReplyRootId, initialMessageId, initialMessageIdIsAnchor]);
|
|
11
21
|
return <ConversationContext.Provider value={value}>{children}</ConversationContext.Provider>;
|
|
12
22
|
};
|
|
13
23
|
export const useConversationContext = () => useContext(ConversationContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_context.js","sourceRoot":"","sources":["../../src/contexts/conversation_context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"conversation_context.js","sourceRoot":"","sources":["../../src/contexts/conversation_context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,aAAa,EAEb,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,GACT,MAAM,OAAO,CAAA;AAiBd,MAAM,mBAAmB,GAAG,aAAa,CAA2B;IAClE,cAAc,EAAE,CAAC;IACjB,sBAAsB,EAAE,IAAI;IAC5B,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,GAAG,EAAE,GAAE,CAAC;IAC7B,wBAAwB,EAAE,KAAK;CAChC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,EAC1C,QAAQ,EACR,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,EAC7C,wBAAwB,GAAG,KAAK,GACC,EAAE,EAAE;IACrC,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAA;IAE9E,SAAS,CAAC,GAAG,EAAE;QACb,mBAAmB,CAAC,oBAAoB,CAAC,CAAA;IAC3C,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAA;IAE1B,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,cAAc;QACd,sBAAsB;QACtB,gBAAgB;QAChB,mBAAmB;QACnB,wBAAwB;KACzB,CAAC,EACF,CAAC,cAAc,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,CACrF,CAAA;IAED,OAAO,CAAC,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;AAC9F,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAA","sourcesContent":["import React, {\n createContext,\n PropsWithChildren,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react'\n\ninterface ConversationContextValue {\n conversationId: number\n currentPageReplyRootId: string | null\n initialMessageId: string | null\n setInitialMessageId: (id: string | null) => void\n initialMessageIdIsAnchor: boolean\n}\n\ninterface ConversationContextProviderProps extends PropsWithChildren {\n conversationId: number\n currentPageReplyRootId: string | null\n initialMessageId?: string | null\n initialMessageIdIsAnchor?: boolean\n}\n\nconst ConversationContext = createContext<ConversationContextValue>({\n conversationId: 0,\n currentPageReplyRootId: null,\n initialMessageId: null,\n setInitialMessageId: () => {},\n initialMessageIdIsAnchor: false,\n})\n\nexport const ConversationContextProvider = ({\n children,\n conversationId,\n currentPageReplyRootId,\n initialMessageId: initialMessageIdProp = null,\n initialMessageIdIsAnchor = false,\n}: ConversationContextProviderProps) => {\n const [initialMessageId, setInitialMessageId] = useState(initialMessageIdProp)\n\n useEffect(() => {\n setInitialMessageId(initialMessageIdProp)\n }, [initialMessageIdProp])\n\n const value = useMemo(\n () => ({\n conversationId,\n currentPageReplyRootId,\n initialMessageId,\n setInitialMessageId,\n initialMessageIdIsAnchor,\n }),\n [conversationId, currentPageReplyRootId, initialMessageId, initialMessageIdIsAnchor]\n )\n\n return <ConversationContext.Provider value={value}>{children}</ConversationContext.Provider>\n}\n\nexport const useConversationContext = () => useContext(ConversationContext)\n"]}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { AnyUseSuspenseInfiniteQueryOptions, InfiniteData } from '@tanstack/react-query';
|
|
2
|
+
import { ApiCollection, MessageResource } from '../types';
|
|
3
|
+
import { MessagesPageParam } from '../utils/conversation_messages';
|
|
4
|
+
type Args = {
|
|
4
5
|
conversation_id: number;
|
|
5
6
|
reply_root_id?: string | null;
|
|
6
|
-
}
|
|
7
|
+
};
|
|
8
|
+
export type ConversationMessagesOptions = Omit<AnyUseSuspenseInfiniteQueryOptions, 'getNextPageParam' | 'getPreviousPageParam' | 'initialData' | 'initialPageParam' | 'queryFn' | 'queryKey'>;
|
|
9
|
+
export declare const useConversationMessages: ({ conversation_id, reply_root_id }: Args, opts?: ConversationMessagesOptions) => {
|
|
7
10
|
messages: MessageResource[];
|
|
8
|
-
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<
|
|
11
|
+
refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<InfiniteData<ApiCollection<MessageResource>, MessagesPageParam>, Response>>;
|
|
9
12
|
isRefetching: boolean;
|
|
10
|
-
|
|
13
|
+
fetchOlderMessages: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<InfiniteData<ApiCollection<MessageResource>, MessagesPageParam>, Response>>;
|
|
14
|
+
hasMoreOlderMessages: boolean;
|
|
15
|
+
fetchNewerMessages: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<InfiniteData<ApiCollection<MessageResource>, MessagesPageParam>, Response>>;
|
|
16
|
+
hasMoreNewerMessages: boolean;
|
|
11
17
|
queryKey: import("./use_suspense_api").RequestQueryKey;
|
|
12
18
|
};
|
|
19
|
+
export {};
|
|
13
20
|
//# sourceMappingURL=use_conversation_messages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_conversation_messages.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use_conversation_messages.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,YAAY,EAGb,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACzD,OAAO,EAEL,iBAAiB,EAIlB,MAAM,gCAAgC,CAAA;AAKvC,KAAK,IAAI,GAAG;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAEtE,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,kCAAkC,EAChC,kBAAkB,GAClB,sBAAsB,GACtB,aAAa,GACb,kBAAkB,GAClB,SAAS,GACT,UAAU,CACb,CAAA;AAED,eAAO,MAAM,uBAAuB,GAClC,oCAAoC,IAAI,EACxC,OAAO,2BAA2B;;;;;;;;;CA6EnC,CAAA"}
|
|
@@ -1,13 +1,62 @@
|
|
|
1
|
+
import { useSuspenseInfiniteQuery, useSuspenseQueries, } from '@tanstack/react-query';
|
|
1
2
|
import { useMemo } from 'react';
|
|
3
|
+
import { useConversationContext } from '../contexts/conversation_context';
|
|
4
|
+
import { anchoredSeedPageParams, newerPageParam, olderPageParam, sortAndFilterMessages, } from '../utils/conversation_messages';
|
|
2
5
|
import { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages';
|
|
3
|
-
import {
|
|
6
|
+
import { useApiClient } from './use_api_client';
|
|
7
|
+
import { throwResponseError } from './use_suspense_api';
|
|
4
8
|
export const useConversationMessages = ({ conversation_id, reply_root_id }, opts) => {
|
|
5
|
-
const
|
|
9
|
+
const apiClient = useApiClient();
|
|
10
|
+
const { initialMessageId } = useConversationContext();
|
|
11
|
+
const anchored = !reply_root_id && !!initialMessageId;
|
|
12
|
+
const requestArgs = getMessagesRequestArgs({ conversation_id, reply_root_id });
|
|
6
13
|
const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id });
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
const fetchPage = (pageParam) => {
|
|
15
|
+
const data = {
|
|
16
|
+
...requestArgs.data,
|
|
17
|
+
...(pageParam.where ? { where: pageParam.where } : {}),
|
|
18
|
+
...(pageParam.order ? { order: pageParam.order } : {}),
|
|
19
|
+
};
|
|
20
|
+
return apiClient.chat
|
|
21
|
+
.get({ url: requestArgs.url, data })
|
|
22
|
+
.catch(throwResponseError);
|
|
23
|
+
};
|
|
24
|
+
const seedPageParams = anchored ? anchoredSeedPageParams(initialMessageId) : [];
|
|
25
|
+
const seedQueries = useSuspenseQueries({
|
|
26
|
+
queries: seedPageParams.map((pageParam, index) => ({
|
|
27
|
+
queryKey: [...queryKey, 'seed', index],
|
|
28
|
+
queryFn: () => fetchPage(pageParam),
|
|
29
|
+
staleTime: Infinity,
|
|
30
|
+
gcTime: 0,
|
|
31
|
+
})),
|
|
32
|
+
});
|
|
33
|
+
const initialData = anchored
|
|
34
|
+
? {
|
|
35
|
+
pages: seedQueries.map(q => q.data),
|
|
36
|
+
pageParams: seedPageParams,
|
|
37
|
+
}
|
|
38
|
+
: undefined;
|
|
39
|
+
const initialPageParam = anchored ? seedPageParams[0] : {};
|
|
40
|
+
const { data, refetch, isRefetching, fetchNextPage, hasNextPage, fetchPreviousPage, hasPreviousPage, } = useSuspenseInfiniteQuery({
|
|
41
|
+
queryKey,
|
|
42
|
+
queryFn: ({ pageParam }) => fetchPage(pageParam),
|
|
43
|
+
initialPageParam,
|
|
44
|
+
initialData,
|
|
45
|
+
getNextPageParam: olderPageParam,
|
|
46
|
+
getPreviousPageParam: anchored ? newerPageParam : () => undefined,
|
|
47
|
+
...(opts || {}),
|
|
48
|
+
...(anchored ? { staleTime: Infinity, refetchOnMount: false } : {}),
|
|
49
|
+
});
|
|
50
|
+
const messages = useMemo(() => sortAndFilterMessages(data.pages), [data.pages]);
|
|
51
|
+
return {
|
|
52
|
+
messages,
|
|
53
|
+
refetch,
|
|
54
|
+
isRefetching,
|
|
55
|
+
fetchOlderMessages: fetchNextPage,
|
|
56
|
+
hasMoreOlderMessages: hasNextPage,
|
|
57
|
+
fetchNewerMessages: fetchPreviousPage,
|
|
58
|
+
hasMoreNewerMessages: hasPreviousPage,
|
|
59
|
+
queryKey,
|
|
60
|
+
};
|
|
12
61
|
};
|
|
13
62
|
//# sourceMappingURL=use_conversation_messages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_conversation_messages.js","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"use_conversation_messages.js","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AnyUseSuspenseInfiniteQueryOptions,\n InfiniteData,\n useSuspenseInfiniteQuery,\n useSuspenseQueries,\n} from '@tanstack/react-query'\nimport { useMemo } from 'react'\nimport { useConversationContext } from '../contexts/conversation_context'\nimport { ApiCollection, MessageResource } from '../types'\nimport {\n anchoredSeedPageParams,\n MessagesPageParam,\n newerPageParam,\n olderPageParam,\n sortAndFilterMessages,\n} from '../utils/conversation_messages'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'\nimport { useApiClient } from './use_api_client'\nimport { throwResponseError } from './use_suspense_api'\n\ntype Args = { conversation_id: number; reply_root_id?: string | null }\n\nexport type ConversationMessagesOptions = Omit<\n AnyUseSuspenseInfiniteQueryOptions,\n | 'getNextPageParam'\n | 'getPreviousPageParam'\n | 'initialData'\n | 'initialPageParam'\n | 'queryFn'\n | 'queryKey'\n>\n\nexport const useConversationMessages = (\n { conversation_id, reply_root_id }: Args,\n opts?: ConversationMessagesOptions\n) => {\n const apiClient = useApiClient()\n const { initialMessageId } = useConversationContext()\n const anchored = !reply_root_id && !!initialMessageId\n\n const requestArgs = getMessagesRequestArgs({ conversation_id, reply_root_id })\n const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id })\n\n const fetchPage = (pageParam: MessagesPageParam) => {\n const data = {\n ...requestArgs.data,\n ...(pageParam.where ? { where: pageParam.where } : {}),\n ...(pageParam.order ? { order: pageParam.order } : {}),\n }\n return apiClient.chat\n .get<ApiCollection<MessageResource>>({ url: requestArgs.url, data })\n .catch(throwResponseError)\n }\n\n const seedPageParams = anchored ? anchoredSeedPageParams(initialMessageId) : []\n const seedQueries = useSuspenseQueries({\n queries: seedPageParams.map((pageParam, index) => ({\n queryKey: [...queryKey, 'seed', index],\n queryFn: () => fetchPage(pageParam),\n staleTime: Infinity,\n gcTime: 0,\n })),\n })\n\n const initialData: InfiniteData<ApiCollection<MessageResource>, MessagesPageParam> | undefined =\n anchored\n ? {\n pages: seedQueries.map(q => q.data),\n pageParams: seedPageParams,\n }\n : undefined\n\n const initialPageParam: MessagesPageParam = anchored ? seedPageParams[0] : {}\n\n const {\n data,\n refetch,\n isRefetching,\n fetchNextPage,\n hasNextPage,\n fetchPreviousPage,\n hasPreviousPage,\n } = useSuspenseInfiniteQuery<\n ApiCollection<MessageResource>,\n Response,\n InfiniteData<ApiCollection<MessageResource>, MessagesPageParam>,\n typeof queryKey,\n MessagesPageParam\n >({\n queryKey,\n queryFn: ({ pageParam }) => fetchPage(pageParam),\n initialPageParam,\n initialData,\n getNextPageParam: olderPageParam,\n getPreviousPageParam: anchored ? newerPageParam : () => undefined,\n ...(opts || {}),\n ...(anchored ? { staleTime: Infinity, refetchOnMount: false } : {}),\n })\n\n const messages = useMemo(() => sortAndFilterMessages(data.pages), [data.pages])\n\n return {\n messages,\n refetch,\n isRefetching,\n fetchOlderMessages: fetchNextPage,\n hasMoreOlderMessages: hasNextPage,\n fetchNewerMessages: fetchPreviousPage,\n hasMoreNewerMessages: hasPreviousPage,\n queryKey,\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_features.d.ts","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAI1E,wBAAgB,WAAW;;kCAiBT,MAAM;EASvB;AAED,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"use_features.d.ts","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAI1E,wBAAgB,WAAW;;kCAiBT,MAAM;EASvB;AAED,eAAO,MAAM,iBAAiB;;;;;;CAM7B,CAAA"}
|
|
@@ -26,6 +26,7 @@ export const availableFeatures = {
|
|
|
26
26
|
message_reporting: 'ROLLOUT_MOBILE_message_reporting',
|
|
27
27
|
granular_notifications_ui: 'ROLLOUT_granular_notification_preferences_ui',
|
|
28
28
|
custom_conversation_avatars: 'ROLLOUT_custom_conversation_avatars',
|
|
29
|
+
jump_to_unread: 'ROLLOUT_jump_to_unread',
|
|
29
30
|
};
|
|
30
31
|
const stableEmptyFeatures = {
|
|
31
32
|
data: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_features.js","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C,MAAM,UAAU,WAAW;IACzB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAA;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC;QAChC,QAAQ,EAAE,mBAAmB,EAAE;QAC/B,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,SAAS,CAAC,IAAI;iBAClB,GAAG,CAAiC,WAAW,CAAC;iBAChD,KAAK,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,CAAA;QACrC,CAAC;QACD,SAAS,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,YAAY;KACvC,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAA;IAE1B,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,WAAmB,EAAE,EAAE,CACtB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,EAC3E,CAAC,QAAQ,CAAC,CACX,CAAA;IAED,OAAO;QACL,QAAQ;QACR,cAAc;KACf,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,6BAA6B,EAAE,uCAAuC;IACtE,iBAAiB,EAAE,kCAAkC;IACrD,yBAAyB,EAAE,8CAA8C;IACzE,2BAA2B,EAAE,qCAAqC;
|
|
1
|
+
{"version":3,"file":"use_features.js","sourceRoot":"","sources":["../../src/hooks/use_features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAGnC,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C,MAAM,UAAU,WAAW;IACzB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,WAAW,GAAG,sBAAsB,EAAE,CAAA;IAE5C,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC;QAChC,QAAQ,EAAE,mBAAmB,EAAE;QAC/B,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,SAAS,CAAC,IAAI;iBAClB,GAAG,CAAiC,WAAW,CAAC;iBAChD,KAAK,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,CAAA;QACrC,CAAC;QACD,SAAS,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,YAAY;KACvC,CAAC,CAAA;IAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAA;IAE1B,MAAM,cAAc,GAAG,WAAW,CAChC,CAAC,WAAmB,EAAE,EAAE,CACtB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,EAC3E,CAAC,QAAQ,CAAC,CACX,CAAA;IAED,OAAO;QACL,QAAQ;QACR,cAAc;KACf,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,6BAA6B,EAAE,uCAAuC;IACtE,iBAAiB,EAAE,kCAAkC;IACrD,yBAAyB,EAAE,8CAA8C;IACzE,2BAA2B,EAAE,qCAAqC;IAClE,cAAc,EAAE,wBAAwB;CACzC,CAAA;AAED,MAAM,mBAAmB,GAAmC;IAC1D,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,IAAI,EAAE;QACJ,KAAK,EAAE,CAAC;QACR,UAAU,EAAE,CAAC;KACd;CACF,CAAA","sourcesContent":["import { useSuspenseQuery } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport { ApiCollection } from '../types'\nimport type { FeatureResource } from '../types/resources/feature_resource'\nimport { getFeaturesRequestArgs, getFeaturesQueryKey } from '../utils/request/get_features'\nimport { useApiClient } from './use_api_client'\n\nexport function useFeatures() {\n const apiClient = useApiClient()\n const requestArgs = getFeaturesRequestArgs()\n\n const { data } = useSuspenseQuery({\n queryKey: getFeaturesQueryKey(),\n queryFn: () => {\n return apiClient.chat\n .get<ApiCollection<FeatureResource>>(requestArgs)\n .catch(() => stableEmptyFeatures)\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n })\n\n const features = data.data\n\n const featureEnabled = useCallback(\n (featureName: string) =>\n features.some(feature => feature.name === featureName && feature.enabled),\n [features]\n )\n\n return {\n features,\n featureEnabled,\n }\n}\n\nexport const availableFeatures = {\n gender_specific_conversations: 'ROLLOUT_gender_specific_conversations',\n message_reporting: 'ROLLOUT_MOBILE_message_reporting',\n granular_notifications_ui: 'ROLLOUT_granular_notification_preferences_ui',\n custom_conversation_avatars: 'ROLLOUT_custom_conversation_avatars',\n jump_to_unread: 'ROLLOUT_jump_to_unread',\n}\n\nconst stableEmptyFeatures: ApiCollection<FeatureResource> = {\n data: [],\n links: {},\n meta: {\n count: 0,\n totalCount: 0,\n },\n}\n"]}
|
|
@@ -70,6 +70,7 @@ export declare const useSuspensePaginator: <T extends ResourceObject>(args: Susp
|
|
|
70
70
|
isFetchPreviousPageError: boolean;
|
|
71
71
|
isFetchingPreviousPage: boolean;
|
|
72
72
|
};
|
|
73
|
+
export declare const throwResponseError: (error: unknown) => Promise<never>;
|
|
73
74
|
export type RequestQueryKey = [
|
|
74
75
|
SuspenseGetOptions['url'],
|
|
75
76
|
SuspenseGetOptions['data'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_suspense_api.d.ts","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,YAAY,EAGZ,uBAAuB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAA;AAGzD,OAAO,EAAE,GAAG,EAAgB,MAAM,kBAAkB,CAAA;AAEpD,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,IAAI,IAAI,CACrF,uBAAuB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,EACvD,UAAU,GAAG,SAAS,CACvB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,EACxE,MAAM,kBAAkB,EACxB,UAAU,uBAAuB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBrC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,kCAAkC,EAClC,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,GAAG,UAAU,CACjE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,cAAc,EAC3D,MAAM,kBAAkB,EACxB,OAAO,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChC,CAAA;
|
|
1
|
+
{"version":3,"file":"use_suspense_api.d.ts","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,YAAY,EAGZ,uBAAuB,EACxB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAA;AAGzD,OAAO,EAAE,GAAG,EAAgB,MAAM,kBAAkB,CAAA;AAEpD,UAAU,kBAAmB,SAAQ,UAAU;IAC7C,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,IAAI,IAAI,CACrF,uBAAuB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,EACvD,UAAU,GAAG,SAAS,CACvB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,EACxE,MAAM,kBAAkB,EACxB,UAAU,uBAAuB,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBrC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,kCAAkC,EAClC,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,GAAG,UAAU,CACjE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,cAAc,EAC3D,MAAM,kBAAkB,EACxB,OAAO,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChC,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,mBAMhD,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,kBAAkB,CAAC,KAAK,CAAC;IACzB,kBAAkB,CAAC,MAAM,CAAC;IAC1B,kBAAkB,CAAC,SAAS,CAAC;IAC7B,kBAAkB,CAAC,KAAK,CAAC;IACzB,kBAAkB,CAAC,eAAe,CAAC;CACpC,CAAA;AACD,eAAO,MAAM,kBAAkB,GAAI,MAAM,kBAAkB,KAAG,eAM7D,CAAA"}
|
|
@@ -44,7 +44,7 @@ export const useSuspensePaginator = (args, opts) => {
|
|
|
44
44
|
const totalCount = query.data?.pages[0]?.meta?.totalCount || data.length;
|
|
45
45
|
return { ...query, data, totalCount };
|
|
46
46
|
};
|
|
47
|
-
const throwResponseError = (error) => {
|
|
47
|
+
export const throwResponseError = (error) => {
|
|
48
48
|
if (error instanceof Response) {
|
|
49
49
|
throw new ResponseError(error);
|
|
50
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use_suspense_api.js","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"use_suspense_api.js","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AnyUseSuspenseInfiniteQueryOptions,\n InfiniteData,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n UseSuspenseQueryOptions,\n} from '@tanstack/react-query'\nimport { ApiCollection, ApiResource, ResourceObject } from '../types'\nimport { FailedResponse } from '../types/api_primitives'\nimport { Log } from '../utils'\nimport { GetRequest, RequestData } from '../utils/client'\nimport { ResponseError } from '../utils/response_error'\nimport { getNextPageParamFromMeta } from './paginator_meta'\nimport { App, useApiClient } from './use_api_client'\n\ninterface SuspenseGetOptions extends GetRequest {\n app?: App\n reply_root_id?: string | null\n}\n\nexport type SuspenseGetQueryOptions<T extends ResourceObject | ResourceObject[]> = Omit<\n UseSuspenseQueryOptions<ApiResource<T>, FailedResponse>,\n 'queryKey' | 'queryFn'\n>\n\nexport const useSuspenseGet = <T extends ResourceObject | ResourceObject[]>(\n args: SuspenseGetOptions,\n options?: SuspenseGetQueryOptions<T>\n) => {\n type Resource = ApiResource<T>\n const apiClient = useApiClient()\n\n const { data, ...query } = useSuspenseQuery<Resource, FailedResponse>({\n queryKey: getRequestQueryKey(args),\n queryFn: ({ queryKey }) => {\n const [url, d, headers, app = 'chat'] = queryKey as RequestQueryKey\n return apiClient[app]\n .get({ url, data: d, headers })\n .catch(throwResponseError) as Promise<Resource>\n },\n ...options,\n })\n\n return { ...data, ...query }\n}\n\nexport type SuspensePaginatorOptions = Omit<\n AnyUseSuspenseInfiniteQueryOptions,\n 'getNextPageParam' | 'initialPageParam' | 'queryFn' | 'queryKey'\n>\n\nexport const useSuspensePaginator = <T extends ResourceObject>(\n args: SuspenseGetOptions,\n opts?: SuspensePaginatorOptions\n) => {\n const apiClient = useApiClient()\n const query = useSuspenseInfiniteQuery<\n ApiCollection<T>,\n Response,\n InfiniteData<ApiCollection<T>>,\n any,\n Partial<RequestData> | undefined\n >({\n queryKey: getRequestQueryKey(args),\n queryFn: ({ pageParam }) => {\n Log.info('useSuspenseGet', { pageParam })\n\n const pageParmWhere = pageParam?.where || {}\n const argsWhere = args.data.where || {}\n const where = { ...argsWhere, ...pageParmWhere }\n const app = args.app || 'chat'\n const offset = pageParam?.offset || args.data.offset\n const data = { ...args.data, where, offset }\n\n return apiClient[app]\n .get<ApiCollection<T>>({\n url: args.url,\n data,\n })\n .catch(throwResponseError)\n },\n initialPageParam: {} as Partial<RequestData>,\n getNextPageParam: lastPage => getNextPageParamFromMeta(lastPage.meta?.next),\n ...(opts || {}),\n })\n\n const data: T[] = query.data?.pages.flatMap(page => page.data) || []\n const totalCount = query.data?.pages[0]?.meta?.totalCount || data.length\n\n return { ...query, data, totalCount }\n}\n\nexport const throwResponseError = (error: unknown) => {\n if (error instanceof Response) {\n throw new ResponseError(error as FailedResponse)\n }\n\n return Promise.reject(error)\n}\n\nexport type RequestQueryKey = [\n SuspenseGetOptions['url'],\n SuspenseGetOptions['data'],\n SuspenseGetOptions['headers'],\n SuspenseGetOptions['app'],\n SuspenseGetOptions['reply_root_id'],\n]\nexport const getRequestQueryKey = (args: SuspenseGetOptions): RequestQueryKey => [\n args.url,\n args.data,\n args.headers,\n args.app || 'chat',\n args.reply_root_id,\n]\n"]}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { HeaderTitleProps } from '@react-navigation/elements';
|
|
2
2
|
import { StaticScreenProps } from '@react-navigation/native';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { ReplyShadowMessage } from '../components/conversation/reply_shadow_message';
|
|
5
|
-
import { MessageResource } from '../types';
|
|
6
4
|
import { ConversationBadgeResource } from '../types/resources/conversation_badge';
|
|
7
5
|
export type ConversationRouteProps = {
|
|
8
6
|
conversation_id: number;
|
|
@@ -11,6 +9,7 @@ export type ConversationRouteProps = {
|
|
|
11
9
|
chat_group_graph_id?: string;
|
|
12
10
|
clear_input?: boolean;
|
|
13
11
|
editing_message_id?: number | null;
|
|
12
|
+
message_id?: string;
|
|
14
13
|
title?: string;
|
|
15
14
|
subtitle?: string;
|
|
16
15
|
badge?: ConversationBadgeResource;
|
|
@@ -19,23 +18,6 @@ export type ConversationRouteProps = {
|
|
|
19
18
|
};
|
|
20
19
|
export type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>;
|
|
21
20
|
export declare function ConversationScreen({ route }: ConversationScreenProps): React.JSX.Element;
|
|
22
|
-
export type DateSeparator = {
|
|
23
|
-
type: 'DateSeparator';
|
|
24
|
-
id: string;
|
|
25
|
-
date: string;
|
|
26
|
-
};
|
|
27
|
-
type ReplyShadowMessage = {
|
|
28
|
-
type: 'ReplyShadowMessage';
|
|
29
|
-
id: string;
|
|
30
|
-
messageId: string;
|
|
31
|
-
isReplyShadowMessage: boolean;
|
|
32
|
-
nextRendersAuthor: boolean;
|
|
33
|
-
};
|
|
34
|
-
interface GroupMessagesProps {
|
|
35
|
-
ms: MessageResource[];
|
|
36
|
-
inReplyScreen?: boolean;
|
|
37
|
-
}
|
|
38
|
-
export declare const groupMessages: ({ ms, inReplyScreen }: GroupMessagesProps) => (MessageResource | DateSeparator | ReplyShadowMessage)[];
|
|
39
21
|
interface ConversationScreenTitleProps extends HeaderTitleProps {
|
|
40
22
|
conversation_id: number;
|
|
41
23
|
badge?: ConversationBadgeResource;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAmD,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AA6BvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAMjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA0BpE;AAuMD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,eAAO,MAAM,uBAAuB,GAAI,8DAOrC,4BAA4B,sBAoC9B,CAAA"}
|
|
@@ -21,20 +21,26 @@ import { useConversation } from '../hooks/use_conversation';
|
|
|
21
21
|
import { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events';
|
|
22
22
|
import { useConversationMessages } from '../hooks/use_conversation_messages';
|
|
23
23
|
import { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events';
|
|
24
|
+
import { useFeatures } from '../hooks/use_features';
|
|
24
25
|
import { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read';
|
|
25
26
|
import { normalizeAnalyticsMetadata, usePublishProductAnalyticsEvent, } from '../hooks/use_product_analytics';
|
|
26
27
|
import { getRelativeDateStatus } from '../utils/date';
|
|
27
|
-
import
|
|
28
|
+
import { groupMessages } from '../utils/group_messages';
|
|
28
29
|
import { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles';
|
|
29
30
|
import { isSystemMessage } from '../utils/system_messages';
|
|
30
31
|
export function ConversationScreen({ route }) {
|
|
31
|
-
const { conversation_id, reply_root_id } = route.params;
|
|
32
|
+
const { conversation_id, message_id, reply_root_id } = route.params;
|
|
32
33
|
const { data: conversation } = useConversation({ conversation_id });
|
|
34
|
+
const { featureEnabled } = useFeatures();
|
|
33
35
|
usePublishProductAnalyticsEvent('chat.mobile.conversations.show.opened', {
|
|
34
36
|
reply_root_id,
|
|
35
37
|
...normalizeAnalyticsMetadata(conversation),
|
|
36
38
|
});
|
|
37
|
-
|
|
39
|
+
const lastReadMessageSortKey = conversation.conversationMembership?.lastReadMessageSortKey ?? null;
|
|
40
|
+
const jumpToUnreadAnchor = featureEnabled('jump_to_unread') ? lastReadMessageSortKey : null;
|
|
41
|
+
const initialMessageId = message_id ?? jumpToUnreadAnchor;
|
|
42
|
+
const initialMessageIdIsAnchor = !!initialMessageId && !message_id;
|
|
43
|
+
return (<ConversationContextProvider conversationId={conversation_id} currentPageReplyRootId={reply_root_id ?? null} initialMessageId={initialMessageId} initialMessageIdIsAnchor={initialMessageIdIsAnchor}>
|
|
38
44
|
<ConversationScreenContent route={route}/>
|
|
39
45
|
</ConversationContextProvider>);
|
|
40
46
|
}
|
|
@@ -43,7 +49,7 @@ function ConversationScreenContent({ route }) {
|
|
|
43
49
|
const navigation = useNavigation();
|
|
44
50
|
const { conversation_id, editing_message_id, reply_root_id, reply_root_author_name } = route.params;
|
|
45
51
|
const { data: conversation } = useConversation(route.params);
|
|
46
|
-
const { messages, refetch, isRefetching,
|
|
52
|
+
const { messages, refetch, isRefetching, fetchOlderMessages } = useConversationMessages({
|
|
47
53
|
conversation_id,
|
|
48
54
|
reply_root_id,
|
|
49
55
|
});
|
|
@@ -117,7 +123,7 @@ function ConversationScreenContent({ route }) {
|
|
|
117
123
|
return <SystemMessage message={item} conversationId={conversation_id}/>;
|
|
118
124
|
}
|
|
119
125
|
return (<Message {...item} canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages} conversation_id={conversation_id} latestReadMessageSortKey={conversation?.latestReadMessageSortKey} inReplyScreen={!!reply_root_id}/>);
|
|
120
|
-
}} onEndReached={() =>
|
|
126
|
+
}} onEndReached={() => fetchOlderMessages()} ListHeaderComponent={<View style={styles.listHeader}/>}/>)}
|
|
121
127
|
<JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton}/>
|
|
122
128
|
{!noMessages && <TypingIndicator />}
|
|
123
129
|
{showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}
|
|
@@ -168,101 +174,6 @@ const useDateSeparatorStyles = () => {
|
|
|
168
174
|
},
|
|
169
175
|
});
|
|
170
176
|
};
|
|
171
|
-
export const groupMessages = ({ ms, inReplyScreen }) => {
|
|
172
|
-
let enrichedMessages = [];
|
|
173
|
-
let encounteredOneOfMyMessages = false;
|
|
174
|
-
ms.forEach((message, i) => {
|
|
175
|
-
const prevMessage = ms[i + 1];
|
|
176
|
-
const nextMessage = ms[i - 1];
|
|
177
|
-
const date = dayjs(message.createdAt).format('YYYY-MM-DD');
|
|
178
|
-
const prevMessageIsDateSeparator = prevMessage && date !== dayjs(prevMessage.createdAt).format('YYYY-MM-DD');
|
|
179
|
-
if (isSystemMessage(message)) {
|
|
180
|
-
message.myLatestInConversation = false;
|
|
181
|
-
message.lastInGroup = true;
|
|
182
|
-
message.renderAuthor = false;
|
|
183
|
-
message.nextRendersAuthor = nextMessage?.renderAuthor;
|
|
184
|
-
message.isReplyShadowMessage = false;
|
|
185
|
-
message.nextIsReplyShadowMessage = false;
|
|
186
|
-
message.threadPosition = null;
|
|
187
|
-
enrichedMessages.push(message);
|
|
188
|
-
if (prevMessageIsDateSeparator) {
|
|
189
|
-
enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date });
|
|
190
|
-
}
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
const inThread = message.replyRootId !== null;
|
|
194
|
-
const nextMessageInThread = nextMessage?.replyRootId !== null;
|
|
195
|
-
const threadRoot = message.replyRootId === message.id;
|
|
196
|
-
const nextMessageThreadRoot = nextMessage?.replyRootId === nextMessage?.id;
|
|
197
|
-
const prevMessageDifferentThread = message.replyRootId !== prevMessage?.replyRootId;
|
|
198
|
-
const nextMessageDifferentThread = message.replyRootId !== nextMessage?.replyRootId;
|
|
199
|
-
const prevMessageDifferentAuthor = message.author?.id !== prevMessage?.author?.id;
|
|
200
|
-
const nextMessageDifferentAuthor = message.author?.id !== nextMessage?.author?.id;
|
|
201
|
-
const prevMessageMoreThan5Minutes = prevMessage &&
|
|
202
|
-
new Date(message.createdAt).getTime() - new Date(prevMessage.createdAt).getTime() > 60000 * 5;
|
|
203
|
-
const nextMessageMoreThan5Minutes = nextMessage &&
|
|
204
|
-
new Date(nextMessage.createdAt).getTime() - new Date(message.createdAt).getTime() > 60000 * 5;
|
|
205
|
-
const nextMessageIsDateSeparator = nextMessage && date !== dayjs(nextMessage.createdAt).format('YYYY-MM-DD');
|
|
206
|
-
const insertReplyShadowMessage = message.replyRootId &&
|
|
207
|
-
!threadRoot &&
|
|
208
|
-
(prevMessageDifferentThread || prevMessageIsDateSeparator);
|
|
209
|
-
const lastInGroup = !nextMessage ||
|
|
210
|
-
nextMessageDifferentAuthor ||
|
|
211
|
-
nextMessageMoreThan5Minutes ||
|
|
212
|
-
nextMessageDifferentThread ||
|
|
213
|
-
nextMessageIsDateSeparator;
|
|
214
|
-
const renderAuthor = !message.mine &&
|
|
215
|
-
(!prevMessage ||
|
|
216
|
-
prevMessageDifferentAuthor ||
|
|
217
|
-
prevMessageMoreThan5Minutes ||
|
|
218
|
-
prevMessageDifferentThread ||
|
|
219
|
-
prevMessageIsDateSeparator);
|
|
220
|
-
const nextIsReplyShadowMessage = nextMessageInThread &&
|
|
221
|
-
!nextMessageThreadRoot &&
|
|
222
|
-
(nextMessageDifferentThread || nextMessageIsDateSeparator);
|
|
223
|
-
if (message.mine && !encounteredOneOfMyMessages) {
|
|
224
|
-
encounteredOneOfMyMessages = true;
|
|
225
|
-
message.myLatestInConversation = true;
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
message.myLatestInConversation = false;
|
|
229
|
-
}
|
|
230
|
-
message.lastInGroup = lastInGroup;
|
|
231
|
-
message.renderAuthor = renderAuthor;
|
|
232
|
-
message.threadPosition = null;
|
|
233
|
-
message.nextRendersAuthor = nextMessage?.renderAuthor;
|
|
234
|
-
message.isReplyShadowMessage = false;
|
|
235
|
-
message.nextIsReplyShadowMessage = nextIsReplyShadowMessage;
|
|
236
|
-
if (!inReplyScreen && inThread) {
|
|
237
|
-
message.prevIsMyReply = prevMessage?.mine;
|
|
238
|
-
message.nextIsMyReply = nextMessage?.mine;
|
|
239
|
-
const firstInThread = threadRoot;
|
|
240
|
-
const lastInThread = nextMessageDifferentThread || nextMessageIsDateSeparator;
|
|
241
|
-
if (firstInThread && lastInThread)
|
|
242
|
-
message.threadPosition = null; // ensures we don't render a connector for root replies that aren't immediately followed up a reply
|
|
243
|
-
else if (firstInThread)
|
|
244
|
-
message.threadPosition = 'first';
|
|
245
|
-
else if (lastInThread)
|
|
246
|
-
message.threadPosition = 'last';
|
|
247
|
-
else
|
|
248
|
-
message.threadPosition = 'center';
|
|
249
|
-
}
|
|
250
|
-
enrichedMessages.push(message);
|
|
251
|
-
if (insertReplyShadowMessage) {
|
|
252
|
-
enrichedMessages.push({
|
|
253
|
-
type: 'ReplyShadowMessage',
|
|
254
|
-
id: `${message.id}-${message.replyRootId}`,
|
|
255
|
-
messageId: message.replyRootId,
|
|
256
|
-
isReplyShadowMessage: true,
|
|
257
|
-
nextRendersAuthor: message?.renderAuthor,
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
if (!prevMessage || date !== dayjs(prevMessage.createdAt).format('YYYY-MM-DD')) {
|
|
261
|
-
enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date });
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
return enrichedMessages;
|
|
265
|
-
};
|
|
266
177
|
export const ConversationScreenTitle = ({ conversation_id, badge, children, style, deleted, muted, }) => {
|
|
267
178
|
const styles = usePressableHeaderStyle();
|
|
268
179
|
const navigation = useNavigation();
|