@planningcenter/chat-react-native 4.2.1-qa-staging.5 → 4.2.1-rc.0
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/conversation/message_form.d.ts +1 -2
- package/build/components/conversation/message_form.d.ts.map +1 -1
- package/build/components/conversation/message_form.js +51 -54
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/components/conversation/message_list.d.ts +2 -3
- package/build/components/conversation/message_list.d.ts.map +1 -1
- package/build/components/conversation/message_list.js +66 -152
- package/build/components/conversation/message_list.js.map +1 -1
- package/build/contexts/api_provider.d.ts.map +1 -1
- package/build/contexts/api_provider.js +1 -2
- package/build/contexts/api_provider.js.map +1 -1
- package/build/contexts/conversation_context.d.ts +1 -3
- package/build/contexts/conversation_context.d.ts.map +1 -1
- package/build/contexts/conversation_context.js +18 -23
- package/build/contexts/conversation_context.js.map +1 -1
- package/build/hooks/index.d.ts +0 -1
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +0 -1
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/paginator_meta.d.ts +1 -3
- package/build/hooks/paginator_meta.d.ts.map +1 -1
- package/build/hooks/paginator_meta.js +8 -25
- package/build/hooks/paginator_meta.js.map +1 -1
- package/build/hooks/use_api.d.ts.map +1 -1
- package/build/hooks/use_api.js +8 -5
- package/build/hooks/use_api.js.map +1 -1
- package/build/hooks/use_conversation_messages.d.ts +2 -9
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +45 -84
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.d.ts +1 -17
- package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.js +80 -89
- package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
- package/build/hooks/use_mark_latest_message_read.d.ts +1 -2
- package/build/hooks/use_mark_latest_message_read.d.ts.map +1 -1
- package/build/hooks/use_mark_latest_message_read.js +3 -4
- package/build/hooks/use_mark_latest_message_read.js.map +1 -1
- package/build/hooks/use_message_create_or_update.d.ts.map +1 -1
- package/build/hooks/use_message_create_or_update.js +80 -91
- package/build/hooks/use_message_create_or_update.js.map +1 -1
- package/build/hooks/use_message_reaction_toggle.d.ts.map +1 -1
- package/build/hooks/use_message_reaction_toggle.js +40 -45
- package/build/hooks/use_message_reaction_toggle.js.map +1 -1
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +8 -5
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/screens/conversation_new/components/services_form.js +8 -9
- package/build/screens/conversation_new/components/services_form.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +0 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +254 -481
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts.map +1 -1
- package/build/screens/message_actions_screen.js +26 -21
- package/build/screens/message_actions_screen.js.map +1 -1
- package/build/screens/message_report_screen.d.ts.map +1 -1
- package/build/screens/message_report_screen.js +44 -17
- package/build/screens/message_report_screen.js.map +1 -1
- package/build/screens/reactions_screen.d.ts.map +1 -1
- package/build/screens/reactions_screen.js +88 -70
- package/build/screens/reactions_screen.js.map +1 -1
- package/build/types/api_primitives.d.ts +0 -2
- package/build/types/api_primitives.d.ts.map +1 -1
- package/build/types/api_primitives.js.map +1 -1
- package/build/types/resources/member.d.ts +0 -1
- package/build/types/resources/member.d.ts.map +1 -1
- package/build/types/resources/member.js.map +1 -1
- package/build/utils/cache/messages_cache.d.ts +0 -1
- package/build/utils/cache/messages_cache.d.ts.map +1 -1
- package/build/utils/cache/messages_cache.js +0 -3
- package/build/utils/cache/messages_cache.js.map +1 -1
- package/build/utils/cache/optimistically_update_message.d.ts +1 -2
- package/build/utils/cache/optimistically_update_message.d.ts.map +1 -1
- package/build/utils/cache/optimistically_update_message.js +4 -4
- package/build/utils/cache/optimistically_update_message.js.map +1 -1
- package/build/utils/client/types.d.ts +0 -1
- package/build/utils/client/types.d.ts.map +1 -1
- package/build/utils/client/types.js.map +1 -1
- package/build/utils/generate_placeholder_ulid.d.ts +6 -0
- package/build/utils/generate_placeholder_ulid.d.ts.map +1 -1
- package/build/utils/generate_placeholder_ulid.js +2 -2
- package/build/utils/generate_placeholder_ulid.js.map +1 -1
- package/build/utils/request/get_messages.d.ts +6 -18
- package/build/utils/request/get_messages.d.ts.map +1 -1
- package/build/utils/request/get_messages.js +12 -10
- package/build/utils/request/get_messages.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/hooks/paginator_meta.test.ts +2 -73
- package/src/components/conversation/__tests__/message_list.test.tsx +0 -42
- package/src/components/conversation/message_form.tsx +0 -3
- package/src/components/conversation/message_list.tsx +4 -58
- package/src/contexts/api_provider.tsx +1 -2
- package/src/contexts/conversation_context.tsx +1 -6
- package/src/hooks/index.ts +0 -1
- package/src/hooks/paginator_meta.ts +5 -29
- package/src/hooks/use_api.ts +5 -4
- package/src/hooks/use_conversation_messages.ts +11 -52
- package/src/hooks/use_conversation_messages_jolt_events.ts +43 -62
- package/src/hooks/use_mark_latest_message_read.ts +3 -4
- package/src/hooks/use_message_create_or_update.ts +8 -8
- package/src/hooks/use_message_reaction_toggle.ts +1 -3
- package/src/hooks/use_suspense_api.ts +5 -4
- package/src/screens/conversation_new/components/services_form.tsx +5 -5
- package/src/screens/conversation_screen.tsx +14 -123
- package/src/screens/message_actions_screen.tsx +5 -3
- package/src/screens/message_report_screen.tsx +3 -2
- package/src/screens/reactions_screen.tsx +4 -2
- package/src/types/api_primitives.ts +0 -2
- package/src/types/resources/member.ts +0 -1
- package/src/utils/cache/__tests__/messages_cache.test.ts +1 -14
- package/src/utils/cache/messages_cache.ts +0 -3
- package/src/utils/cache/optimistically_update_message.ts +5 -2
- package/src/utils/client/types.ts +0 -1
- package/src/utils/generate_placeholder_ulid.ts +2 -2
- package/src/utils/request/get_messages.ts +14 -12
- package/build/components/conversation/anchor_not_found_boundary.d.ts +0 -18
- package/build/components/conversation/anchor_not_found_boundary.d.ts.map +0 -1
- package/build/components/conversation/anchor_not_found_boundary.js +0 -20
- package/build/components/conversation/anchor_not_found_boundary.js.map +0 -1
- package/build/hooks/use_conversation_message_lookup.d.ts +0 -7
- package/build/hooks/use_conversation_message_lookup.d.ts.map +0 -1
- package/build/hooks/use_conversation_message_lookup.js +0 -52
- package/build/hooks/use_conversation_message_lookup.js.map +0 -1
- package/build/hooks/use_direct_message_eligibility.d.ts +0 -14
- package/build/hooks/use_direct_message_eligibility.d.ts.map +0 -1
- package/build/hooks/use_direct_message_eligibility.js +0 -87
- package/build/hooks/use_direct_message_eligibility.js.map +0 -1
- package/build/hooks/use_fetch_newer_messages.d.ts +0 -9
- package/build/hooks/use_fetch_newer_messages.d.ts.map +0 -1
- package/build/hooks/use_fetch_newer_messages.js +0 -69
- package/build/hooks/use_fetch_newer_messages.js.map +0 -1
- package/build/hooks/use_fetch_newer_on_foreground.d.ts +0 -8
- package/build/hooks/use_fetch_newer_on_foreground.d.ts.map +0 -1
- package/build/hooks/use_fetch_newer_on_foreground.js +0 -42
- package/build/hooks/use_fetch_newer_on_foreground.js.map +0 -1
- package/build/hooks/use_held_back_messages.d.ts +0 -11
- package/build/hooks/use_held_back_messages.d.ts.map +0 -1
- package/build/hooks/use_held_back_messages.js +0 -24
- package/build/hooks/use_held_back_messages.js.map +0 -1
- package/build/utils/cache/find_message_in_caches.d.ts +0 -4
- package/build/utils/cache/find_message_in_caches.d.ts.map +0 -1
- package/build/utils/cache/find_message_in_caches.js +0 -16
- package/build/utils/cache/find_message_in_caches.js.map +0 -1
- package/build/utils/cache/invalidate_refetchable_queries.d.ts +0 -3
- package/build/utils/cache/invalidate_refetchable_queries.d.ts.map +0 -1
- package/build/utils/cache/invalidate_refetchable_queries.js +0 -8
- package/build/utils/cache/invalidate_refetchable_queries.js.map +0 -1
- package/build/utils/cache/prepend_newer_page.d.ts +0 -7
- package/build/utils/cache/prepend_newer_page.d.ts.map +0 -1
- package/build/utils/cache/prepend_newer_page.js +0 -15
- package/build/utils/cache/prepend_newer_page.js.map +0 -1
- package/build/utils/gated_message_cache.d.ts +0 -7
- package/build/utils/gated_message_cache.d.ts.map +0 -1
- package/build/utils/gated_message_cache.js +0 -13
- package/build/utils/gated_message_cache.js.map +0 -1
- package/build/utils/ulid.d.ts +0 -3
- package/build/utils/ulid.d.ts.map +0 -1
- package/build/utils/ulid.js +0 -7
- package/build/utils/ulid.js.map +0 -1
- package/src/__tests__/hooks/use_conversation_messages.test.ts +0 -22
- package/src/__tests__/hooks/use_conversation_messages_jolt_events.test.ts +0 -33
- package/src/__tests__/hooks/use_direct_message_eligibility.test.tsx +0 -83
- package/src/__tests__/screens/conversation_new/components/services_form.test.tsx +0 -91
- package/src/__tests__/utils/gated_message_cache.test.ts +0 -26
- package/src/__tests__/utils/request/get_messages.test.ts +0 -24
- package/src/__tests__/utils/ulid.test.ts +0 -15
- package/src/components/conversation/__tests__/anchor_not_found_boundary.test.tsx +0 -51
- package/src/components/conversation/anchor_not_found_boundary.tsx +0 -21
- package/src/hooks/__tests__/use_fetch_newer_messages.test.tsx +0 -95
- package/src/hooks/__tests__/use_held_back_messages.test.tsx +0 -60
- package/src/hooks/__tests__/use_message_reaction_toggle.test.tsx +0 -73
- package/src/hooks/use_conversation_message_lookup.ts +0 -29
- package/src/hooks/use_direct_message_eligibility.ts +0 -40
- package/src/hooks/use_fetch_newer_messages.ts +0 -52
- package/src/hooks/use_fetch_newer_on_foreground.ts +0 -25
- package/src/hooks/use_held_back_messages.ts +0 -33
- package/src/utils/cache/__tests__/find_message_in_caches.test.ts +0 -37
- package/src/utils/cache/__tests__/invalidate_refetchable_queries.test.ts +0 -23
- package/src/utils/cache/__tests__/prepend_newer_page.test.ts +0 -34
- package/src/utils/cache/find_message_in_caches.ts +0 -20
- package/src/utils/cache/invalidate_refetchable_queries.ts +0 -9
- package/src/utils/cache/prepend_newer_page.ts +0 -19
- package/src/utils/gated_message_cache.ts +0 -19
- package/src/utils/ulid.ts +0 -11
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
-
export const useHeldBackMessages = ({
|
|
3
|
-
fetchNewer,
|
|
4
|
-
newestMessageId,
|
|
5
|
-
readingHistory,
|
|
6
|
-
caughtUp
|
|
7
|
-
}) => {
|
|
8
|
-
const heldBackSince = useRef(null);
|
|
9
|
-
const onSkippedNewMessage = useCallback(() => {
|
|
10
|
-
heldBackSince.current ??= newestMessageId ?? null;
|
|
11
|
-
}, [newestMessageId]);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const since = heldBackSince.current;
|
|
14
|
-
if (readingHistory || !caughtUp || !since) return;
|
|
15
|
-
heldBackSince.current = null;
|
|
16
|
-
fetchNewer(since).catch(() => {
|
|
17
|
-
heldBackSince.current ??= since;
|
|
18
|
-
});
|
|
19
|
-
}, [caughtUp, fetchNewer, readingHistory]);
|
|
20
|
-
return {
|
|
21
|
-
onSkippedNewMessage
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
//# sourceMappingURL=use_held_back_messages.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use_held_back_messages.js","names":["useCallback","useEffect","useRef","useHeldBackMessages","fetchNewer","newestMessageId","readingHistory","caughtUp","heldBackSince","onSkippedNewMessage","current","since","catch"],"sources":["../../src/hooks/use_held_back_messages.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\n\ntype Options = {\n fetchNewer: (newestMessageId: string) => Promise<void>\n newestMessageId?: string\n readingHistory: boolean\n caughtUp: boolean\n}\n\nexport const useHeldBackMessages = ({\n fetchNewer,\n newestMessageId,\n readingHistory,\n caughtUp,\n}: Options) => {\n const heldBackSince = useRef<string | null>(null)\n\n const onSkippedNewMessage = useCallback(() => {\n heldBackSince.current ??= newestMessageId ?? null\n }, [newestMessageId])\n\n useEffect(() => {\n const since = heldBackSince.current\n if (readingHistory || !caughtUp || !since) return\n\n heldBackSince.current = null\n fetchNewer(since).catch(() => {\n heldBackSince.current ??= since\n })\n }, [caughtUp, fetchNewer, readingHistory])\n\n return { onSkippedNewMessage }\n}\n"],"mappings":"AAAA,SAASA,WAAW,EAAEC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAStD,OAAO,MAAMC,mBAAmB,GAAGA,CAAC;EAClCC,UAAU;EACVC,eAAe;EACfC,cAAc;EACdC;AACO,CAAC,KAAK;EACb,MAAMC,aAAa,GAAGN,MAAM,CAAgB,IAAI,CAAC;EAEjD,MAAMO,mBAAmB,GAAGT,WAAW,CAAC,MAAM;IAC5CQ,aAAa,CAACE,OAAO,KAAKL,eAAe,IAAI,IAAI;EACnD,CAAC,EAAE,CAACA,eAAe,CAAC,CAAC;EAErBJ,SAAS,CAAC,MAAM;IACd,MAAMU,KAAK,GAAGH,aAAa,CAACE,OAAO;IACnC,IAAIJ,cAAc,IAAI,CAACC,QAAQ,IAAI,CAACI,KAAK,EAAE;IAE3CH,aAAa,CAACE,OAAO,GAAG,IAAI;IAC5BN,UAAU,CAACO,KAAK,CAAC,CAACC,KAAK,CAAC,MAAM;MAC5BJ,aAAa,CAACE,OAAO,KAAKC,KAAK;IACjC,CAAC,CAAC;EACJ,CAAC,EAAE,CAACJ,QAAQ,EAAEH,UAAU,EAAEE,cAAc,CAAC,CAAC;EAE1C,OAAO;IAAEG;EAAoB,CAAC;AAChC,CAAC","ignoreList":[]}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
-
import { MessageResource } from '../../types';
|
|
3
|
-
export declare const findMessageInCaches: (queryClient: QueryClient, conversation_id: number, message_id: string) => MessageResource | undefined;
|
|
4
|
-
//# sourceMappingURL=find_message_in_caches.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find_message_in_caches.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/find_message_in_caches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAiB,eAAe,EAAE,MAAM,aAAa,CAAA;AAK5D,eAAO,MAAM,mBAAmB,GAC9B,aAAa,WAAW,EACxB,iBAAiB,MAAM,EACvB,YAAY,MAAM,KACjB,eAAe,GAAG,SASpB,CAAA"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { getMessagesRequestArgs } from '../request/get_messages';
|
|
2
|
-
export const findMessageInCaches = (queryClient, conversation_id, message_id) => {
|
|
3
|
-
const {
|
|
4
|
-
url
|
|
5
|
-
} = getMessagesRequestArgs({
|
|
6
|
-
conversation_id
|
|
7
|
-
});
|
|
8
|
-
for (const [, data] of queryClient.getQueriesData({
|
|
9
|
-
queryKey: [url]
|
|
10
|
-
})) {
|
|
11
|
-
const found = data?.pages.flatMap(page => page.data).find(message => message.id === message_id);
|
|
12
|
-
if (found) return found;
|
|
13
|
-
}
|
|
14
|
-
return undefined;
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=find_message_in_caches.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find_message_in_caches.js","names":["getMessagesRequestArgs","findMessageInCaches","queryClient","conversation_id","message_id","url","data","getQueriesData","queryKey","found","pages","flatMap","page","find","message","id","undefined"],"sources":["../../../src/utils/cache/find_message_in_caches.ts"],"sourcesContent":["import { InfiniteData, QueryClient } from '@tanstack/react-query'\nimport { ApiCollection, MessageResource } from '../../types'\nimport { getMessagesRequestArgs } from '../request/get_messages'\n\ntype QueryData = InfiniteData<ApiCollection<MessageResource>>\n\nexport const findMessageInCaches = (\n queryClient: QueryClient,\n conversation_id: number,\n message_id: string\n): MessageResource | undefined => {\n const { url } = getMessagesRequestArgs({ conversation_id })\n\n for (const [, data] of queryClient.getQueriesData<QueryData>({ queryKey: [url] })) {\n const found = data?.pages.flatMap(page => page.data).find(message => message.id === message_id)\n if (found) return found\n }\n\n return undefined\n}\n"],"mappings":"AAEA,SAASA,sBAAsB,QAAQ,yBAAyB;AAIhE,OAAO,MAAMC,mBAAmB,GAAGA,CACjCC,WAAwB,EACxBC,eAAuB,EACvBC,UAAkB,KACc;EAChC,MAAM;IAAEC;EAAI,CAAC,GAAGL,sBAAsB,CAAC;IAAEG;EAAgB,CAAC,CAAC;EAE3D,KAAK,MAAM,GAAGG,IAAI,CAAC,IAAIJ,WAAW,CAACK,cAAc,CAAY;IAAEC,QAAQ,EAAE,CAACH,GAAG;EAAE,CAAC,CAAC,EAAE;IACjF,MAAMI,KAAK,GAAGH,IAAI,EAAEI,KAAK,CAACC,OAAO,CAACC,IAAI,IAAIA,IAAI,CAACN,IAAI,CAAC,CAACO,IAAI,CAACC,OAAO,IAAIA,OAAO,CAACC,EAAE,KAAKX,UAAU,CAAC;IAC/F,IAAIK,KAAK,EAAE,OAAOA,KAAK;EACzB;EAEA,OAAOO,SAAS;AAClB,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invalidate_refetchable_queries.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/invalidate_refetchable_queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAO1D,eAAO,MAAM,4BAA4B,GAAI,aAAa,WAAW,kBACoB,CAAA"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const isAnchoredMessagesWindow = query => {
|
|
2
|
-
const [, params] = query.queryKey;
|
|
3
|
-
return !!params?.where?.id_around;
|
|
4
|
-
};
|
|
5
|
-
export const invalidateRefetchableQueries = queryClient => queryClient.invalidateQueries({
|
|
6
|
-
predicate: query => !isAnchoredMessagesWindow(query)
|
|
7
|
-
});
|
|
8
|
-
//# sourceMappingURL=invalidate_refetchable_queries.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"invalidate_refetchable_queries.js","names":["isAnchoredMessagesWindow","query","params","queryKey","where","id_around","invalidateRefetchableQueries","queryClient","invalidateQueries","predicate"],"sources":["../../../src/utils/cache/invalidate_refetchable_queries.ts"],"sourcesContent":["import { Query, QueryClient } from '@tanstack/react-query'\n\nconst isAnchoredMessagesWindow = (query: Query) => {\n const [, params] = query.queryKey as [unknown, { where?: { id_around?: string } } | undefined]\n return !!params?.where?.id_around\n}\n\nexport const invalidateRefetchableQueries = (queryClient: QueryClient) =>\n queryClient.invalidateQueries({ predicate: query => !isAnchoredMessagesWindow(query) })\n"],"mappings":"AAEA,MAAMA,wBAAwB,GAAIC,KAAY,IAAK;EACjD,MAAM,GAAGC,MAAM,CAAC,GAAGD,KAAK,CAACE,QAAqE;EAC9F,OAAO,CAAC,CAACD,MAAM,EAAEE,KAAK,EAAEC,SAAS;AACnC,CAAC;AAED,OAAO,MAAMC,4BAA4B,GAAIC,WAAwB,IACnEA,WAAW,CAACC,iBAAiB,CAAC;EAAEC,SAAS,EAAER,KAAK,IAAI,CAACD,wBAAwB,CAACC,KAAK;AAAE,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { InfiniteData } from '@tanstack/react-query';
|
|
2
|
-
import { ApiCollection, ResourceObject } from '../../types';
|
|
3
|
-
import { RequestData } from '../client';
|
|
4
|
-
type PagesData<T extends ResourceObject> = InfiniteData<ApiCollection<T>, Partial<RequestData>>;
|
|
5
|
-
export declare function prependNewerPage<T extends ResourceObject>(data: PagesData<T> | undefined, pages: ApiCollection<T>[]): PagesData<T> | undefined;
|
|
6
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=prepend_newer_page.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prepend_newer_page.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/prepend_newer_page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAEvC,KAAK,SAAS,CAAC,CAAC,SAAS,cAAc,IAAI,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAA;AAE/F,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,cAAc,EACvD,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,EAC9B,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,GACxB,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAS1B"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export function prependNewerPage(data, pages) {
|
|
2
|
-
if (!data || data.pages.length === 0) return data;
|
|
3
|
-
const knownIds = new Set(data.pages.flatMap(page => page.data.map(record => record.id)));
|
|
4
|
-
const fresh = pages.flatMap(page => page.data).filter(record => !knownIds.has(record.id));
|
|
5
|
-
if (fresh.length === 0) return data;
|
|
6
|
-
const [first, ...rest] = data.pages;
|
|
7
|
-
return {
|
|
8
|
-
...data,
|
|
9
|
-
pages: [{
|
|
10
|
-
...first,
|
|
11
|
-
data: [...fresh, ...first.data]
|
|
12
|
-
}, ...rest]
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=prepend_newer_page.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prepend_newer_page.js","names":["prependNewerPage","data","pages","length","knownIds","Set","flatMap","page","map","record","id","fresh","filter","has","first","rest"],"sources":["../../../src/utils/cache/prepend_newer_page.ts"],"sourcesContent":["import { InfiniteData } from '@tanstack/react-query'\nimport { ApiCollection, ResourceObject } from '../../types'\nimport { RequestData } from '../client'\n\ntype PagesData<T extends ResourceObject> = InfiniteData<ApiCollection<T>, Partial<RequestData>>\n\nexport function prependNewerPage<T extends ResourceObject>(\n data: PagesData<T> | undefined,\n pages: ApiCollection<T>[]\n): PagesData<T> | undefined {\n if (!data || data.pages.length === 0) return data\n\n const knownIds = new Set(data.pages.flatMap(page => page.data.map(record => record.id)))\n const fresh = pages.flatMap(page => page.data).filter(record => !knownIds.has(record.id))\n if (fresh.length === 0) return data\n\n const [first, ...rest] = data.pages\n return { ...data, pages: [{ ...first, data: [...fresh, ...first.data] }, ...rest] }\n}\n"],"mappings":"AAMA,OAAO,SAASA,gBAAgBA,CAC9BC,IAA8B,EAC9BC,KAAyB,EACC;EAC1B,IAAI,CAACD,IAAI,IAAIA,IAAI,CAACC,KAAK,CAACC,MAAM,KAAK,CAAC,EAAE,OAAOF,IAAI;EAEjD,MAAMG,QAAQ,GAAG,IAAIC,GAAG,CAACJ,IAAI,CAACC,KAAK,CAACI,OAAO,CAACC,IAAI,IAAIA,IAAI,CAACN,IAAI,CAACO,GAAG,CAACC,MAAM,IAAIA,MAAM,CAACC,EAAE,CAAC,CAAC,CAAC;EACxF,MAAMC,KAAK,GAAGT,KAAK,CAACI,OAAO,CAACC,IAAI,IAAIA,IAAI,CAACN,IAAI,CAAC,CAACW,MAAM,CAACH,MAAM,IAAI,CAACL,QAAQ,CAACS,GAAG,CAACJ,MAAM,CAACC,EAAE,CAAC,CAAC;EACzF,IAAIC,KAAK,CAACR,MAAM,KAAK,CAAC,EAAE,OAAOF,IAAI;EAEnC,MAAM,CAACa,KAAK,EAAE,GAAGC,IAAI,CAAC,GAAGd,IAAI,CAACC,KAAK;EACnC,OAAO;IAAE,GAAGD,IAAI;IAAEC,KAAK,EAAE,CAAC;MAAE,GAAGY,KAAK;MAAEb,IAAI,EAAE,CAAC,GAAGU,KAAK,EAAE,GAAGG,KAAK,CAACb,IAAI;IAAE,CAAC,EAAE,GAAGc,IAAI;EAAE,CAAC;AACrF","ignoreList":[]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { MessagesCache } from '../hooks/use_conversation_messages_jolt_events';
|
|
2
|
-
export declare const gatedMessageCache: ({ queryKey, acceptNewMessages, onSkippedNewMessage, }: {
|
|
3
|
-
queryKey: unknown[];
|
|
4
|
-
acceptNewMessages: boolean;
|
|
5
|
-
onSkippedNewMessage?: () => void;
|
|
6
|
-
}) => MessagesCache;
|
|
7
|
-
//# sourceMappingURL=gated_message_cache.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gated_message_cache.d.ts","sourceRoot":"","sources":["../../src/utils/gated_message_cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAEnF,eAAO,MAAM,iBAAiB,GAAI,uDAI/B;IACD,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAA;CACjC,KAAG,aAQF,CAAA"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const gatedMessageCache = ({
|
|
2
|
-
queryKey,
|
|
3
|
-
acceptNewMessages,
|
|
4
|
-
onSkippedNewMessage
|
|
5
|
-
}) => ({
|
|
6
|
-
queryKey,
|
|
7
|
-
canUpdate: event => {
|
|
8
|
-
if (event !== 'message.created' || acceptNewMessages) return true;
|
|
9
|
-
onSkippedNewMessage?.();
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=gated_message_cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gated_message_cache.js","names":["gatedMessageCache","queryKey","acceptNewMessages","onSkippedNewMessage","canUpdate","event"],"sources":["../../src/utils/gated_message_cache.ts"],"sourcesContent":["import type { MessagesCache } from '../hooks/use_conversation_messages_jolt_events'\n\nexport const gatedMessageCache = ({\n queryKey,\n acceptNewMessages,\n onSkippedNewMessage,\n}: {\n queryKey: unknown[]\n acceptNewMessages: boolean\n onSkippedNewMessage?: () => void\n}): MessagesCache => ({\n queryKey,\n canUpdate: event => {\n if (event !== 'message.created' || acceptNewMessages) return true\n\n onSkippedNewMessage?.()\n return false\n },\n})\n"],"mappings":"AAEA,OAAO,MAAMA,iBAAiB,GAAGA,CAAC;EAChCC,QAAQ;EACRC,iBAAiB;EACjBC;AAKF,CAAC,MAAqB;EACpBF,QAAQ;EACRG,SAAS,EAAEC,KAAK,IAAI;IAClB,IAAIA,KAAK,KAAK,iBAAiB,IAAIH,iBAAiB,EAAE,OAAO,IAAI;IAEjEC,mBAAmB,GAAG,CAAC;IACvB,OAAO,KAAK;EACd;AACF,CAAC,CAAC","ignoreList":[]}
|
package/build/utils/ulid.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ulid.d.ts","sourceRoot":"","sources":["../../src/utils/ulid.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,qCAAqC,CAAA;AAI5D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMnD"}
|
package/build/utils/ulid.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export const ULID_CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; // Crockford's Base32
|
|
2
|
-
|
|
3
|
-
const TIME_LENGTH = 10;
|
|
4
|
-
export function decodeUlidTime(ulid) {
|
|
5
|
-
return ulid.slice(0, TIME_LENGTH).toUpperCase().split('').reduce((time, char) => time * 32 + ULID_CHARS.indexOf(char), 0);
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=ulid.js.map
|
package/build/utils/ulid.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ulid.js","names":["ULID_CHARS","TIME_LENGTH","decodeUlidTime","ulid","slice","toUpperCase","split","reduce","time","char","indexOf"],"sources":["../../src/utils/ulid.ts"],"sourcesContent":["export const ULID_CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' // Crockford's Base32\n\nconst TIME_LENGTH = 10\n\nexport function decodeUlidTime(ulid: string): number {\n return ulid\n .slice(0, TIME_LENGTH)\n .toUpperCase()\n .split('')\n .reduce((time, char) => time * 32 + ULID_CHARS.indexOf(char), 0)\n}\n"],"mappings":"AAAA,OAAO,MAAMA,UAAU,GAAG,kCAAkC,EAAC;;AAE7D,MAAMC,WAAW,GAAG,EAAE;AAEtB,OAAO,SAASC,cAAcA,CAACC,IAAY,EAAU;EACnD,OAAOA,IAAI,CACRC,KAAK,CAAC,CAAC,EAAEH,WAAW,CAAC,CACrBI,WAAW,CAAC,CAAC,CACbC,KAAK,CAAC,EAAE,CAAC,CACTC,MAAM,CAAC,CAACC,IAAI,EAAEC,IAAI,KAAKD,IAAI,GAAG,EAAE,GAAGR,UAAU,CAACU,OAAO,CAACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACpE","ignoreList":[]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { anchoredRetry } from '../../hooks/use_conversation_messages'
|
|
2
|
-
import { FailedResponse } from '../../types/api_primitives'
|
|
3
|
-
import { ResponseError } from '../../utils/response_error'
|
|
4
|
-
|
|
5
|
-
const responseError = (status: number) =>
|
|
6
|
-
new ResponseError({ status, statusText: 'nope' } as unknown as FailedResponse)
|
|
7
|
-
|
|
8
|
-
describe('anchoredRetry', () => {
|
|
9
|
-
it('gives up straight away on a missing anchor', () => {
|
|
10
|
-
expect(anchoredRetry(0, responseError(404))).toBe(false)
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('does not hammer a rate limit', () => {
|
|
14
|
-
expect(anchoredRetry(0, responseError(429))).toBe(false)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('retries other failures a few times', () => {
|
|
18
|
-
expect(anchoredRetry(0, responseError(500))).toBe(true)
|
|
19
|
-
expect(anchoredRetry(2, new Error('network'))).toBe(true)
|
|
20
|
-
expect(anchoredRetry(3, responseError(500))).toBe(false)
|
|
21
|
-
})
|
|
22
|
-
})
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { queryKeysForEvent } from '../../hooks/use_conversation_messages_jolt_events'
|
|
2
|
-
|
|
3
|
-
const cache = { queryKey: ['shown'] }
|
|
4
|
-
const gated = { queryKey: ['shown'], canUpdate: (e: string) => e !== 'message.created' }
|
|
5
|
-
const topLevel = { sort_key: '01M', reply_root_id: null }
|
|
6
|
-
const replyInThread = { sort_key: '01R', reply_root_id: '01ROOT' }
|
|
7
|
-
const replyElsewhere = { sort_key: '01S', reply_root_id: '01OTHER' }
|
|
8
|
-
const theRoot = { sort_key: '01ROOT', reply_root_id: '01ROOT' }
|
|
9
|
-
|
|
10
|
-
describe('queryKeysForEvent', () => {
|
|
11
|
-
it('writes every message event to the conversation view', () => {
|
|
12
|
-
const view = { replyRootId: null, cache }
|
|
13
|
-
|
|
14
|
-
expect(queryKeysForEvent('message.created', view, topLevel)).toEqual([['shown']])
|
|
15
|
-
expect(queryKeysForEvent('message.created', view, replyInThread)).toEqual([['shown']])
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('writes only this thread and its root to a reply view', () => {
|
|
19
|
-
const view = { replyRootId: '01ROOT', cache }
|
|
20
|
-
|
|
21
|
-
expect(queryKeysForEvent('message.created', view, replyInThread)).toEqual([['shown']])
|
|
22
|
-
expect(queryKeysForEvent('message.updated', view, theRoot)).toEqual([['shown']])
|
|
23
|
-
expect(queryKeysForEvent('message.created', view, topLevel)).toEqual([])
|
|
24
|
-
expect(queryKeysForEvent('message.created', view, replyElsewhere)).toEqual([])
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('honors the gate on the shown cache', () => {
|
|
28
|
-
const view = { replyRootId: null, cache: gated }
|
|
29
|
-
|
|
30
|
-
expect(queryKeysForEvent('message.created', view, topLevel)).toEqual([])
|
|
31
|
-
expect(queryKeysForEvent('reaction', view, topLevel)).toEqual([['shown']])
|
|
32
|
-
})
|
|
33
|
-
})
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
-
import { renderHook, waitFor } from '@testing-library/react-native'
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
|
-
import { useApiClient } from '../../hooks/use_api_client'
|
|
6
|
-
import { useDirectMessageEligibility } from '../../hooks/use_direct_message_eligibility'
|
|
7
|
-
|
|
8
|
-
jest.mock('../../hooks/use_api_client')
|
|
9
|
-
|
|
10
|
-
const mockedUseApiClient = useApiClient as jest.MockedFunction<typeof useApiClient>
|
|
11
|
-
const mockGet = jest.fn()
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
mockGet.mockReset()
|
|
15
|
-
mockedUseApiClient.mockReturnValue({ chat: { get: mockGet } } as any)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
const createWrapper = () => {
|
|
19
|
-
const queryClient = buildTestQueryClient()
|
|
20
|
-
return ({ children }: { children: React.ReactNode }) => (
|
|
21
|
-
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const args = { groupId: 'Groups-Group-42', personId: 75179873 }
|
|
26
|
-
|
|
27
|
-
test("reads the member's eligibility from the chat group", async () => {
|
|
28
|
-
mockGet.mockResolvedValue({
|
|
29
|
-
data: {
|
|
30
|
-
id: '75179873',
|
|
31
|
-
type: 'Member',
|
|
32
|
-
canDirectMessage: false,
|
|
33
|
-
directMessagesDisabled: true,
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const { result } = renderHook(() => useDirectMessageEligibility(args), {
|
|
38
|
-
wrapper: createWrapper(),
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
await waitFor(() => expect(result.current.eligibility).toBeDefined())
|
|
42
|
-
|
|
43
|
-
expect(mockGet).toHaveBeenCalledWith({
|
|
44
|
-
url: '/me/groups/Groups-Group-42/members/75179873',
|
|
45
|
-
data: { fields: { Member: ['can_direct_message', 'direct_messages_disabled'] } },
|
|
46
|
-
})
|
|
47
|
-
expect(result.current.eligibility).toEqual({
|
|
48
|
-
canDirectMessage: false,
|
|
49
|
-
directMessagesDisabled: true,
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
test('has no answer until the member loads', () => {
|
|
54
|
-
mockGet.mockReturnValue(new Promise(() => {}))
|
|
55
|
-
|
|
56
|
-
const { result } = renderHook(() => useDirectMessageEligibility(args), {
|
|
57
|
-
wrapper: createWrapper(),
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
expect(result.current.eligibility).toBeUndefined()
|
|
61
|
-
expect(result.current.isLoading).toBe(true)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
test('reports a failed lookup without an answer', async () => {
|
|
65
|
-
mockGet.mockRejectedValue(new Error('404'))
|
|
66
|
-
|
|
67
|
-
const { result } = renderHook(() => useDirectMessageEligibility(args), {
|
|
68
|
-
wrapper: createWrapper(),
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
await waitFor(() => expect(result.current.isError).toBe(true))
|
|
72
|
-
|
|
73
|
-
expect(result.current.eligibility).toBeUndefined()
|
|
74
|
-
expect(result.current.isLoading).toBe(false)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
test('does not ask when disabled', () => {
|
|
78
|
-
renderHook(() => useDirectMessageEligibility({ ...args, enabled: false }), {
|
|
79
|
-
wrapper: createWrapper(),
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
expect(mockGet).not.toHaveBeenCalled()
|
|
83
|
-
})
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { DefaultTheme, ThemeProvider } from '@react-navigation/native'
|
|
2
|
-
import { render } from '@testing-library/react-native'
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
|
5
|
-
import { useFindOrCreateServicesConversation } from '../../../../hooks/services/use_find_or_create_services_conversation'
|
|
6
|
-
import { useTeamMembersForNewConversation } from '../../../../hooks/services/use_team_members_for_new_conversation'
|
|
7
|
-
import { ServicesForm } from '../../../../screens/conversation_new/components/services_form'
|
|
8
|
-
|
|
9
|
-
jest.mock('react-native-reanimated', () => ({
|
|
10
|
-
...jest.requireActual('react-native-reanimated/mock'),
|
|
11
|
-
LayoutAnimationConfig: ({ children }: { children: React.ReactNode }) => children,
|
|
12
|
-
}))
|
|
13
|
-
jest.mock('@react-navigation/native', () => ({
|
|
14
|
-
...jest.requireActual('@react-navigation/native'),
|
|
15
|
-
useNavigation: () => ({ navigate: jest.fn(), dispatch: jest.fn(), getParent: () => undefined }),
|
|
16
|
-
}))
|
|
17
|
-
jest.mock('../../../../hooks/use_api_client', () => ({ useApiClient: () => ({}) }))
|
|
18
|
-
jest.mock('../../../../hooks/use_upload_client', () => ({ useUploadClient: () => ({}) }))
|
|
19
|
-
jest.mock('../../../../hooks/use_features', () => ({
|
|
20
|
-
...jest.requireActual('../../../../hooks/use_features'),
|
|
21
|
-
useFeatures: () => ({ features: [], featureEnabled: () => false }),
|
|
22
|
-
}))
|
|
23
|
-
jest.mock('../../../../hooks/use_conversation_validate', () => ({
|
|
24
|
-
useConversationValidate: () => ({ warnings: [], validationPending: false }),
|
|
25
|
-
}))
|
|
26
|
-
jest.mock('../../../../hooks/services/use_services_chat_conversation_payload', () => ({
|
|
27
|
-
useServicesChatConversationPayload: () => ({ payload: undefined, isLoading: false }),
|
|
28
|
-
}))
|
|
29
|
-
jest.mock('../../../../hooks/services/use_services_team', () => ({
|
|
30
|
-
useServicesTeams: () => [],
|
|
31
|
-
}))
|
|
32
|
-
jest.mock('../../../../hooks/services/use_team_plans', () => ({
|
|
33
|
-
useTeamPlans: () => ({
|
|
34
|
-
planOptions: [],
|
|
35
|
-
isFetching: false,
|
|
36
|
-
isError: false,
|
|
37
|
-
findPlan: () => undefined,
|
|
38
|
-
}),
|
|
39
|
-
}))
|
|
40
|
-
jest.mock('../../../../hooks/services/use_team_members_for_new_conversation', () => ({
|
|
41
|
-
useTeamMembersForNewConversation: jest.fn(() => ({ members: [], isError: false })),
|
|
42
|
-
}))
|
|
43
|
-
jest.mock('../../../../hooks/services/use_find_or_create_services_conversation', () => ({
|
|
44
|
-
useFindOrCreateServicesConversation: jest.fn(() => ({
|
|
45
|
-
mutate: jest.fn(),
|
|
46
|
-
isPending: false,
|
|
47
|
-
selectionHasConversation: false,
|
|
48
|
-
isLoadingConversationCheck: false,
|
|
49
|
-
})),
|
|
50
|
-
}))
|
|
51
|
-
|
|
52
|
-
const mockedFindOrCreate = jest.mocked(useFindOrCreateServicesConversation)
|
|
53
|
-
const mockedTeamMembers = jest.mocked(useTeamMembersForNewConversation)
|
|
54
|
-
|
|
55
|
-
const latestArgs = <T extends jest.Mock>(mock: T) => mock.mock.calls.at(-1)?.[0]
|
|
56
|
-
|
|
57
|
-
const safeAreaMetrics = {
|
|
58
|
-
frame: { x: 0, y: 0, width: 390, height: 844 },
|
|
59
|
-
insets: { top: 0, right: 0, bottom: 0, left: 0 },
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const renderForm = (props: { initialPlanId?: number } = {}) =>
|
|
63
|
-
render(
|
|
64
|
-
<SafeAreaProvider initialMetrics={safeAreaMetrics}>
|
|
65
|
-
<ThemeProvider value={DefaultTheme}>
|
|
66
|
-
<ServicesForm initialTeamIds={[1, 2]} {...props} />
|
|
67
|
-
</ThemeProvider>
|
|
68
|
-
</SafeAreaProvider>
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
describe('ServicesForm', () => {
|
|
72
|
-
beforeEach(() => {
|
|
73
|
-
jest.clearAllMocks()
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('filters by plan when opened from a plan', () => {
|
|
77
|
-
const { getByRole } = renderForm({ initialPlanId: 42 })
|
|
78
|
-
|
|
79
|
-
expect(getByRole('switch').props.value).toBe(true)
|
|
80
|
-
expect(latestArgs(mockedFindOrCreate)).toMatchObject({ teamIds: [1, 2], planId: 42 })
|
|
81
|
-
expect(latestArgs(mockedTeamMembers)).toMatchObject({ teamIds: [1, 2], planId: 42 })
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('does not filter by plan when opened without a plan', () => {
|
|
85
|
-
const { getByRole } = renderForm()
|
|
86
|
-
|
|
87
|
-
expect(getByRole('switch').props.value).toBe(false)
|
|
88
|
-
expect(latestArgs(mockedFindOrCreate)).toMatchObject({ teamIds: [1, 2], planId: undefined })
|
|
89
|
-
expect(latestArgs(mockedTeamMembers)).toMatchObject({ teamIds: [1, 2], planId: undefined })
|
|
90
|
-
})
|
|
91
|
-
})
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { gatedMessageCache } from '../../utils/gated_message_cache'
|
|
2
|
-
|
|
3
|
-
describe('gatedMessageCache', () => {
|
|
4
|
-
const queryKey = ['messages']
|
|
5
|
-
|
|
6
|
-
it('keeps new messages out while they are not accepted and reports the skip', () => {
|
|
7
|
-
const onSkippedNewMessage = jest.fn()
|
|
8
|
-
const cache = gatedMessageCache({ queryKey, acceptNewMessages: false, onSkippedNewMessage })
|
|
9
|
-
|
|
10
|
-
expect(cache.queryKey).toBe(queryKey)
|
|
11
|
-
expect(cache.canUpdate?.('message.created')).toBe(false)
|
|
12
|
-
expect(onSkippedNewMessage).toHaveBeenCalledTimes(1)
|
|
13
|
-
expect(cache.canUpdate?.('message.updated')).toBe(true)
|
|
14
|
-
expect(cache.canUpdate?.('message.destroyed')).toBe(true)
|
|
15
|
-
expect(cache.canUpdate?.('reaction')).toBe(true)
|
|
16
|
-
expect(onSkippedNewMessage).toHaveBeenCalledTimes(1)
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('lets new messages in once they are accepted', () => {
|
|
20
|
-
const onSkippedNewMessage = jest.fn()
|
|
21
|
-
const cache = gatedMessageCache({ queryKey, acceptNewMessages: true, onSkippedNewMessage })
|
|
22
|
-
|
|
23
|
-
expect(cache.canUpdate?.('message.created')).toBe(true)
|
|
24
|
-
expect(onSkippedNewMessage).not.toHaveBeenCalled()
|
|
25
|
-
})
|
|
26
|
-
})
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { getMessagesQueryKey, getMessagesRequestArgs } from '../../../utils/request/get_messages'
|
|
2
|
-
|
|
3
|
-
describe('getMessagesRequestArgs', () => {
|
|
4
|
-
it('requests the newest page by default', () => {
|
|
5
|
-
const { data } = getMessagesRequestArgs({ conversation_id: 1 })
|
|
6
|
-
|
|
7
|
-
expect(data).not.toHaveProperty('where')
|
|
8
|
-
expect(data).not.toHaveProperty('order')
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
it('opens around the anchor when one is given', () => {
|
|
12
|
-
const { data } = getMessagesRequestArgs({ conversation_id: 1, anchor: '01ANCHOR' })
|
|
13
|
-
|
|
14
|
-
expect(data).toMatchObject({ where: { id_around: '01ANCHOR' } })
|
|
15
|
-
expect(data).not.toHaveProperty('order')
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('keeps anchored and live queries in separate cache entries', () => {
|
|
19
|
-
const live = getMessagesQueryKey({ conversation_id: 1 })
|
|
20
|
-
const anchored = getMessagesQueryKey({ conversation_id: 1, anchor: '01ANCHOR' })
|
|
21
|
-
|
|
22
|
-
expect(anchored).not.toEqual(live)
|
|
23
|
-
})
|
|
24
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { generatePlaceholderUlid } from '../../utils/generate_placeholder_ulid'
|
|
2
|
-
import { decodeUlidTime } from '../../utils/ulid'
|
|
3
|
-
|
|
4
|
-
describe('decodeUlidTime', () => {
|
|
5
|
-
it('decodes the spec example', () => {
|
|
6
|
-
expect(decodeUlidTime('01ARYZ6S41TSV4RRFFQ69G5FAV')).toBe(1469918176385)
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
it('round-trips a placeholder ulid', () => {
|
|
10
|
-
const now = Date.now()
|
|
11
|
-
jest.spyOn(Date, 'now').mockReturnValue(now)
|
|
12
|
-
|
|
13
|
-
expect(decodeUlidTime(generatePlaceholderUlid())).toBe(now)
|
|
14
|
-
})
|
|
15
|
-
})
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/react-native'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { Text } from 'react-native'
|
|
4
|
-
import { FailedResponse } from '../../../types/api_primitives'
|
|
5
|
-
import { ResponseError } from '../../../utils/response_error'
|
|
6
|
-
import { AnchorNotFoundBoundary } from '../anchor_not_found_boundary'
|
|
7
|
-
|
|
8
|
-
const responseError = (status: number) =>
|
|
9
|
-
new ResponseError({ status, statusText: 'nope' } as unknown as FailedResponse)
|
|
10
|
-
|
|
11
|
-
function Thrower({ error }: { error: Error | null }) {
|
|
12
|
-
if (error) throw error
|
|
13
|
-
return <Text>content</Text>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
describe('AnchorNotFoundBoundary', () => {
|
|
17
|
-
beforeEach(() => jest.spyOn(console, 'error').mockImplementation(() => {}))
|
|
18
|
-
|
|
19
|
-
it('reports a missing anchor and renders nothing while the parent drops it', () => {
|
|
20
|
-
const onAnchorNotFound = jest.fn()
|
|
21
|
-
|
|
22
|
-
render(
|
|
23
|
-
<AnchorNotFoundBoundary onAnchorNotFound={onAnchorNotFound}>
|
|
24
|
-
<Thrower error={responseError(404)} />
|
|
25
|
-
</AnchorNotFoundBoundary>
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
expect(onAnchorNotFound).toHaveBeenCalledTimes(1)
|
|
29
|
-
expect(screen.queryByText('content')).toBeNull()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('lets every other error through untouched', () => {
|
|
33
|
-
const onAnchorNotFound = jest.fn()
|
|
34
|
-
|
|
35
|
-
expect(() =>
|
|
36
|
-
render(
|
|
37
|
-
<AnchorNotFoundBoundary onAnchorNotFound={onAnchorNotFound}>
|
|
38
|
-
<Thrower error={responseError(403)} />
|
|
39
|
-
</AnchorNotFoundBoundary>
|
|
40
|
-
)
|
|
41
|
-
).toThrow()
|
|
42
|
-
expect(() =>
|
|
43
|
-
render(
|
|
44
|
-
<AnchorNotFoundBoundary onAnchorNotFound={onAnchorNotFound}>
|
|
45
|
-
<Thrower error={new Error('render blew up')} />
|
|
46
|
-
</AnchorNotFoundBoundary>
|
|
47
|
-
)
|
|
48
|
-
).toThrow('render blew up')
|
|
49
|
-
expect(onAnchorNotFound).not.toHaveBeenCalled()
|
|
50
|
-
})
|
|
51
|
-
})
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React, { PropsWithChildren } from 'react'
|
|
2
|
-
import { ResponseError } from '../../utils/response_error'
|
|
3
|
-
|
|
4
|
-
type Props = PropsWithChildren<{ onAnchorNotFound: () => void }>
|
|
5
|
-
|
|
6
|
-
export class AnchorNotFoundBoundary extends React.Component<Props, { recovering: boolean }> {
|
|
7
|
-
state = { recovering: false }
|
|
8
|
-
|
|
9
|
-
static getDerivedStateFromError(error: Error) {
|
|
10
|
-
if (error instanceof ResponseError && error.status === 404) return { recovering: true }
|
|
11
|
-
throw error
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
componentDidCatch() {
|
|
15
|
-
this.props.onAnchorNotFound()
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
render() {
|
|
19
|
-
return this.state.recovering ? null : this.props.children
|
|
20
|
-
}
|
|
21
|
-
}
|