@planningcenter/chat-react-native 1.6.2-rc.3 → 1.7.0-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.
Files changed (50) hide show
  1. package/build/components/conversation/message_reaction.d.ts +8 -0
  2. package/build/components/conversation/message_reaction.d.ts.map +1 -0
  3. package/build/components/conversation/message_reaction.js +44 -0
  4. package/build/components/conversation/message_reaction.js.map +1 -0
  5. package/build/hooks/use_conversation_messages.d.ts +45 -0
  6. package/build/hooks/use_conversation_messages.d.ts.map +1 -0
  7. package/build/hooks/use_conversation_messages.js +33 -0
  8. package/build/hooks/use_conversation_messages.js.map +1 -0
  9. package/build/hooks/use_suspense_api.d.ts +3 -2
  10. package/build/hooks/use_suspense_api.d.ts.map +1 -1
  11. package/build/hooks/use_suspense_api.js +3 -2
  12. package/build/hooks/use_suspense_api.js.map +1 -1
  13. package/build/navigation/index.d.ts +5 -0
  14. package/build/navigation/index.d.ts.map +1 -1
  15. package/build/navigation/index.js +9 -3
  16. package/build/navigation/index.js.map +1 -1
  17. package/build/screens/conversation_screen.d.ts.map +1 -1
  18. package/build/screens/conversation_screen.js +91 -37
  19. package/build/screens/conversation_screen.js.map +1 -1
  20. package/build/screens/message_actions_screen.d.ts +10 -0
  21. package/build/screens/message_actions_screen.d.ts.map +1 -0
  22. package/build/screens/message_actions_screen.js +128 -0
  23. package/build/screens/message_actions_screen.js.map +1 -0
  24. package/build/types/api_primitives.d.ts +1 -2
  25. package/build/types/api_primitives.d.ts.map +1 -1
  26. package/build/types/api_primitives.js.map +1 -1
  27. package/build/utils/cache/index.d.ts +2 -0
  28. package/build/utils/cache/index.d.ts.map +1 -0
  29. package/build/utils/cache/index.js +2 -0
  30. package/build/utils/cache/index.js.map +1 -0
  31. package/build/utils/cache/page_mutations.d.ts +37 -0
  32. package/build/utils/cache/page_mutations.d.ts.map +1 -0
  33. package/build/utils/cache/page_mutations.js +42 -0
  34. package/build/utils/cache/page_mutations.js.map +1 -0
  35. package/build/utils/index.d.ts +1 -0
  36. package/build/utils/index.d.ts.map +1 -1
  37. package/build/utils/index.js +1 -0
  38. package/build/utils/index.js.map +1 -1
  39. package/package.json +3 -2
  40. package/src/__tests__/utils/cache/page_mutations.ts +206 -0
  41. package/src/components/conversation/message_reaction.tsx +57 -0
  42. package/src/hooks/use_conversation_messages.ts +43 -0
  43. package/src/hooks/use_suspense_api.ts +16 -2
  44. package/src/navigation/index.tsx +9 -3
  45. package/src/screens/conversation_screen.tsx +111 -40
  46. package/src/screens/message_actions_screen.tsx +167 -0
  47. package/src/types/api_primitives.ts +1 -1
  48. package/src/utils/cache/index.ts +1 -0
  49. package/src/utils/cache/page_mutations.ts +66 -0
  50. package/src/utils/index.ts +1 -0
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { ReactionCountResource } from '../../types/resources/reaction';
3
+ export declare const REACTION_EMOJIS: Record<ReactionCountResource['value'], string>;
4
+ export declare function MessageReaction({ reaction, onPress, }: {
5
+ reaction: ReactionCountResource;
6
+ onPress: () => void;
7
+ }): React.JSX.Element;
8
+ //# sourceMappingURL=message_reaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message_reaction.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/message_reaction.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAA;AAEtE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,CAM1E,CAAA;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,qBASA"}
@@ -0,0 +1,44 @@
1
+ import { PlatformPressable } from '@react-navigation/elements';
2
+ import colorFunction from 'color';
3
+ import React from 'react';
4
+ import { StyleSheet } from 'react-native';
5
+ import { Text } from '../../components/display';
6
+ import { useTheme } from '../../hooks';
7
+ export const REACTION_EMOJIS = {
8
+ thumbs_up: '👍',
9
+ thumbs_down: '👎',
10
+ pray: '🙏',
11
+ laugh: '😂',
12
+ heart: '❤️',
13
+ };
14
+ export function MessageReaction({ reaction, onPress, }) {
15
+ const styles = useReactionStyles(reaction);
16
+ return (<PlatformPressable key={reaction.value} style={styles.reaction} onPress={onPress}>
17
+ <Text style={styles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>
18
+ <Text style={styles.reactionText}>{reaction.count}</Text>
19
+ </PlatformPressable>);
20
+ }
21
+ const useReactionStyles = ({ mine }) => {
22
+ const { colors } = useTheme();
23
+ const activeBorderColor = colorFunction(colors.interaction).alpha(0.8).string();
24
+ const activeColor = colorFunction(colors.interaction).alpha(0.2).string();
25
+ return StyleSheet.create({
26
+ reaction: {
27
+ borderWidth: 1,
28
+ borderColor: mine ? activeBorderColor : colors.fillColorNeutral040,
29
+ backgroundColor: mine ? activeColor : colors.fillColorNeutral050Base,
30
+ borderRadius: 16,
31
+ paddingVertical: 2,
32
+ paddingHorizontal: 12,
33
+ flexDirection: 'row',
34
+ alignItems: 'center',
35
+ gap: 4,
36
+ },
37
+ reactionEmoji: { fontSize: 12, paddingTop: 0 },
38
+ reactionText: { fontSize: 12, color: colors.textColorDefaultPrimary },
39
+ pressed: {
40
+ opacity: 0.5,
41
+ },
42
+ });
43
+ };
44
+ //# sourceMappingURL=message_reaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message_reaction.js","sourceRoot":"","sources":["../../../src/components/conversation/message_reaction.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,aAAa,MAAM,OAAO,CAAA;AACjC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGtC,MAAM,CAAC,MAAM,eAAe,GAAmD;IAC7E,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;CACZ,CAAA;AAED,MAAM,UAAU,eAAe,CAAC,EAC9B,QAAQ,EACR,OAAO,GAIR;IACC,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IAE1C,OAAO,CACL,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAC/E;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAC1E;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAC1D;IAAA,EAAE,iBAAiB,CAAC,CACrB,CAAA;AACH,CAAC;AAED,MAAM,iBAAiB,GAAG,CAAC,EAAE,IAAI,EAAoB,EAAE,EAAE;IACvD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC7B,MAAM,iBAAiB,GAAG,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAA;IAC/E,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAA;IAEzE,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,QAAQ,EAAE;YACR,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB;YAClE,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,uBAAuB;YACpE,YAAY,EAAE,EAAE;YAChB,eAAe,EAAE,CAAC;YAClB,iBAAiB,EAAE,EAAE;YACrB,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,CAAC;SACP;QACD,aAAa,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;QAC9C,YAAY,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,uBAAuB,EAAE;QACrE,OAAO,EAAE;YACP,OAAO,EAAE,GAAG;SACb;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { PlatformPressable } from '@react-navigation/elements'\nimport colorFunction from 'color'\nimport React from 'react'\nimport { StyleSheet } from 'react-native'\nimport { Text } from '../../components/display'\nimport { useTheme } from '../../hooks'\nimport { ReactionCountResource } from '../../types/resources/reaction'\n\nexport const REACTION_EMOJIS: Record<ReactionCountResource['value'], string> = {\n thumbs_up: '👍',\n thumbs_down: '👎',\n pray: '🙏',\n laugh: '😂',\n heart: '❤️',\n}\n\nexport function MessageReaction({\n reaction,\n onPress,\n}: {\n reaction: ReactionCountResource\n onPress: () => void\n}) {\n const styles = useReactionStyles(reaction)\n\n return (\n <PlatformPressable key={reaction.value} style={styles.reaction} onPress={onPress}>\n <Text style={styles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>\n <Text style={styles.reactionText}>{reaction.count}</Text>\n </PlatformPressable>\n )\n}\n\nconst useReactionStyles = ({ mine }: { mine: number }) => {\n const { colors } = useTheme()\n const activeBorderColor = colorFunction(colors.interaction).alpha(0.8).string()\n const activeColor = colorFunction(colors.interaction).alpha(0.2).string()\n\n return StyleSheet.create({\n reaction: {\n borderWidth: 1,\n borderColor: mine ? activeBorderColor : colors.fillColorNeutral040,\n backgroundColor: mine ? activeColor : colors.fillColorNeutral050Base,\n borderRadius: 16,\n paddingVertical: 2,\n paddingHorizontal: 12,\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n reactionEmoji: { fontSize: 12, paddingTop: 0 },\n reactionText: { fontSize: 12, color: colors.textColorDefaultPrimary },\n pressed: {\n opacity: 0.5,\n },\n })\n}\n"]}
@@ -0,0 +1,45 @@
1
+ import { MessageResource } from '../types';
2
+ import { SuspensePaginatorOptions } from './use_suspense_api';
3
+ export declare const useConversationMessages: ({ conversation_id }: {
4
+ conversation_id: string;
5
+ }, opts?: SuspensePaginatorOptions) => {
6
+ messages: MessageResource[];
7
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../types").ApiCollection<MessageResource>, unknown>, Response>>;
8
+ isRefetching: boolean;
9
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../types").ApiCollection<MessageResource>, unknown>, Response>>;
10
+ queryKey: (string | {
11
+ perPage: number;
12
+ fields: {
13
+ Message: string[];
14
+ Person: string[];
15
+ ReactionCount: string[];
16
+ };
17
+ include: string[];
18
+ })[];
19
+ };
20
+ export declare const getMessagesRequestArgs: ({ conversation_id }: {
21
+ conversation_id: string;
22
+ }) => {
23
+ url: string;
24
+ data: {
25
+ perPage: number;
26
+ fields: {
27
+ Message: string[];
28
+ Person: string[];
29
+ ReactionCount: string[];
30
+ };
31
+ include: string[];
32
+ };
33
+ };
34
+ export declare const getMessagesQueryKey: ({ conversation_id }: {
35
+ conversation_id: string;
36
+ }) => (string | {
37
+ perPage: number;
38
+ fields: {
39
+ Message: string[];
40
+ Person: string[];
41
+ ReactionCount: string[];
42
+ };
43
+ include: string[];
44
+ })[];
45
+ //# sourceMappingURL=use_conversation_messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_conversation_messages.d.ts","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,wBAAwB,EAAwB,MAAM,oBAAoB,CAAA;AAEnF,eAAO,MAAM,uBAAuB,wBACb;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,SACzC,wBAAwB;;;;;;;;;;;;;;CAUhC,CAAA;AAED,eAAO,MAAM,sBAAsB,wBAAyB;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;CAoBrF,CAAA;AAEF,eAAO,MAAM,mBAAmB,wBAAyB;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE;;;;;;;;IAGnF,CAAA"}
@@ -0,0 +1,33 @@
1
+ import { useSuspensePaginator } from './use_suspense_api';
2
+ export const useConversationMessages = ({ conversation_id }, opts) => {
3
+ const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator(getMessagesRequestArgs({ conversation_id }), opts);
4
+ const queryKey = getMessagesQueryKey({ conversation_id });
5
+ const messages = data.sort((a, b) => -a.id.localeCompare(b.id));
6
+ return { messages, refetch, isRefetching, fetchNextPage, queryKey };
7
+ };
8
+ export const getMessagesRequestArgs = ({ conversation_id }) => ({
9
+ url: `/me/conversations/${conversation_id}/messages`,
10
+ data: {
11
+ perPage: 25,
12
+ fields: {
13
+ Message: [
14
+ 'text',
15
+ 'text_edited_at',
16
+ 'mine',
17
+ 'attachments',
18
+ 'created_at',
19
+ 'deleted_at',
20
+ 'author',
21
+ 'reaction_counts',
22
+ ],
23
+ Person: ['name', 'avatar'],
24
+ ReactionCount: ['value', 'count', 'mine', 'message_id', 'author_ids'],
25
+ },
26
+ include: ['author', 'reaction_counts'],
27
+ },
28
+ });
29
+ export const getMessagesQueryKey = ({ conversation_id }) => {
30
+ const requestArgs = getMessagesRequestArgs({ conversation_id });
31
+ return [requestArgs.url, requestArgs.data];
32
+ };
33
+ //# sourceMappingURL=use_conversation_messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_conversation_messages.js","sourceRoot":"","sources":["../../src/hooks/use_conversation_messages.ts"],"names":[],"mappings":"AACA,OAAO,EAA4B,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAEnF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,EAAE,eAAe,EAA+B,EAChD,IAA+B,EAC/B,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,oBAAoB,CACzE,sBAAsB,CAAC,EAAE,eAAe,EAAE,CAAC,EAC3C,IAAI,CACL,CAAA;IACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,eAAe,EAAE,CAAC,CAAA;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAE/D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AACrE,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EAAE,eAAe,EAA+B,EAAE,EAAE,CAAC,CAAC;IAC3F,GAAG,EAAE,qBAAqB,eAAe,WAAW;IACpD,IAAI,EAAE;QACJ,OAAO,EAAE,EAAE;QACX,MAAM,EAAE;YACN,OAAO,EAAE;gBACP,MAAM;gBACN,gBAAgB;gBAChB,MAAM;gBACN,aAAa;gBACb,YAAY;gBACZ,YAAY;gBACZ,QAAQ;gBACR,iBAAiB;aAClB;YACD,MAAM,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;YAC1B,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC;SACtE;QACD,OAAO,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC;KACvC;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,eAAe,EAA+B,EAAE,EAAE;IACtF,MAAM,WAAW,GAAG,sBAAsB,CAAC,EAAE,eAAe,EAAE,CAAC,CAAA;IAC/D,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;AAC5C,CAAC,CAAA","sourcesContent":["import { MessageResource } from '../types'\nimport { SuspensePaginatorOptions, useSuspensePaginator } from './use_suspense_api'\n\nexport const useConversationMessages = (\n { conversation_id }: { conversation_id: string },\n opts?: SuspensePaginatorOptions\n) => {\n const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator<MessageResource>(\n getMessagesRequestArgs({ conversation_id }),\n opts\n )\n const queryKey = getMessagesQueryKey({ conversation_id })\n const messages = data.sort((a, b) => -a.id.localeCompare(b.id))\n\n return { messages, refetch, isRefetching, fetchNextPage, queryKey }\n}\n\nexport const getMessagesRequestArgs = ({ conversation_id }: { conversation_id: string }) => ({\n url: `/me/conversations/${conversation_id}/messages`,\n data: {\n perPage: 25,\n fields: {\n Message: [\n 'text',\n 'text_edited_at',\n 'mine',\n 'attachments',\n 'created_at',\n 'deleted_at',\n 'author',\n 'reaction_counts',\n ],\n Person: ['name', 'avatar'],\n ReactionCount: ['value', 'count', 'mine', 'message_id', 'author_ids'],\n },\n include: ['author', 'reaction_counts'],\n },\n})\n\nexport const getMessagesQueryKey = ({ conversation_id }: { conversation_id: string }) => {\n const requestArgs = getMessagesRequestArgs({ conversation_id })\n return [requestArgs.url, requestArgs.data]\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { InfiniteData } from '@tanstack/react-query';
1
+ import { AnyUseSuspenseInfiniteQueryOptions, InfiniteData } from '@tanstack/react-query';
2
2
  import { ApiCollection, ApiResource, ResourceObject } from '../types';
3
3
  import { GetRequest } from '../utils/client/types';
4
4
  export declare const useSuspenseGet: <T extends ResourceObject | ResourceObject[]>(args: GetRequest) => (T extends ResourceObject ? ApiResource<T> : ApiCollection<T>) & {
@@ -25,7 +25,8 @@ export declare const useSuspenseGet: <T extends ResourceObject | ResourceObject[
25
25
  refetch: (options?: import("@tanstack/react-query").RefetchOptions) => Promise<import("@tanstack/react-query").QueryObserverResult<T extends ResourceObject ? ApiResource<T> : ApiCollection<T>, Response>>;
26
26
  fetchStatus: import("@tanstack/react-query").FetchStatus;
27
27
  };
28
- export declare const useSuspensePaginator: <T extends ResourceObject>(args: GetRequest) => {
28
+ export type SuspensePaginatorOptions = Omit<AnyUseSuspenseInfiniteQueryOptions, 'getNextPageParam' | 'initialPageParam' | 'queryFn' | 'queryKey'>;
29
+ export declare const useSuspensePaginator: <T extends ResourceObject>(args: GetRequest, opts?: SuspensePaginatorOptions) => {
29
30
  data: T[];
30
31
  error: Response | null;
31
32
  isError: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"use_suspense_api.d.ts","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA8C,MAAM,uBAAuB,CAAA;AAGhG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,EAAE,UAAU,EAAe,MAAM,uBAAuB,CAAA;AAE/D,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,QAAQ,UAAU;;;;;;;;;;;;;;;;;;;;;;;CAQ3F,CAAA;AAOD,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,cAAc,QAAQ,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsC9E,CAAA"}
1
+ {"version":3,"file":"use_suspense_api.d.ts","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,EAClC,YAAY,EAGb,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACrE,OAAO,EAAE,UAAU,EAAe,MAAM,uBAAuB,CAAA;AAE/D,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EAAE,QAAQ,UAAU;;;;;;;;;;;;;;;;;;;;;;;CAQ3F,CAAA;AAOD,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,kCAAkC,EAClC,kBAAkB,GAAG,kBAAkB,GAAG,SAAS,GAAG,UAAU,CACjE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,cAAc,QACrD,UAAU,SACT,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwChC,CAAA"}
@@ -1,4 +1,4 @@
1
- import { useSuspenseInfiniteQuery, useSuspenseQuery } from '@tanstack/react-query';
1
+ import { useSuspenseInfiniteQuery, useSuspenseQuery, } from '@tanstack/react-query';
2
2
  import { useContext } from 'react';
3
3
  import { ChatContext } from '../contexts';
4
4
  export const useSuspenseGet = (args) => {
@@ -7,7 +7,7 @@ export const useSuspenseGet = (args) => {
7
7
  });
8
8
  return { ...data, ...query };
9
9
  };
10
- export const useSuspensePaginator = (args) => {
10
+ export const useSuspensePaginator = (args, opts) => {
11
11
  const { client } = useContext(ChatContext);
12
12
  const query = useSuspenseInfiniteQuery({
13
13
  queryKey: [args.url, args.data],
@@ -32,6 +32,7 @@ export const useSuspensePaginator = (args) => {
32
32
  return { offset: Number(offset) };
33
33
  return undefined;
34
34
  },
35
+ ...(opts || {}),
35
36
  });
36
37
  const data = query.data?.pages.flatMap(page => page.data) || [];
37
38
  return { ...query, data };
@@ -1 +1 @@
1
- {"version":3,"file":"use_suspense_api.js","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAIzC,MAAM,CAAC,MAAM,cAAc,GAAG,CAA8C,IAAgB,EAAE,EAAE;IAG9F,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,gBAAgB,CAAqB;QAC9D,QAAQ,EAAE,CAAC,IAAI,CAAC;KACjB,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAA;AAC9B,CAAC,CAAA;AAOD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAA2B,IAAgB,EAAE,EAAE;IACjF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,wBAAwB,CAMpC;QACA,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;QAC/B,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;YACzB,MAAM,aAAa,GAAG,SAAS,EAAE,KAAK,IAAI,EAAE,CAAA;YAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;YACvC,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,EAAE,GAAG,aAAa,EAAE,CAAA;YAEhD,MAAM,MAAM,GAAG,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;YACpD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;YAE5C,OAAO,MAAM,CAAC,GAAG,CAAC;gBAChB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI;aACL,CAAC,CAAA;QACJ,CAAC;QACD,gBAAgB,EAAE,EAA0B;QAC5C,gBAAgB,EAAE,QAAQ,CAAC,EAAE;YAC3B,MAAM,IAAI,GAAa,QAAQ,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAA;YAChD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAA;YAE7B,IAAI,IAAI;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAA;YAC3C,IAAI,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAA;YAE7C,OAAO,SAAS,CAAA;QAClB,CAAC;KACF,CAAC,CAAA;IAEF,MAAM,IAAI,GAAQ,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAEpE,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC,CAAA","sourcesContent":["import { InfiniteData, useSuspenseInfiniteQuery, useSuspenseQuery } from '@tanstack/react-query'\nimport { useContext } from 'react'\nimport { ChatContext } from '../contexts'\nimport { ApiCollection, ApiResource, ResourceObject } from '../types'\nimport { GetRequest, RequestData } from '../utils/client/types'\n\nexport const useSuspenseGet = <T extends ResourceObject | ResourceObject[]>(args: GetRequest) => {\n type Resource = T extends ResourceObject ? ApiResource<T> : ApiCollection<T>\n\n const { data, ...query } = useSuspenseQuery<Resource, Response>({\n queryKey: [args],\n })\n\n return { ...data, ...query }\n}\n\ntype NextMeta = Partial<{\n offset: string\n idLt: string\n}>\n\nexport const useSuspensePaginator = <T extends ResourceObject>(args: GetRequest) => {\n const { client } = useContext(ChatContext)\n const query = useSuspenseInfiniteQuery<\n ApiCollection<T>,\n Response,\n InfiniteData<ApiCollection<T>>,\n any,\n Partial<RequestData> | undefined\n >({\n queryKey: [args.url, args.data],\n queryFn: ({ pageParam }) => {\n const pageParmWhere = pageParam?.where || {}\n const argsWhere = args.data.where || {}\n const where = { ...argsWhere, ...pageParmWhere }\n\n const offset = pageParam?.offset || args.data.offset\n const data = { ...args.data, where, offset }\n\n return client.get({\n url: args.url,\n data,\n })\n },\n initialPageParam: {} as Partial<RequestData>,\n getNextPageParam: lastPage => {\n const next: NextMeta = lastPage.meta?.next || {}\n const { offset, idLt } = next\n\n if (idLt) return { where: { id_lt: idLt } }\n if (offset) return { offset: Number(offset) }\n\n return undefined\n },\n })\n\n const data: T[] = query.data?.pages.flatMap(page => page.data) || []\n\n return { ...query, data }\n}\n"]}
1
+ {"version":3,"file":"use_suspense_api.js","sourceRoot":"","sources":["../../src/hooks/use_suspense_api.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAIzC,MAAM,CAAC,MAAM,cAAc,GAAG,CAA8C,IAAgB,EAAE,EAAE;IAG9F,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,gBAAgB,CAAqB;QAC9D,QAAQ,EAAE,CAAC,IAAI,CAAC;KACjB,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAA;AAC9B,CAAC,CAAA;AAYD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAAgB,EAChB,IAA+B,EAC/B,EAAE;IACF,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,wBAAwB,CAMpC;QACA,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;QAC/B,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;YACzB,MAAM,aAAa,GAAG,SAAS,EAAE,KAAK,IAAI,EAAE,CAAA;YAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;YACvC,MAAM,KAAK,GAAG,EAAE,GAAG,SAAS,EAAE,GAAG,aAAa,EAAE,CAAA;YAEhD,MAAM,MAAM,GAAG,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;YACpD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;YAE5C,OAAO,MAAM,CAAC,GAAG,CAAC;gBAChB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,IAAI;aACL,CAAC,CAAA;QACJ,CAAC;QACD,gBAAgB,EAAE,EAA0B;QAC5C,gBAAgB,EAAE,QAAQ,CAAC,EAAE;YAC3B,MAAM,IAAI,GAAa,QAAQ,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE,CAAA;YAChD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAA;YAE7B,IAAI,IAAI;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAA;YAC3C,IAAI,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAA;YAE7C,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;KAChB,CAAC,CAAA;IAEF,MAAM,IAAI,GAAQ,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAEpE,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC,CAAA","sourcesContent":["import {\n AnyUseSuspenseInfiniteQueryOptions,\n InfiniteData,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n} from '@tanstack/react-query'\nimport { useContext } from 'react'\nimport { ChatContext } from '../contexts'\nimport { ApiCollection, ApiResource, ResourceObject } from '../types'\nimport { GetRequest, RequestData } from '../utils/client/types'\n\nexport const useSuspenseGet = <T extends ResourceObject | ResourceObject[]>(args: GetRequest) => {\n type Resource = T extends ResourceObject ? ApiResource<T> : ApiCollection<T>\n\n const { data, ...query } = useSuspenseQuery<Resource, Response>({\n queryKey: [args],\n })\n\n return { ...data, ...query }\n}\n\ntype NextMeta = Partial<{\n offset: string\n idLt: string\n}>\n\nexport type SuspensePaginatorOptions = Omit<\n AnyUseSuspenseInfiniteQueryOptions,\n 'getNextPageParam' | 'initialPageParam' | 'queryFn' | 'queryKey'\n>\n\nexport const useSuspensePaginator = <T extends ResourceObject>(\n args: GetRequest,\n opts?: SuspensePaginatorOptions\n) => {\n const { client } = useContext(ChatContext)\n const query = useSuspenseInfiniteQuery<\n ApiCollection<T>,\n Response,\n InfiniteData<ApiCollection<T>>,\n any,\n Partial<RequestData> | undefined\n >({\n queryKey: [args.url, args.data],\n queryFn: ({ pageParam }) => {\n const pageParmWhere = pageParam?.where || {}\n const argsWhere = args.data.where || {}\n const where = { ...argsWhere, ...pageParmWhere }\n\n const offset = pageParam?.offset || args.data.offset\n const data = { ...args.data, where, offset }\n\n return client.get({\n url: args.url,\n data,\n })\n },\n initialPageParam: {} as Partial<RequestData>,\n getNextPageParam: lastPage => {\n const next: NextMeta = lastPage.meta?.next || {}\n const { offset, idLt } = next\n\n if (idLt) return { where: { id_lt: idLt } }\n if (offset) return { offset: Number(offset) }\n\n return undefined\n },\n ...(opts || {}),\n })\n\n const data: T[] = query.data?.pages.flatMap(page => page.data) || []\n\n return { ...query, data }\n}\n"]}
@@ -4,6 +4,7 @@ import { NotFound } from '../screens/not_found';
4
4
  import { ScreenLayout } from './screenLayout';
5
5
  import { ConversationsScreen } from '../screens/conversations_screen';
6
6
  import { ConversationScreen } from '../screens/conversation_screen';
7
+ import { MessageActionsScreen } from '../screens/message_actions_screen';
7
8
  export declare const ChatStack: import("@react-navigation/native").TypedNavigator<{
8
9
  ParamList: import("@react-navigation/native").ParamListBase;
9
10
  NavigatorID: undefined;
@@ -32,6 +33,10 @@ export declare const ChatStack: import("@react-navigation/native").TypedNavigato
32
33
  readonly Conversation: {
33
34
  readonly screen: typeof ConversationScreen;
34
35
  };
36
+ readonly MessageActions: {
37
+ readonly screen: typeof MessageActionsScreen;
38
+ readonly options: import("@react-navigation/native-stack").NativeStackNavigationOptions;
39
+ };
35
40
  readonly NotFound: {
36
41
  readonly screen: typeof NotFound;
37
42
  readonly options: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/navigation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAInE,eAAO,MAAM,SAAS;;;;;;;;;uOAApB,mBAAmB;;;;;;;;;uBA0C+lhB,gBAAiB,KAAK;;;;;;;;;;;;;;;;;;;;EATxohB,CAAA;AAEF,KAAK,kBAAkB,GAAG,eAAe,CAAC,OAAO,SAAS,CAAC,CAAA;AAE3D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,eAAe,CAAC;QACxB,UAAU,aAAc,SAAQ,kBAAkB;SAAG;KACtD;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/navigation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAGnE,OAAO,EAAE,oBAAoB,EAAsB,MAAM,mCAAmC,CAAA;AAE5F,eAAO,MAAM,SAAS;;;;;;;;;uOAFb,mBAAkB;;;;;;;;;uBAiDq3gB,gBAAiB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;EATp6gB,CAAA;AAEF,KAAK,kBAAkB,GAAG,eAAe,CAAC,OAAO,SAAS,CAAC,CAAA;AAE3D,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,eAAe,CAAC;QACxB,UAAU,aAAc,SAAQ,kBAAkB;SAAG;KACtD;CACF"}
@@ -4,8 +4,9 @@ import { NotFound } from '../screens/not_found';
4
4
  import { ScreenLayout } from './screenLayout';
5
5
  import { ConversationsScreen } from '../screens/conversations_screen';
6
6
  import { ConversationScreen } from '../screens/conversation_screen';
7
- import { HeaderBackButton, PlatformPressable } from '@react-navigation/elements';
7
+ import { HeaderBackButton, HeaderButton } from '@react-navigation/elements';
8
8
  import { Icon } from '../components';
9
+ import { MessageActionsScreen, ReactScreenOptions } from '../screens/message_actions_screen';
9
10
  export const ChatStack = createNativeStackNavigator({
10
11
  screenLayout: ScreenLayout,
11
12
  screens: {
@@ -13,15 +14,20 @@ export const ChatStack = createNativeStackNavigator({
13
14
  screen: ConversationsScreen,
14
15
  options: ({ route, navigation }) => ({
15
16
  headerTitle: route.params?.title ?? 'Chat',
16
- headerLeft: () => (<PlatformPressable onPress={() => null}>
17
+ headerLeft: () => (<HeaderButton>
17
18
  <Icon name="general.threeReducingHorizontalBars" size={18}/>
18
- </PlatformPressable>),
19
+ </HeaderButton>),
19
20
  headerRight: () => (<HeaderBackButton onPress={navigation.goBack} backImage={() => <Icon name="general.x" size={18}/>}/>),
20
21
  }),
21
22
  },
22
23
  Conversation: {
23
24
  screen: ConversationScreen,
24
25
  },
26
+ MessageActions: {
27
+ screen: MessageActionsScreen,
28
+ // Something about sheetAllowedDetents declared inline breaks TS
29
+ options: ReactScreenOptions,
30
+ },
25
31
  NotFound: {
26
32
  screen: NotFound,
27
33
  options: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/navigation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAA;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAChF,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAEpC,MAAM,CAAC,MAAM,SAAS,GAAG,0BAA0B,CAAC;IAClD,YAAY,EAAE,YAAY;IAC1B,OAAO,EAAE;QACP,aAAa,EAAE;YACb,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;gBACnC,WAAW,EAAG,KAAK,CAAC,MAA6B,EAAE,KAAK,IAAI,MAAM;gBAClE,UAAU,EAAE,GAAG,EAAE,CAAC,CAChB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CACrC;YAAA,CAAC,IAAI,CAAC,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAC5D;UAAA,EAAE,iBAAiB,CAAC,CACrB;gBACD,WAAW,EAAE,GAAG,EAAE,CAAC,CACjB,CAAC,gBAAgB,CACf,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAC3B,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EACrD,CACH;aACF,CAAC;SACH;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,kBAAkB;SAC3B;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK;aACb;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,GAAG;aACV;SACF;KACF;CACF,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { StaticParamList } from '@react-navigation/native'\nimport { createNativeStackNavigator } from '@react-navigation/native-stack'\nimport { NotFound } from '../screens/not_found'\nimport { ScreenLayout } from './screenLayout'\nimport { ConversationsScreen } from '../screens/conversations_screen'\nimport { ConversationScreen } from '../screens/conversation_screen'\nimport { HeaderBackButton, PlatformPressable } from '@react-navigation/elements'\nimport { Icon } from '../components'\n\nexport const ChatStack = createNativeStackNavigator({\n screenLayout: ScreenLayout,\n screens: {\n Conversations: {\n screen: ConversationsScreen,\n options: ({ route, navigation }) => ({\n headerTitle: (route.params as { title?: string })?.title ?? 'Chat',\n headerLeft: () => (\n <PlatformPressable onPress={() => null}>\n <Icon name=\"general.threeReducingHorizontalBars\" size={18} />\n </PlatformPressable>\n ),\n headerRight: () => (\n <HeaderBackButton\n onPress={navigation.goBack}\n backImage={() => <Icon name=\"general.x\" size={18} />}\n />\n ),\n }),\n },\n Conversation: {\n screen: ConversationScreen,\n },\n NotFound: {\n screen: NotFound,\n options: {\n title: '404',\n },\n linking: {\n path: '*',\n },\n },\n },\n})\n\ntype ChatStackParamList = StaticParamList<typeof ChatStack>\n\ndeclare global {\n namespace ReactNavigation {\n interface RootParamList extends ChatStackParamList {}\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/navigation/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAA;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAE5F,MAAM,CAAC,MAAM,SAAS,GAAG,0BAA0B,CAAC;IAClD,YAAY,EAAE,YAAY;IAC1B,OAAO,EAAE;QACP,aAAa,EAAE;YACb,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;gBACnC,WAAW,EAAG,KAAK,CAAC,MAA6B,EAAE,KAAK,IAAI,MAAM;gBAClE,UAAU,EAAE,GAAG,EAAE,CAAC,CAChB,CAAC,YAAY,CACX;YAAA,CAAC,IAAI,CAAC,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAC5D;UAAA,EAAE,YAAY,CAAC,CAChB;gBACD,WAAW,EAAE,GAAG,EAAE,CAAC,CACjB,CAAC,gBAAgB,CACf,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAC3B,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAG,CAAC,EACrD,CACH;aACF,CAAC;SACH;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,kBAAkB;SAC3B;QACD,cAAc,EAAE;YACd,MAAM,EAAE,oBAAoB;YAC5B,gEAAgE;YAChE,OAAO,EAAE,kBAAkB;SAC5B;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK;aACb;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,GAAG;aACV;SACF;KACF;CACF,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { StaticParamList } from '@react-navigation/native'\nimport { createNativeStackNavigator } from '@react-navigation/native-stack'\nimport { NotFound } from '../screens/not_found'\nimport { ScreenLayout } from './screenLayout'\nimport { ConversationsScreen } from '../screens/conversations_screen'\nimport { ConversationScreen } from '../screens/conversation_screen'\nimport { HeaderBackButton, HeaderButton } from '@react-navigation/elements'\nimport { Icon } from '../components'\nimport { MessageActionsScreen, ReactScreenOptions } from '../screens/message_actions_screen'\n\nexport const ChatStack = createNativeStackNavigator({\n screenLayout: ScreenLayout,\n screens: {\n Conversations: {\n screen: ConversationsScreen,\n options: ({ route, navigation }) => ({\n headerTitle: (route.params as { title?: string })?.title ?? 'Chat',\n headerLeft: () => (\n <HeaderButton>\n <Icon name=\"general.threeReducingHorizontalBars\" size={18} />\n </HeaderButton>\n ),\n headerRight: () => (\n <HeaderBackButton\n onPress={navigation.goBack}\n backImage={() => <Icon name=\"general.x\" size={18} />}\n />\n ),\n }),\n },\n Conversation: {\n screen: ConversationScreen,\n },\n MessageActions: {\n screen: MessageActionsScreen,\n // Something about sheetAllowedDetents declared inline breaks TS\n options: ReactScreenOptions,\n },\n NotFound: {\n screen: NotFound,\n options: {\n title: '404',\n },\n linking: {\n path: '*',\n },\n },\n },\n})\n\ntype ChatStackParamList = StaticParamList<typeof ChatStack>\n\ndeclare global {\n namespace ReactNavigation {\n interface RootParamList extends ChatStackParamList {}\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAoB,MAAM,OAAO,CAAA;AAOxC,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;IACtD,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;CAC5B,CAAC,CAAA;AAEF,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBAkDpE"}
1
+ {"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EAGlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAoB,MAAM,OAAO,CAAA;AAUxC,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;IACtD,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;CAC5B,CAAC,CAAA;AAEF,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA6CpE"}
@@ -1,12 +1,18 @@
1
- import { useNavigation } from '@react-navigation/native';
1
+ import { PlatformPressable } from '@react-navigation/elements';
2
+ import { useNavigation, useTheme as useNavigationTheme, } from '@react-navigation/native';
3
+ import colorFunction from 'color';
2
4
  import React, { useEffect } from 'react';
3
- import { FlatList, SafeAreaView, StyleSheet, TextInput, View } from 'react-native';
4
- import { Text } from '../components/display';
5
- import { useSuspenseGet, useSuspensePaginator } from '../hooks/use_suspense_api';
5
+ import { FlatList, StyleSheet, TextInput, View } from 'react-native';
6
+ import { SafeAreaView } from 'react-native-safe-area-context';
7
+ import { MessageReaction } from '../components/conversation/message_reaction';
8
+ import { Avatar, Text } from '../components/display';
6
9
  import { useTheme } from '../hooks';
10
+ import { useConversationMessages } from '../hooks/use_conversation_messages';
11
+ import { useSuspenseGet } from '../hooks/use_suspense_api';
7
12
  export function ConversationScreen({ route }) {
8
13
  const navigation = useNavigation();
9
14
  const { conversation_id } = route.params;
15
+ const styles = useStyles();
10
16
  const { data: conversation } = useSuspenseGet({
11
17
  url: `/me/conversations/${conversation_id}`,
12
18
  data: {
@@ -15,55 +21,103 @@ export function ConversationScreen({ route }) {
15
21
  },
16
22
  },
17
23
  });
18
- const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator({
19
- url: `/me/conversations/${conversation_id}/messages`,
20
- data: {
21
- perPage: 25,
22
- fields: {
23
- Message: ['text', 'mine'],
24
- },
25
- },
24
+ const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({
25
+ conversation_id,
26
26
  });
27
27
  useEffect(() => {
28
28
  navigation.setOptions({ title: conversation?.title });
29
29
  }, [conversation, conversation_id, navigation]);
30
- return (<SafeAreaView style={styles.container}>
31
- <FlatList inverted contentContainerStyle={styles.listContainer} refreshing={isRefetching} onRefresh={refetch} data={data} keyExtractor={item => item.id} renderItem={({ item }) => <Message {...item}/>} onEndReached={() => fetchNextPage()}/>
30
+ return (<SafeAreaView style={styles.container} edges={['top', 'bottom', 'left', 'right']}>
31
+ <FlatList inverted contentContainerStyle={styles.listContainer} refreshing={isRefetching} onRefresh={refetch} data={messages} keyExtractor={item => item.id} renderItem={({ item }) => <Message {...item} conversation_id={conversation_id}/>} onEndReached={() => fetchNextPage()}/>
32
32
  <View style={styles.textInputContainer}>
33
33
  <TextInput aria-disabled={true} placeholder="Send a message" onChangeText={() => console.log('TODO: Implement sending a message')} value="" style={styles.textInput}/>
34
34
  </View>
35
35
  </SafeAreaView>);
36
36
  }
37
- function Message(message) {
38
- const { text } = message;
39
- const styles = useMessageStyles(message);
40
- return <Text style={styles.message}>{text}</Text>;
37
+ const useStyles = () => {
38
+ const navigationTheme = useNavigationTheme();
39
+ return StyleSheet.create({
40
+ container: {
41
+ flex: 1,
42
+ justifyContent: 'center',
43
+ backgroundColor: navigationTheme.colors.card,
44
+ },
45
+ listContainer: {
46
+ gap: 12,
47
+ paddingHorizontal: 16,
48
+ paddingVertical: 12,
49
+ },
50
+ textInputContainer: {
51
+ borderTopWidth: 1,
52
+ padding: 12,
53
+ backgroundColor: navigationTheme.colors.card,
54
+ },
55
+ textInput: { borderRadius: 16, borderWidth: 1, padding: 12 },
56
+ });
57
+ };
58
+ function Message(props) {
59
+ const { text, conversation_id, reactionCounts } = props;
60
+ const styles = useMessageStyles(props);
61
+ const navigation = useNavigation();
62
+ const handleMessagePress = () => {
63
+ navigation.navigate('MessageActions', {
64
+ message_id: props.id,
65
+ conversation_id,
66
+ });
67
+ };
68
+ // TODO: open the reaction screen to show who reacted
69
+ const handleReactionPress = handleMessagePress;
70
+ if (!text)
71
+ return null;
72
+ return (<View style={styles.message}>
73
+ {!props.mine && (<View style={styles.messageAuthor}>
74
+ <Avatar size={'md'} sourceUri={props.author.avatar}/>
75
+ </View>)}
76
+ <View style={styles.messageContent}>
77
+ {!props.mine && (<Text variant="tertiary" style={styles.authorName}>
78
+ {props.author.name}
79
+ </Text>)}
80
+ <PlatformPressable style={styles.messageBubble} onLongPress={handleMessagePress}>
81
+ <Text style={styles.messageText}>{text}</Text>
82
+ </PlatformPressable>
83
+ <View style={styles.messageReactions}>
84
+ {reactionCounts.map(reaction => (<MessageReaction key={reaction.value} reaction={reaction} onPress={handleReactionPress}/>))}
85
+ </View>
86
+ </View>
87
+ </View>);
41
88
  }
42
89
  const useMessageStyles = ({ mine }) => {
43
90
  const { colors } = useTheme();
91
+ const activeColor = colorFunction(colors.interaction).alpha(0.2).string();
44
92
  return StyleSheet.create({
45
93
  message: {
46
- alignSelf: mine ? 'flex-end' : 'flex-start',
47
- backgroundColor: mine ? colors.fillColorNeutral040 : colors.fillColorNeutral050Base,
48
- borderRadius: 16,
49
- borderBottomLeftRadius: mine ? 16 : 0,
50
- borderBottomRightRadius: mine ? 0 : 16,
51
- padding: 12,
94
+ gap: 8,
95
+ flexDirection: mine ? 'row-reverse' : 'row',
96
+ },
97
+ messageContent: {
98
+ gap: 8,
99
+ flexShrink: 1,
100
+ },
101
+ messageAuthor: {
102
+ flexDirection: 'row',
103
+ gap: 8,
104
+ },
105
+ authorName: {},
106
+ authorAvatar: {},
107
+ messageBubble: {
108
+ backgroundColor: mine ? activeColor : colors.fillColorNeutral070,
109
+ borderRadius: 12,
110
+ paddingVertical: 6,
111
+ paddingHorizontal: 8,
112
+ },
113
+ messageText: {
52
114
  color: colors.textColorDefaultPrimary,
53
115
  },
116
+ messageReactions: {
117
+ flexDirection: 'row',
118
+ gap: 4,
119
+ justifyContent: mine ? 'flex-end' : 'flex-start',
120
+ },
54
121
  });
55
122
  };
56
- const styles = StyleSheet.create({
57
- container: {
58
- flex: 1,
59
- justifyContent: 'center',
60
- },
61
- listContainer: {
62
- gap: 12,
63
- paddingHorizontal: 16,
64
- paddingTop: 12,
65
- },
66
- textInputContainer: { borderTopWidth: 1, padding: 12 },
67
- textInput: { borderRadius: 16, borderWidth: 1, padding: 12 },
68
- });
69
123
  //# sourceMappingURL=conversation_screen.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation_screen.js","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport React, { useEffect } from 'react'\nimport { FlatList, SafeAreaView, StyleSheet, TextInput, View } from 'react-native'\nimport { Text } from '../components/display'\nimport { useSuspenseGet, useSuspensePaginator } from '../hooks/use_suspense_api'\nimport { ConversationResource, MessageResource } from '../types'\nimport { useTheme } from '../hooks'\n\nexport type ConversationScreenProps = StaticScreenProps<{\n conversation_id: string\n chat_group_graph_id: string\n}>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const navigation = useNavigation()\n const { conversation_id } = route.params\n\n const { data: conversation } = useSuspenseGet<ConversationResource>({\n url: `/me/conversations/${conversation_id}`,\n data: {\n fields: {\n Conversation: ['title'],\n },\n },\n })\n\n const { data, refetch, isRefetching, fetchNextPage } = useSuspensePaginator<MessageResource>({\n url: `/me/conversations/${conversation_id}/messages`,\n data: {\n perPage: 25,\n fields: {\n Message: ['text', 'mine'],\n },\n },\n })\n\n useEffect(() => {\n navigation.setOptions({ title: conversation?.title })\n }, [conversation, conversation_id, navigation])\n\n return (\n <SafeAreaView style={styles.container}>\n <FlatList\n inverted\n contentContainerStyle={styles.listContainer}\n refreshing={isRefetching}\n onRefresh={refetch}\n data={data}\n keyExtractor={item => item.id}\n renderItem={({ item }) => <Message {...item} />}\n onEndReached={() => fetchNextPage()}\n />\n <View style={styles.textInputContainer}>\n <TextInput\n aria-disabled={true}\n placeholder=\"Send a message\"\n onChangeText={() => console.log('TODO: Implement sending a message')}\n value=\"\"\n style={styles.textInput}\n />\n </View>\n </SafeAreaView>\n )\n}\n\nfunction Message(message: MessageResource) {\n const { text } = message\n const styles = useMessageStyles(message)\n\n return <Text style={styles.message}>{text}</Text>\n}\n\nconst useMessageStyles = ({ mine }: MessageResource) => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n message: {\n alignSelf: mine ? 'flex-end' : 'flex-start',\n backgroundColor: mine ? colors.fillColorNeutral040 : colors.fillColorNeutral050Base,\n borderRadius: 16,\n borderBottomLeftRadius: mine ? 16 : 0,\n borderBottomRightRadius: mine ? 0 : 16,\n padding: 12,\n color: colors.textColorDefaultPrimary,\n },\n })\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n listContainer: {\n gap: 12,\n paddingHorizontal: 16,\n paddingTop: 12,\n },\n textInputContainer: { borderTopWidth: 1, padding: 12 },\n textInput: { borderRadius: 16, borderWidth: 1, padding: 12 },\n})\n"]}
1
+ {"version":3,"file":"conversation_screen.js","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { PlatformPressable } from '@react-navigation/elements'\nimport {\n StaticScreenProps,\n useNavigation,\n useTheme as useNavigationTheme,\n} from '@react-navigation/native'\nimport colorFunction from 'color'\nimport React, { useEffect } from 'react'\nimport { FlatList, StyleSheet, TextInput, View } from 'react-native'\nimport { SafeAreaView } from 'react-native-safe-area-context'\nimport { MessageReaction } from '../components/conversation/message_reaction'\nimport { Avatar, Text } from '../components/display'\nimport { useTheme } from '../hooks'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useSuspenseGet } from '../hooks/use_suspense_api'\nimport { ConversationResource, MessageResource } from '../types'\n\nexport type ConversationScreenProps = StaticScreenProps<{\n conversation_id: string\n chat_group_graph_id: string\n}>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const navigation = useNavigation()\n const { conversation_id } = route.params\n const styles = useStyles()\n\n const { data: conversation } = useSuspenseGet<ConversationResource>({\n url: `/me/conversations/${conversation_id}`,\n data: {\n fields: {\n Conversation: ['title'],\n },\n },\n })\n\n const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({\n conversation_id,\n })\n\n useEffect(() => {\n navigation.setOptions({ title: conversation?.title })\n }, [conversation, conversation_id, navigation])\n\n return (\n <SafeAreaView style={styles.container} edges={['top', 'bottom', 'left', 'right']}>\n <FlatList\n inverted\n contentContainerStyle={styles.listContainer}\n refreshing={isRefetching}\n onRefresh={refetch}\n data={messages}\n keyExtractor={item => item.id}\n renderItem={({ item }) => <Message {...item} conversation_id={conversation_id} />}\n onEndReached={() => fetchNextPage()}\n />\n <View style={styles.textInputContainer}>\n <TextInput\n aria-disabled={true}\n placeholder=\"Send a message\"\n onChangeText={() => console.log('TODO: Implement sending a message')}\n value=\"\"\n style={styles.textInput}\n />\n </View>\n </SafeAreaView>\n )\n}\n\nconst useStyles = () => {\n const navigationTheme = useNavigationTheme()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n backgroundColor: navigationTheme.colors.card,\n },\n listContainer: {\n gap: 12,\n paddingHorizontal: 16,\n paddingVertical: 12,\n },\n textInputContainer: {\n borderTopWidth: 1,\n padding: 12,\n backgroundColor: navigationTheme.colors.card,\n },\n textInput: { borderRadius: 16, borderWidth: 1, padding: 12 },\n })\n}\n\nfunction Message(props: MessageResource & { conversation_id: string }) {\n const { text, conversation_id, reactionCounts } = props\n const styles = useMessageStyles(props)\n const navigation = useNavigation()\n const handleMessagePress = () => {\n navigation.navigate('MessageActions', {\n message_id: props.id,\n conversation_id,\n })\n }\n // TODO: open the reaction screen to show who reacted\n const handleReactionPress = handleMessagePress\n\n if (!text) return null\n\n return (\n <View style={styles.message}>\n {!props.mine && (\n <View style={styles.messageAuthor}>\n <Avatar size={'md'} sourceUri={props.author.avatar} />\n </View>\n )}\n <View style={styles.messageContent}>\n {!props.mine && (\n <Text variant=\"tertiary\" style={styles.authorName}>\n {props.author.name}\n </Text>\n )}\n <PlatformPressable style={styles.messageBubble} onLongPress={handleMessagePress}>\n <Text style={styles.messageText}>{text}</Text>\n </PlatformPressable>\n <View style={styles.messageReactions}>\n {reactionCounts.map(reaction => (\n <MessageReaction\n key={reaction.value}\n reaction={reaction}\n onPress={handleReactionPress}\n />\n ))}\n </View>\n </View>\n </View>\n )\n}\n\nconst useMessageStyles = ({ mine }: MessageResource) => {\n const { colors } = useTheme()\n const activeColor = colorFunction(colors.interaction).alpha(0.2).string()\n\n return StyleSheet.create({\n message: {\n gap: 8,\n flexDirection: mine ? 'row-reverse' : 'row',\n },\n messageContent: {\n gap: 8,\n flexShrink: 1,\n },\n messageAuthor: {\n flexDirection: 'row',\n gap: 8,\n },\n authorName: {},\n authorAvatar: {},\n messageBubble: {\n backgroundColor: mine ? activeColor : colors.fillColorNeutral070,\n borderRadius: 12,\n paddingVertical: 6,\n paddingHorizontal: 8,\n },\n messageText: {\n color: colors.textColorDefaultPrimary,\n },\n messageReactions: {\n flexDirection: 'row',\n gap: 4,\n justifyContent: mine ? 'flex-end' : 'flex-start',\n },\n })\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import { StaticScreenProps } from '@react-navigation/native';
2
+ import { NativeStackNavigationOptions } from '@react-navigation/native-stack';
3
+ import React from 'react';
4
+ export declare const ReactScreenOptions: NativeStackNavigationOptions;
5
+ export type ReactionScreenProps = StaticScreenProps<{
6
+ message_id: string;
7
+ conversation_id: string;
8
+ }>;
9
+ export declare function MessageActionsScreen({ route }: ReactionScreenProps): React.JSX.Element;
10
+ //# sourceMappingURL=message_actions_screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message_actions_screen.d.ts","sourceRoot":"","sources":["../../src/screens/message_actions_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAG7E,OAAO,KAAqB,MAAM,OAAO,CAAA;AAYzC,eAAO,MAAM,kBAAkB,EAAE,4BAKhC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;IAClD,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAC,CAAA;AAEF,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,EAAE,mBAAmB,qBAmGlE"}