@planningcenter/chat-react-native 3.2.0-rc.3 → 3.2.0-rc.5

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 (48) hide show
  1. package/build/components/conversation/message_form.d.ts +2 -2
  2. package/build/components/conversation/message_form.d.ts.map +1 -1
  3. package/build/components/conversation/message_form.js +95 -41
  4. package/build/components/conversation/message_form.js.map +1 -1
  5. package/build/components/conversations/action_toggle_button.d.ts +1 -1
  6. package/build/components/conversations/action_toggle_button.d.ts.map +1 -1
  7. package/build/components/conversations/action_toggle_button.js +2 -1
  8. package/build/components/conversations/action_toggle_button.js.map +1 -1
  9. package/build/components/conversations/conversation_actions.js +20 -5
  10. package/build/components/conversations/conversation_actions.js.map +1 -1
  11. package/build/contexts/chat_context.d.ts +1 -0
  12. package/build/contexts/chat_context.d.ts.map +1 -1
  13. package/build/contexts/chat_context.js +3 -1
  14. package/build/contexts/chat_context.js.map +1 -1
  15. package/build/hooks/use_giphy.d.ts +9 -0
  16. package/build/hooks/use_giphy.d.ts.map +1 -0
  17. package/build/hooks/use_giphy.js +63 -0
  18. package/build/hooks/use_giphy.js.map +1 -0
  19. package/build/hooks/use_message_create.d.ts +11 -0
  20. package/build/hooks/use_message_create.d.ts.map +1 -0
  21. package/build/hooks/use_message_create.js +35 -0
  22. package/build/hooks/use_message_create.js.map +1 -0
  23. package/build/navigation/index.d.ts +5 -0
  24. package/build/navigation/index.d.ts.map +1 -1
  25. package/build/navigation/index.js +5 -0
  26. package/build/navigation/index.js.map +1 -1
  27. package/build/screens/conversation_screen.d.ts +1 -0
  28. package/build/screens/conversation_screen.d.ts.map +1 -1
  29. package/build/screens/conversation_screen.js +1 -1
  30. package/build/screens/conversation_screen.js.map +1 -1
  31. package/build/screens/message_actions_screen.d.ts +2 -2
  32. package/build/screens/message_actions_screen.d.ts.map +1 -1
  33. package/build/screens/message_actions_screen.js.map +1 -1
  34. package/build/screens/send_giphy_screen.d.ts +10 -0
  35. package/build/screens/send_giphy_screen.d.ts.map +1 -0
  36. package/build/screens/send_giphy_screen.js +98 -0
  37. package/build/screens/send_giphy_screen.js.map +1 -0
  38. package/package.json +2 -2
  39. package/src/components/conversation/message_form.tsx +127 -58
  40. package/src/components/conversations/action_toggle_button.tsx +2 -1
  41. package/src/components/conversations/conversation_actions.tsx +29 -6
  42. package/src/contexts/chat_context.tsx +4 -1
  43. package/src/hooks/use_giphy.ts +97 -0
  44. package/src/hooks/use_message_create.ts +55 -0
  45. package/src/navigation/index.tsx +5 -0
  46. package/src/screens/conversation_screen.tsx +2 -1
  47. package/src/screens/message_actions_screen.tsx +2 -2
  48. package/src/screens/send_giphy_screen.tsx +155 -0
@@ -14,7 +14,7 @@ interface MessagesFormRootProps extends ViewProps {
14
14
  declare function MessageFormRoot({ conversation, children }: MessagesFormRootProps): React.JSX.Element;
15
15
  declare function MessageFormInput(): React.JSX.Element;
16
16
  declare function MessageFormSubmitBtn(): React.JSX.Element;
17
- declare function MessageFormAttachmentPicker(): React.JSX.Element;
18
- declare function MessageFormCommands(): React.JSX.Element;
17
+ declare function MessageFormAttachmentPicker(): React.JSX.Element | null;
18
+ declare function MessageFormCommands(): React.JSX.Element | null;
19
19
  export {};
20
20
  //# sourceMappingURL=message_form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"message_form.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/message_form.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAA+B,SAAS,EAAE,MAAM,cAAc,CAAA;AAKrE,OAAO,EAA8B,oBAAoB,EAAmB,MAAM,aAAa,CAAA;AAG/F,eAAO,MAAM,WAAW;;;;;;CAMvB,CAAA;AAED,UAAU,qBAAsB,SAAQ,SAAS;IAC/C,YAAY,EAAE,oBAAoB,CAAA;CACnC;AASD,iBAAS,eAAe,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,qBAAqB,qBA+CzE;AAED,iBAAS,gBAAgB,sBAcxB;AAED,iBAAS,oBAAoB,sBAe5B;AAED,iBAAS,2BAA2B,sBASnC;AAED,iBAAS,mBAAmB,sBAI3B"}
1
+ {"version":3,"file":"message_form.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/message_form.tsx"],"names":[],"mappings":"AACA,OAAO,KAA0C,MAAM,OAAO,CAAA;AAC9D,OAAO,EAA+B,SAAS,EAAE,MAAM,cAAc,CAAA;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAKlD,eAAO,MAAM,WAAW;;;;;;CAMvB,CAAA;AAED,UAAU,qBAAsB,SAAQ,SAAS;IAC/C,YAAY,EAAE,oBAAoB,CAAA;CACnC;AAYD,iBAAS,eAAe,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,qBAAqB,qBAsEzE;AAED,iBAAS,gBAAgB,sBAqBxB;AAED,iBAAS,oBAAoB,sBAe5B;AAED,iBAAS,2BAA2B,6BAenC;AAED,iBAAS,mBAAmB,6BA4B3B"}
@@ -1,12 +1,10 @@
1
- import { useTheme as useNavigationTheme } from '@react-navigation/native';
2
- import { useMutation, useQueryClient } from '@tanstack/react-query';
3
- import React from 'react';
1
+ import { useNavigation, useTheme as useNavigationTheme, useRoute } from '@react-navigation/native';
2
+ import React, { useContext, useEffect, useState } from 'react';
4
3
  import { StyleSheet, TextInput, View } from 'react-native';
5
- import { IconButton } from '../../components';
4
+ import { IconButton, Text } from '../../components';
6
5
  import { useTheme } from '../../hooks';
