@planningcenter/chat-react-native 4.2.1-qa-staging.2 → 4.2.1-qa-staging.4
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.map +1 -1
- package/build/components/conversation/message_form.js +1 -1
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/contexts/conversation_context.d.ts +3 -1
- package/build/contexts/conversation_context.d.ts.map +1 -1
- package/build/contexts/conversation_context.js +23 -18
- package/build/contexts/conversation_context.js.map +1 -1
- package/build/hooks/use_conversation_message_lookup.d.ts +7 -0
- package/build/hooks/use_conversation_message_lookup.d.ts.map +1 -0
- package/build/hooks/use_conversation_message_lookup.js +52 -0
- package/build/hooks/use_conversation_message_lookup.js.map +1 -0
- package/build/hooks/use_conversation_messages.d.ts +1 -0
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +8 -1
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.d.ts +12 -4
- package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.js +82 -88
- package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
- package/build/hooks/use_fetch_newer_messages.d.ts.map +1 -1
- package/build/hooks/use_fetch_newer_messages.js +27 -21
- package/build/hooks/use_fetch_newer_messages.js.map +1 -1
- package/build/hooks/use_fetch_newer_on_foreground.d.ts +1 -1
- package/build/hooks/use_fetch_newer_on_foreground.d.ts.map +1 -1
- package/build/hooks/use_fetch_newer_on_foreground.js +2 -1
- package/build/hooks/use_fetch_newer_on_foreground.js.map +1 -1
- package/build/hooks/use_held_back_messages.d.ts +11 -0
- package/build/hooks/use_held_back_messages.d.ts.map +1 -0
- package/build/hooks/use_held_back_messages.js +24 -0
- package/build/hooks/use_held_back_messages.js.map +1 -0
- package/build/hooks/use_message_create_or_update.d.ts.map +1 -1
- package/build/hooks/use_message_create_or_update.js +91 -80
- 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 +45 -40
- package/build/hooks/use_message_reaction_toggle.js.map +1 -1
- package/build/screens/conversation_new/components/services_form.js.map +1 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +495 -157
- 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 +21 -26
- 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 +17 -44
- 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 +70 -88
- package/build/screens/reactions_screen.js.map +1 -1
- package/build/utils/cache/find_message_in_caches.d.ts +4 -0
- package/build/utils/cache/find_message_in_caches.d.ts.map +1 -0
- package/build/utils/cache/find_message_in_caches.js +16 -0
- package/build/utils/cache/find_message_in_caches.js.map +1 -0
- package/build/utils/cache/messages_cache.d.ts +1 -0
- package/build/utils/cache/messages_cache.d.ts.map +1 -1
- package/build/utils/cache/messages_cache.js +3 -0
- package/build/utils/cache/messages_cache.js.map +1 -1
- package/build/utils/cache/optimistically_update_message.d.ts +2 -1
- 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/cache/prepend_newer_page.d.ts +1 -1
- package/build/utils/cache/prepend_newer_page.d.ts.map +1 -1
- package/build/utils/cache/prepend_newer_page.js +10 -9
- package/build/utils/cache/prepend_newer_page.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/hooks/use_conversation_messages.test.ts +22 -0
- package/src/__tests__/hooks/use_conversation_messages_jolt_events.test.ts +22 -25
- package/src/components/conversation/message_form.tsx +1 -2
- package/src/contexts/conversation_context.tsx +6 -1
- package/src/hooks/__tests__/use_fetch_newer_messages.test.tsx +68 -0
- package/src/hooks/__tests__/use_held_back_messages.test.tsx +60 -0
- package/src/hooks/__tests__/use_message_reaction_toggle.test.tsx +73 -0
- package/src/hooks/use_conversation_message_lookup.ts +29 -0
- package/src/hooks/use_conversation_messages.ts +9 -0
- package/src/hooks/use_conversation_messages_jolt_events.ts +43 -41
- package/src/hooks/use_fetch_newer_messages.ts +19 -12
- package/src/hooks/use_fetch_newer_on_foreground.ts +2 -2
- package/src/hooks/use_held_back_messages.ts +33 -0
- package/src/hooks/use_message_create_or_update.ts +8 -8
- package/src/hooks/use_message_reaction_toggle.ts +3 -1
- package/src/screens/conversation_new/components/services_form.tsx +1 -1
- package/src/screens/conversation_screen.tsx +21 -20
- package/src/screens/message_actions_screen.tsx +3 -5
- package/src/screens/message_report_screen.tsx +2 -3
- package/src/screens/reactions_screen.tsx +2 -4
- package/src/utils/cache/__tests__/find_message_in_caches.test.ts +37 -0
- package/src/utils/cache/__tests__/messages_cache.test.ts +14 -1
- package/src/utils/cache/__tests__/prepend_newer_page.test.ts +13 -14
- package/src/utils/cache/find_message_in_caches.ts +20 -0
- package/src/utils/cache/messages_cache.ts +3 -0
- package/src/utils/cache/optimistically_update_message.ts +2 -5
- package/src/utils/cache/prepend_newer_page.ts +7 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimistically_update_message.js","names":["chatQueryClient","getMessagesQueryKey","updateOrCreateRecordInPagesData","optimisticallyUpdateMessage","conversationId","message","text","replyRootId","queryKey","conversation_id","reply_root_id","optimisticMessage","setQueryData","data","record","processRecord","next","prev","pending"],"sources":["../../../src/utils/cache/optimistically_update_message.ts"],"sourcesContent":["import { InfiniteData } from '@tanstack/react-query'\nimport { chatQueryClient } from '../../contexts/api_provider'\nimport { ApiCollection, MessageResource } from '../../types'\nimport { getMessagesQueryKey } from '../../utils/request/get_messages'\nimport { updateOrCreateRecordInPagesData } from './page_mutations'\n\nexport function optimisticallyUpdateMessage({\n conversationId,\n message,\n text,\n replyRootId,\n}: {\n conversationId: number\n message: MessageResource\n text: string\n replyRootId?: string | null\n}) {\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n\n
|
|
1
|
+
{"version":3,"file":"optimistically_update_message.js","names":["chatQueryClient","getMessagesQueryKey","updateOrCreateRecordInPagesData","optimisticallyUpdateMessage","conversationId","message","text","replyRootId","queryKey","conversation_id","reply_root_id","optimisticMessage","setQueryData","data","record","processRecord","next","prev","pending"],"sources":["../../../src/utils/cache/optimistically_update_message.ts"],"sourcesContent":["import { InfiniteData } from '@tanstack/react-query'\nimport { chatQueryClient } from '../../contexts/api_provider'\nimport { ApiCollection, MessageResource } from '../../types'\nimport { getMessagesQueryKey } from '../../utils/request/get_messages'\nimport { updateOrCreateRecordInPagesData } from './page_mutations'\n\nexport function optimisticallyUpdateMessage({\n conversationId,\n message,\n text,\n replyRootId,\n queryKey = getMessagesQueryKey({ conversation_id: conversationId, reply_root_id: replyRootId }),\n}: {\n conversationId: number\n message: MessageResource\n text: string\n replyRootId?: string | null\n queryKey?: unknown[]\n}) {\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n\n let optimisticMessage = message\n\n chatQueryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: message,\n processRecord: (next, prev) => {\n optimisticMessage = {\n ...(prev || next),\n text,\n pending: true,\n }\n return optimisticMessage\n },\n })\n )\n\n return optimisticMessage\n}\n"],"mappings":"AACA,SAASA,eAAe,QAAQ,6BAA6B;AAE7D,SAASC,mBAAmB,QAAQ,kCAAkC;AACtE,SAASC,+BAA+B,QAAQ,kBAAkB;AAElE,OAAO,SAASC,2BAA2BA,CAAC;EAC1CC,cAAc;EACdC,OAAO;EACPC,IAAI;EACJC,WAAW;EACXC,QAAQ,GAAGP,mBAAmB,CAAC;IAAEQ,eAAe,EAAEL,cAAc;IAAEM,aAAa,EAAEH;EAAY,CAAC;AAOhG,CAAC,EAAE;EAGD,IAAII,iBAAiB,GAAGN,OAAO;EAE/BL,eAAe,CAACY,YAAY,CAAYJ,QAAQ,EAAEK,IAAI,IACpDX,+BAA+B,CAAC;IAC9BW,IAAI;IACJC,MAAM,EAAET,OAAO;IACfU,aAAa,EAAEA,CAACC,IAAI,EAAEC,IAAI,KAAK;MAC7BN,iBAAiB,GAAG;QAClB,IAAIM,IAAI,IAAID,IAAI,CAAC;QACjBV,IAAI;QACJY,OAAO,EAAE;MACX,CAAC;MACD,OAAOP,iBAAiB;IAC1B;EACF,CAAC,CACH,CAAC;EAED,OAAOA,iBAAiB;AAC1B","ignoreList":[]}
|
|
@@ -2,6 +2,6 @@ import { InfiniteData } from '@tanstack/react-query';
|
|
|
2
2
|
import { ApiCollection, ResourceObject } from '../../types';
|
|
3
3
|
import { RequestData } from '../client';
|
|
4
4
|
type PagesData<T extends ResourceObject> = InfiniteData<ApiCollection<T>, Partial<RequestData>>;
|
|
5
|
-
export declare function prependNewerPage<T extends ResourceObject>(data: PagesData<T> | undefined,
|
|
5
|
+
export declare function prependNewerPage<T extends ResourceObject>(data: PagesData<T> | undefined, pages: ApiCollection<T>[]): PagesData<T> | undefined;
|
|
6
6
|
export {};
|
|
7
7
|
//# sourceMappingURL=prepend_newer_page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,14 +1,15 @@
|
|
|
1
|
-
export function prependNewerPage(data,
|
|
2
|
-
if (!data) return data;
|
|
3
|
-
const knownIds = new Set(data.pages.flatMap(
|
|
4
|
-
const fresh = page.data.filter(record => !knownIds.has(record.id));
|
|
5
|
-
if (fresh.length === 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;
|
|
6
7
|
return {
|
|
8
|
+
...data,
|
|
7
9
|
pages: [{
|
|
8
|
-
...
|
|
9
|
-
data: fresh
|
|
10
|
-
}, ...
|
|
11
|
-
pageParams: [pageParam, ...data.pageParams]
|
|
10
|
+
...first,
|
|
11
|
+
data: [...fresh, ...first.data]
|
|
12
|
+
}, ...rest]
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=prepend_newer_page.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepend_newer_page.js","names":["prependNewerPage","data","
|
|
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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "4.2.1-qa-staging.
|
|
3
|
+
"version": "4.2.1-qa-staging.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
|
35
35
|
"@fortawesome/react-native-fontawesome": "^0.3.2",
|
|
36
|
-
"@planningcenter/emoji-keyboard": "4.2.1-qa-staging.
|
|
36
|
+
"@planningcenter/emoji-keyboard": "4.2.1-qa-staging.4",
|
|
37
37
|
"lodash-inflection": "^1.5.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"sf-symbols-typescript": "^2.2.0",
|
|
85
85
|
"typescript": "~6.0.3"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "1afcd60f0a1a2840897f18200201b71fe4c18b0f"
|
|
88
88
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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,36 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
queryKeysForEvent,
|
|
3
|
-
resolveMessageCaches,
|
|
4
|
-
} from '../../hooks/use_conversation_messages_jolt_events'
|
|
1
|
+
import { queryKeysForEvent } from '../../hooks/use_conversation_messages_jolt_events'
|
|
5
2
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
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' }
|
|
8
9
|
|
|
9
|
-
describe('
|
|
10
|
-
it('
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
expect(resolveMessageCaches([main, threaded], [gate])).toEqual([gate, { queryKey: threaded }])
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('appends caches that are not among the defaults', () => {
|
|
17
|
-
const extra = { queryKey: ['anchored'] }
|
|
10
|
+
describe('queryKeysForEvent', () => {
|
|
11
|
+
it('writes every message event to the conversation view', () => {
|
|
12
|
+
const view = { replyRootId: null, cache }
|
|
18
13
|
|
|
19
|
-
expect(
|
|
14
|
+
expect(queryKeysForEvent('message.created', view, topLevel)).toEqual([['shown']])
|
|
15
|
+
expect(queryKeysForEvent('message.created', view, replyInThread)).toEqual([['shown']])
|
|
20
16
|
})
|
|
21
|
-
})
|
|
22
17
|
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
it('writes only this thread and its root to a reply view', () => {
|
|
19
|
+
const view = { replyRootId: '01ROOT', cache }
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
expect(queryKeysForEvent('message.updated',
|
|
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([])
|
|
28
25
|
})
|
|
29
26
|
|
|
30
|
-
it('
|
|
31
|
-
const
|
|
27
|
+
it('honors the gate on the shown cache', () => {
|
|
28
|
+
const view = { replyRootId: null, cache: gated }
|
|
32
29
|
|
|
33
|
-
expect(queryKeysForEvent('message.created',
|
|
34
|
-
expect(queryKeysForEvent('
|
|
30
|
+
expect(queryKeysForEvent('message.created', view, topLevel)).toEqual([])
|
|
31
|
+
expect(queryKeysForEvent('reaction', view, topLevel)).toEqual([['shown']])
|
|
35
32
|
})
|
|
36
33
|
})
|
|
@@ -229,8 +229,6 @@ function MessageFormRoot({
|
|
|
229
229
|
const handleSubmit = () => {
|
|
230
230
|
if (!canSubmit) return
|
|
231
231
|
|
|
232
|
-
onBeforeSubmit?.()
|
|
233
|
-
|
|
234
232
|
if (canGiphy && usingGiphy) {
|
|
235
233
|
TextInput.State.blurTextInput(TextInput.State.currentlyFocusedInput())
|
|
236
234
|
Haptic.impactLight()
|
|
@@ -252,6 +250,7 @@ function MessageFormRoot({
|
|
|
252
250
|
mutateAsync({ text: messageText })
|
|
253
251
|
reset()
|
|
254
252
|
} else {
|
|
253
|
+
onBeforeSubmit?.()
|
|
255
254
|
mutateAsync({ text: messageText, attachments: attachmentsForSubmit })
|
|
256
255
|
reset()
|
|
257
256
|
}
|
|
@@ -3,29 +3,34 @@ import React, { createContext, PropsWithChildren, useContext, useMemo } from 're
|
|
|
3
3
|
interface ConversationContextValue {
|
|
4
4
|
conversationId: number
|
|
5
5
|
currentPageReplyRootId: string | null
|
|
6
|
+
messagesQueryKey: unknown[] | null
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
interface ConversationContextProviderProps extends PropsWithChildren {
|
|
9
10
|
conversationId: number
|
|
10
11
|
currentPageReplyRootId: string | null
|
|
12
|
+
messagesQueryKey?: unknown[] | null
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
const ConversationContext = createContext<ConversationContextValue>({
|
|
14
16
|
conversationId: 0,
|
|
15
17
|
currentPageReplyRootId: null,
|
|
18
|
+
messagesQueryKey: null,
|
|
16
19
|
})
|
|
17
20
|
|
|
18
21
|
export const ConversationContextProvider = ({
|
|
19
22
|
children,
|
|
20
23
|
conversationId,
|
|
21
24
|
currentPageReplyRootId,
|
|
25
|
+
messagesQueryKey = null,
|
|
22
26
|
}: ConversationContextProviderProps) => {
|
|
23
27
|
const value = useMemo(
|
|
24
28
|
() => ({
|
|
25
29
|
conversationId,
|
|
26
30
|
currentPageReplyRootId,
|
|
31
|
+
messagesQueryKey,
|
|
27
32
|
}),
|
|
28
|
-
[conversationId, currentPageReplyRootId]
|
|
33
|
+
[conversationId, currentPageReplyRootId, messagesQueryKey]
|
|
29
34
|
)
|
|
30
35
|
|
|
31
36
|
return <ConversationContext.Provider value={value}>{children}</ConversationContext.Provider>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { InfiniteData, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { act, renderHook } from '@testing-library/react-native'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
|
+
import type { ApiCollection, MessageResource } from '../../types'
|
|
6
|
+
import { getMessagesQueryKey } from '../../utils/request/get_messages'
|
|
7
|
+
import { ApiClient, useApiClient } from '../use_api_client'
|
|
8
|
+
import { useFetchNewerMessages } from '../use_fetch_newer_messages'
|
|
9
|
+
|
|
10
|
+
jest.mock('../use_api_client')
|
|
11
|
+
|
|
12
|
+
type QueryData = InfiniteData<ApiCollection<MessageResource>>
|
|
13
|
+
|
|
14
|
+
const page = (ids: string[], next?: { idGt: string }) => ({
|
|
15
|
+
data: ids.map(id => ({ id, type: 'Message' }) as unknown as MessageResource),
|
|
16
|
+
links: {},
|
|
17
|
+
meta: { count: ids.length, totalCount: ids.length, next },
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const queryKey = getMessagesQueryKey({ conversation_id: 1 })
|
|
21
|
+
let queryClient = buildTestQueryClient()
|
|
22
|
+
const get = jest.fn()
|
|
23
|
+
|
|
24
|
+
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
25
|
+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
const cachedIds = () =>
|
|
29
|
+
queryClient.getQueryData<QueryData>(queryKey)?.pages.flatMap(p => p.data.map(m => m.id))
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
queryClient = buildTestQueryClient()
|
|
33
|
+
queryClient.setQueryData<QueryData>(queryKey, {
|
|
34
|
+
pages: [page(['01C', '01B']), page(['01A'])],
|
|
35
|
+
pageParams: [{}, { where: { id_lt: '01B' } }],
|
|
36
|
+
})
|
|
37
|
+
get.mockReset()
|
|
38
|
+
;(useApiClient as jest.MockedFunction<typeof useApiClient>).mockReturnValue({
|
|
39
|
+
chat: { get },
|
|
40
|
+
} as unknown as ApiClient)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('useFetchNewerMessages', () => {
|
|
44
|
+
it('follows meta.next until everything newer is in the cache', async () => {
|
|
45
|
+
get
|
|
46
|
+
.mockResolvedValueOnce(page(['01D', '01E'], { idGt: '01E' }))
|
|
47
|
+
.mockResolvedValueOnce(page(['01F']))
|
|
48
|
+
const { result } = renderHook(() => useFetchNewerMessages({ conversation_id: 1, queryKey }), {
|
|
49
|
+
wrapper,
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
await act(() => result.current('01C'))
|
|
53
|
+
|
|
54
|
+
expect(get).toHaveBeenCalledTimes(2)
|
|
55
|
+
expect(get.mock.calls[1][0].data.where).toEqual({ id_gt: '01E' })
|
|
56
|
+
expect(cachedIds()).toEqual(['01D', '01E', '01F', '01C', '01B', '01A'])
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('rejects when the request fails so the caller can try again later', async () => {
|
|
60
|
+
get.mockRejectedValueOnce(new Error('offline'))
|
|
61
|
+
const { result } = renderHook(() => useFetchNewerMessages({ conversation_id: 1, queryKey }), {
|
|
62
|
+
wrapper,
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
await expect(act(() => result.current('01C'))).rejects.toThrow('offline')
|
|
66
|
+
expect(cachedIds()).toEqual(['01C', '01B', '01A'])
|
|
67
|
+
})
|
|
68
|
+
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { act, renderHook } from '@testing-library/react-native'
|
|
2
|
+
import { useHeldBackMessages } from '../use_held_back_messages'
|
|
3
|
+
|
|
4
|
+
type Props = { newestMessageId?: string; readingHistory: boolean; caughtUp: boolean }
|
|
5
|
+
|
|
6
|
+
const setup = (fetchNewer: jest.Mock, initial: Props) =>
|
|
7
|
+
renderHook((props: Props) => useHeldBackMessages({ fetchNewer, ...props }), {
|
|
8
|
+
initialProps: initial,
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
describe('useHeldBackMessages', () => {
|
|
12
|
+
it('catches up from where the first skip happened, not from the newest message', async () => {
|
|
13
|
+
const fetchNewer = jest.fn().mockResolvedValue(undefined)
|
|
14
|
+
const { result, rerender } = setup(fetchNewer, {
|
|
15
|
+
newestMessageId: 'A',
|
|
16
|
+
readingHistory: true,
|
|
17
|
+
caughtUp: true,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
act(() => result.current.onSkippedNewMessage())
|
|
21
|
+
rerender({ newestMessageId: 'B', readingHistory: true, caughtUp: true })
|
|
22
|
+
await act(async () => rerender({ newestMessageId: 'B', readingHistory: false, caughtUp: true }))
|
|
23
|
+
|
|
24
|
+
expect(fetchNewer).toHaveBeenCalledTimes(1)
|
|
25
|
+
expect(fetchNewer).toHaveBeenCalledWith('A')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('keeps the cursor when the catch-up fails and tries again next time', async () => {
|
|
29
|
+
const fetchNewer = jest
|
|
30
|
+
.fn()
|
|
31
|
+
.mockRejectedValueOnce(new Error('offline'))
|
|
32
|
+
.mockResolvedValue(undefined)
|
|
33
|
+
const { result, rerender } = setup(fetchNewer, {
|
|
34
|
+
newestMessageId: 'A',
|
|
35
|
+
readingHistory: true,
|
|
36
|
+
caughtUp: true,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
act(() => result.current.onSkippedNewMessage())
|
|
40
|
+
await act(async () => rerender({ newestMessageId: 'A', readingHistory: false, caughtUp: true }))
|
|
41
|
+
rerender({ newestMessageId: 'C', readingHistory: true, caughtUp: true })
|
|
42
|
+
await act(async () => rerender({ newestMessageId: 'C', readingHistory: false, caughtUp: true }))
|
|
43
|
+
|
|
44
|
+
expect(fetchNewer).toHaveBeenCalledTimes(2)
|
|
45
|
+
expect(fetchNewer).toHaveBeenLastCalledWith('A')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('does nothing when nothing was held back', async () => {
|
|
49
|
+
const fetchNewer = jest.fn()
|
|
50
|
+
const { rerender } = setup(fetchNewer, {
|
|
51
|
+
newestMessageId: 'A',
|
|
52
|
+
readingHistory: true,
|
|
53
|
+
caughtUp: true,
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
await act(async () => rerender({ newestMessageId: 'A', readingHistory: false, caughtUp: true }))
|
|
57
|
+
|
|
58
|
+
expect(fetchNewer).not.toHaveBeenCalled()
|
|
59
|
+
})
|
|
60
|
+
})
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { InfiniteData, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { act, renderHook } from '@testing-library/react-native'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
|
+
import { ConversationContextProvider } from '../../contexts/conversation_context'
|
|
6
|
+
import type { ApiCollection, MessageResource } from '../../types'
|
|
7
|
+
import { getMessagesQueryKey } from '../../utils/request/get_messages'
|
|
8
|
+
import { ApiClient, useApiClient } from '../use_api_client'
|
|
9
|
+
import { useMessageReactionToggle } from '../use_message_reaction_toggle'
|
|
10
|
+
|
|
11
|
+
jest.mock('../use_api_client')
|
|
12
|
+
|
|
13
|
+
type QueryData = InfiniteData<ApiCollection<MessageResource>>
|
|
14
|
+
|
|
15
|
+
const message = { id: '01M', type: 'Message', reactionCounts: [] } as unknown as MessageResource
|
|
16
|
+
const liveKey = getMessagesQueryKey({ conversation_id: 1 })
|
|
17
|
+
const anchoredKey = getMessagesQueryKey({ conversation_id: 1, anchor: '01A' })
|
|
18
|
+
const seed = (): QueryData => ({
|
|
19
|
+
pages: [{ data: [message], links: {}, meta: { count: 1, totalCount: 1 } }],
|
|
20
|
+
pageParams: [{}],
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const heartsIn = (queryClient: ReturnType<typeof buildTestQueryClient>, key: unknown[]) =>
|
|
24
|
+
queryClient
|
|
25
|
+
.getQueryData<QueryData>(key)
|
|
26
|
+
?.pages[0].data[0].reactionCounts.map(r => `${r.value}:${r.count}`)
|
|
27
|
+
|
|
28
|
+
describe('useMessageReactionToggle', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
;(useApiClient as jest.MockedFunction<typeof useApiClient>).mockReturnValue({
|
|
31
|
+
chat: { post: jest.fn(() => new Promise(() => {})) },
|
|
32
|
+
} as unknown as ApiClient)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('applies the optimistic reaction to the cache the screen is showing', async () => {
|
|
36
|
+
const queryClient = buildTestQueryClient({ defaultOptions: { queries: { gcTime: Infinity } } })
|
|
37
|
+
queryClient.setQueryData<QueryData>(anchoredKey, seed())
|
|
38
|
+
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
39
|
+
<QueryClientProvider client={queryClient}>
|
|
40
|
+
<ConversationContextProvider
|
|
41
|
+
conversationId={1}
|
|
42
|
+
currentPageReplyRootId={null}
|
|
43
|
+
messagesQueryKey={anchoredKey}
|
|
44
|
+
>
|
|
45
|
+
{children}
|
|
46
|
+
</ConversationContextProvider>
|
|
47
|
+
</QueryClientProvider>
|
|
48
|
+
)
|
|
49
|
+
const { result } = renderHook(() => useMessageReactionToggle({ conversation_id: 1, message }), {
|
|
50
|
+
wrapper,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
await act(async () => result.current.handleReactionToggle({ value: 'heart', mine: false }))
|
|
54
|
+
|
|
55
|
+
expect(heartsIn(queryClient, anchoredKey)).toEqual(['heart:1'])
|
|
56
|
+
expect(queryClient.getQueryData(liveKey)).toBeUndefined()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('falls back to the live cache when no screen key is provided', async () => {
|
|
60
|
+
const queryClient = buildTestQueryClient({ defaultOptions: { queries: { gcTime: Infinity } } })
|
|
61
|
+
queryClient.setQueryData<QueryData>(liveKey, seed())
|
|
62
|
+
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
63
|
+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
64
|
+
)
|
|
65
|
+
const { result } = renderHook(() => useMessageReactionToggle({ conversation_id: 1, message }), {
|
|
66
|
+
wrapper,
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
await act(async () => result.current.handleReactionToggle({ value: 'heart', mine: false }))
|
|
70
|
+
|
|
71
|
+
expect(heartsIn(queryClient, liveKey)).toEqual(['heart:1'])
|
|
72
|
+
})
|
|
73
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useQueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { useCallback, useSyncExternalStore } from 'react'
|
|
3
|
+
import { findMessageInCaches } from '../utils/cache/find_message_in_caches'
|
|
4
|
+
import { useConversationMessage } from './use_conversation_message'
|
|
5
|
+
|
|
6
|
+
type Options = {
|
|
7
|
+
conversation_id: number
|
|
8
|
+
message_id: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useConversationMessageLookup = ({ conversation_id, message_id }: Options) => {
|
|
12
|
+
const queryClient = useQueryClient()
|
|
13
|
+
const subscribe = useCallback(
|
|
14
|
+
(onChange: () => void) => queryClient.getQueryCache().subscribe(onChange),
|
|
15
|
+
[queryClient]
|
|
16
|
+
)
|
|
17
|
+
const getSnapshot = useCallback(
|
|
18
|
+
() => findMessageInCaches(queryClient, conversation_id, message_id),
|
|
19
|
+
[conversation_id, message_id, queryClient]
|
|
20
|
+
)
|
|
21
|
+
const cached = useSyncExternalStore(subscribe, getSnapshot)
|
|
22
|
+
const fetched = useConversationMessage({
|
|
23
|
+
conversation_id,
|
|
24
|
+
messageId: message_id,
|
|
25
|
+
enabled: !cached,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
return cached ?? fetched.message
|
|
29
|
+
}
|
|
@@ -2,6 +2,7 @@ import { useMemo } from 'react'
|
|
|
2
2
|
import { MessageResource } from '../types'
|
|
3
3
|
import { replaceEqualById } from '../utils/replace_equal_by_id'
|
|
4
4
|
import { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'
|
|
5
|
+
import { ResponseError } from '../utils/response_error'
|
|
5
6
|
import { getNewerPageParam } from './paginator_meta'
|
|
6
7
|
import { SuspensePaginatorOptions, useSuspensePaginator } from './use_suspense_api'
|
|
7
8
|
|
|
@@ -11,6 +12,13 @@ type Options = {
|
|
|
11
12
|
anchor?: string | null
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
export const anchoredRetry = (failureCount: number, error: unknown) => {
|
|
16
|
+
const status = error instanceof ResponseError ? error.status : undefined
|
|
17
|
+
if (status === 404 || status === 429) return false
|
|
18
|
+
|
|
19
|
+
return failureCount < 3
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
export const useConversationMessages = (
|
|
15
23
|
{ conversation_id, reply_root_id, anchor }: Options,
|
|
16
24
|
opts?: SuspensePaginatorOptions
|
|
@@ -33,6 +41,7 @@ export const useConversationMessages = (
|
|
|
33
41
|
getPreviousPageParam: (page, _pages, pageParam) => getNewerPageParam(page, pageParam),
|
|
34
42
|
gcTime: 0,
|
|
35
43
|
staleTime: Infinity,
|
|
44
|
+
retry: anchoredRetry,
|
|
36
45
|
}
|
|
37
46
|
: {}),
|
|
38
47
|
...opts,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InfiniteData, useQueryClient } from '@tanstack/react-query'
|
|
2
2
|
import { ApiCollection, MessageResource } from '../types'
|
|
3
3
|
import { JoltReactionEvent, JoltTypingEvent } from '../types/jolt_events'
|
|
4
4
|
import {
|
|
@@ -12,16 +12,14 @@ import {
|
|
|
12
12
|
updateCacheWithIndividualMessage,
|
|
13
13
|
updateCacheWithReaction,
|
|
14
14
|
updateCacheReplyRoots,
|
|
15
|
-
getThreadedMessagesQueryKey,
|
|
16
15
|
} from '../utils/cache/messages_cache'
|
|
17
16
|
import { transformMessageEventDataToMessageResource } from '../utils/jolt/transform_message_event_data_to_message_resource'
|
|
18
17
|
import { completeMessageCreationTracking } from '../utils/performance_tracking'
|
|
19
18
|
import { getMessageQueryKey } from '../utils/request/get_message'
|
|
20
|
-
import {
|
|
19
|
+
import { getMessagesQueryKey } from '../utils/request/get_messages'
|
|
21
20
|
import { useApiClient } from './use_api_client'
|
|
22
21
|
import { useCurrentPerson } from './use_current_person'
|
|
23
22
|
import { useJoltChannel, useJoltEvent } from './use_jolt'
|
|
24
|
-
import { getRequestQueryKey } from './use_suspense_api'
|
|
25
23
|
import { TYPING_TIMEOUT_INTERVAL, useTypingStatusCache } from './use_typing_status_cache'
|
|
26
24
|
|
|
27
25
|
export type MessagesJoltEvent =
|
|
@@ -35,38 +33,48 @@ export interface MessagesCache {
|
|
|
35
33
|
canUpdate?: (event: MessagesJoltEvent) => boolean
|
|
36
34
|
}
|
|
37
35
|
|
|
36
|
+
export interface MessagesView {
|
|
37
|
+
replyRootId: string | null
|
|
38
|
+
cache: MessagesCache
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type MessageEventData = { sort_key: string; reply_root_id?: string | null }
|
|
42
|
+
|
|
38
43
|
interface Props {
|
|
39
44
|
conversationId: number
|
|
40
|
-
|
|
45
|
+
replyRootId?: string | null
|
|
46
|
+
messageCache?: MessagesCache
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const defaultHashes = new Set(defaults.map(hashKey))
|
|
46
|
-
const resolved = defaults.map(queryKey => overrideByHash.get(hashKey(queryKey)) ?? { queryKey })
|
|
47
|
-
const extras = overrides.filter(cache => !defaultHashes.has(hashKey(cache.queryKey)))
|
|
48
|
-
return [...resolved, ...extras]
|
|
49
|
-
}
|
|
49
|
+
const belongsToView = (replyRootId: string | null, data: MessageEventData) =>
|
|
50
|
+
replyRootId === null || data.reply_root_id === replyRootId || data.sort_key === replyRootId
|
|
50
51
|
|
|
51
52
|
export const queryKeysForEvent = (
|
|
52
53
|
event: MessagesJoltEvent,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
) =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
export function useConversationMessagesJoltEvents({
|
|
54
|
+
view: MessagesView,
|
|
55
|
+
data: MessageEventData
|
|
56
|
+
) => {
|
|
57
|
+
const accepted = !view.cache.canUpdate || view.cache.canUpdate(event)
|
|
58
|
+
return belongsToView(view.replyRootId, data) && accepted ? [view.cache.queryKey] : []
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function useConversationMessagesJoltEvents({
|
|
62
|
+
conversationId,
|
|
63
|
+
replyRootId = null,
|
|
64
|
+
messageCache,
|
|
65
|
+
}: Props) {
|
|
61
66
|
const queryClient = useQueryClient()
|
|
62
67
|
const currentPerson = useCurrentPerson()
|
|
63
68
|
const joltChannel = useJoltChannel(`chat.conversations.${conversationId}`)
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
const view: MessagesView = {
|
|
70
|
+
replyRootId,
|
|
71
|
+
cache: messageCache ?? {
|
|
72
|
+
queryKey: getMessagesQueryKey({
|
|
73
|
+
conversation_id: conversationId,
|
|
74
|
+
reply_root_id: replyRootId,
|
|
75
|
+
}),
|
|
76
|
+
},
|
|
77
|
+
}
|
|
70
78
|
const apiClient = useApiClient()
|
|
71
79
|
|
|
72
80
|
const { addTypingEvent, removeTypingEventById, removeAllTypingEventsByAuthorId } =
|
|
@@ -87,11 +95,7 @@ export function useConversationMessagesJoltEvents({ conversationId, messageCache
|
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
|
|
90
|
-
const targetQueryKeys = queryKeysForEvent(
|
|
91
|
-
e.event,
|
|
92
|
-
cachesTouchedBy(data.reply_root_id),
|
|
93
|
-
messageCaches
|
|
94
|
-
)
|
|
98
|
+
const targetQueryKeys = queryKeysForEvent(e.event, view, data)
|
|
95
99
|
targetQueryKeys.forEach(queryKey =>
|
|
96
100
|
updateCacheWithMessage(queryClient, queryKey, message, e.event)
|
|
97
101
|
)
|
|
@@ -116,11 +120,7 @@ export function useConversationMessagesJoltEvents({ conversationId, messageCache
|
|
|
116
120
|
currentPersonId: currentPerson.id,
|
|
117
121
|
})
|
|
118
122
|
|
|
119
|
-
queryKeysForEvent(
|
|
120
|
-
'message.destroyed',
|
|
121
|
-
cachesTouchedBy(data.reply_root_id),
|
|
122
|
-
messageCaches
|
|
123
|
-
).forEach(queryKey =>
|
|
123
|
+
queryKeysForEvent('message.destroyed', view, data).forEach(queryKey =>
|
|
124
124
|
queryClient.setQueryData<QueryData>(queryKey, prev =>
|
|
125
125
|
deleteRecordInPagesData({ data: prev, record: message })
|
|
126
126
|
)
|
|
@@ -128,11 +128,13 @@ export function useConversationMessagesJoltEvents({ conversationId, messageCache
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
const handleReactionJoltEvent = async (e: JoltReactionEvent) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
).forEach(queryKey =>
|
|
131
|
+
const data = {
|
|
132
|
+
sort_key: e.data.data.message_sort_key,
|
|
133
|
+
reply_root_id: e.data.data.reply_root_id,
|
|
134
|
+
}
|
|
135
|
+
queryKeysForEvent('reaction', view, data).forEach(queryKey =>
|
|
136
|
+
updateCacheWithReaction(queryClient, queryKey, e, currentPerson.id)
|
|
137
|
+
)
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
const handleTypingEvent = async (e: JoltTypingEvent) => {
|