@planningcenter/chat-react-native 2.0.1-rc.0 → 2.1.0-rc.1
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.d.ts.map +1 -1
- package/build/components/conversation/message.js +7 -2
- package/build/components/conversation/message.js.map +1 -1
- package/build/components/conversation/message_reaction.d.ts +1 -1
- package/build/components/conversation/message_reaction.d.ts.map +1 -1
- package/build/components/conversation/message_reaction.js +1 -1
- package/build/components/conversation/message_reaction.js.map +1 -1
- package/build/components/conversations.d.ts.map +1 -1
- package/build/components/conversations.js +76 -30
- package/build/components/conversations.js.map +1 -1
- package/build/components/display/badge.d.ts +2 -6
- package/build/components/display/badge.d.ts.map +1 -1
- package/build/components/display/badge.js +1 -5
- package/build/components/display/badge.js.map +1 -1
- package/build/components/display/tabs.d.ts +17 -0
- package/build/components/display/tabs.d.ts.map +1 -0
- package/build/components/display/tabs.js +97 -0
- package/build/components/display/tabs.js.map +1 -0
- package/build/components/index.d.ts +1 -1
- package/build/components/index.d.ts.map +1 -1
- package/build/components/index.js +1 -1
- package/build/components/index.js.map +1 -1
- package/build/components/{error_boundary.d.ts → page/error_boundary.d.ts} +6 -4
- package/build/components/page/error_boundary.d.ts.map +1 -0
- package/build/components/page/error_boundary.js +115 -0
- package/build/components/page/error_boundary.js.map +1 -0
- package/build/components/page/loading.d.ts +3 -0
- package/build/components/page/loading.d.ts.map +1 -0
- package/build/components/page/loading.js +24 -0
- package/build/components/page/loading.js.map +1 -0
- package/build/contexts/api_provider.js +2 -2
- package/build/contexts/api_provider.js.map +1 -1
- package/build/hooks/use_conversation_jolt_events.d.ts +2 -0
- package/build/hooks/use_conversation_jolt_events.d.ts.map +1 -0
- package/build/hooks/use_conversation_jolt_events.js +47 -0
- package/build/hooks/use_conversation_jolt_events.js.map +1 -0
- package/build/hooks/use_conversation_messages.d.ts +2 -18
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +2 -2
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversations.d.ts +37 -0
- package/build/hooks/use_conversations.d.ts.map +1 -0
- package/build/hooks/use_conversations.js +48 -0
- package/build/hooks/use_conversations.js.map +1 -0
- package/build/hooks/use_jolt.d.ts +9 -0
- package/build/hooks/use_jolt.d.ts.map +1 -0
- package/build/hooks/use_jolt.js +71 -0
- package/build/hooks/use_jolt.js.map +1 -0
- package/build/hooks/use_suspense_api.d.ts +7 -2
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +7 -2
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/navigation/index.d.ts +11 -2
- package/build/navigation/index.d.ts.map +1 -1
- package/build/navigation/index.js +14 -6
- package/build/navigation/index.js.map +1 -1
- package/build/navigation/screenLayout.d.ts.map +1 -1
- package/build/navigation/screenLayout.js +5 -8
- package/build/navigation/screenLayout.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts +1 -1
- package/build/screens/message_actions_screen.d.ts.map +1 -1
- package/build/screens/message_actions_screen.js +1 -1
- package/build/screens/message_actions_screen.js.map +1 -1
- package/build/screens/reactions_screen.d.ts +11 -0
- package/build/screens/reactions_screen.d.ts.map +1 -0
- package/build/screens/reactions_screen.js +83 -0
- package/build/screens/reactions_screen.js.map +1 -0
- package/build/types/resources/app_name.d.ts +2 -0
- package/build/types/resources/app_name.d.ts.map +1 -0
- package/build/types/resources/app_name.js +2 -0
- package/build/types/resources/app_name.js.map +1 -0
- package/build/types/resources/conversation.d.ts +18 -10
- package/build/types/resources/conversation.d.ts.map +1 -1
- package/build/types/resources/conversation.js.map +1 -1
- package/build/types/resources/conversation_badge.d.ts +12 -0
- package/build/types/resources/conversation_badge.d.ts.map +1 -0
- package/build/types/resources/conversation_badge.js +2 -0
- package/build/types/resources/conversation_badge.js.map +1 -0
- package/build/types/resources/group_resource.d.ts +12 -0
- package/build/types/resources/group_resource.d.ts.map +1 -0
- package/build/types/resources/group_resource.js +2 -0
- package/build/types/resources/group_resource.js.map +1 -0
- package/build/types/resources/index.d.ts +2 -1
- package/build/types/resources/index.d.ts.map +1 -1
- package/build/types/resources/index.js +2 -1
- package/build/types/resources/index.js.map +1 -1
- package/build/types/resources/member.d.ts +23 -0
- package/build/types/resources/member.d.ts.map +1 -0
- package/build/types/resources/member.js +2 -0
- package/build/types/resources/member.js.map +1 -0
- package/build/types/resources/member_ability.d.ts +6 -0
- package/build/types/resources/member_ability.d.ts.map +1 -0
- package/build/types/resources/member_ability.js +2 -0
- package/build/types/resources/member_ability.js.map +1 -0
- package/build/types/resources/reaction.d.ts +1 -1
- package/build/types/resources/reaction.js.map +1 -1
- package/build/utils/cache/page_mutations.d.ts +19 -2
- package/build/utils/cache/page_mutations.d.ts.map +1 -1
- package/build/utils/cache/page_mutations.js +21 -7
- package/build/utils/cache/page_mutations.js.map +1 -1
- package/build/utils/date.d.ts +4 -0
- package/build/utils/date.d.ts.map +1 -0
- package/build/utils/date.js +23 -0
- package/build/utils/date.js.map +1 -0
- package/package.json +7 -3
- package/src/__tests__/utils/cache/page_mutations.ts +7 -46
- package/src/components/conversation/message.tsx +8 -3
- package/src/components/conversation/message_reaction.tsx +6 -2
- package/src/components/conversations.tsx +95 -32
- package/src/components/display/badge.tsx +3 -8
- package/src/components/display/tabs.tsx +142 -0
- package/src/components/index.tsx +1 -1
- package/src/components/page/error_boundary.tsx +135 -0
- package/src/components/page/loading.tsx +28 -0
- package/src/contexts/api_provider.tsx +3 -3
- package/src/hooks/use_conversation_jolt_events.ts +67 -0
- package/src/hooks/use_conversation_messages.ts +6 -2
- package/src/hooks/use_conversations.ts +53 -0
- package/src/hooks/use_jolt.ts +101 -0
- package/src/hooks/use_suspense_api.ts +10 -3
- package/src/navigation/index.tsx +23 -7
- package/src/navigation/screenLayout.tsx +5 -10
- package/src/screens/message_actions_screen.tsx +1 -1
- package/src/screens/reactions_screen.tsx +131 -0
- package/src/types/resources/app_name.ts +1 -0
- package/src/types/resources/conversation.ts +18 -10
- package/src/types/resources/conversation_badge.ts +10 -0
- package/src/types/resources/group_resource.ts +10 -0
- package/src/types/resources/index.ts +2 -1
- package/src/types/resources/member.ts +24 -0
- package/src/types/resources/member_ability.ts +5 -0
- package/src/types/resources/reaction.ts +1 -1
- package/src/utils/cache/page_mutations.ts +32 -9
- package/src/utils/date.ts +25 -0
- package/build/components/error_boundary.d.ts.map +0 -1
- package/build/components/error_boundary.js +0 -24
- package/build/components/error_boundary.js.map +0 -1
- package/src/components/error_boundary.tsx +0 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reaction.js","sourceRoot":"","sources":["../../../src/types/resources/reaction.ts"],"names":[],"mappings":"","sourcesContent":["export interface ReactionCountResource {\n type: 'ReactionCount'\n id: string\n value: 'thumbs_up' | 'thumbs_down' | 'pray' | 'laugh' | 'heart'\n count: number\n mine: number\n messageId: string\n authorIds:
|
|
1
|
+
{"version":3,"file":"reaction.js","sourceRoot":"","sources":["../../../src/types/resources/reaction.ts"],"names":[],"mappings":"","sourcesContent":["export interface ReactionCountResource {\n type: 'ReactionCount'\n id: string\n value: 'thumbs_up' | 'thumbs_down' | 'pray' | 'laugh' | 'heart'\n count: number\n mine: number\n messageId: string\n authorIds: string[]\n}\n"]}
|
|
@@ -14,7 +14,7 @@ export declare function updateRecordInPagesData<T extends ResourceObject>({ data
|
|
|
14
14
|
pageParams: any;
|
|
15
15
|
};
|
|
16
16
|
record: T;
|
|
17
|
-
processRecord?: (
|
|
17
|
+
processRecord?: (_next: T, _prev?: T) => T;
|
|
18
18
|
}): {
|
|
19
19
|
pages: {
|
|
20
20
|
data: T[];
|
|
@@ -29,9 +29,26 @@ export declare function addRecordInPagesData<T extends ResourceObject>({ data, r
|
|
|
29
29
|
pageParams: any;
|
|
30
30
|
};
|
|
31
31
|
record: T;
|
|
32
|
-
processRecord?: (
|
|
32
|
+
processRecord?: (_next: T, _prev?: T) => T;
|
|
33
33
|
}): {
|
|
34
34
|
pages: ApiCollection<T>[];
|
|
35
35
|
pageParams: any;
|
|
36
36
|
} | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* deleteRecordInPagesData
|
|
39
|
+
*/
|
|
40
|
+
export declare function deleteRecordInPagesData<T extends ResourceObject>({ data, record, }: {
|
|
41
|
+
data?: {
|
|
42
|
+
pages: ApiCollection<T>[];
|
|
43
|
+
pageParams: any;
|
|
44
|
+
};
|
|
45
|
+
record: T;
|
|
46
|
+
}): {
|
|
47
|
+
pages: {
|
|
48
|
+
data: T[];
|
|
49
|
+
links: Record<string, string>;
|
|
50
|
+
meta: import("../../types").CollectionMeta;
|
|
51
|
+
}[];
|
|
52
|
+
pageParams: any;
|
|
53
|
+
} | undefined;
|
|
37
54
|
//# sourceMappingURL=page_mutations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page_mutations.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/page_mutations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE3D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,cAAc,EAAE,EAChE,IAAI,EACJ,MAAM,EACN,aAAsB,GACvB,EAAE;IACD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,CAAA;IACrD,MAAM,EAAE,CAAC,CAAA;IACT,aAAa,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"page_mutations.d.ts","sourceRoot":"","sources":["../../../src/utils/cache/page_mutations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE3D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,cAAc,EAAE,EAChE,IAAI,EACJ,MAAM,EACN,aAAsB,GACvB,EAAE;IACD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,CAAA;IACrD,MAAM,EAAE,CAAC,CAAA;IACT,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;CAC3C;;;;;;gBAHiD,GAAG;cA4BpD;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAAE,EAC7D,IAAI,EACJ,MAAM,EACN,aAAsB,GACvB,EAAE;IACD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,CAAA;IACrD,MAAM,EAAE,CAAC,CAAA;IACT,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;CAC3C;;gBAHiD,GAAG;cAapD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,cAAc,EAAE,EAChE,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,CAAA;IACrD,MAAM,EAAE,CAAC,CAAA;CACV;;;;;;gBAFiD,GAAG;cAcpD"}
|
|
@@ -15,7 +15,7 @@ export function updateRecordInPagesData({ data, record, processRecord = r => r,
|
|
|
15
15
|
const newData = page.data.map(message => {
|
|
16
16
|
if (message.id === record.id) {
|
|
17
17
|
foundRecord = true;
|
|
18
|
-
return processRecord(record);
|
|
18
|
+
return processRecord(record, message);
|
|
19
19
|
}
|
|
20
20
|
return message;
|
|
21
21
|
});
|
|
@@ -24,9 +24,9 @@ export function updateRecordInPagesData({ data, record, processRecord = r => r,
|
|
|
24
24
|
if (!foundRecord) {
|
|
25
25
|
// Can be used to add as well but it's not at all efficient. It's better to use addRecordInPagesData.
|
|
26
26
|
// This is a fallback for when the record is not found in the cache.
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
newPages[
|
|
27
|
+
const firstPage = { ...newPages[0] };
|
|
28
|
+
firstPage.data = [processRecord(record), ...firstPage.data];
|
|
29
|
+
newPages[0] = firstPage;
|
|
30
30
|
}
|
|
31
31
|
return { ...data, pages: newPages };
|
|
32
32
|
}
|
|
@@ -34,9 +34,23 @@ export function addRecordInPagesData({ data, record, processRecord = r => r, })
|
|
|
34
34
|
if (!data)
|
|
35
35
|
return data;
|
|
36
36
|
const newPages = [...data.pages];
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
newPages[
|
|
37
|
+
const firstPage = { ...newPages[0] };
|
|
38
|
+
firstPage.data = [processRecord(record), ...firstPage.data];
|
|
39
|
+
newPages[0] = firstPage;
|
|
40
|
+
return { ...data, pages: newPages };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* deleteRecordInPagesData
|
|
44
|
+
*/
|
|
45
|
+
export function deleteRecordInPagesData({ data, record, }) {
|
|
46
|
+
if (!data)
|
|
47
|
+
return data;
|
|
48
|
+
const newPages = data.pages.map(page => {
|
|
49
|
+
const newData = page.data.filter(message => {
|
|
50
|
+
return message.id !== record.id;
|
|
51
|
+
});
|
|
52
|
+
return { ...page, data: newData };
|
|
53
|
+
});
|
|
40
54
|
return { ...data, pages: newPages };
|
|
41
55
|
}
|
|
42
56
|
//# sourceMappingURL=page_mutations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page_mutations.js","sourceRoot":"","sources":["../../../src/utils/cache/page_mutations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAA2B,EAChE,IAAI,EACJ,MAAM,EACN,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAKvB;IACC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YACtC,IAAI,OAAO,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;gBAC7B,WAAW,GAAG,IAAI,CAAA;gBAClB,OAAO,aAAa,CAAC,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"page_mutations.js","sourceRoot":"","sources":["../../../src/utils/cache/page_mutations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAA2B,EAChE,IAAI,EACJ,MAAM,EACN,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAKvB;IACC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,IAAI,WAAW,GAAG,KAAK,CAAA;IACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YACtC,IAAI,OAAO,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;gBAC7B,WAAW,GAAG,IAAI,CAAA;gBAClB,OAAO,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YACvC,CAAC;YACD,OAAO,OAAO,CAAA;QAChB,CAAC,CAAC,CAAA;QAEF,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,qGAAqG;QACrG,oEAAoE;QACpE,MAAM,SAAS,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QACpC,SAAS,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC3D,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;IACzB,CAAC;IAED,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAA2B,EAC7D,IAAI,EACJ,MAAM,EACN,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAKvB;IACC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;IAChC,MAAM,SAAS,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;IACpC,SAAS,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAE3D,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;IAEvB,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAA2B,EAChE,IAAI,EACJ,MAAM,GAIP;IACC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;YACzC,OAAO,OAAO,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAA;QACjC,CAAC,CAAC,CAAA;QAEF,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;AACrC,CAAC","sourcesContent":["/**\n * Helpers to handle updating messages in the cache\n * Messages are ordered by ULID on the client so we may\n * have diverging logic from other kinds of api data\n */\n\nimport { ApiCollection, ResourceObject } from '../../types'\n\n/**\n * updateRecordInPagesData\n * Can be used to add as well but it's not at all efficient. It's better to use addRecordInPagesData.\n */\nexport function updateRecordInPagesData<T extends ResourceObject>({\n data,\n record,\n processRecord = r => r,\n}: {\n data?: { pages: ApiCollection<T>[]; pageParams: any }\n record: T\n processRecord?: (_next: T, _prev?: T) => T\n}) {\n if (!data) return data\n\n let foundRecord = false\n const newPages = data.pages.map(page => {\n const newData = page.data.map(message => {\n if (message.id === record.id) {\n foundRecord = true\n return processRecord(record, message)\n }\n return message\n })\n\n return { ...page, data: newData }\n })\n\n if (!foundRecord) {\n // Can be used to add as well but it's not at all efficient. It's better to use addRecordInPagesData.\n // This is a fallback for when the record is not found in the cache.\n const firstPage = { ...newPages[0] }\n firstPage.data = [processRecord(record), ...firstPage.data]\n newPages[0] = firstPage\n }\n\n return { ...data, pages: newPages }\n}\n\nexport function addRecordInPagesData<T extends ResourceObject>({\n data,\n record,\n processRecord = r => r,\n}: {\n data?: { pages: ApiCollection<T>[]; pageParams: any }\n record: T\n processRecord?: (_next: T, _prev?: T) => T\n}) {\n if (!data) return data\n\n const newPages = [...data.pages]\n const firstPage = { ...newPages[0] }\n firstPage.data = [processRecord(record), ...firstPage.data]\n\n newPages[0] = firstPage\n\n return { ...data, pages: newPages }\n}\n\n/**\n * deleteRecordInPagesData\n */\nexport function deleteRecordInPagesData<T extends ResourceObject>({\n data,\n record,\n}: {\n data?: { pages: ApiCollection<T>[]; pageParams: any }\n record: T\n}) {\n if (!data) return data\n\n const newPages = data.pages.map(page => {\n const newData = page.data.filter(message => {\n return message.id !== record.id\n })\n\n return { ...page, data: newData }\n })\n\n return { ...data, pages: newPages }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/utils/date.ts"],"names":[],"mappings":"AAGA,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;AAEvC,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,SAAS,OAcjD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { date as formatDate } from '@planningcenter/datetime-fmt';
|
|
2
|
+
import moment from 'moment-timezone';
|
|
3
|
+
export function formatDatePreview(date) {
|
|
4
|
+
if (!date)
|
|
5
|
+
return '';
|
|
6
|
+
const now = moment();
|
|
7
|
+
const isToday = now.isSame(date, 'day');
|
|
8
|
+
const isThisWeek = now.isSame(date, 'week');
|
|
9
|
+
const isThisYear = now.isSame(date, 'year');
|
|
10
|
+
if (isToday)
|
|
11
|
+
return moment(date).format('h:mm a');
|
|
12
|
+
if (isThisWeek)
|
|
13
|
+
return formatDate(date, { style: 'relative-short' });
|
|
14
|
+
if (isThisYear)
|
|
15
|
+
return formatDate(date, { style: 'abbreviated' });
|
|
16
|
+
// TODO: Org date format
|
|
17
|
+
return formatShorterDate(date);
|
|
18
|
+
}
|
|
19
|
+
const formatShorterDate = (date) => {
|
|
20
|
+
// Drop the century from the year
|
|
21
|
+
return formatDate(date, { style: 'short', year: true }).replace(/20(\d{2})/, '$1');
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=date.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/utils/date.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,MAAM,MAAM,iBAAiB,CAAA;AAIpC,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAA;IAEpB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAA;IACpB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACvC,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC3C,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAE3C,IAAI,OAAO;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACjD,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAA;IACpE,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAA;IAEjE,wBAAwB;IACxB,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAA;AAChC,CAAC;AAED,MAAM,iBAAiB,GAAG,CAAC,IAAe,EAAE,EAAE;IAC5C,iCAAiC;IACjC,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;AACpF,CAAC,CAAA","sourcesContent":["import { date as formatDate } from '@planningcenter/datetime-fmt'\nimport moment from 'moment-timezone'\n\ntype DateProps = string | number | Date\n\nexport function formatDatePreview(date?: DateProps) {\n if (!date) return ''\n\n const now = moment()\n const isToday = now.isSame(date, 'day')\n const isThisWeek = now.isSame(date, 'week')\n const isThisYear = now.isSame(date, 'year')\n\n if (isToday) return moment(date).format('h:mm a')\n if (isThisWeek) return formatDate(date, { style: 'relative-short' })\n if (isThisYear) return formatDate(date, { style: 'abbreviated' })\n\n // TODO: Org date format\n return formatShorterDate(date)\n}\n\nconst formatShorterDate = (date: DateProps) => {\n // Drop the century from the year\n return formatDate(date, { style: 'short', year: true }).replace(/20(\\d{2})/, '$1')\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0-rc.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -24,13 +24,17 @@
|
|
|
24
24
|
"react-native-url-polyfill": "^2.0.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@planningcenter/
|
|
27
|
+
"@planningcenter/datetime-fmt": ">=1.0.0",
|
|
28
|
+
"@planningcenter/icons": ">=15.0.0",
|
|
29
|
+
"@planningcenter/jolt-client": ">=2.0.0",
|
|
28
30
|
"@react-navigation/elements": "*",
|
|
29
31
|
"@react-navigation/native": ">=7.0.0",
|
|
30
32
|
"@react-navigation/native-stack": ">=7.0.0",
|
|
31
33
|
"@tanstack/react-query": "^5.0.0",
|
|
32
34
|
"color": "^3.1.2",
|
|
33
35
|
"lodash": "*",
|
|
36
|
+
"moment": ">=2.0.0",
|
|
37
|
+
"moment-timezone": ">=2.0.0",
|
|
34
38
|
"react": "*",
|
|
35
39
|
"react-native": "*",
|
|
36
40
|
"react-native-device-info": "*",
|
|
@@ -47,5 +51,5 @@
|
|
|
47
51
|
"prettier": "^3.4.2",
|
|
48
52
|
"typescript": "<5.6.0"
|
|
49
53
|
},
|
|
50
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "f75cb36bdd241b841ea1279d73c772ed5210bb8a"
|
|
51
55
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { deleteRecordInPagesData, updateRecordInPagesData } from '../../../utils/'
|
|
2
2
|
|
|
3
3
|
const data = {
|
|
4
4
|
pageParams: {},
|
|
@@ -105,6 +105,7 @@ describe('updateRecordInPagesData', () => {
|
|
|
105
105
|
pages: [
|
|
106
106
|
{
|
|
107
107
|
data: [
|
|
108
|
+
{ id, type: 'Message', text: `updated example ${id}` },
|
|
108
109
|
{ id: '1', type: 'Message', text: 'message 1' },
|
|
109
110
|
{ id: '2', type: 'Message', text: 'message 2' },
|
|
110
111
|
],
|
|
@@ -116,7 +117,6 @@ describe('updateRecordInPagesData', () => {
|
|
|
116
117
|
data: [
|
|
117
118
|
{ id: '3', type: 'Message', text: 'message 3' },
|
|
118
119
|
{ id: '4', type: 'Message', text: 'message 4' },
|
|
119
|
-
{ id, type: 'Message', text: `updated example ${id}` },
|
|
120
120
|
],
|
|
121
121
|
included: [],
|
|
122
122
|
links: {},
|
|
@@ -127,49 +127,14 @@ describe('updateRecordInPagesData', () => {
|
|
|
127
127
|
})
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
describe('
|
|
131
|
-
it('should
|
|
132
|
-
const id = '
|
|
130
|
+
describe('deleteRecordInPagesData', () => {
|
|
131
|
+
it('should delete records from page', () => {
|
|
132
|
+
const id = '4'
|
|
133
133
|
const record = createRecord({ id })
|
|
134
134
|
|
|
135
|
-
const result =
|
|
136
|
-
data,
|
|
137
|
-
record,
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
expect(result).toEqual({
|
|
141
|
-
pageParams: {},
|
|
142
|
-
pages: [
|
|
143
|
-
{
|
|
144
|
-
data: [
|
|
145
|
-
{ id: '1', type: 'Message', text: 'message 1' },
|
|
146
|
-
{ id: '2', type: 'Message', text: 'message 2' },
|
|
147
|
-
],
|
|
148
|
-
included: [],
|
|
149
|
-
links: {},
|
|
150
|
-
meta: { count: 2, totalCount: 2 },
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
data: [
|
|
154
|
-
{ id: '3', type: 'Message', text: 'message 3' },
|
|
155
|
-
{ id: '4', type: 'Message', text: 'message 4' },
|
|
156
|
-
record,
|
|
157
|
-
],
|
|
158
|
-
included: [],
|
|
159
|
-
links: {},
|
|
160
|
-
meta: { count: 2, totalCount: 2 },
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
})
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it('should add the record in the pages data and update with a custom processRecord function', () => {
|
|
167
|
-
const id = '8'
|
|
168
|
-
const record = createRecord({ id })
|
|
169
|
-
const result = addRecordInPagesData<typeof record>({
|
|
135
|
+
const result = deleteRecordInPagesData<typeof record>({
|
|
170
136
|
data,
|
|
171
137
|
record,
|
|
172
|
-
processRecord: r => ({ ...r, text: 'updated ' + r.text }),
|
|
173
138
|
})
|
|
174
139
|
|
|
175
140
|
expect(result).toEqual({
|
|
@@ -185,11 +150,7 @@ describe('addRecordInPagesData', () => {
|
|
|
185
150
|
meta: { count: 2, totalCount: 2 },
|
|
186
151
|
},
|
|
187
152
|
{
|
|
188
|
-
data: [
|
|
189
|
-
{ id: '3', type: 'Message', text: 'message 3' },
|
|
190
|
-
{ id: '4', type: 'Message', text: 'message 4' },
|
|
191
|
-
{ ...record, text: `updated example ${id}` },
|
|
192
|
-
],
|
|
153
|
+
data: [{ id: '3', type: 'Message', text: 'message 3' }],
|
|
193
154
|
included: [],
|
|
194
155
|
links: {},
|
|
195
156
|
meta: { count: 2, totalCount: 2 },
|
|
@@ -7,6 +7,7 @@ import { MessageReaction } from '../../components/conversation/message_reaction'
|
|
|
7
7
|
import { Avatar, Text } from '../../components/display'
|
|
8
8
|
import { useTheme } from '../../hooks'
|
|
9
9
|
import { MessageResource } from '../../types'
|
|
10
|
+
import { ReactionCountResource } from '../../types/resources/reaction'
|
|
10
11
|
|
|
11
12
|
/** Message
|
|
12
13
|
* Component for display of a message within a conversation list
|
|
@@ -21,9 +22,13 @@ export function Message(props: MessageResource & { conversation_id: string }) {
|
|
|
21
22
|
conversation_id,
|
|
22
23
|
})
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const handleReactionPress = (reaction: ReactionCountResource) => {
|
|
26
|
+
navigation.navigate('Reactions', {
|
|
27
|
+
message_id: props.id,
|
|
28
|
+
conversation_id,
|
|
29
|
+
reaction_value: reaction.value,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
27
32
|
if (!text) return null
|
|
28
33
|
|
|
29
34
|
return (
|
|
@@ -19,12 +19,16 @@ export function MessageReaction({
|
|
|
19
19
|
onPress,
|
|
20
20
|
}: {
|
|
21
21
|
reaction: ReactionCountResource
|
|
22
|
-
onPress: () => void
|
|
22
|
+
onPress: (_reaction: ReactionCountResource) => void
|
|
23
23
|
}) {
|
|
24
24
|
const styles = useReactionStyles(reaction)
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
|
-
<PlatformPressable
|
|
27
|
+
<PlatformPressable
|
|
28
|
+
key={reaction.value}
|
|
29
|
+
style={styles.reaction}
|
|
30
|
+
onPress={() => onPress(reaction)}
|
|
31
|
+
>
|
|
28
32
|
<Text style={styles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>
|
|
29
33
|
<Text style={styles.reactionText}>{reaction.count}</Text>
|
|
30
34
|
</PlatformPressable>
|
|
@@ -1,45 +1,42 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import { FlatList, Pressable, StyleSheet } from 'react-native'
|
|
3
|
+
import { FlatList, Pressable, StyleSheet, View } from 'react-native'
|
|
4
4
|
import { useTheme } from '../hooks'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { Heading, Text } from './display'
|
|
5
|
+
import { useConversationsJoltEvents } from '../hooks/use_conversation_jolt_events'
|
|
6
|
+
import { useConversations } from '../hooks/use_conversations'
|
|
7
|
+
import { formatDatePreview } from '../utils/date'
|
|
8
|
+
import { AvatarGroup, Badge, Heading, Text, TextButton } from './display'
|
|
9
9
|
|
|
10
10
|
export const Conversations = () => {
|
|
11
11
|
const styles = useStyles()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
data: {
|
|
15
|
-
perPage: 20,
|
|
16
|
-
order: '-last_message',
|
|
17
|
-
fields: {
|
|
18
|
-
Conversation: [
|
|
19
|
-
'title',
|
|
20
|
-
'last_message_created_at',
|
|
21
|
-
'last_message_author_name',
|
|
22
|
-
'last_message_text_preview',
|
|
23
|
-
'unread_count',
|
|
24
|
-
],
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
const { data: conversations, fetchNextPage } = useSuspensePaginator<ConversationResource>(request)
|
|
12
|
+
|
|
13
|
+
const { conversations, fetchNextPage, refetch, isRefetching } = useConversations()
|
|
29
14
|
|
|
30
15
|
// TODO: Filter using the API
|
|
31
16
|
const nonEmptyConversations = conversations.filter(c => c.lastMessageTextPreview) || []
|
|
32
|
-
|
|
33
17
|
const navigation = useNavigation()
|
|
34
18
|
|
|
19
|
+
useConversationsJoltEvents()
|
|
20
|
+
|
|
35
21
|
return (
|
|
36
22
|
<FlatList
|
|
37
23
|
data={nonEmptyConversations}
|
|
38
24
|
contentContainerStyle={styles.container}
|
|
39
25
|
style={styles.scrollView}
|
|
26
|
+
onRefresh={refetch}
|
|
27
|
+
refreshing={isRefetching}
|
|
28
|
+
ListHeaderComponent={
|
|
29
|
+
<View style={styles.header}>
|
|
30
|
+
<Heading numberOfLines={1} variant="h2">
|
|
31
|
+
Conversations
|
|
32
|
+
</Heading>
|
|
33
|
+
<TextButton>Mark all read</TextButton>
|
|
34
|
+
</View>
|
|
35
|
+
}
|
|
40
36
|
ListEmptyComponent={<Text>No conversations found</Text>}
|
|
41
37
|
renderItem={({ item }) => (
|
|
42
38
|
<Pressable
|
|
39
|
+
style={styles.conversation}
|
|
43
40
|
onPress={() =>
|
|
44
41
|
navigation.navigate('Conversation', {
|
|
45
42
|
conversation_id: item.id,
|
|
@@ -47,12 +44,30 @@ export const Conversations = () => {
|
|
|
47
44
|
})
|
|
48
45
|
}
|
|
49
46
|
>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
<AvatarGroup size="lg" sourceUris={item.previewAvatarUrls || []} />
|
|
48
|
+
<View style={styles.conversationBody}>
|
|
49
|
+
<Heading numberOfLines={1} variant="h3" style={styles.conversationTitle}>
|
|
50
|
+
{item.title}
|
|
51
|
+
</Heading>
|
|
52
|
+
<Text style={styles.listItem} numberOfLines={2}>
|
|
53
|
+
{item.lastMessageAuthorName}: {item.lastMessageTextPreview}
|
|
54
|
+
</Text>
|
|
55
|
+
<View style={styles.conversationBadges}>
|
|
56
|
+
{item.badges?.map(badge => (
|
|
57
|
+
<Badge
|
|
58
|
+
key={badge.text}
|
|
59
|
+
variant="meta"
|
|
60
|
+
productLogoName={badge.appName}
|
|
61
|
+
label={badge.pcoResourceType}
|
|
62
|
+
metaLabel={badge.text || ''}
|
|
63
|
+
/>
|
|
64
|
+
))}
|
|
65
|
+
</View>
|
|
66
|
+
</View>
|
|
67
|
+
<View style={styles.conversationExtra}>
|
|
68
|
+
<Text variant="secondary">{formatDatePreview(item.lastMessageCreatedAt)}</Text>
|
|
69
|
+
<UnreadCountBadge count={item.unreadCount} />
|
|
70
|
+
</View>
|
|
56
71
|
</Pressable>
|
|
57
72
|
)}
|
|
58
73
|
onEndReached={() => fetchNextPage()}
|
|
@@ -60,13 +75,61 @@ export const Conversations = () => {
|
|
|
60
75
|
)
|
|
61
76
|
}
|
|
62
77
|
|
|
78
|
+
const UnreadCountBadge = ({ count }: { count: number }) => {
|
|
79
|
+
const styles = useStyles()
|
|
80
|
+
const displayCount = count > 99 ? '99+' : count
|
|
81
|
+
|
|
82
|
+
if (count === 0) return null
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<Text variant="tertiary" style={styles.unreadCountBadge}>
|
|
86
|
+
{displayCount}
|
|
87
|
+
</Text>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
63
91
|
const useStyles = () => {
|
|
64
92
|
const { colors } = useTheme()
|
|
65
93
|
|
|
66
94
|
return StyleSheet.create({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
95
|
+
header: {
|
|
96
|
+
flexDirection: 'row',
|
|
97
|
+
justifyContent: 'space-between',
|
|
98
|
+
paddingTop: 8,
|
|
99
|
+
paddingBottom: 8,
|
|
100
|
+
paddingHorizontal: 16,
|
|
101
|
+
},
|
|
102
|
+
scrollView: { flex: 1 },
|
|
103
|
+
container: { gap: 8, paddingVertical: 16 },
|
|
70
104
|
listItem: { color: colors.fillColorNeutral020 },
|
|
105
|
+
conversation: {
|
|
106
|
+
flexDirection: 'row',
|
|
107
|
+
gap: 8,
|
|
108
|
+
borderBottomWidth: 1,
|
|
109
|
+
borderBottomColor: colors.fillColorNeutral060,
|
|
110
|
+
paddingTop: 4,
|
|
111
|
+
paddingBottom: 12,
|
|
112
|
+
paddingHorizontal: 16,
|
|
113
|
+
},
|
|
114
|
+
conversationTitle: {},
|
|
115
|
+
conversationBody: {
|
|
116
|
+
flex: 1,
|
|
117
|
+
rowGap: 2,
|
|
118
|
+
},
|
|
119
|
+
conversationExtra: {
|
|
120
|
+
rowGap: 2,
|
|
121
|
+
},
|
|
122
|
+
conversationBadges: {
|
|
123
|
+
marginTop: 4,
|
|
124
|
+
alignItems: 'flex-start',
|
|
125
|
+
},
|
|
126
|
+
unreadCountBadge: {
|
|
127
|
+
alignSelf: 'flex-end',
|
|
128
|
+
backgroundColor: colors.interaction,
|
|
129
|
+
paddingVertical: 0,
|
|
130
|
+
paddingHorizontal: 10,
|
|
131
|
+
borderRadius: 24,
|
|
132
|
+
color: 'white',
|
|
133
|
+
},
|
|
71
134
|
})
|
|
72
135
|
}
|
|
@@ -54,12 +54,7 @@ type VariantStyles = Record<
|
|
|
54
54
|
}
|
|
55
55
|
>
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
groups: 'groups',
|
|
59
|
-
services: 'services',
|
|
60
|
-
} as const
|
|
61
|
-
|
|
62
|
-
type PoductLogoNameUnion = (typeof LOGO_NAMES)[keyof typeof LOGO_NAMES]
|
|
57
|
+
type ProductLogoName = 'Groups' | 'Services' | 'groups' | 'services'
|
|
63
58
|
|
|
64
59
|
const PRODUCT_LOGO_COMPONENT_MAP = {
|
|
65
60
|
groups: GroupsLogo,
|
|
@@ -90,7 +85,7 @@ interface BadgeProps {
|
|
|
90
85
|
/**
|
|
91
86
|
* Adds a product logo to the left of the text.
|
|
92
87
|
*/
|
|
93
|
-
productLogoName?:
|
|
88
|
+
productLogoName?: ProductLogoName
|
|
94
89
|
/**
|
|
95
90
|
* Shows an icon of the user choice to the left of the text.
|
|
96
91
|
*/
|
|
@@ -123,7 +118,7 @@ export function Badge({
|
|
|
123
118
|
const hasMetaLabel = Boolean(metaLabel)
|
|
124
119
|
|
|
125
120
|
const showLogo = showBadgeLogo && productLogoName && isMeta
|
|
126
|
-
const ProductLogoSvg = showLogo && PRODUCT_LOGO_COMPONENT_MAP[productLogoName]
|
|
121
|
+
const ProductLogoSvg = showLogo && PRODUCT_LOGO_COMPONENT_MAP[productLogoName?.toLowerCase()]
|
|
127
122
|
const badgeLabel = isMetaSubtle && hasMetaLabel ? `${label}:` : label
|
|
128
123
|
|
|
129
124
|
return (
|