7
- import { useApiClient } from '../../hooks/use_api_client';
8
- import { getMessagesQueryKey, getMessagesRequestArgs } from '../../hooks/use_conversation_messages';
9
- import { updateOrCreateRecordInPagesData } from '../../utils';
6
+ import { useMessageCreate } from '../../hooks/use_message_create';
7
+ import { ChatContext } from '../../contexts/chat_context';
10
8
  export const MessageForm = {
11
9
  Root: MessageFormRoot,
12
10
  TextInput: MessageFormInput,
@@ -19,57 +17,106 @@ const MessageFormContext = React.createContext({
19
17
  setText: (_text) => { },
20
18
  onSubmit: () => { },
21
19
  disabled: false,
20
+ canGiphy: false,
21
+ usingGiphy: false,
22
+ setUsingGiphy: (_usingGiphy) => { },
22
23
  });
23
24
  function MessageFormRoot({ conversation, children }) {
25
+ const { giphyApiKey } = useContext(ChatContext);
26
+ const canGiphy = !!giphyApiKey;
24
27
  const styles = useMessageFormStyles();
25
28
  const [text, setText] = React.useState('');
26
- const apiClient = useApiClient();
27
- const queryClient = useQueryClient();
28
- const { mutate, isPending } = useMutation({
29
- mutationFn: async () => {
30
- const requestParams = getMessagesRequestArgs({ conversation_id: conversation.id });
31
- const fieldsWithValueJoined = Object.fromEntries(Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')]));
32
- return apiClient.chat.post({
33
- url: `/me/conversations/${conversation.id}/messages`,
34
- data: {
35
- ...requestParams.data,
36
- data: {
37
- type: 'Message',
38
- attributes: { text },
39
- },
40
- fields: fieldsWithValueJoined,
41
- },
42
- });
43
- },
44
- onSuccess: (result) => {
45
- const updatedMessage = result.data;
46
- const queryKey = getMessagesQueryKey({ conversation_id: conversation.id });
29
+ const [usingGiphy, setUsingGiphy] = useState(false);
30
+ const navigation = useNavigation();
31
+ const route = useRoute();
32
+ const { status, isPending, reset, mutate } = useMessageCreate({ conversationId: conversation.id });
33
+ useEffect(() => {
34
+ if (canGiphy && !usingGiphy && text.startsWith('/giphy ')) {
35
+ setUsingGiphy(true);
47
36
  setText('');
48
- queryClient.setQueryData(queryKey, data => updateOrCreateRecordInPagesData({
49
- data,
50
- record: updatedMessage,
51
- }));
52
- },
53
- });
54
- return (<MessageFormContext.Provider value={{ text, setText, onSubmit: () => mutate(), disabled: isPending }}>
37
+ }
38
+ }, [canGiphy, text, usingGiphy]);
39
+ useEffect(() => {
40
+ switch (status) {
41
+ case 'success':
42
+ setText('');
43
+ reset();
44
+ break;
45
+ }
46
+ }, [reset, status]);
47
+ useEffect(() => {
48
+ if (route.params.clear_input) {
49
+ setText('');
50
+ setUsingGiphy(false);
51
+ navigation.setParams({ ...route.params, clear_input: false });
52
+ }
53
+ }, [navigation, route.params]);
54
+ const canSubmit = (() => {
55
+ if (isPending)
56
+ return false;
57
+ if (text.length > 0)
58
+ return true;
59
+ return false;
60
+ })();
61
+ const disabled = !canSubmit;
62
+ const handleSubmit = () => {
63
+ if (!canSubmit)
64
+ return;
65
+ if (canGiphy && usingGiphy) {
66
+ TextInput.State.blurTextInput(TextInput.State.currentlyFocusedInput());
67
+ navigation.navigate('SendGiphy', {
68
+ conversation_id: conversation.id,
69
+ search_term: text,
70
+ });
71
+ }
72
+ else {
73
+ mutate({ text });
74
+ }
75
+ };
76
+ return (<MessageFormContext.Provider value={{
77
+ text,
78
+ setText,
79
+ onSubmit: handleSubmit,
80
+ disabled,
81
+ canGiphy,
82
+ usingGiphy,
83
+ setUsingGiphy,
84
+ }}>
55
85
  <View style={styles.textInputContainer}>{children}</View>
56
86
  </MessageFormContext.Provider>);
57
87
  }
58
88
  function MessageFormInput() {
59
89
  const styles = useMessageFormStyles();
60
- const { text, setText, onSubmit } = React.useContext(MessageFormContext);
61
- return (<TextInput aria-disabled={true} placeholder="Send a message" onChangeText={setText} value={text} style={styles.textInput} onSubmitEditing={onSubmit}/>);
90
+ const { text, setText, onSubmit, usingGiphy } = React.useContext(MessageFormContext);
91
+ return (<View style={styles.textInput}>
92
+ {usingGiphy ? (<View style={styles.giphyBadge}>
93
+ <Text>/Giphy</Text>
94
+ </View>) : null}
95
+
96
+ <TextInput aria-disabled={true} placeholder="Send a message" onChangeText={setText} value={text} onSubmitEditing={onSubmit}/>
97
+ </View>);
62
98
  }
63
99
  function MessageFormSubmitBtn() {
64
100
  const styles = useMessageFormStyles();
65
- const { onSubmit, disabled } = React.useContext(MessageFormContext);
66
- return (<IconButton disabled={disabled} accessibilityLabel="Send message" size="md" appearance="neutral" style={styles.textInputSend} name={'general.upArrow'} onPress={onSubmit}/>);
101
+ const { onSubmit, disabled, usingGiphy } = React.useContext(MessageFormContext);
102
+ return (<IconButton disabled={disabled} accessibilityLabel={usingGiphy ? 'Search Giphy' : 'Send message'} size="md" appearance="neutral" style={styles.textInputSend} name={usingGiphy ? 'general.search' : 'general.upArrow'} onPress={onSubmit}/>);
67
103
  }
68
104
  function MessageFormAttachmentPicker() {
105
+ const { usingGiphy } = React.useContext(MessageFormContext);
106
+ if (usingGiphy) {
107
+ return null;
108
+ }
69
109
  return (<IconButton accessibilityLabel="Shazam" size="md" appearance="neutral" name={'general.paperclip'}/>);
70
110
  }
71
111
  function MessageFormCommands() {
72
- return (<IconButton accessibilityLabel="Shazam" size="md" appearance="neutral" name={'general.bolt'}/>);
112
+ const { canGiphy, usingGiphy, setUsingGiphy } = React.useContext(MessageFormContext);
113
+ if (!canGiphy) {
114
+ return null;
115
+ }
116
+ if (usingGiphy) {
117
+ return (<IconButton accessibilityLabel="Exit Giphy Search" size="md" appearance="neutral" name={'general.x'} onPress={() => setUsingGiphy(false)}/>);
118
+ }
119
+ return (<IconButton accessibilityLabel="Search Giphy" size="md" appearance="neutral" name={'general.bolt'} onPress={() => setUsingGiphy(true)}/>);
73
120
  }
74
121
  const useMessageFormStyles = () => {
75
122
  const theme = useTheme();
@@ -91,12 +138,19 @@ const useMessageFormStyles = () => {
91
138
  paddingHorizontal: 20,
92
139
  borderColor: theme.colors.fillColorNeutral050Base,
93
140
  flex: 1,
141
+ flexDirection: 'row',
142
+ gap: 12,
143
+ },
144
+ giphyBadge: {
145
+ backgroundColor: theme.colors.fillColorNeutral050Base,
146
+ borderRadius: 24,
147
+ padding: 8,
148
+ paddingHorizontal: 12,
94
149
  },
95
150
  textInputSend: {
96
151
  borderRadius: 24,
97
152
  height: 36,
98
153
  width: 36,
99
- backgroundColor: theme.colors.fillColorNeutral040,
100
154
  },
101
155
  });
102
156
  };
@@ -1 +1 @@
1
- {"version":3,"file":"message_form.js","sourceRoot":"","sources":["../../../src/components/conversation/message_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useTheme as useNavigationTheme } from '@react-navigation/native'\nimport { InfiniteData, useMutation, useQueryClient } from '@tanstack/react-query'\nimport React from 'react'\nimport { StyleSheet, TextInput, View, ViewProps } from 'react-native'\nimport { IconButton } from '../../components'\nimport { useTheme } from '../../hooks'\nimport { useApiClient } from '../../hooks/use_api_client'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from '../../hooks/use_conversation_messages'\nimport { ApiCollection, ApiResource, ConversationResource, MessageResource } from '../../types'\nimport { updateOrCreateRecordInPagesData } from '../../utils'\n\nexport const MessageForm = {\n Root: MessageFormRoot,\n TextInput: MessageFormInput,\n SubmitButton: MessageFormSubmitBtn,\n AttachmentPicker: MessageFormAttachmentPicker,\n Commands: MessageFormCommands,\n}\n\ninterface MessagesFormRootProps extends ViewProps {\n conversation: ConversationResource\n}\n\nconst MessageFormContext = React.createContext({\n text: '',\n setText: (_text: string) => {},\n onSubmit: () => {},\n disabled: false,\n})\n\nfunction MessageFormRoot({ conversation, children }: MessagesFormRootProps) {\n const styles = useMessageFormStyles()\n const [text, setText] = React.useState('')\n const apiClient = useApiClient()\n const queryClient = useQueryClient()\n\n const { mutate, isPending } = useMutation({\n mutationFn: async () => {\n const requestParams = getMessagesRequestArgs({ conversation_id: conversation.id })\n const fieldsWithValueJoined = Object.fromEntries(\n Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')])\n )\n\n return apiClient.chat.post<ApiResource<MessageResource>>({\n url: `/me/conversations/${conversation.id}/messages`,\n data: {\n ...requestParams.data,\n data: {\n type: 'Message',\n attributes: { text },\n },\n fields: fieldsWithValueJoined,\n },\n })\n },\n onSuccess: (result: ApiResource<MessageResource>) => {\n const updatedMessage = result.data\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n const queryKey = getMessagesQueryKey({ conversation_id: conversation.id })\n\n setText('')\n queryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: updatedMessage,\n })\n )\n },\n })\n\n return (\n <MessageFormContext.Provider\n value={{ text, setText, onSubmit: () => mutate(), disabled: isPending }}\n >\n <View style={styles.textInputContainer}>{children}</View>\n </MessageFormContext.Provider>\n )\n}\n\nfunction MessageFormInput() {\n const styles = useMessageFormStyles()\n const { text, setText, onSubmit } = React.useContext(MessageFormContext)\n\n return (\n <TextInput\n aria-disabled={true}\n placeholder=\"Send a message\"\n onChangeText={setText}\n value={text}\n style={styles.textInput}\n onSubmitEditing={onSubmit}\n />\n )\n}\n\nfunction MessageFormSubmitBtn() {\n const styles = useMessageFormStyles()\n const { onSubmit, disabled } = React.useContext(MessageFormContext)\n\n return (\n <IconButton\n disabled={disabled}\n accessibilityLabel=\"Send message\"\n size=\"md\"\n appearance=\"neutral\"\n style={styles.textInputSend}\n name={'general.upArrow'}\n onPress={onSubmit}\n />\n )\n}\n\nfunction MessageFormAttachmentPicker() {\n return (\n <IconButton\n accessibilityLabel=\"Shazam\"\n size=\"md\"\n appearance=\"neutral\"\n name={'general.paperclip'}\n />\n )\n}\n\nfunction MessageFormCommands() {\n return (\n <IconButton accessibilityLabel=\"Shazam\" size=\"md\" appearance=\"neutral\" name={'general.bolt'} />\n )\n}\n\nconst useMessageFormStyles = () => {\n const theme = useTheme()\n const navigationTheme = useNavigationTheme()\n\n return StyleSheet.create({\n textInputContainer: {\n borderColor: theme.colors.fillColorNeutral050Base,\n borderTopWidth: 1,\n padding: 12,\n backgroundColor: navigationTheme.colors.card,\n flexDirection: 'row',\n alignItems: 'center',\n gap: 12,\n },\n textInput: {\n borderRadius: 24,\n borderWidth: 1,\n padding: 12,\n paddingHorizontal: 20,\n borderColor: theme.colors.fillColorNeutral050Base,\n flex: 1,\n },\n textInputSend: {\n borderRadius: 24,\n height: 36,\n width: 36,\n backgroundColor: theme.colors.fillColorNeutral040,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"message_form.js","sourceRoot":"","sources":["../../../src/components/conversation/message_form.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation, useTheme as useNavigationTheme, useRoute } from '@react-navigation/native'\nimport React, { useContext, useEffect, useState } from 'react'\nimport { StyleSheet, TextInput, View, ViewProps } from 'react-native'\nimport { IconButton, Text } from '../../components'\nimport { useTheme } from '../../hooks'\nimport { ConversationResource } from '../../types'\nimport { useMessageCreate } from '../../hooks/use_message_create'\nimport { ConversationScreenProps } from '../../screens/conversation_screen'\nimport { ChatContext } from '../../contexts/chat_context'\n\nexport const MessageForm = {\n Root: MessageFormRoot,\n TextInput: MessageFormInput,\n SubmitButton: MessageFormSubmitBtn,\n AttachmentPicker: MessageFormAttachmentPicker,\n Commands: MessageFormCommands,\n}\n\ninterface MessagesFormRootProps extends ViewProps {\n conversation: ConversationResource\n}\n\nconst MessageFormContext = React.createContext({\n text: '',\n setText: (_text: string) => {},\n onSubmit: () => {},\n disabled: false,\n canGiphy: false,\n usingGiphy: false,\n setUsingGiphy: (_usingGiphy: boolean) => {},\n})\n\nfunction MessageFormRoot({ conversation, children }: MessagesFormRootProps) {\n const { giphyApiKey } = useContext(ChatContext)\n const canGiphy = !!giphyApiKey\n const styles = useMessageFormStyles()\n const [text, setText] = React.useState('')\n const [usingGiphy, setUsingGiphy] = useState(false)\n const navigation = useNavigation()\n const route = useRoute() as ConversationScreenProps['route']\n const { status, isPending, reset, mutate } = useMessageCreate({ conversationId: conversation.id })\n\n useEffect(() => {\n if (canGiphy && !usingGiphy && text.startsWith('/giphy ')) {\n setUsingGiphy(true)\n setText('')\n }\n }, [canGiphy, text, usingGiphy])\n\n useEffect(() => {\n switch (status) {\n case 'success':\n setText('')\n reset()\n break\n }\n }, [reset, status])\n\n useEffect(() => {\n if (route.params.clear_input) {\n setText('')\n setUsingGiphy(false)\n navigation.setParams({ ...route.params, clear_input: false })\n }\n }, [navigation, route.params])\n\n const canSubmit = (() => {\n if (isPending) return false\n if (text.length > 0) return true\n return false\n })()\n const disabled = !canSubmit\n\n const handleSubmit = () => {\n if (!canSubmit) return\n\n if (canGiphy && usingGiphy) {\n TextInput.State.blurTextInput(TextInput.State.currentlyFocusedInput())\n navigation.navigate('SendGiphy', {\n conversation_id: conversation.id,\n search_term: text,\n })\n } else {\n mutate({ text })\n }\n }\n\n return (\n <MessageFormContext.Provider\n value={{\n text,\n setText,\n onSubmit: handleSubmit,\n disabled,\n canGiphy,\n usingGiphy,\n setUsingGiphy,\n }}\n >\n <View style={styles.textInputContainer}>{children}</View>\n </MessageFormContext.Provider>\n )\n}\n\nfunction MessageFormInput() {\n const styles = useMessageFormStyles()\n const { text, setText, onSubmit, usingGiphy } = React.useContext(MessageFormContext)\n\n return (\n <View style={styles.textInput}>\n {usingGiphy ? (\n <View style={styles.giphyBadge}>\n <Text>/Giphy</Text>\n </View>\n ) : null}\n\n <TextInput\n aria-disabled={true}\n placeholder=\"Send a message\"\n onChangeText={setText}\n value={text}\n onSubmitEditing={onSubmit}\n />\n </View>\n )\n}\n\nfunction MessageFormSubmitBtn() {\n const styles = useMessageFormStyles()\n const { onSubmit, disabled, usingGiphy } = React.useContext(MessageFormContext)\n\n return (\n <IconButton\n disabled={disabled}\n accessibilityLabel={usingGiphy ? 'Search Giphy' : 'Send message'}\n size=\"md\"\n appearance=\"neutral\"\n style={styles.textInputSend}\n name={usingGiphy ? 'general.search' : 'general.upArrow'}\n onPress={onSubmit}\n />\n )\n}\n\nfunction MessageFormAttachmentPicker() {\n const { usingGiphy } = React.useContext(MessageFormContext)\n\n if (usingGiphy) {\n return null\n }\n\n return (\n <IconButton\n accessibilityLabel=\"Shazam\"\n size=\"md\"\n appearance=\"neutral\"\n name={'general.paperclip'}\n />\n )\n}\n\nfunction MessageFormCommands() {\n const { canGiphy, usingGiphy, setUsingGiphy } = React.useContext(MessageFormContext)\n\n if (!canGiphy) {\n return null\n }\n\n if (usingGiphy) {\n return (\n <IconButton\n accessibilityLabel=\"Exit Giphy Search\"\n size=\"md\"\n appearance=\"neutral\"\n name={'general.x'}\n onPress={() => setUsingGiphy(false)}\n />\n )\n }\n\n return (\n <IconButton\n accessibilityLabel=\"Search Giphy\"\n size=\"md\"\n appearance=\"neutral\"\n name={'general.bolt'}\n onPress={() => setUsingGiphy(true)}\n />\n )\n}\n\nconst useMessageFormStyles = () => {\n const theme = useTheme()\n const navigationTheme = useNavigationTheme()\n\n return StyleSheet.create({\n textInputContainer: {\n borderColor: theme.colors.fillColorNeutral050Base,\n borderTopWidth: 1,\n padding: 12,\n backgroundColor: navigationTheme.colors.card,\n flexDirection: 'row',\n alignItems: 'center',\n gap: 12,\n },\n textInput: {\n borderRadius: 24,\n borderWidth: 1,\n padding: 12,\n paddingHorizontal: 20,\n borderColor: theme.colors.fillColorNeutral050Base,\n flex: 1,\n flexDirection: 'row',\n gap: 12,\n },\n giphyBadge: {\n backgroundColor: theme.colors.fillColorNeutral050Base,\n borderRadius: 24,\n padding: 8,\n paddingHorizontal: 12,\n },\n textInputSend: {\n borderRadius: 24,\n height: 36,\n width: 36,\n },\n })\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { type PressableProps } from 'react-native';
2
+ import { type PressableProps } from 'react-native-gesture-handler';
3
3
  import { IconString } from '../display';
4
4
  interface ActionToggleButtonProps extends PressableProps {
5
5
  backgroundColor: string;
@@ -1 +1 @@
1
- {"version":3,"file":"action_toggle_button.d.ts","sourceRoot":"","sources":["../../../src/components/conversations/action_toggle_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAQ,UAAU,EAAiB,MAAM,YAAY,CAAA;AAI5D,UAAU,uBAAwB,SAAQ,cAAc;IACtD,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE;QACb,IAAI,EAAE;YAAE,QAAQ,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;QAC7C,KAAK,EAAE;YAAE,QAAQ,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAC/C,CAAA;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,eAAe,EACf,OAAO,EACP,aAAa,EACb,QAAgB,EAChB,OAAO,EACP,OAAe,EACf,GAAG,KAAK,EACT,EAAE,uBAAuB,qBA8BzB"}
1
+ {"version":3,"file":"action_toggle_button.d.ts","sourceRoot":"","sources":["../../../src/components/conversations/action_toggle_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7E,OAAO,EAAQ,UAAU,EAAiB,MAAM,YAAY,CAAA;AAI5D,UAAU,uBAAwB,SAAQ,cAAc;IACtD,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE;QACb,IAAI,EAAE;YAAE,QAAQ,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;QAC7C,KAAK,EAAE;YAAE,QAAQ,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAC/C,CAAA;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,eAAe,EACf,OAAO,EACP,aAAa,EACb,QAAgB,EAChB,OAAO,EACP,OAAe,EACf,GAAG,KAAK,EACT,EAAE,uBAAuB,qBA8BzB"}
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
- import { Pressable, StyleSheet } from 'react-native';
2
+ import { StyleSheet } from 'react-native';
3
+ import { Pressable } from 'react-native-gesture-handler';
3
4
  import { Icon, Spinner, Text } from '../display';
4
5
  import { useCreateAndroidRippleColor, useTheme } from '../../hooks';
5
6
  import { platformFontWeightMedium, platformPressedOpacityStyle } from '../../utils/styles';
@@ -1 +1 @@
1
- {"version":3,"file":"action_toggle_button.js","sourceRoot":"","sources":["../../../src/components/conversations/action_toggle_button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { Pressable, StyleSheet, type PressableProps } from 'react-native'\nimport { Icon, IconString, Spinner, Text } from '../display'\nimport { useCreateAndroidRippleColor, useTheme } from '../../hooks'\nimport { platformFontWeightMedium, platformPressedOpacityStyle } from '../../utils/styles'\n\ninterface ActionToggleButtonProps extends PressableProps {\n backgroundColor: string\n toggled: boolean\n toggleContent: {\n true: { iconName: IconString; label: string }\n false: { iconName: IconString; label: string }\n }\n loading?: boolean\n}\n\nexport function ActionToggleButton({\n backgroundColor,\n onPress,\n toggleContent,\n disabled = false,\n toggled,\n loading = false,\n ...props\n}: ActionToggleButtonProps) {\n const styles = useStyles({ backgroundColor, disabled })\n const androidRippleColor = useCreateAndroidRippleColor({\n color: backgroundColor,\n })\n\n const { iconName, label } = toggleContent[toggled ? 'true' : 'false']\n\n return (\n <Pressable\n onPress={onPress}\n style={({ pressed }) => [styles.button, pressed && platformPressedOpacityStyle]}\n android_ripple={{ color: androidRippleColor, borderless: false, foreground: true }}\n disabled={disabled || loading}\n accessibilityRole=\"togglebutton\"\n accessibilityState={{ checked: toggled }}\n {...props}\n >\n {loading ? (\n <Spinner size={20} />\n ) : (\n <>\n <Icon name={iconName} style={styles.icon} size={20} />\n <Text variant=\"footnote\" style={styles.text}>\n {label}\n </Text>\n </>\n )}\n </Pressable>\n )\n}\n\nconst useStyles = ({ backgroundColor, disabled }: Partial<ActionToggleButtonProps>) => {\n const { colors } = useTheme()\n const fillColor = disabled ? colors.textColorDefaultDisabled : colors.fillColorNeutral100Inverted\n const buttonBackgroundColor = disabled\n ? colors.fillColorButtonNeutralSolidDisabled\n : backgroundColor\n\n return StyleSheet.create({\n button: {\n flex: 1,\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n height: '100%',\n backgroundColor: buttonBackgroundColor,\n },\n icon: {\n color: fillColor,\n marginTop: 4,\n },\n text: {\n color: fillColor,\n fontWeight: platformFontWeightMedium,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"action_toggle_button.js","sourceRoot":"","sources":["../../../src/components/conversations/action_toggle_button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { StyleSheet } from 'react-native'\nimport { Pressable, type PressableProps } from 'react-native-gesture-handler'\nimport { Icon, IconString, Spinner, Text } from '../display'\nimport { useCreateAndroidRippleColor, useTheme } from '../../hooks'\nimport { platformFontWeightMedium, platformPressedOpacityStyle } from '../../utils/styles'\n\ninterface ActionToggleButtonProps extends PressableProps {\n backgroundColor: string\n toggled: boolean\n toggleContent: {\n true: { iconName: IconString; label: string }\n false: { iconName: IconString; label: string }\n }\n loading?: boolean\n}\n\nexport function ActionToggleButton({\n backgroundColor,\n onPress,\n toggleContent,\n disabled = false,\n toggled,\n loading = false,\n ...props\n}: ActionToggleButtonProps) {\n const styles = useStyles({ backgroundColor, disabled })\n const androidRippleColor = useCreateAndroidRippleColor({\n color: backgroundColor,\n })\n\n const { iconName, label } = toggleContent[toggled ? 'true' : 'false']\n\n return (\n <Pressable\n onPress={onPress}\n style={({ pressed }) => [styles.button, pressed && platformPressedOpacityStyle]}\n android_ripple={{ color: androidRippleColor, borderless: false, foreground: true }}\n disabled={disabled || loading}\n accessibilityRole=\"togglebutton\"\n accessibilityState={{ checked: toggled }}\n {...props}\n >\n {loading ? (\n <Spinner size={20} />\n ) : (\n <>\n <Icon name={iconName} style={styles.icon} size={20} />\n <Text variant=\"footnote\" style={styles.text}>\n {label}\n </Text>\n </>\n )}\n </Pressable>\n )\n}\n\nconst useStyles = ({ backgroundColor, disabled }: Partial<ActionToggleButtonProps>) => {\n const { colors } = useTheme()\n const fillColor = disabled ? colors.textColorDefaultDisabled : colors.fillColorNeutral100Inverted\n const buttonBackgroundColor = disabled\n ? colors.fillColorButtonNeutralSolidDisabled\n : backgroundColor\n\n return StyleSheet.create({\n button: {\n flex: 1,\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n height: '100%',\n backgroundColor: buttonBackgroundColor,\n },\n icon: {\n color: fillColor,\n marginTop: 4,\n },\n text: {\n color: fillColor,\n fontWeight: platformFontWeightMedium,\n },\n })\n}\n"]}
@@ -38,18 +38,33 @@ export function ConversationActions({ children, conversation, style, onPress, })
38
38
  function LeftActions({ conversation, onClose }) {
39
39
  const styles = useStyles();
40
40
  const [muted, setMuted] = useState(conversation.muted);
41
+ const [latestMessageUnread, setLatestMessageUnread] = useState(conversation.unreadCount > 0);
42
+ const emptyConversation = conversation.lastMessageCreatedAt === null;
43
+ const muteToggleContent = {
44
+ true: { iconName: 'general.bellMuted', label: 'Mute' },
45
+ false: { iconName: 'general.bell', label: 'Unmute' },
46
+ };
47
+ const latestMessageUnreadToggleContent = {
48
+ true: { iconName: 'general.outlinedTextMessage', label: 'Mark read' },
49
+ false: { iconName: 'general.textMessageNotifications', label: 'Mark unread' },
50
+ };
41
51
  const handleMute = useCallback(() => {
42
52
  setMuted(!muted);
43
53
  onClose();
44
54
  }, [muted, onClose]);
55
+ const handleLatestMessageUnread = useCallback(() => {
56
+ setLatestMessageUnread(!latestMessageUnread);
57
+ onClose();
58
+ }, [latestMessageUnread, onClose]);
45
59
  return (<View style={styles.actionButtonContainer}>
46
- <ActionToggleButton loading={false} toggled={muted} toggleContent={{
47
- true: { iconName: 'general.bellMuted', label: 'Mute' },
48
- false: { iconName: 'general.bell', label: 'Unmute' },
49
- }} onPress={() => handleMute()} backgroundColor={tokens.fillColorInteractionSwipeSecondary}/>
60
+ <ActionToggleButton loading={false} // TODO: Might need this when there is data fetching
61
+ disabled={emptyConversation} toggled={latestMessageUnread} onPress={() => handleLatestMessageUnread()} toggleContent={latestMessageUnreadToggleContent} backgroundColor={tokens.fillColorInteractionSwipeDefault}/>
62
+ <ActionToggleButton loading={false} // TODO: Might need this when there is data fetching
63
+ toggled={muted} onPress={() => handleMute()} toggleContent={muteToggleContent} backgroundColor={tokens.fillColorInteractionSwipeSecondary}/>
50
64
  </View>);
51
65
  }
52
66
  const ACTION_BUTTON_WIDTH = 120;
67
+ const ACTION_BUTTON_COUNT = 2;
53
68
  const useStyles = () => {
54
69
  const { colors } = useTheme();
55
70
  return StyleSheet.create({
@@ -59,7 +74,7 @@ const useStyles = () => {
59
74
  actionButtonContainer: {
60
75
  flexDirection: 'row',
61
76
  alignItems: 'center',
62
- width: ACTION_BUTTON_WIDTH,
77
+ width: ACTION_BUTTON_WIDTH * ACTION_BUTTON_COUNT,
63
78
  alignContent: 'stretch',
64
79
  },
65
80
  swipeableContainer: {
@@ -1 +1 @@
1
- {"version":3,"file":"conversation_actions.js","sourceRoot":"","sources":["../../../src/components/conversations/conversation_actions.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport { Platform, View, StyleSheet, ViewStyle, Pressable } from 'react-native'\nimport ReanimatedSwipeable, {\n SwipeableMethods,\n} from 'react-native-gesture-handler/ReanimatedSwipeable'\nimport { useTheme } from '../../hooks'\nimport { ActionToggleButton } from './action_toggle_button'\nimport { tokens } from '../../vendor/tapestry/tokens'\nimport { ConversationResource } from '../../types'\nimport { useConversationActionsContext } from '../../contexts/swipeable_active_conversation'\n\nexport function ConversationActions({\n children,\n conversation,\n style,\n onPress,\n}: {\n children: ReactNode\n conversation: ConversationResource\n onPress: () => void\n style?: ViewStyle\n}) {\n const swipeableRef = useRef<SwipeableMethods>(null)\n const styles = useStyles()\n const { activeConversationId, setActiveConversationId } = useConversationActionsContext()\n const [disabled, setDisabled] = useState(false)\n const overshootLeft = Platform.OS === 'ios'\n\n const handleSwipeableClose = () => {\n setDisabled(false)\n swipeableRef.current?.close()\n }\n\n const handleSwipeableOpen = () => {\n setDisabled(true)\n setActiveConversationId(conversation.id)\n }\n\n const handlePress = useCallback(() => {\n if (disabled || !onPress) return\n onPress()\n }, [disabled, onPress])\n\n useEffect(() => {\n if (activeConversationId === conversation.id) return\n\n handleSwipeableClose()\n }, [activeConversationId, conversation.id])\n\n return (\n <ReanimatedSwipeable\n ref={swipeableRef}\n childrenContainerStyle={styles.swipeableChildContainer}\n containerStyle={styles.swipeableContainer}\n overshootFriction={8}\n overshootLeft={overshootLeft}\n overshootRight={false}\n onSwipeableOpenStartDrag={handleSwipeableOpen}\n onSwipeableClose={() => setDisabled(false)}\n renderLeftActions={() => (\n <LeftActions conversation={conversation} onClose={handleSwipeableClose} />\n )}\n >\n <Pressable onPress={handlePress} style={style}>\n {children}\n </Pressable>\n </ReanimatedSwipeable>\n )\n}\n\ninterface LeftActionsProps {\n conversation: ConversationResource\n onClose: () => void\n}\n\nfunction LeftActions({ conversation, onClose }: LeftActionsProps) {\n const styles = useStyles()\n const [muted, setMuted] = useState(conversation.muted)\n\n const handleMute = useCallback(() => {\n setMuted(!muted)\n onClose()\n }, [muted, onClose])\n\n return (\n <View style={styles.actionButtonContainer}>\n <ActionToggleButton\n loading={false}\n toggled={muted}\n toggleContent={{\n true: { iconName: 'general.bellMuted', label: 'Mute' },\n false: { iconName: 'general.bell', label: 'Unmute' },\n }}\n onPress={() => handleMute()}\n backgroundColor={tokens.fillColorInteractionSwipeSecondary}\n />\n </View>\n )\n}\n\nconst ACTION_BUTTON_WIDTH = 120\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n swipeableChildContainer: {\n backgroundColor: colors.surfaceColor100,\n },\n actionButtonContainer: {\n flexDirection: 'row',\n alignItems: 'center',\n width: ACTION_BUTTON_WIDTH,\n alignContent: 'stretch',\n },\n swipeableContainer: {\n backgroundColor: colors.surfaceColor090,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"conversation_actions.js","sourceRoot":"","sources":["../../../src/components/conversations/conversation_actions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAa,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAClF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAa,SAAS,EAAE,MAAM,cAAc,CAAA;AAC/E,OAAO,mBAEN,MAAM,kDAAkD,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAA;AAErD,OAAO,EAAE,6BAA6B,EAAE,MAAM,8CAA8C,CAAA;AAE5F,MAAM,UAAU,mBAAmB,CAAC,EAClC,QAAQ,EACR,YAAY,EACZ,KAAK,EACL,OAAO,GAMR;IACC,MAAM,YAAY,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAA;IACnD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,GAAG,6BAA6B,EAAE,CAAA;IACzF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC/C,MAAM,aAAa,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAA;IAE3C,MAAM,oBAAoB,GAAG,GAAG,EAAE;QAChC,WAAW,CAAC,KAAK,CAAC,CAAA;QAClB,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,CAAA;IAC/B,CAAC,CAAA;IAED,MAAM,mBAAmB,GAAG,GAAG,EAAE;QAC/B,WAAW,CAAC,IAAI,CAAC,CAAA;QACjB,uBAAuB,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;IAC1C,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,IAAI,QAAQ,IAAI,CAAC,OAAO;YAAE,OAAM;QAChC,OAAO,EAAE,CAAA;IACX,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAA;IAEvB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,oBAAoB,KAAK,YAAY,CAAC,EAAE;YAAE,OAAM;QAEpD,oBAAoB,EAAE,CAAA;IACxB,CAAC,EAAE,CAAC,oBAAoB,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,CAAA;IAE3C,OAAO,CACL,CAAC,mBAAmB,CAClB,GAAG,CAAC,CAAC,YAAY,CAAC,CAClB,sBAAsB,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,CACvD,cAAc,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAC1C,iBAAiB,CAAC,CAAC,CAAC,CAAC,CACrB,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,cAAc,CAAC,CAAC,KAAK,CAAC,CACtB,wBAAwB,CAAC,CAAC,mBAAmB,CAAC,CAC9C,gBAAgB,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAC3C,iBAAiB,CAAC,CAAC,GAAG,EAAE,CAAC,CACvB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAAC,EAAG,CAC3E,CAAC,CAEF;MAAA,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAC5C;QAAA,CAAC,QAAQ,CACX;MAAA,EAAE,SAAS,CACb;IAAA,EAAE,mBAAmB,CAAC,CACvB,CAAA;AACH,CAAC;AAOD,SAAS,WAAW,CAAC,EAAE,YAAY,EAAE,OAAO,EAAoB;IAC9D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IACtD,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,WAAW,GAAG,CAAC,CAAC,CAAA;IAC5F,MAAM,iBAAiB,GAAG,YAAY,CAAC,oBAAoB,KAAK,IAAI,CAAA;IAEpE,MAAM,iBAAiB,GAAG;QACxB,IAAI,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE;QACtD,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE;KAC5C,CAAA;IAEV,MAAM,gCAAgC,GAAG;QACvC,IAAI,EAAE,EAAE,QAAQ,EAAE,6BAA6B,EAAE,KAAK,EAAE,WAAW,EAAE;QACrE,KAAK,EAAE,EAAE,QAAQ,EAAE,kCAAkC,EAAE,KAAK,EAAE,aAAa,EAAE;KACrE,CAAA;IAEV,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;QAClC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAA;QAChB,OAAO,EAAE,CAAA;IACX,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;IAEpB,MAAM,yBAAyB,GAAG,WAAW,CAAC,GAAG,EAAE;QACjD,sBAAsB,CAAC,CAAC,mBAAmB,CAAC,CAAA;QAC5C,OAAO,EAAE,CAAA;IACX,CAAC,EAAE,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAA;IAElC,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,CACxC;MAAA,CAAC,kBAAkB,CACjB,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,oDAAoD;KACpE,QAAQ,CAAC,CAAC,iBAAiB,CAAC,CAC5B,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAC7B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,yBAAyB,EAAE,CAAC,CAC3C,aAAa,CAAC,CAAC,gCAAgC,CAAC,CAChD,eAAe,CAAC,CAAC,MAAM,CAAC,gCAAgC,CAAC,EAE3D;MAAA,CAAC,kBAAkB,CACjB,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,oDAAoD;KACpE,OAAO,CAAC,CAAC,KAAK,CAAC,CACf,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,CAC5B,aAAa,CAAC,CAAC,iBAAiB,CAAC,CACjC,eAAe,CAAC,CAAC,MAAM,CAAC,kCAAkC,CAAC,EAE/D;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAC/B,MAAM,mBAAmB,GAAG,CAAC,CAAA;AAE7B,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,uBAAuB,EAAE;YACvB,eAAe,EAAE,MAAM,CAAC,eAAe;SACxC;QACD,qBAAqB,EAAE;YACrB,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,mBAAmB,GAAG,mBAAmB;YAChD,YAAY,EAAE,SAAS;SACxB;QACD,kBAAkB,EAAE;YAClB,eAAe,EAAE,MAAM,CAAC,eAAe;SACxC;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport { Platform, View, StyleSheet, ViewStyle, Pressable } from 'react-native'\nimport ReanimatedSwipeable, {\n SwipeableMethods,\n} from 'react-native-gesture-handler/ReanimatedSwipeable'\nimport { useTheme } from '../../hooks'\nimport { ActionToggleButton } from './action_toggle_button'\nimport { tokens } from '../../vendor/tapestry/tokens'\nimport { ConversationResource } from '../../types'\nimport { useConversationActionsContext } from '../../contexts/swipeable_active_conversation'\n\nexport function ConversationActions({\n children,\n conversation,\n style,\n onPress,\n}: {\n children: ReactNode\n conversation: ConversationResource\n onPress: () => void\n style?: ViewStyle\n}) {\n const swipeableRef = useRef<SwipeableMethods>(null)\n const styles = useStyles()\n const { activeConversationId, setActiveConversationId } = useConversationActionsContext()\n const [disabled, setDisabled] = useState(false)\n const overshootLeft = Platform.OS === 'ios'\n\n const handleSwipeableClose = () => {\n setDisabled(false)\n swipeableRef.current?.close()\n }\n\n const handleSwipeableOpen = () => {\n setDisabled(true)\n setActiveConversationId(conversation.id)\n }\n\n const handlePress = useCallback(() => {\n if (disabled || !onPress) return\n onPress()\n }, [disabled, onPress])\n\n useEffect(() => {\n if (activeConversationId === conversation.id) return\n\n handleSwipeableClose()\n }, [activeConversationId, conversation.id])\n\n return (\n <ReanimatedSwipeable\n ref={swipeableRef}\n childrenContainerStyle={styles.swipeableChildContainer}\n containerStyle={styles.swipeableContainer}\n overshootFriction={8}\n overshootLeft={overshootLeft}\n overshootRight={false}\n onSwipeableOpenStartDrag={handleSwipeableOpen}\n onSwipeableClose={() => setDisabled(false)}\n renderLeftActions={() => (\n <LeftActions conversation={conversation} onClose={handleSwipeableClose} />\n )}\n >\n <Pressable onPress={handlePress} style={style}>\n {children}\n </Pressable>\n </ReanimatedSwipeable>\n )\n}\n\ninterface LeftActionsProps {\n conversation: ConversationResource\n onClose: () => void\n}\n\nfunction LeftActions({ conversation, onClose }: LeftActionsProps) {\n const styles = useStyles()\n const [muted, setMuted] = useState(conversation.muted)\n const [latestMessageUnread, setLatestMessageUnread] = useState(conversation.unreadCount > 0)\n const emptyConversation = conversation.lastMessageCreatedAt === null\n\n const muteToggleContent = {\n true: { iconName: 'general.bellMuted', label: 'Mute' },\n false: { iconName: 'general.bell', label: 'Unmute' },\n } as const\n\n const latestMessageUnreadToggleContent = {\n true: { iconName: 'general.outlinedTextMessage', label: 'Mark read' },\n false: { iconName: 'general.textMessageNotifications', label: 'Mark unread' },\n } as const\n\n const handleMute = useCallback(() => {\n setMuted(!muted)\n onClose()\n }, [muted, onClose])\n\n const handleLatestMessageUnread = useCallback(() => {\n setLatestMessageUnread(!latestMessageUnread)\n onClose()\n }, [latestMessageUnread, onClose])\n\n return (\n <View style={styles.actionButtonContainer}>\n <ActionToggleButton\n loading={false} // TODO: Might need this when there is data fetching\n disabled={emptyConversation}\n toggled={latestMessageUnread}\n onPress={() => handleLatestMessageUnread()}\n toggleContent={latestMessageUnreadToggleContent}\n backgroundColor={tokens.fillColorInteractionSwipeDefault}\n />\n <ActionToggleButton\n loading={false} // TODO: Might need this when there is data fetching\n toggled={muted}\n onPress={() => handleMute()}\n toggleContent={muteToggleContent}\n backgroundColor={tokens.fillColorInteractionSwipeSecondary}\n />\n </View>\n )\n}\n\nconst ACTION_BUTTON_WIDTH = 120\nconst ACTION_BUTTON_COUNT = 2\n\nconst useStyles = () => {\n const { colors } = useTheme()\n return StyleSheet.create({\n swipeableChildContainer: {\n backgroundColor: colors.surfaceColor100,\n },\n actionButtonContainer: {\n flexDirection: 'row',\n alignItems: 'center',\n width: ACTION_BUTTON_WIDTH * ACTION_BUTTON_COUNT,\n alignContent: 'stretch',\n },\n swipeableContainer: {\n backgroundColor: colors.surfaceColor090,\n },\n })\n}\n"]}
@@ -9,6 +9,7 @@ export type ChatContextValue = {
9
9
  theme: ChatTheme;
10
10
  env?: ENV;
11
11
  session: Session;
12
+ giphyApiKey?: string;
12
13
  };
13
14
  export interface ChatProviderProps extends Omit<ChatContextValue, 'client' | 'theme' | 'session'> {
14
15
  theme: CreateChatThemeProps;
@@ -1 +1 @@
1
- {"version":3,"file":"chat_context.d.ts","sourceRoot":"","sources":["../../src/contexts/chat_context.tsx"],"names":[],"mappings":"AACA,OAAO,KAAiC,MAAM,OAAO,CAAA;AACrD,OAAO,EAAE,eAAe,EAAkB,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EAAE,SAAS,EAAgB,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEtE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,sBAAsB,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,IAAI,CAAA;IAC1D,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAC/F,KAAK,EAAE,oBAAoB,CAAA;CAC5B;AAED,eAAO,MAAM,WAAW,iCAMtB,CAAA;AAEF,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,qBAc5F;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,eAAe,CAAA;CAC9B;AAED,eAAO,MAAM,kBAAkB,yDAG5B,oBAAoB,KAAG,SAYzB,CAAA"}
1
+ {"version":3,"file":"chat_context.d.ts","sourceRoot":"","sources":["../../src/contexts/chat_context.tsx"],"names":[],"mappings":"AACA,OAAO,KAAiC,MAAM,OAAO,CAAA;AACrD,OAAO,EAAE,eAAe,EAAkB,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EAAE,SAAS,EAAgB,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEtE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,sBAAsB,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,IAAI,CAAA;IAC1D,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAC/F,KAAK,EAAE,oBAAoB,CAAA;CAC5B;AAED,eAAO,MAAM,WAAW,iCAOtB,CAAA;AAEF,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;IAAE,QAAQ,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,qBAe5F;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,eAAe,CAAA;CAC9B;AAED,eAAO,MAAM,kBAAkB,yDAG5B,oBAAoB,KAAG,SAYzB,CAAA"}
@@ -9,9 +9,10 @@ export const ChatContext = createContext({
9
9
  env: undefined,
10
10
  onUnauthorizedResponse: () => { },
11
11
  session: new Session(),
12
+ giphyApiKey: undefined,
12
13
  });
13
14
  export function ChatProvider({ children, value }) {
14
- const { env, token, onUnauthorizedResponse } = value;
15
+ const { env, token, onUnauthorizedResponse, giphyApiKey } = value;
15
16
  const theme = useCreateChatTheme(value.theme || {});
16
17
  const session = useMemo(() => new Session({ token, env }), [env, token]);
17
18
  const contextValue = {
@@ -20,6 +21,7 @@ export function ChatProvider({ children, value }) {
20
21
  onUnauthorizedResponse,
21
22
  session,
22
23
  theme,
24
+ giphyApiKey,
23
25
  };
24
26
  return <ChatContext.Provider value={contextValue}>{children}</ChatContext.Provider>;
25
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chat_context.js","sourceRoot":"","sources":["../../src/contexts/chat_context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC9B,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,EAAmB,cAAc,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,EAAoC,OAAO,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EAAa,YAAY,EAAgB,MAAM,gBAAgB,CAAA;AActE,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAmB;IACzD,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC;IAC5B,KAAK,EAAE,SAAS;IAChB,GAAG,EAAE,SAAS;IACd,sBAAsB,EAAE,GAAG,EAAE,GAAE,CAAC;IAChC,OAAO,EAAE,IAAI,OAAO,EAAE;CACvB,CAAC,CAAA;AAEF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAA+C;IAC3F,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAA;IACpD,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IACnD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;IAExE,MAAM,YAAY,GAAqB;QACrC,GAAG;QACH,KAAK;QACL,sBAAsB;QACtB,OAAO;QACP,KAAK;KACN,CAAA;IAED,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;AACrF,CAAC;AAOD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EACjC,KAAK,EAAE,WAAW,GAAG,EAAE,EACvB,WAAW,EAAE,cAAc,GACN,EAAa,EAAE;IACpC,MAAM,mBAAmB,GAAG,cAAc,EAAE,IAAI,OAAO,CAAA;IACvD,MAAM,WAAW,GAAG,cAAc,IAAI,mBAAmB,CAAA;IAEzD,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;QACpD,MAAM,EAAE;YACN,GAAG,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;SACpE;KACF,CAAA;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import { merge } from 'lodash'\nimport React, { createContext, useMemo } from 'react'\nimport { ColorSchemeName, useColorScheme } from 'react-native'\nimport { DeepPartial } from '../types'\nimport { ENV, PartialToken, ResponseError, Session } from '../utils'\nimport { ChatTheme, defaultTheme, DefaultTheme } from '../utils/theme'\n\nexport type ChatContextValue = {\n token?: PartialToken\n onUnauthorizedResponse: (_response: ResponseError) => void\n theme: ChatTheme\n env?: ENV\n session: Session\n}\n\nexport interface ChatProviderProps extends Omit<ChatContextValue, 'client' | 'theme' | 'session'> {\n theme: CreateChatThemeProps\n}\n\nexport const ChatContext = createContext<ChatContextValue>({\n theme: defaultTheme('light'),\n token: undefined,\n env: undefined,\n onUnauthorizedResponse: () => {},\n session: new Session(),\n})\n\nexport function ChatProvider({ children, value }: { children: any; value: ChatProviderProps }) {\n const { env, token, onUnauthorizedResponse } = value\n const theme = useCreateChatTheme(value.theme || {})\n const session = useMemo(() => new Session({ token, env }), [env, token])\n\n const contextValue: ChatContextValue = {\n env,\n token,\n onUnauthorizedResponse,\n session,\n theme,\n }\n\n return <ChatContext.Provider value={contextValue}>{children}</ChatContext.Provider>\n}\n\nexport interface CreateChatThemeProps {\n theme?: DeepPartial<DefaultTheme>\n colorScheme?: ColorSchemeName\n}\n\nexport const useCreateChatTheme = ({\n theme: customTheme = {},\n colorScheme: appColorScheme,\n}: CreateChatThemeProps): ChatTheme => {\n const internalColorScheme = useColorScheme() || 'light'\n const colorScheme = appColorScheme || internalColorScheme\n\n const theme = {\n ...merge({}, defaultTheme(colorScheme), customTheme),\n colors: {\n ...merge({}, defaultTheme(colorScheme).colors, customTheme?.colors),\n },\n }\n\n return theme\n}\n"]}
1
+ {"version":3,"file":"chat_context.js","sourceRoot":"","sources":["../../src/contexts/chat_context.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC9B,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,EAAmB,cAAc,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,EAAoC,OAAO,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EAAa,YAAY,EAAgB,MAAM,gBAAgB,CAAA;AAetE,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAmB;IACzD,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC;IAC5B,KAAK,EAAE,SAAS;IAChB,GAAG,EAAE,SAAS;IACd,sBAAsB,EAAE,GAAG,EAAE,GAAE,CAAC;IAChC,OAAO,EAAE,IAAI,OAAO,EAAE;IACtB,WAAW,EAAE,SAAS;CACvB,CAAC,CAAA;AAEF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,EAA+C;IAC3F,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;IACjE,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IACnD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;IAExE,MAAM,YAAY,GAAqB;QACrC,GAAG;QACH,KAAK;QACL,sBAAsB;QACtB,OAAO;QACP,KAAK;QACL,WAAW;KACZ,CAAA;IAED,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAA;AACrF,CAAC;AAOD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EACjC,KAAK,EAAE,WAAW,GAAG,EAAE,EACvB,WAAW,EAAE,cAAc,GACN,EAAa,EAAE;IACpC,MAAM,mBAAmB,GAAG,cAAc,EAAE,IAAI,OAAO,CAAA;IACvD,MAAM,WAAW,GAAG,cAAc,IAAI,mBAAmB,CAAA;IAEzD,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;QACpD,MAAM,EAAE;YACN,GAAG,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;SACpE;KACF,CAAA;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA","sourcesContent":["import { merge } from 'lodash'\nimport React, { createContext, useMemo } from 'react'\nimport { ColorSchemeName, useColorScheme } from 'react-native'\nimport { DeepPartial } from '../types'\nimport { ENV, PartialToken, ResponseError, Session } from '../utils'\nimport { ChatTheme, defaultTheme, DefaultTheme } from '../utils/theme'\n\nexport type ChatContextValue = {\n token?: PartialToken\n onUnauthorizedResponse: (_response: ResponseError) => void\n theme: ChatTheme\n env?: ENV\n session: Session\n giphyApiKey?: string\n}\n\nexport interface ChatProviderProps extends Omit<ChatContextValue, 'client' | 'theme' | 'session'> {\n theme: CreateChatThemeProps\n}\n\nexport const ChatContext = createContext<ChatContextValue>({\n theme: defaultTheme('light'),\n token: undefined,\n env: undefined,\n onUnauthorizedResponse: () => {},\n session: new Session(),\n giphyApiKey: undefined,\n})\n\nexport function ChatProvider({ children, value }: { children: any; value: ChatProviderProps }) {\n const { env, token, onUnauthorizedResponse, giphyApiKey } = value\n const theme = useCreateChatTheme(value.theme || {})\n const session = useMemo(() => new Session({ token, env }), [env, token])\n\n const contextValue: ChatContextValue = {\n env,\n token,\n onUnauthorizedResponse,\n session,\n theme,\n giphyApiKey,\n }\n\n return <ChatContext.Provider value={contextValue}>{children}</ChatContext.Provider>\n}\n\nexport interface CreateChatThemeProps {\n theme?: DeepPartial<DefaultTheme>\n colorScheme?: ColorSchemeName\n}\n\nexport const useCreateChatTheme = ({\n theme: customTheme = {},\n colorScheme: appColorScheme,\n}: CreateChatThemeProps): ChatTheme => {\n const internalColorScheme = useColorScheme() || 'light'\n const colorScheme = appColorScheme || internalColorScheme\n\n const theme = {\n ...merge({}, defaultTheme(colorScheme), customTheme),\n colors: {\n ...merge({}, defaultTheme(colorScheme).colors, customTheme?.colors),\n },\n }\n\n return theme\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { DenormalizedGiphyAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource';
2
+ export declare function useGiphy(term?: string): {
3
+ isSearching: boolean;
4
+ result: DenormalizedGiphyAttachmentResourceForCreate;
5
+ resultIndex: number;
6
+ nextResult: () => void;
7
+ prevResult: () => void;
8
+ };
9
+ //# sourceMappingURL=use_giphy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_giphy.d.ts","sourceRoot":"","sources":["../../src/hooks/use_giphy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4CAA4C,EAAE,MAAM,qDAAqD,CAAA;AA0BlH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,MAAW;;;;;;EA8CzC"}
@@ -0,0 +1,63 @@
1
+ import { useCallback, useContext, useEffect, useState } from 'react';
2
+ import { ChatContext } from '../contexts/chat_context';
3
+ export function useGiphy(term = '') {
4
+ const { giphyApiKey } = useContext(ChatContext);
5
+ const [isSearching, setIsSearching] = useState(false);
6
+ const [results, setResults] = useState([]);
7
+ const [resultIndex, setResultIndex] = useState(0);
8
+ const result = results[resultIndex];
9
+ useEffect(() => {
10
+ if (!giphyApiKey || !term) {
11
+ setResults([]);
12
+ return;
13
+ }
14
+ setIsSearching(true);
15
+ fetch(`https://api.giphy.com/v1/gifs/search?api_key=${giphyApiKey}&q=${term}&limit=20&rating=g`)
16
+ .then(response => response.json())
17
+ .then(data => {
18
+ const originalGiphys = data.data;
19
+ const denormalizedGiphys = denormalizeGiphys(term, originalGiphys);
20
+ setResults(denormalizedGiphys);
21
+ setResultIndex(0);
22
+ })
23
+ .catch(error => {
24
+ console.error('Error fetching gifs:', error);
25
+ })
26
+ .finally(() => {
27
+ setIsSearching(false);
28
+ });
29
+ }, [giphyApiKey, term]);
30
+ const nextResult = useCallback(() => {
31
+ setResultIndex(oldResultIndex => (oldResultIndex < results.length - 1 ? oldResultIndex + 1 : 0));
32
+ }, [results.length]);
33
+ const prevResult = useCallback(() => {
34
+ setResultIndex(oldResultIndex => (oldResultIndex > 0 ? oldResultIndex - 1 : results.length - 1));
35
+ }, [results.length]);
36
+ return {
37
+ isSearching,
38
+ result,
39
+ resultIndex,
40
+ nextResult,
41
+ prevResult,
42
+ };
43
+ }
44
+ function denormalizeGiphys(term, giphys) {
45
+ return giphys.map(giphy => ({
46
+ type: 'giphy',
47
+ id: giphy.id,
48
+ title: term,
49
+ original_giphy_title: giphy.title,
50
+ title_link: giphy.url,
51
+ thumb_url: giphy.images.fixed_width.url,
52
+ giphy: {
53
+ original: giphy.images.original,
54
+ fixed_height: giphy.images.fixed_height,
55
+ fixed_height_still: giphy.images.fixed_height_still,
56
+ fixed_height_downsampled: giphy.images.fixed_height_downsampled,
57
+ fixed_width: giphy.images.fixed_width,
58
+ fixed_width_still: giphy.images.fixed_width_still,
59
+ fixed_width_downsampled: giphy.images.fixed_width_downsampled,
60
+ },
61
+ }));
62
+ }
63
+ //# sourceMappingURL=use_giphy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_giphy.js","sourceRoot":"","sources":["../../src/hooks/use_giphy.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useContext, useEffect, useState } from 'react'\nimport { DenormalizedGiphyAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource'\nimport { ChatContext } from '../contexts/chat_context'\n\ninterface GiphyGif {\n id: string\n url: string\n title: string\n images: {\n original: GiphyVariant\n fixed_height: GiphyVariant\n fixed_height_still: GiphyVariant\n fixed_height_downsampled: GiphyVariant\n fixed_width: GiphyVariant\n fixed_width_still: GiphyVariant\n fixed_width_downsampled: GiphyVariant\n }\n}\n\ninterface GiphyVariant {\n url: string\n width: number\n height: number\n size: string\n frames: string\n}\n\nexport function useGiphy(term: string = '') {\n const { giphyApiKey } = useContext(ChatContext)\n const [isSearching, setIsSearching] = useState(false)\n const [results, setResults] = useState<DenormalizedGiphyAttachmentResourceForCreate[]>([])\n const [resultIndex, setResultIndex] = useState(0)\n const result = results[resultIndex]\n\n useEffect(() => {\n if (!giphyApiKey || !term) {\n setResults([])\n return\n }\n\n setIsSearching(true)\n fetch(`https://api.giphy.com/v1/gifs/search?api_key=${giphyApiKey}&q=${term}&limit=20&rating=g`)\n .then(response => response.json())\n .then(data => {\n const originalGiphys: GiphyGif[] = data.data\n const denormalizedGiphys = denormalizeGiphys(term, originalGiphys)\n\n setResults(denormalizedGiphys)\n setResultIndex(0)\n })\n .catch(error => {\n console.error('Error fetching gifs:', error)\n })\n .finally(() => {\n setIsSearching(false)\n })\n }, [giphyApiKey, term])\n\n const nextResult = useCallback(() => {\n setResultIndex(oldResultIndex => (oldResultIndex < results.length - 1 ? oldResultIndex + 1 : 0))\n }, [results.length])\n\n const prevResult = useCallback(() => {\n setResultIndex(oldResultIndex => (oldResultIndex > 0 ? oldResultIndex - 1 : results.length - 1))\n }, [results.length])\n\n return {\n isSearching,\n result,\n resultIndex,\n nextResult,\n prevResult,\n }\n}\n\nfunction denormalizeGiphys(\n term: string,\n giphys: GiphyGif[]\n): DenormalizedGiphyAttachmentResourceForCreate[] {\n return giphys.map(giphy => ({\n type: 'giphy',\n id: giphy.id,\n title: term,\n original_giphy_title: giphy.title,\n title_link: giphy.url,\n thumb_url: giphy.images.fixed_width.url,\n giphy: {\n original: giphy.images.original,\n fixed_height: giphy.images.fixed_height,\n fixed_height_still: giphy.images.fixed_height_still,\n fixed_height_downsampled: giphy.images.fixed_height_downsampled,\n fixed_width: giphy.images.fixed_width,\n fixed_width_still: giphy.images.fixed_width_still,\n fixed_width_downsampled: giphy.images.fixed_width_downsampled,\n },\n }))\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { ApiResource, MessageResource } from '../types';
2
+ import { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource';
3
+ interface Props {
4
+ conversationId: number;
5
+ }
6
+ export declare function useMessageCreate({ conversationId }: Props): import("@tanstack/react-query").UseMutationResult<ApiResource<MessageResource>, Error, {
7
+ text: string;
8
+ attachments?: DenormalizedAttachmentResourceForCreate[];
9
+ }, unknown>;
10
+ export {};
11
+ //# sourceMappingURL=use_message_create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_message_create.d.ts","sourceRoot":"","sources":["../../src/hooks/use_message_create.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAGtE,OAAO,EAAE,uCAAuC,EAAE,MAAM,qDAAqD,CAAA;AAE7G,UAAU,KAAK;IACb,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,cAAc,EAAE,EAAE,KAAK;UAO9C,MAAM;kBACE,uCAAuC,EAAE;YAkC5D"}
@@ -0,0 +1,35 @@
1
+ import { useMutation } from '@tanstack/react-query';
2
+ import { getMessagesQueryKey, getMessagesRequestArgs } from './use_conversation_messages';
3
+ import { useApiClient } from './use_api_client';
4
+ import { queryClient } from '../contexts/api_provider';
5
+ import { updateOrCreateRecordInPagesData } from '../utils';
6
+ export function useMessageCreate({ conversationId }) {
7
+ const apiClient = useApiClient();
8
+ const mutation = useMutation({
9
+ mutationFn: ({ text, attachments, }) => {
10
+ const requestParams = getMessagesRequestArgs({ conversation_id: conversationId });
11
+ const fieldsWithValueJoined = Object.fromEntries(Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')]));
12
+ return apiClient.chat.post({
13
+ url: `/me/conversations/${conversationId}/messages`,
14
+ data: {
15
+ ...requestParams.data,
16
+ data: {
17
+ type: 'Message',
18
+ attributes: { text, ...(attachments ? { attachments } : {}) },
19
+ },
20
+ fields: fieldsWithValueJoined,
21
+ },
22
+ });
23
+ },
24
+ onSuccess: (result) => {
25
+ const updatedMessage = result.data;
26
+ const queryKey = getMessagesQueryKey({ conversation_id: conversationId });
27
+ queryClient.setQueryData(queryKey, data => updateOrCreateRecordInPagesData({
28
+ data,
29
+ record: updatedMessage,
30
+ }));
31
+ },
32
+ });
33
+ return mutation;
34
+ }
35
+ //# sourceMappingURL=use_message_create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use_message_create.js","sourceRoot":"","sources":["../../src/hooks/use_message_create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACzF,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAA;AAO1D,MAAM,UAAU,gBAAgB,CAAC,EAAE,cAAc,EAAS;IACxD,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,QAAQ,GAAG,WAAW,CAAC;QAC3B,UAAU,EAAE,CAAC,EACX,IAAI,EACJ,WAAW,GAIZ,EAAE,EAAE;YACH,MAAM,aAAa,GAAG,sBAAsB,CAAC,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,CAAA;YACjF,MAAM,qBAAqB,GAAG,MAAM,CAAC,WAAW,CAC9C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAC5E,CAAA;YAED,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAA+B;gBACvD,GAAG,EAAE,qBAAqB,cAAc,WAAW;gBACnD,IAAI,EAAE;oBACJ,GAAG,aAAa,CAAC,IAAI;oBACrB,IAAI,EAAE;wBACJ,IAAI,EAAE,SAAS;wBACf,UAAU,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;qBAC9D;oBACD,MAAM,EAAE,qBAAqB;iBAC9B;aACF,CAAC,CAAA;QACJ,CAAC;QACD,SAAS,EAAE,CAAC,MAAoC,EAAE,EAAE;YAClD,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAA;YAElC,MAAM,QAAQ,GAAG,mBAAmB,CAAC,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC,CAAA;YAEzE,WAAW,CAAC,YAAY,CAAY,QAAQ,EAAE,IAAI,CAAC,EAAE,CACnD,+BAA+B,CAAC;gBAC9B,IAAI;gBACJ,MAAM,EAAE,cAAc;aACvB,CAAC,CACH,CAAA;QACH,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAA;AACjB,CAAC","sourcesContent":["import { InfiniteData, useMutation } from '@tanstack/react-query'\nimport { getMessagesQueryKey, getMessagesRequestArgs } from './use_conversation_messages'\nimport { useApiClient } from './use_api_client'\nimport { ApiCollection, ApiResource, MessageResource } from '../types'\nimport { queryClient } from '../contexts/api_provider'\nimport { updateOrCreateRecordInPagesData } from '../utils'\nimport { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource'\n\ninterface Props {\n conversationId: number\n}\n\nexport function useMessageCreate({ conversationId }: Props) {\n const apiClient = useApiClient()\n const mutation = useMutation({\n mutationFn: ({\n text,\n attachments,\n }: {\n text: string\n attachments?: DenormalizedAttachmentResourceForCreate[]\n }) => {\n const requestParams = getMessagesRequestArgs({ conversation_id: conversationId })\n const fieldsWithValueJoined = Object.fromEntries(\n Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')])\n )\n\n return apiClient.chat.post<ApiResource<MessageResource>>({\n url: `/me/conversations/${conversationId}/messages`,\n data: {\n ...requestParams.data,\n data: {\n type: 'Message',\n attributes: { text, ...(attachments ? { attachments } : {}) },\n },\n fields: fieldsWithValueJoined,\n },\n })\n },\n onSuccess: (result: ApiResource<MessageResource>) => {\n const updatedMessage = result.data\n type QueryData = InfiniteData<ApiCollection<MessageResource>>\n const queryKey = getMessagesQueryKey({ conversation_id: conversationId })\n\n queryClient.setQueryData<QueryData>(queryKey, data =>\n updateOrCreateRecordInPagesData({\n data,\n record: updatedMessage,\n })\n )\n },\n })\n\n return mutation\n}\n"]}