@planningcenter/chat-react-native 3.6.0 → 3.6.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/conversation/attachments/attachment_card.d.ts.map +1 -1
- package/build/components/conversation/attachments/attachment_card.js +1 -2
- package/build/components/conversation/attachments/attachment_card.js.map +1 -1
- package/build/components/conversation/attachments/generic_file_attachment.d.ts.map +1 -1
- package/build/components/conversation/attachments/generic_file_attachment.js +0 -1
- package/build/components/conversation/attachments/generic_file_attachment.js.map +1 -1
- package/build/components/conversation/attachments/giphy_attachment.d.ts.map +1 -1
- package/build/components/conversation/attachments/giphy_attachment.js +9 -4
- package/build/components/conversation/attachments/giphy_attachment.js.map +1 -1
- package/build/components/conversation/attachments/video_attachment.js +0 -3
- package/build/components/conversation/attachments/video_attachment.js.map +1 -1
- package/build/components/conversation/jump_to_bottom_button.d.ts +7 -0
- package/build/components/conversation/jump_to_bottom_button.d.ts.map +1 -0
- package/build/components/conversation/jump_to_bottom_button.js +84 -0
- package/build/components/conversation/jump_to_bottom_button.js.map +1 -0
- package/build/components/conversation/message.js +5 -3
- package/build/components/conversation/message.js.map +1 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +15 -2
- package/build/screens/conversation_screen.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversation/attachments/attachment_card.tsx +1 -2
- package/src/components/conversation/attachments/generic_file_attachment.tsx +0 -1
- package/src/components/conversation/attachments/giphy_attachment.tsx +11 -5
- package/src/components/conversation/attachments/video_attachment.tsx +0 -3
- package/src/components/conversation/jump_to_bottom_button.tsx +106 -0
- package/src/components/conversation/message.tsx +5 -3
- package/src/screens/conversation_screen.tsx +20 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment_card.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/attachment_card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,EAAc,IAAI,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"attachment_card.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/attachment_card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACxD,OAAO,EAAc,IAAI,EAAE,MAAM,cAAc,CAAA;AAK/C,KAAK,mBAAmB,GAAG,cAAc,CAAC,OAAO,IAAI,CAAC,CAAA;AAEtD,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,qBAQzE;AAED,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,qBAQxE"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
|
-
import { MESSAGE_ATTACHMENT_WIDTH_SINGLE } from './constants';
|
|
4
3
|
import { Text } from '../../display';
|
|
5
4
|
import { tokens } from '../../../vendor/tapestry/tokens';
|
|
6
5
|
import { useTheme } from '../../../hooks';
|
|
@@ -23,7 +22,7 @@ const useStyles = () => {
|
|
|
23
22
|
padding: 8,
|
|
24
23
|
backgroundColor: colors.surfaceColor100,
|
|
25
24
|
borderRadius: 8,
|
|
26
|
-
minWidth:
|
|
25
|
+
minWidth: '100%',
|
|
27
26
|
minHeight: 60,
|
|
28
27
|
justifyContent: 'center',
|
|
29
28
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment_card.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/attachment_card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"attachment_card.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/attachment_card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAIzC,MAAM,UAAU,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAuB;IACxE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAClC;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,EAAE,QAAQ,EAA2B;IACvE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAC7D;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,IAAI,EAAE;YACJ,OAAO,EAAE,CAAC;YACV,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE,EAAE;YACb,cAAc,EAAE,QAAQ;SACzB;QACD,KAAK,EAAE;YACL,KAAK,EAAE,MAAM,CAAC,uBAAuB;YACrC,QAAQ,EAAE,MAAM,CAAC,UAAU;SAC5B;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React, { ComponentProps, ReactNode } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Text } from '../../display'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { useTheme } from '../../../hooks'\n\ntype AttachmentCardProps = ComponentProps<typeof View>\n\nexport function AttachmentCard({ children, ...props }: AttachmentCardProps) {\n const styles = useStyles()\n\n return (\n <View style={styles.card} {...props}>\n {children}\n </View>\n )\n}\n\nexport function AttachmentCardTitle({ children }: { children: ReactNode }) {\n const styles = useStyles()\n\n return (\n <Text style={styles.title} numberOfLines={1} selectable={false}>\n {children}\n </Text>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n card: {\n padding: 8,\n backgroundColor: colors.surfaceColor100,\n borderRadius: 8,\n minWidth: '100%',\n minHeight: 60,\n justifyContent: 'center',\n },\n title: {\n color: colors.textColorDefaultPrimary,\n fontSize: tokens.fontSizeSm,\n },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic_file_attachment.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/generic_file_attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,qCAAqC,EAAE,MAAM,2DAA2D,CAAA;AAOjH,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,4BAA4B,GAC7B,EAAE;IACD,UAAU,EAAE,qCAAqC,CAAA;IACjD,4BAA4B,EAAE,CAAC,UAAU,EAAE,qCAAqC,KAAK,IAAI,CAAA;CAC1F,qBAiCA;
|
|
1
|
+
{"version":3,"file":"generic_file_attachment.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/generic_file_attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,qCAAqC,EAAE,MAAM,2DAA2D,CAAA;AAOjH,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,4BAA4B,GAC7B,EAAE;IACD,UAAU,EAAE,qCAAqC,CAAA;IACjD,4BAA4B,EAAE,CAAC,UAAU,EAAE,qCAAqC,KAAK,IAAI,CAAA;CAC1F,qBAiCA;AAwBD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,uJAWjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic_file_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/generic_file_attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAExD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAA;AAExD,MAAM,UAAU,qBAAqB,CAAC,EACpC,UAAU,EACV,4BAA4B,GAI7B;IACC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,UAAU,CAAC,UAAU,CAAA;IAC5D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAA;IACnD,MAAM,aAAa,GAAG,WAAW,KAAK,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;IAExE,KAAK,UAAU,cAAc;QAC3B,IAAI,GAAG,EAAE,CAAC;YACR,uCAAuC;YACvC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,CACL,CAAC,iBAAiB,CAChB,OAAO,CAAC,CAAC,cAAc,CAAC,CACxB,WAAW,CAAC,CAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC,UAAU,CAAC,CAAC,CAC5D,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,oBAAoB,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CACzE,iBAAiB,CAAC,MAAM,CACxB,iBAAiB,CAAC,CAAC,iBAAiB,aAAa,4CAA4C,CAAC,CAE9F;MAAA,CAAC,cAAc,CACb;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;UAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACxB;YAAA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EACzC;YAAA,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CACtD;UAAA,EAAE,IAAI,CACR;QAAA,EAAE,IAAI,CACR;MAAA,EAAE,cAAc,CAClB;IAAA,EAAE,iBAAiB,CAAC,CACrB,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAE7B,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,GAAG,EAAE,CAAC;YACN,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,eAAe;SAChC;QACD,KAAK,EAAE;YACL,GAAG,EAAE,CAAC;YACN,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"generic_file_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/generic_file_attachment.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { Linking, StyleSheet, View } from 'react-native'\nimport { DenormalizedMessageAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'\nimport { AttachmentCard, AttachmentCardTitle } from './attachment_card'\nimport { Icon } from '../../display'\nimport { useTheme } from '../../../hooks'\nimport { PlatformPressable } from '@react-navigation/elements'\nimport { tokens } from '../../../vendor/tapestry/tokens'\n\nexport function GenericFileAttachment({\n attachment,\n onMessageAttachmentLongPress,\n}: {\n attachment: DenormalizedMessageAttachmentResource\n onMessageAttachmentLongPress: (attachment: DenormalizedMessageAttachmentResource) => void\n}) {\n const styles = useStyles()\n const { colors } = useTheme()\n\n const { url, filename, contentType } = attachment.attributes\n const iconName = getAttachmentIconName(contentType)\n const fileTypeLabel = contentType === 'application/pdf' ? 'PDF' : 'file'\n\n async function handleDownload() {\n if (url) {\n // Open link in the default web browser\n Linking.openURL(url)\n }\n }\n\n return (\n <PlatformPressable\n onPress={handleDownload}\n onLongPress={() => onMessageAttachmentLongPress(attachment)}\n android_ripple={{ color: colors.androidRippleNeutral, foreground: true }}\n accessibilityRole=\"link\"\n accessibilityHint={`Press to open ${fileTypeLabel} in a browser. Long press for more options`}\n >\n <AttachmentCard>\n <View style={styles.container}>\n <View style={styles.stack}>\n <Icon name={iconName} style={styles.icon} />\n <AttachmentCardTitle>{filename}</AttachmentCardTitle>\n </View>\n </View>\n </AttachmentCard>\n </PlatformPressable>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n gap: 4,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n },\n stack: {\n gap: 4,\n flexDirection: 'row',\n alignItems: 'center',\n },\n icon: {\n color: colors.textColorDefaultPrimary,\n fontSize: tokens.fontSizeMd,\n },\n })\n}\n\nexport function getAttachmentIconName(type: string) {\n const isImage = type.startsWith('image/')\n const isVideo = type.startsWith('video/')\n const isAudio = type.startsWith('audio/')\n const isPdf = type === 'application/pdf'\n\n if (isImage) return 'general.outlinedImageFile'\n if (isVideo) return 'general.outlinedVideoFile'\n if (isAudio) return 'general.outlinedMusicFile'\n if (isPdf) return 'general.outlinedPdfFile'\n return 'general.outlinedGenericFile'\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"giphy_attachment.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/giphy_attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,EAAE,mCAAmC,EAAE,MAAM,2DAA2D,CAAA;
|
|
1
|
+
{"version":3,"file":"giphy_attachment.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/giphy_attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,EAAE,mCAAmC,EAAE,MAAM,2DAA2D,CAAA;AAI/G,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,kBAAkB,GACnB,EAAE;IACD,UAAU,EAAE,mCAAmC,CAAA;IAC/C,kBAAkB,EAAE,MAAM,IAAI,CAAA;CAC/B,qBAgCA"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Text,
|
|
2
|
+
import { Text, StyleSheet, Linking } from 'react-native';
|
|
3
3
|
import { tokens } from '../../../vendor/tapestry/tokens';
|
|
4
4
|
import { useTheme } from '../../../hooks';
|
|
5
5
|
import { PlatformPressable } from '@react-navigation/elements';
|
|
6
|
+
import { Image } from '../../display';
|
|
6
7
|
export function GiphyAttachment({ attachment, onMessageLongPress, }) {
|
|
7
|
-
const styles = useStyles();
|
|
8
8
|
const { colors } = useTheme();
|
|
9
9
|
const { title, titleLink, giphy } = attachment;
|
|
10
10
|
const { url } = giphy.fixedWidth;
|
|
11
11
|
const { width, height } = assertKeysAreNumbers(giphy.fixedWidth);
|
|
12
|
+
const styles = useStyles({ imageWidth: width, imageHeight: height });
|
|
12
13
|
function handlePress() {
|
|
13
14
|
if (titleLink) {
|
|
14
15
|
// Open Giphy link in the default web browser
|
|
@@ -16,7 +17,7 @@ export function GiphyAttachment({ attachment, onMessageLongPress, }) {
|
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
return (<PlatformPressable onPress={handlePress} onLongPress={onMessageLongPress} style={styles.container} android_ripple={{ color: colors.androidRippleNeutral, foreground: true }}>
|
|
19
|
-
<Image source={{ uri: url }} style={
|
|
20
|
+
<Image source={{ uri: url }} wrapperStyle={styles.imageWrapper} style={styles.image} alt={title}/>
|
|
20
21
|
<Text style={styles.link}>
|
|
21
22
|
<Text style={styles.tag}>/giphy</Text> {title}
|
|
22
23
|
</Text>
|
|
@@ -33,12 +34,16 @@ const assertNumber = (value) => {
|
|
|
33
34
|
}
|
|
34
35
|
return 0;
|
|
35
36
|
};
|
|
36
|
-
const useStyles = () => {
|
|
37
|
+
const useStyles = ({ imageWidth, imageHeight }) => {
|
|
37
38
|
const { colors } = useTheme();
|
|
38
39
|
return StyleSheet.create({
|
|
39
40
|
container: {
|
|
40
41
|
gap: 4,
|
|
41
42
|
},
|
|
43
|
+
imageWrapper: {
|
|
44
|
+
width: '100%',
|
|
45
|
+
aspectRatio: imageWidth / imageHeight,
|
|
46
|
+
},
|
|
42
47
|
image: {
|
|
43
48
|
borderRadius: 8,
|
|
44
49
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"giphy_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/giphy_attachment.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"giphy_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/giphy_attachment.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { Text, StyleSheet, Linking } from 'react-native'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { useTheme } from '../../../hooks'\nimport { DenormalizedGiphyAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'\nimport { PlatformPressable } from '@react-navigation/elements'\nimport { Image } from '../../display'\n\nexport function GiphyAttachment({\n attachment,\n onMessageLongPress,\n}: {\n attachment: DenormalizedGiphyAttachmentResource\n onMessageLongPress: () => void\n}) {\n const { colors } = useTheme()\n const { title, titleLink, giphy } = attachment\n const { url } = giphy.fixedWidth\n const { width, height } = assertKeysAreNumbers(giphy.fixedWidth)\n const styles = useStyles({ imageWidth: width, imageHeight: height })\n\n function handlePress() {\n if (titleLink) {\n // Open Giphy link in the default web browser\n Linking.openURL(titleLink)\n }\n }\n\n return (\n <PlatformPressable\n onPress={handlePress}\n onLongPress={onMessageLongPress}\n style={styles.container}\n android_ripple={{ color: colors.androidRippleNeutral, foreground: true }}\n >\n <Image\n source={{ uri: url }}\n wrapperStyle={styles.imageWrapper}\n style={styles.image}\n alt={title}\n />\n <Text style={styles.link}>\n <Text style={styles.tag}>/giphy</Text> {title}\n </Text>\n </PlatformPressable>\n )\n}\n\nconst assertKeysAreNumbers = (obj: Object): Record<any, number> => {\n return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, assertNumber(value)]))\n}\n\nconst assertNumber = (value: string): number => {\n if (typeof value === 'number') return value\n\n if (typeof value === 'string' && !isNaN(Number(value))) {\n return Number(value)\n }\n\n return 0\n}\n\nconst useStyles = ({ imageWidth, imageHeight }: { imageWidth: number; imageHeight: number }) => {\n const { colors } = useTheme()\n return StyleSheet.create({\n container: {\n gap: 4,\n },\n imageWrapper: {\n width: '100%',\n aspectRatio: imageWidth / imageHeight,\n },\n image: {\n borderRadius: 8,\n },\n link: {\n fontSize: tokens.fontSizeSm,\n color: colors.interaction,\n paddingHorizontal: 8,\n paddingVertical: 6,\n },\n tag: {\n fontWeight: 'bold',\n },\n })\n}\n"]}
|
|
@@ -48,12 +48,9 @@ const useStyles = () => {
|
|
|
48
48
|
container: {
|
|
49
49
|
borderRadius: 8,
|
|
50
50
|
overflow: 'hidden',
|
|
51
|
-
maxWidth: 320,
|
|
52
|
-
maxHeight: 320,
|
|
53
51
|
},
|
|
54
52
|
video: {
|
|
55
53
|
width: '100%',
|
|
56
|
-
height: 'auto',
|
|
57
54
|
backgroundColor: colors.fillColorNeutral070,
|
|
58
55
|
},
|
|
59
56
|
thumbnailOverlay: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/video_attachment.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"video_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/video_attachment.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useRef, useState } from 'react'\nimport { View, StyleSheet } from 'react-native'\nimport { DenormalizedMessageAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'\nimport { MESSAGE_ATTACHMENT_WIDTH_SINGLE } from './constants'\nimport { Icon } from '../../display'\nimport { Video, VideoPlayerHandle } from '../../../utils/native_adapters'\nimport { PlatformPressable } from '@react-navigation/elements'\nimport { useTheme } from '../../../hooks'\nimport { tokens } from '../../../vendor/tapestry/tokens'\n\nexport function VideoAttachment({\n attachment,\n onMessageAttachmentLongPress,\n}: {\n attachment: DenormalizedMessageAttachmentResource\n onMessageAttachmentLongPress: (attachment: DenormalizedMessageAttachmentResource) => void\n}) {\n const { colors } = useTheme()\n const styles = useStyles()\n\n const { attributes } = attachment\n const { width = MESSAGE_ATTACHMENT_WIDTH_SINGLE, height = MESSAGE_ATTACHMENT_WIDTH_SINGLE } =\n attributes.metadata || {}\n const { url } = attributes\n\n const videoRef = useRef<VideoPlayerHandle>(null)\n const [isOpen, setIsOpen] = useState(false)\n\n function openVideo() {\n if (!isOpen && videoRef.current) {\n videoRef.current.presentFullscreenPlayer()\n videoRef.current.play()\n setIsOpen(true)\n }\n }\n\n function onFullscreenPlayerWillDismiss() {\n videoRef.current?.pause()\n setIsOpen(false)\n }\n\n const viewRef = useRef<View>(null)\n\n return (\n <View style={styles.container} ref={viewRef}>\n <PlatformPressable\n onPress={openVideo}\n onLongPress={() => onMessageAttachmentLongPress(attachment)}\n android_ripple={{ color: colors.androidRippleNeutral, foreground: true }}\n accessibilityLabel=\"Play Video\"\n accessibilityHint=\"Press to play video. Long press for more options\"\n >\n <View style={styles.thumbnailOverlay} />\n <Video.Player\n ref={videoRef}\n source={{ uri: url }}\n aspectRatio={width / height}\n style={styles.video}\n onFullscreenPlayerWillDismiss={onFullscreenPlayerWillDismiss}\n />\n {!isOpen && (\n <View style={styles.playContainer}>\n <View style={styles.playCircle}>\n <Icon\n name=\"services.play\"\n style={styles.playIcon}\n accessibilityElementsHidden={true}\n />\n </View>\n </View>\n )}\n </PlatformPressable>\n </View>\n )\n}\nconst OVERLAY_Z_INDEX = 1\n\nconst useStyles = () => {\n const { colors } = useTheme()\n const overlayBackgroundColor =\n colors.name === 'light'\n ? tokens.fillColorTransparencyDark010\n : tokens.fillColorTransparencyDark030\n\n return StyleSheet.create({\n container: {\n borderRadius: 8,\n overflow: 'hidden',\n },\n video: {\n width: '100%',\n backgroundColor: colors.fillColorNeutral070,\n },\n thumbnailOverlay: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: overlayBackgroundColor,\n zIndex: OVERLAY_Z_INDEX,\n },\n playContainer: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: OVERLAY_Z_INDEX + 1,\n },\n playCircle: {\n justifyContent: 'center',\n alignItems: 'center',\n width: 42,\n height: 42,\n borderRadius: 25,\n backgroundColor: colors.fillColorNeutral100Inverted,\n borderColor: colors.borderColorDefaultBase,\n borderWidth: 1,\n },\n playIcon: {\n fontSize: 20,\n },\n })\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface JumpToBottomButtonProps {
|
|
2
|
+
onPress: () => void;
|
|
3
|
+
visible: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const JumpToBottomButton: ({ onPress, visible }: JumpToBottomButtonProps) => import("react").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=jump_to_bottom_button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jump_to_bottom_button.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/jump_to_bottom_button.tsx"],"names":[],"mappings":"AAcA,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,eAAO,MAAM,kBAAkB,yBAA0B,uBAAuB,gCA6C/E,CAAA"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { View, Pressable, StyleSheet } from 'react-native';
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, interpolate, Extrapolation, ReduceMotion, withSpring, } from 'react-native-reanimated';
|
|
4
|
+
import { platformFontWeightMedium } from '../../utils';
|
|
5
|
+
import { useTheme } from '../../hooks';
|
|
6
|
+
import { Icon, Text } from '../display';
|
|
7
|
+
export const JumpToBottomButton = ({ onPress, visible }) => {
|
|
8
|
+
const styles = useStyles();
|
|
9
|
+
const progress = useSharedValue(0);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
progress.value = withSpring(visible ? 1 : 0, {
|
|
12
|
+
mass: 1,
|
|
13
|
+
damping: 16,
|
|
14
|
+
stiffness: 170,
|
|
15
|
+
overshootClamping: false,
|
|
16
|
+
restDisplacementThreshold: 0.2,
|
|
17
|
+
restSpeedThreshold: 2,
|
|
18
|
+
reduceMotion: ReduceMotion.System,
|
|
19
|
+
});
|
|
20
|
+
}, [visible, progress]);
|
|
21
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
22
|
+
return {
|
|
23
|
+
opacity: progress.value,
|
|
24
|
+
transform: [
|
|
25
|
+
{
|
|
26
|
+
translateY: interpolate(progress.value, [0, 1], [12, 0], Extrapolation.CLAMP),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
scale: interpolate(progress.value, [0, 1], [0.9, 1], Extrapolation.CLAMP),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
return (<View>
|
|
35
|
+
<Animated.View style={[styles.container, animatedStyle]}>
|
|
36
|
+
<Pressable onPress={onPress} style={({ pressed }) => [styles.button, pressed && styles.pressed]}>
|
|
37
|
+
<Icon name="general.downArrow" style={styles.icon}/>
|
|
38
|
+
<Text variant="tertiary" style={styles.text}>
|
|
39
|
+
Jump to bottom
|
|
40
|
+
</Text>
|
|
41
|
+
</Pressable>
|
|
42
|
+
</Animated.View>
|
|
43
|
+
</View>);
|
|
44
|
+
};
|
|
45
|
+
const useStyles = () => {
|
|
46
|
+
const { colors } = useTheme();
|
|
47
|
+
return StyleSheet.create({
|
|
48
|
+
container: {
|
|
49
|
+
alignSelf: 'center',
|
|
50
|
+
position: 'absolute',
|
|
51
|
+
bottom: 16,
|
|
52
|
+
zIndex: 2,
|
|
53
|
+
},
|
|
54
|
+
button: {
|
|
55
|
+
flexDirection: 'row',
|
|
56
|
+
alignItems: 'center',
|
|
57
|
+
gap: 6,
|
|
58
|
+
paddingHorizontal: 16,
|
|
59
|
+
paddingVertical: 8,
|
|
60
|
+
borderRadius: 20,
|
|
61
|
+
backgroundColor: colors.fillColorNeutral020,
|
|
62
|
+
shadowColor: colors.fillColorNeutral000,
|
|
63
|
+
shadowOffset: {
|
|
64
|
+
width: 0,
|
|
65
|
+
height: 1,
|
|
66
|
+
},
|
|
67
|
+
shadowOpacity: 0.25,
|
|
68
|
+
shadowRadius: 2.84,
|
|
69
|
+
elevation: 5,
|
|
70
|
+
},
|
|
71
|
+
text: {
|
|
72
|
+
color: colors.fillColorNeutral100Inverted,
|
|
73
|
+
fontWeight: platformFontWeightMedium,
|
|
74
|
+
},
|
|
75
|
+
icon: {
|
|
76
|
+
color: colors.fillColorNeutral100Inverted,
|
|
77
|
+
fontSize: 14,
|
|
78
|
+
},
|
|
79
|
+
pressed: {
|
|
80
|
+
transform: [{ scale: 0.95 }],
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=jump_to_bottom_button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jump_to_bottom_button.js","sourceRoot":"","sources":["../../../src/components/conversation/jump_to_bottom_button.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect } from 'react'\nimport { View, Pressable, StyleSheet } from 'react-native'\nimport Animated, {\n useSharedValue,\n useAnimatedStyle,\n interpolate,\n Extrapolation,\n ReduceMotion,\n withSpring,\n} from 'react-native-reanimated'\nimport { platformFontWeightMedium } from '../../utils'\nimport { useTheme } from '../../hooks'\nimport { Icon, Text } from '../display'\n\ninterface JumpToBottomButtonProps {\n onPress: () => void\n visible: boolean\n}\n\nexport const JumpToBottomButton = ({ onPress, visible }: JumpToBottomButtonProps) => {\n const styles = useStyles()\n const progress = useSharedValue(0)\n\n useEffect(() => {\n progress.value = withSpring(visible ? 1 : 0, {\n mass: 1,\n damping: 16,\n stiffness: 170,\n overshootClamping: false,\n restDisplacementThreshold: 0.2,\n restSpeedThreshold: 2,\n reduceMotion: ReduceMotion.System,\n })\n }, [visible, progress])\n\n const animatedStyle = useAnimatedStyle(() => {\n return {\n opacity: progress.value,\n transform: [\n {\n translateY: interpolate(progress.value, [0, 1], [12, 0], Extrapolation.CLAMP),\n },\n {\n scale: interpolate(progress.value, [0, 1], [0.9, 1], Extrapolation.CLAMP),\n },\n ],\n }\n })\n\n return (\n <View>\n <Animated.View style={[styles.container, animatedStyle]}>\n <Pressable\n onPress={onPress}\n style={({ pressed }) => [styles.button, pressed && styles.pressed]}\n >\n <Icon name=\"general.downArrow\" style={styles.icon} />\n <Text variant=\"tertiary\" style={styles.text}>\n Jump to bottom\n </Text>\n </Pressable>\n </Animated.View>\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n\n return StyleSheet.create({\n container: {\n alignSelf: 'center',\n position: 'absolute',\n bottom: 16,\n zIndex: 2,\n },\n button: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 6,\n paddingHorizontal: 16,\n paddingVertical: 8,\n borderRadius: 20,\n backgroundColor: colors.fillColorNeutral020,\n shadowColor: colors.fillColorNeutral000,\n shadowOffset: {\n width: 0,\n height: 1,\n },\n shadowOpacity: 0.25,\n shadowRadius: 2.84,\n elevation: 5,\n },\n text: {\n color: colors.fillColorNeutral100Inverted,\n fontWeight: platformFontWeightMedium,\n },\n icon: {\n color: colors.fillColorNeutral100Inverted,\n fontSize: 14,\n },\n pressed: {\n transform: [{ scale: 0.95 }],\n },\n })\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native';
|
|
2
2
|
import colorFunction from 'color';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { Platform, Pressable, StyleSheet, View } from 'react-native';
|
|
4
|
+
import { Platform, Pressable, StyleSheet, useWindowDimensions, View } from 'react-native';
|
|
5
5
|
import { MessageReaction } from '../../components/conversation/message_reaction';
|
|
6
6
|
import { Avatar, Text } from '../../components/display';
|
|
7
7
|
import { useTheme } from '../../hooks';
|
|
@@ -98,6 +98,8 @@ const useMessageStyles = (props) => {
|
|
|
98
98
|
const { mine } = props;
|
|
99
99
|
const { colors } = useTheme();
|
|
100
100
|
const activeColor = colorFunction(colors.interaction).alpha(0.2).string();
|
|
101
|
+
const { width } = useWindowDimensions();
|
|
102
|
+
const tabletWidth = width >= 744; // Smallest iPad Mini's width
|
|
101
103
|
return StyleSheet.create({
|
|
102
104
|
message: {
|
|
103
105
|
gap: 8,
|
|
@@ -105,8 +107,8 @@ const useMessageStyles = (props) => {
|
|
|
105
107
|
paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,
|
|
106
108
|
},
|
|
107
109
|
messageContent: {
|
|
110
|
+
flex: 1,
|
|
108
111
|
gap: 4,
|
|
109
|
-
flexShrink: 1,
|
|
110
112
|
},
|
|
111
113
|
messageAuthor: {
|
|
112
114
|
flexDirection: 'row',
|
|
@@ -119,7 +121,7 @@ const useMessageStyles = (props) => {
|
|
|
119
121
|
messageBubble: {
|
|
120
122
|
backgroundColor: mine ? activeColor : colors.fillColorNeutral070,
|
|
121
123
|
borderRadius: 8,
|
|
122
|
-
maxWidth:
|
|
124
|
+
maxWidth: tabletWidth ? 360 : '80%',
|
|
123
125
|
alignSelf: mine ? 'flex-end' : 'flex-start',
|
|
124
126
|
},
|
|
125
127
|
messageText: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/components/conversation/message.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport colorFunction from 'color'\nimport React from 'react'\nimport { Platform, Pressable, StyleSheet, View } from 'react-native'\nimport { MessageReaction } from '../../components/conversation/message_reaction'\nimport { Avatar, Text } from '../../components/display'\nimport { useTheme } from '../../hooks'\nimport { MessageResource } from '../../types'\nimport { ReactionCountResource } from '../../types/resources/reaction'\nimport { MessageAttachments } from './message_attachments'\nimport ErrorBoundary from '../page/error_boundary'\nimport { MessageMarkdown } from './message_markdown'\nimport { DenormalizedMessageAttachmentResource } from '../../types/resources/denormalized_attachment_resource'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../../utils/styles'\nimport Animated, {\n useSharedValue,\n useAnimatedStyle,\n withTiming,\n interpolateColor,\n Easing,\n} from 'react-native-reanimated'\nimport { useLiveRelativeTime } from '../../hooks/use_live_relative_time'\nimport { MessageReadReceipts } from './message_read_receipts'\n\n/** Message\n * Component for display of a message within a conversation list\n */\ninterface MessageProps extends MessageResource {\n canDeleteNonAuthoredMessages: boolean\n conversation_id: number\n latestReadMessageSortKey?: string\n}\n\nexport function Message(props: MessageProps) {\n const { conversation_id, canDeleteNonAuthoredMessages, text, reactionCounts } = props\n const styles = useMessageStyles(props)\n const navigation = useNavigation()\n const { colors } = useTheme()\n const hasReactions = reactionCounts.length > 0\n const [showMessageMetaToggle, setShowMessageMetaToggle] = React.useState(false)\n const showMessageMeta = showMessageMetaToggle || props.myLatestInConversation || false\n const timestamp = useLiveRelativeTime(props.createdAt)\n\n const bgFadeProgress = useSharedValue(0)\n const pressedColor = Platform.select({\n ios: colors.fillColorNeutral050Base,\n default: 'transparent',\n })\n const animatedBackgroundColor = useAnimatedStyle(() => {\n const backgroundColor = interpolateColor(\n bgFadeProgress.value,\n [0, 1],\n ['transparent', pressedColor]\n )\n return {\n backgroundColor,\n }\n })\n\n const handlePressIn = () => {\n bgFadeProgress.value = withTiming(1, { duration: 300, easing: Easing.inOut(Easing.ease) })\n }\n\n const handlePressOut = () => {\n bgFadeProgress.value = withTiming(0, { duration: 300, easing: Easing.inOut(Easing.ease) })\n }\n\n const handleMessageLongPress = () => {\n navigation.navigate('MessageActions', {\n message_id: props.id,\n conversation_id,\n canDeleteNonAuthoredMessages,\n })\n }\n const handleReactionLongPress = (reaction: ReactionCountResource) => {\n navigation.navigate('Reactions', {\n message_id: props.id,\n conversation_id,\n reaction_value: reaction.value,\n })\n }\n\n const handleMessageAttachmentLongPress = (attachment: DenormalizedMessageAttachmentResource) => {\n navigation.navigate('AttachmentActions', {\n attachmentId: attachment?.id,\n attachmentContentType: attachment?.attributes.contentType,\n attachmentUrl: attachment?.attributes.url,\n conversation_id,\n canDeleteNonAuthoredMessages,\n myMessage: props.mine,\n })\n }\n\n const metaProps = {\n authorName: props.author.name,\n createdAt: props.createdAt,\n }\n\n const renderAuthor = (!props.mine && props.renderAuthor) || false\n const messageBottomMargin = props.lastInGroup ? 12 : hasReactions || showMessageMeta ? 8 : 4\n\n return (\n <Pressable\n onLongPress={handleMessageLongPress}\n onPress={() => setShowMessageMetaToggle(!showMessageMetaToggle)}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n android_ripple={{ color: colors.androidRippleNeutral }}\n accessibilityHint=\"Long press to view message actions like reacting and copying.\"\n >\n <Animated.View style={[styles.message, animatedBackgroundColor]}>\n {!props.mine && (\n <View style={styles.messageAuthor}>\n {renderAuthor ? (\n <Avatar size={'md'} sourceUri={props.author.avatar} />\n ) : (\n <View style={styles.avatarPlaceholder} />\n )}\n </View>\n )}\n <View style={[styles.messageContent, { marginBottom: messageBottomMargin }]}>\n {renderAuthor && <Text variant=\"tertiary\">{props.author.name}</Text>}\n <View style={styles.messageBubble}>\n <ErrorBoundary>\n <MessageAttachments\n attachments={props.attachments}\n metaProps={metaProps}\n onMessageAttachmentLongPress={handleMessageAttachmentLongPress}\n onMessageLongPress={handleMessageLongPress}\n />\n </ErrorBoundary>\n {text && (\n <View style={styles.messageText}>\n <MessageMarkdown text={text} />\n </View>\n )}\n </View>\n {hasReactions && (\n <View style={styles.messageReactions}>\n {reactionCounts.map(reaction => (\n <MessageReaction\n key={reaction.value}\n reaction={reaction}\n onLongPress={handleReactionLongPress}\n />\n ))}\n </View>\n )}\n {showMessageMeta && (\n <View style={styles.messageMeta}>\n {props.mine && (\n <MessageReadReceipts\n message={props}\n latestReadMessageSortKey={props.latestReadMessageSortKey}\n />\n )}\n <Text variant=\"footnote\">{timestamp}</Text>\n </View>\n )}\n </View>\n </Animated.View>\n </Pressable>\n )\n}\n\nconst useMessageStyles = (props: MessageResource) => {\n const { mine } = props\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 paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n },\n messageContent: {\n gap: 4,\n flexShrink: 1,\n },\n messageAuthor: {\n flexDirection: 'row',\n gap: 8,\n },\n avatarPlaceholder: {\n width: 32, // Same width as avatar\n height: 32, // Same height as avatar\n },\n messageBubble: {\n backgroundColor: mine ? activeColor : colors.fillColorNeutral070,\n borderRadius: 8,\n maxWidth: 232,\n alignSelf: mine ? 'flex-end' : 'flex-start',\n },\n messageText: {\n paddingVertical: 6,\n paddingHorizontal: 8,\n },\n messageReactions: {\n flexDirection: 'row',\n gap: 4,\n justifyContent: mine ? 'flex-end' : 'flex-start',\n },\n messageMeta: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: mine ? 'flex-end' : 'flex-start',\n gap: 4,\n },\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/components/conversation/message.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport colorFunction from 'color'\nimport React from 'react'\nimport { Platform, Pressable, StyleSheet, useWindowDimensions, View } from 'react-native'\nimport { MessageReaction } from '../../components/conversation/message_reaction'\nimport { Avatar, Text } from '../../components/display'\nimport { useTheme } from '../../hooks'\nimport { MessageResource } from '../../types'\nimport { ReactionCountResource } from '../../types/resources/reaction'\nimport { MessageAttachments } from './message_attachments'\nimport ErrorBoundary from '../page/error_boundary'\nimport { MessageMarkdown } from './message_markdown'\nimport { DenormalizedMessageAttachmentResource } from '../../types/resources/denormalized_attachment_resource'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../../utils/styles'\nimport Animated, {\n useSharedValue,\n useAnimatedStyle,\n withTiming,\n interpolateColor,\n Easing,\n} from 'react-native-reanimated'\nimport { useLiveRelativeTime } from '../../hooks/use_live_relative_time'\nimport { MessageReadReceipts } from './message_read_receipts'\n\n/** Message\n * Component for display of a message within a conversation list\n */\ninterface MessageProps extends MessageResource {\n canDeleteNonAuthoredMessages: boolean\n conversation_id: number\n latestReadMessageSortKey?: string\n}\n\nexport function Message(props: MessageProps) {\n const { conversation_id, canDeleteNonAuthoredMessages, text, reactionCounts } = props\n const styles = useMessageStyles(props)\n const navigation = useNavigation()\n const { colors } = useTheme()\n const hasReactions = reactionCounts.length > 0\n const [showMessageMetaToggle, setShowMessageMetaToggle] = React.useState(false)\n const showMessageMeta = showMessageMetaToggle || props.myLatestInConversation || false\n const timestamp = useLiveRelativeTime(props.createdAt)\n\n const bgFadeProgress = useSharedValue(0)\n const pressedColor = Platform.select({\n ios: colors.fillColorNeutral050Base,\n default: 'transparent',\n })\n const animatedBackgroundColor = useAnimatedStyle(() => {\n const backgroundColor = interpolateColor(\n bgFadeProgress.value,\n [0, 1],\n ['transparent', pressedColor]\n )\n return {\n backgroundColor,\n }\n })\n\n const handlePressIn = () => {\n bgFadeProgress.value = withTiming(1, { duration: 300, easing: Easing.inOut(Easing.ease) })\n }\n\n const handlePressOut = () => {\n bgFadeProgress.value = withTiming(0, { duration: 300, easing: Easing.inOut(Easing.ease) })\n }\n\n const handleMessageLongPress = () => {\n navigation.navigate('MessageActions', {\n message_id: props.id,\n conversation_id,\n canDeleteNonAuthoredMessages,\n })\n }\n const handleReactionLongPress = (reaction: ReactionCountResource) => {\n navigation.navigate('Reactions', {\n message_id: props.id,\n conversation_id,\n reaction_value: reaction.value,\n })\n }\n\n const handleMessageAttachmentLongPress = (attachment: DenormalizedMessageAttachmentResource) => {\n navigation.navigate('AttachmentActions', {\n attachmentId: attachment?.id,\n attachmentContentType: attachment?.attributes.contentType,\n attachmentUrl: attachment?.attributes.url,\n conversation_id,\n canDeleteNonAuthoredMessages,\n myMessage: props.mine,\n })\n }\n\n const metaProps = {\n authorName: props.author.name,\n createdAt: props.createdAt,\n }\n\n const renderAuthor = (!props.mine && props.renderAuthor) || false\n const messageBottomMargin = props.lastInGroup ? 12 : hasReactions || showMessageMeta ? 8 : 4\n\n return (\n <Pressable\n onLongPress={handleMessageLongPress}\n onPress={() => setShowMessageMetaToggle(!showMessageMetaToggle)}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n android_ripple={{ color: colors.androidRippleNeutral }}\n accessibilityHint=\"Long press to view message actions like reacting and copying.\"\n >\n <Animated.View style={[styles.message, animatedBackgroundColor]}>\n {!props.mine && (\n <View style={styles.messageAuthor}>\n {renderAuthor ? (\n <Avatar size={'md'} sourceUri={props.author.avatar} />\n ) : (\n <View style={styles.avatarPlaceholder} />\n )}\n </View>\n )}\n <View style={[styles.messageContent, { marginBottom: messageBottomMargin }]}>\n {renderAuthor && <Text variant=\"tertiary\">{props.author.name}</Text>}\n <View style={styles.messageBubble}>\n <ErrorBoundary>\n <MessageAttachments\n attachments={props.attachments}\n metaProps={metaProps}\n onMessageAttachmentLongPress={handleMessageAttachmentLongPress}\n onMessageLongPress={handleMessageLongPress}\n />\n </ErrorBoundary>\n {text && (\n <View style={styles.messageText}>\n <MessageMarkdown text={text} />\n </View>\n )}\n </View>\n {hasReactions && (\n <View style={styles.messageReactions}>\n {reactionCounts.map(reaction => (\n <MessageReaction\n key={reaction.value}\n reaction={reaction}\n onLongPress={handleReactionLongPress}\n />\n ))}\n </View>\n )}\n {showMessageMeta && (\n <View style={styles.messageMeta}>\n {props.mine && (\n <MessageReadReceipts\n message={props}\n latestReadMessageSortKey={props.latestReadMessageSortKey}\n />\n )}\n <Text variant=\"footnote\">{timestamp}</Text>\n </View>\n )}\n </View>\n </Animated.View>\n </Pressable>\n )\n}\n\nconst useMessageStyles = (props: MessageResource) => {\n const { mine } = props\n const { colors } = useTheme()\n const activeColor = colorFunction(colors.interaction).alpha(0.2).string()\n const { width } = useWindowDimensions()\n const tabletWidth = width >= 744 // Smallest iPad Mini's width\n\n return StyleSheet.create({\n message: {\n gap: 8,\n flexDirection: mine ? 'row-reverse' : 'row',\n paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n },\n messageContent: {\n flex: 1,\n gap: 4,\n },\n messageAuthor: {\n flexDirection: 'row',\n gap: 8,\n },\n avatarPlaceholder: {\n width: 32, // Same width as avatar\n height: 32, // Same height as avatar\n },\n messageBubble: {\n backgroundColor: mine ? activeColor : colors.fillColorNeutral070,\n borderRadius: 8,\n maxWidth: tabletWidth ? 360 : '80%',\n alignSelf: mine ? 'flex-end' : 'flex-start',\n },\n messageText: {\n paddingVertical: 6,\n paddingHorizontal: 8,\n },\n messageReactions: {\n flexDirection: 'row',\n gap: 4,\n justifyContent: mine ? 'flex-end' : 'flex-start',\n },\n messageMeta: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: mine ? 'flex-end' : 'flex-start',\n gap: 4,\n },\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,
|
|
1
|
+
{"version":3,"file":"conversation_screen.d.ts","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,gBAAgB,EAAqB,MAAM,4BAA4B,CAAA;AAC7F,OAAO,EAGL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAmD,MAAM,OAAO,CAAA;AAiBvE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAA;AAOjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC,sBAAsB,CAAC,CAAA;AAE/E,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE,uBAAuB,qBA0GpE;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAwC/E,eAAO,MAAM,aAAa,OAAQ,eAAe,EAAE,wCAkClD,CAAA;AACD,UAAU,4BAA6B,SAAQ,gBAAgB;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,eAAO,MAAM,uBAAuB,0DAMjC,4BAA4B,sBA6B9B,CAAA"}
|
|
@@ -2,7 +2,7 @@ import { date as formatDate } from '@planningcenter/datetime-fmt';
|
|
|
2
2
|
import { HeaderTitle, PlatformPressable } from '@react-navigation/elements';
|
|
3
3
|
import { CommonActions, useNavigation, useTheme as useNavigationTheme, useRoute, } from '@react-navigation/native';
|
|
4
4
|
import moment from 'moment';
|
|
5
|
-
import React, { useEffect } from 'react';
|
|
5
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
6
6
|
import { FlatList, Platform, StyleSheet, View } from 'react-native';
|
|
7
7
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
8
8
|
import { Badge, Icon, Text } from '../components';
|
|
@@ -20,6 +20,7 @@ import { getRelativeDateStatus } from '../utils/date';
|
|
|
20
20
|
import { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read';
|
|
21
21
|
import { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles';
|
|
22
22
|
import { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events';
|
|
23
|
+
import { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button';
|
|
23
24
|
export function ConversationScreen({ route }) {
|
|
24
25
|
const styles = useStyles();
|
|
25
26
|
const navigation = useNavigation();
|
|
@@ -39,6 +40,17 @@ export function ConversationScreen({ route }) {
|
|
|
39
40
|
const showLeaderDisabledReplyBanner = canReply && repliesDisabled;
|
|
40
41
|
const canDeleteNonAuthoredMessages = memberAbility?.canDeleteNonAuthoredMessages ?? false;
|
|
41
42
|
const currentlyEditingMessage = messages.find(m => String(m.id) === String(editing_message_id));
|
|
43
|
+
const listRef = useRef(null);
|
|
44
|
+
const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false);
|
|
45
|
+
const trackScroll = (event) => {
|
|
46
|
+
const offsetY = event.nativeEvent.contentOffset.y;
|
|
47
|
+
setShowJumpToBottomButton(offsetY > 200);
|
|
48
|
+
};
|
|
49
|
+
const handleReturnToBottom = useCallback(() => {
|
|
50
|
+
listRef.current?.scrollToOffset({
|
|
51
|
+
offset: 0,
|
|
52
|
+
});
|
|
53
|
+
}, []);
|
|
42
54
|
useEffect(() => {
|
|
43
55
|
navigation.setParams({
|
|
44
56
|
title: title,
|
|
@@ -55,12 +67,13 @@ export function ConversationScreen({ route }) {
|
|
|
55
67
|
}
|
|
56
68
|
return (<View style={styles.container}>
|
|
57
69
|
<KeyboardView>
|
|
58
|
-
{noMessages ? (<EmptyConversationBlankState />) : (<FlatList inverted contentContainerStyle={styles.listContainer} refreshing={isRefetching} onRefresh={refetch} data={messagesWithSeparators} keyExtractor={item => item.id} renderItem={({ item }) => {
|
|
70
|
+
{noMessages ? (<EmptyConversationBlankState />) : (<FlatList inverted ref={listRef} contentContainerStyle={styles.listContainer} refreshing={isRefetching} onRefresh={refetch} data={messagesWithSeparators} keyExtractor={item => item.id} onScroll={trackScroll} scrollEventThrottle={10} renderItem={({ item }) => {
|
|
59
71
|
if (item.type === 'DateSeparator') {
|
|
60
72
|
return <InlineDateSeparator {...item}/>;
|
|
61
73
|
}
|
|
62
74
|
return (<Message {...item} canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages} conversation_id={conversation_id} latestReadMessageSortKey={conversation?.latestReadMessageSortKey}/>);
|
|
63
75
|
}} onEndReached={() => fetchNextPage()} ListHeaderComponent={<View style={styles.listHeader}/>}/>)}
|
|
76
|
+
<JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton}/>
|
|
64
77
|
{!noMessages && <TypingIndicator conversationId={conversation_id}/>}
|
|
65
78
|
{showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}
|
|
66
79
|
{canReply ? (<MessageForm.Root conversation={conversation} currentlyEditingMessage={currentlyEditingMessage}>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation_screen.js","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { date as formatDate } from '@planningcenter/datetime-fmt'\nimport { HeaderTitle, HeaderTitleProps, PlatformPressable } from '@react-navigation/elements'\nimport {\n CommonActions,\n RouteProp,\n StaticScreenProps,\n useNavigation,\n useTheme as useNavigationTheme,\n useRoute,\n} from '@react-navigation/native'\nimport moment from 'moment'\nimport React, { useEffect } from 'react'\nimport { FlatList, Platform, StyleSheet, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Badge, Icon, Text } from '../components'\nimport {\n LeaderDisabledRepliesBanner,\n MemberDisabledRepliesBanner,\n} from '../components/conversation/disabled_replies_banners'\nimport { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'\nimport { Message } from '../components/conversation/message'\nimport { MessageForm } from '../components/conversation/message_form'\nimport { TypingIndicator } from '../components/conversation/typing_indicator'\nimport { KeyboardView } from '../components/display/keyboard_view'\nimport { useTheme } from '../hooks'\nimport { useConversation } from '../hooks/use_conversation'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'\nimport { MessageResource } from '../types'\nimport { ConversationBadgeResource } from '../types/resources/conversation_badge'\nimport { getRelativeDateStatus } from '../utils/date'\nimport { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'\nimport { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'\n\nexport type ConversationRouteProps = {\n conversation_id: number\n chat_group_graph_id?: string\n clear_input?: boolean\n editing_message_id?: number | null\n title?: string\n subtitle?: string\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const styles = useStyles()\n const navigation = useNavigation()\n const { conversation_id, editing_message_id } = route.params\n const { data: conversation } = useConversation(route.params)\n const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({\n conversation_id,\n })\n useConversationJoltEvents({ conversationId: conversation_id })\n useConversationMessagesJoltEvents({ conversationId: conversation_id })\n useEnsureConversationsRouteExists()\n useMarkLatestMessageRead({ conversation, messages })\n const messagesWithSeparators = groupMessages(messages)\n const noMessages = messagesWithSeparators.length === 0\n\n const { repliesDisabled, memberAbility, badges, title } = conversation\n const canReply = memberAbility?.canReply\n const showLeaderDisabledReplyBanner = canReply && repliesDisabled\n const canDeleteNonAuthoredMessages = memberAbility?.canDeleteNonAuthoredMessages ?? false\n const currentlyEditingMessage = messages.find(m => String(m.id) === String(editing_message_id))\n\n useEffect(() => {\n navigation.setParams({\n title: title,\n badge: badges?.[0],\n deleted: conversation?.deleted,\n })\n }, [navigation, title, badges, conversation?.deleted])\n\n if (!conversation || conversation.deleted) {\n return (\n <View style={styles.container}>\n <Text variant=\"plain\" style={styles.deletedAlert}>\n This conversation has been deleted.\n </Text>\n </View>\n )\n }\n\n return (\n <View style={styles.container}>\n <KeyboardView>\n {noMessages ? (\n <EmptyConversationBlankState />\n ) : (\n <FlatList\n inverted\n contentContainerStyle={styles.listContainer}\n refreshing={isRefetching}\n onRefresh={refetch}\n data={messagesWithSeparators}\n keyExtractor={item => item.id}\n renderItem={({ item }) => {\n if (item.type === 'DateSeparator') {\n return <InlineDateSeparator {...item} />\n }\n\n return (\n <Message\n {...item}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages}\n conversation_id={conversation_id}\n latestReadMessageSortKey={conversation?.latestReadMessageSortKey}\n />\n )\n }}\n onEndReached={() => fetchNextPage()}\n ListHeaderComponent={<View style={styles.listHeader} />}\n />\n )}\n {!noMessages && <TypingIndicator conversationId={conversation_id} />}\n {showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}\n {canReply ? (\n <MessageForm.Root\n conversation={conversation}\n currentlyEditingMessage={currentlyEditingMessage}\n >\n <MessageForm.AttachmentPicker />\n <MessageForm.Commands />\n <MessageForm.TextInput />\n <MessageForm.SubmitButton />\n </MessageForm.Root>\n ) : (\n <MemberDisabledRepliesBanner />\n )}\n </KeyboardView>\n </View>\n )\n}\n\nexport type DateSeparator = { type: 'DateSeparator'; id: string; date: string }\n\nfunction InlineDateSeparator({ date }: DateSeparator) {\n const styles = useDateSeparatorStyles()\n const { isThisYear } = getRelativeDateStatus(date)\n const showYear = !isThisYear\n const dateStamp = formatDate(date, { style: 'long', year: showYear })\n\n return (\n <View style={styles.container}>\n <View style={styles.separator} />\n <Text variant=\"footnote\" style={styles.dateText}>\n {dateStamp}\n </Text>\n <View style={styles.separator} />\n </View>\n )\n}\n\nconst useDateSeparatorStyles = () => {\n const theme = useTheme()\n return StyleSheet.create({\n container: {\n alignItems: 'center',\n flexDirection: 'row',\n paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n paddingVertical: 16,\n },\n separator: {\n flex: 1,\n height: 1,\n borderTopWidth: 1,\n borderTopColor: theme.colors.borderColorDefaultBase,\n },\n dateText: {\n paddingHorizontal: 8,\n },\n })\n}\n\nexport const groupMessages = (ms: MessageResource[]) => {\n let enrichedMessages: (MessageResource | DateSeparator)[] = []\n let encounteredOneOfMyMessages = false\n\n ms.forEach((message, i) => {\n const prevMessage = ms[i + 1]\n const nextMessage = ms[i - 1]\n const date = moment(message.createdAt).format('YYYY-MM-DD')\n const prevMessageDifferentAuthor = message.author?.id !== prevMessage?.author?.id\n const nextMessageDifferentAuthor = message.author?.id !== nextMessage?.author?.id\n const prevMessageMoreThan5Minutes =\n prevMessage &&\n new Date(message.createdAt).getTime() - new Date(prevMessage.createdAt).getTime() > 60000 * 5\n const nextMessageMoreThan5Minutes =\n nextMessage &&\n new Date(nextMessage.createdAt).getTime() - new Date(message.createdAt).getTime() > 60000 * 5\n\n if (message.mine && !encounteredOneOfMyMessages) {\n encounteredOneOfMyMessages = true\n message.myLatestInConversation = true\n } else {\n message.myLatestInConversation = false\n }\n message.lastInGroup = !nextMessage || nextMessageDifferentAuthor || nextMessageMoreThan5Minutes\n message.renderAuthor =\n !message.mine && (!prevMessage || prevMessageDifferentAuthor || prevMessageMoreThan5Minutes)\n\n enrichedMessages.push(message)\n if (!prevMessage || date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')) {\n enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date })\n }\n })\n\n return enrichedMessages\n}\ninterface ConversationScreenTitleProps extends HeaderTitleProps {\n conversation_id: number\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport const ConversationScreenTitle = ({\n conversation_id,\n badge,\n children,\n style,\n deleted,\n}: ConversationScreenTitleProps) => {\n const styles = usePressableHeaderStyle()\n const navigation = useNavigation()\n const resourceType = badge?.pcoResourceType || ''\n const productName = badge?.appName\n const name = badge?.text || undefined\n\n return (\n <PlatformPressable\n style={styles.container}\n onPress={() => {\n if (deleted) return\n\n navigation.navigate('ConversationDetails', { conversation_id })\n }}\n >\n <View style={styles.titleWrapper}>\n <HeaderTitle style={style}>{children}</HeaderTitle>\n {!deleted && <Icon name=\"general.downChevron\" size={12} />}\n </View>\n <Badge\n variant=\"metaSubtle\"\n productLogoName={productName}\n label={resourceType}\n metaLabel={name}\n style={styles.badge}\n />\n </PlatformPressable>\n )\n}\n\nconst usePressableHeaderStyle = () => {\n return StyleSheet.create({\n container: {\n alignItems: Platform.select({ android: 'flex-start', default: 'center' }),\n marginRight: Platform.select({ ios: 20, default: 16 }),\n },\n titleWrapper: {\n alignItems: 'center',\n columnGap: 4,\n flexDirection: 'row',\n flexShrink: 1,\n },\n badge: {\n alignSelf: Platform.select({ android: 'flex-start', default: 'center' }),\n marginTop: 2,\n },\n })\n}\n\nconst useStyles = () => {\n const navigationTheme = useNavigationTheme()\n const { bottom } = useSafeAreaInsets()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n backgroundColor: navigationTheme.colors.card,\n paddingBottom: bottom,\n },\n listContainer: {\n paddingVertical: 12,\n },\n listHeader: {\n // Just whitespace to provide space where the typing indicator can be\n height: 16,\n },\n deletedAlert: {\n textAlign: 'center',\n padding: 16,\n },\n })\n}\n\n/**\n * useEnsureConversationsRouteExists\n */\nconst useEnsureConversationsRouteExists = () => {\n const navigation = useNavigation()\n const { params } = useRoute<RouteProp<ConversationScreenProps['route']>>()\n\n useEffect(() => {\n const navigationState = navigation.getState()\n const routes = navigationState?.routes || []\n const conversationsRoute = routes.find(r => r.name === 'Conversations')\n\n if (conversationsRoute) return\n\n navigation.dispatch(state => {\n return CommonActions.reset({\n ...state,\n routes: [\n { name: 'Conversations', params: { chat_group_graph_id: params?.chat_group_graph_id } },\n ...routes,\n ],\n index: state.index + 1,\n })\n })\n }, [navigation, params?.chat_group_graph_id])\n}\n"]}
|
|
1
|
+
{"version":3,"file":"conversation_screen.js","sourceRoot":"","sources":["../../src/screens/conversation_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { date as formatDate } from '@planningcenter/datetime-fmt'\nimport { HeaderTitle, HeaderTitleProps, PlatformPressable } from '@react-navigation/elements'\nimport {\n CommonActions,\n RouteProp,\n StaticScreenProps,\n useNavigation,\n useTheme as useNavigationTheme,\n useRoute,\n} from '@react-navigation/native'\nimport moment from 'moment'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport { FlatList, Platform, StyleSheet, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Badge, Icon, Text } from '../components'\nimport {\n LeaderDisabledRepliesBanner,\n MemberDisabledRepliesBanner,\n} from '../components/conversation/disabled_replies_banners'\nimport { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'\nimport { Message } from '../components/conversation/message'\nimport { MessageForm } from '../components/conversation/message_form'\nimport { TypingIndicator } from '../components/conversation/typing_indicator'\nimport { KeyboardView } from '../components/display/keyboard_view'\nimport { useTheme } from '../hooks'\nimport { useConversation } from '../hooks/use_conversation'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'\nimport { MessageResource } from '../types'\nimport { ConversationBadgeResource } from '../types/resources/conversation_badge'\nimport { getRelativeDateStatus } from '../utils/date'\nimport { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'\nimport { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'\nimport { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'\nimport { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'\n\nexport type ConversationRouteProps = {\n conversation_id: number\n chat_group_graph_id?: string\n clear_input?: boolean\n editing_message_id?: number | null\n title?: string\n subtitle?: string\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>\n\nexport function ConversationScreen({ route }: ConversationScreenProps) {\n const styles = useStyles()\n const navigation = useNavigation()\n const { conversation_id, editing_message_id } = route.params\n const { data: conversation } = useConversation(route.params)\n const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({\n conversation_id,\n })\n useConversationJoltEvents({ conversationId: conversation_id })\n useConversationMessagesJoltEvents({ conversationId: conversation_id })\n useEnsureConversationsRouteExists()\n useMarkLatestMessageRead({ conversation, messages })\n const messagesWithSeparators = groupMessages(messages)\n const noMessages = messagesWithSeparators.length === 0\n\n const { repliesDisabled, memberAbility, badges, title } = conversation\n const canReply = memberAbility?.canReply\n const showLeaderDisabledReplyBanner = canReply && repliesDisabled\n const canDeleteNonAuthoredMessages = memberAbility?.canDeleteNonAuthoredMessages ?? false\n const currentlyEditingMessage = messages.find(m => String(m.id) === String(editing_message_id))\n\n const listRef = useRef<FlatList>(null)\n const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)\n\n const trackScroll = (event: any) => {\n const offsetY = event.nativeEvent.contentOffset.y\n setShowJumpToBottomButton(offsetY > 200)\n }\n\n const handleReturnToBottom = useCallback(() => {\n listRef.current?.scrollToOffset({\n offset: 0,\n })\n }, [])\n\n useEffect(() => {\n navigation.setParams({\n title: title,\n badge: badges?.[0],\n deleted: conversation?.deleted,\n })\n }, [navigation, title, badges, conversation?.deleted])\n\n if (!conversation || conversation.deleted) {\n return (\n <View style={styles.container}>\n <Text variant=\"plain\" style={styles.deletedAlert}>\n This conversation has been deleted.\n </Text>\n </View>\n )\n }\n\n return (\n <View style={styles.container}>\n <KeyboardView>\n {noMessages ? (\n <EmptyConversationBlankState />\n ) : (\n <FlatList\n inverted\n ref={listRef}\n contentContainerStyle={styles.listContainer}\n refreshing={isRefetching}\n onRefresh={refetch}\n data={messagesWithSeparators}\n keyExtractor={item => item.id}\n onScroll={trackScroll}\n scrollEventThrottle={10}\n renderItem={({ item }) => {\n if (item.type === 'DateSeparator') {\n return <InlineDateSeparator {...item} />\n }\n\n return (\n <Message\n {...item}\n canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages}\n conversation_id={conversation_id}\n latestReadMessageSortKey={conversation?.latestReadMessageSortKey}\n />\n )\n }}\n onEndReached={() => fetchNextPage()}\n ListHeaderComponent={<View style={styles.listHeader} />}\n />\n )}\n <JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />\n {!noMessages && <TypingIndicator conversationId={conversation_id} />}\n {showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}\n {canReply ? (\n <MessageForm.Root\n conversation={conversation}\n currentlyEditingMessage={currentlyEditingMessage}\n >\n <MessageForm.AttachmentPicker />\n <MessageForm.Commands />\n <MessageForm.TextInput />\n <MessageForm.SubmitButton />\n </MessageForm.Root>\n ) : (\n <MemberDisabledRepliesBanner />\n )}\n </KeyboardView>\n </View>\n )\n}\n\nexport type DateSeparator = { type: 'DateSeparator'; id: string; date: string }\n\nfunction InlineDateSeparator({ date }: DateSeparator) {\n const styles = useDateSeparatorStyles()\n const { isThisYear } = getRelativeDateStatus(date)\n const showYear = !isThisYear\n const dateStamp = formatDate(date, { style: 'long', year: showYear })\n\n return (\n <View style={styles.container}>\n <View style={styles.separator} />\n <Text variant=\"footnote\" style={styles.dateText}>\n {dateStamp}\n </Text>\n <View style={styles.separator} />\n </View>\n )\n}\n\nconst useDateSeparatorStyles = () => {\n const theme = useTheme()\n return StyleSheet.create({\n container: {\n alignItems: 'center',\n flexDirection: 'row',\n paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,\n paddingVertical: 16,\n },\n separator: {\n flex: 1,\n height: 1,\n borderTopWidth: 1,\n borderTopColor: theme.colors.borderColorDefaultBase,\n },\n dateText: {\n paddingHorizontal: 8,\n },\n })\n}\n\nexport const groupMessages = (ms: MessageResource[]) => {\n let enrichedMessages: (MessageResource | DateSeparator)[] = []\n let encounteredOneOfMyMessages = false\n\n ms.forEach((message, i) => {\n const prevMessage = ms[i + 1]\n const nextMessage = ms[i - 1]\n const date = moment(message.createdAt).format('YYYY-MM-DD')\n const prevMessageDifferentAuthor = message.author?.id !== prevMessage?.author?.id\n const nextMessageDifferentAuthor = message.author?.id !== nextMessage?.author?.id\n const prevMessageMoreThan5Minutes =\n prevMessage &&\n new Date(message.createdAt).getTime() - new Date(prevMessage.createdAt).getTime() > 60000 * 5\n const nextMessageMoreThan5Minutes =\n nextMessage &&\n new Date(nextMessage.createdAt).getTime() - new Date(message.createdAt).getTime() > 60000 * 5\n\n if (message.mine && !encounteredOneOfMyMessages) {\n encounteredOneOfMyMessages = true\n message.myLatestInConversation = true\n } else {\n message.myLatestInConversation = false\n }\n message.lastInGroup = !nextMessage || nextMessageDifferentAuthor || nextMessageMoreThan5Minutes\n message.renderAuthor =\n !message.mine && (!prevMessage || prevMessageDifferentAuthor || prevMessageMoreThan5Minutes)\n\n enrichedMessages.push(message)\n if (!prevMessage || date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')) {\n enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date })\n }\n })\n\n return enrichedMessages\n}\ninterface ConversationScreenTitleProps extends HeaderTitleProps {\n conversation_id: number\n badge?: ConversationBadgeResource\n deleted?: boolean\n}\n\nexport const ConversationScreenTitle = ({\n conversation_id,\n badge,\n children,\n style,\n deleted,\n}: ConversationScreenTitleProps) => {\n const styles = usePressableHeaderStyle()\n const navigation = useNavigation()\n const resourceType = badge?.pcoResourceType || ''\n const productName = badge?.appName\n const name = badge?.text || undefined\n\n return (\n <PlatformPressable\n style={styles.container}\n onPress={() => {\n if (deleted) return\n\n navigation.navigate('ConversationDetails', { conversation_id })\n }}\n >\n <View style={styles.titleWrapper}>\n <HeaderTitle style={style}>{children}</HeaderTitle>\n {!deleted && <Icon name=\"general.downChevron\" size={12} />}\n </View>\n <Badge\n variant=\"metaSubtle\"\n productLogoName={productName}\n label={resourceType}\n metaLabel={name}\n style={styles.badge}\n />\n </PlatformPressable>\n )\n}\n\nconst usePressableHeaderStyle = () => {\n return StyleSheet.create({\n container: {\n alignItems: Platform.select({ android: 'flex-start', default: 'center' }),\n marginRight: Platform.select({ ios: 20, default: 16 }),\n },\n titleWrapper: {\n alignItems: 'center',\n columnGap: 4,\n flexDirection: 'row',\n flexShrink: 1,\n },\n badge: {\n alignSelf: Platform.select({ android: 'flex-start', default: 'center' }),\n marginTop: 2,\n },\n })\n}\n\nconst useStyles = () => {\n const navigationTheme = useNavigationTheme()\n const { bottom } = useSafeAreaInsets()\n\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n backgroundColor: navigationTheme.colors.card,\n paddingBottom: bottom,\n },\n listContainer: {\n paddingVertical: 12,\n },\n listHeader: {\n // Just whitespace to provide space where the typing indicator can be\n height: 16,\n },\n deletedAlert: {\n textAlign: 'center',\n padding: 16,\n },\n })\n}\n\n/**\n * useEnsureConversationsRouteExists\n */\nconst useEnsureConversationsRouteExists = () => {\n const navigation = useNavigation()\n const { params } = useRoute<RouteProp<ConversationScreenProps['route']>>()\n\n useEffect(() => {\n const navigationState = navigation.getState()\n const routes = navigationState?.routes || []\n const conversationsRoute = routes.find(r => r.name === 'Conversations')\n\n if (conversationsRoute) return\n\n navigation.dispatch(state => {\n return CommonActions.reset({\n ...state,\n routes: [\n { name: 'Conversations', params: { chat_group_graph_id: params?.chat_group_graph_id } },\n ...routes,\n ],\n index: state.index + 1,\n })\n })\n }, [navigation, params?.chat_group_graph_id])\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.1-rc.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"prettier": "^3.4.2",
|
|
56
56
|
"typescript": "<5.6.0"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "1645d7c15ce9a88987e199b10d6081787206e771"
|
|
59
59
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { ComponentProps, ReactNode } from 'react'
|
|
2
2
|
import { StyleSheet, View } from 'react-native'
|
|
3
|
-
import { MESSAGE_ATTACHMENT_WIDTH_SINGLE } from './constants'
|
|
4
3
|
import { Text } from '../../display'
|
|
5
4
|
import { tokens } from '../../../vendor/tapestry/tokens'
|
|
6
5
|
import { useTheme } from '../../../hooks'
|
|
@@ -35,7 +34,7 @@ const useStyles = () => {
|
|
|
35
34
|
padding: 8,
|
|
36
35
|
backgroundColor: colors.surfaceColor100,
|
|
37
36
|
borderRadius: 8,
|
|
38
|
-
minWidth:
|
|
37
|
+
minWidth: '100%',
|
|
39
38
|
minHeight: 60,
|
|
40
39
|
justifyContent: 'center',
|
|
41
40
|
},
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { Text,
|
|
2
|
+
import { Text, StyleSheet, Linking } from 'react-native'
|
|
3
3
|
import { tokens } from '../../../vendor/tapestry/tokens'
|
|
4
4
|
import { useTheme } from '../../../hooks'
|
|
5
5
|
import { DenormalizedGiphyAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'
|
|
6
6
|
import { PlatformPressable } from '@react-navigation/elements'
|
|
7
|
+
import { Image } from '../../display'
|
|
7
8
|
|
|
8
9
|
export function GiphyAttachment({
|
|
9
10
|
attachment,
|
|
@@ -12,11 +13,11 @@ export function GiphyAttachment({
|
|
|
12
13
|
attachment: DenormalizedGiphyAttachmentResource
|
|
13
14
|
onMessageLongPress: () => void
|
|
14
15
|
}) {
|
|
15
|
-
const styles = useStyles()
|
|
16
16
|
const { colors } = useTheme()
|
|
17
17
|
const { title, titleLink, giphy } = attachment
|
|
18
18
|
const { url } = giphy.fixedWidth
|
|
19
19
|
const { width, height } = assertKeysAreNumbers(giphy.fixedWidth)
|
|
20
|
+
const styles = useStyles({ imageWidth: width, imageHeight: height })
|
|
20
21
|
|
|
21
22
|
function handlePress() {
|
|
22
23
|
if (titleLink) {
|
|
@@ -34,8 +35,9 @@ export function GiphyAttachment({
|
|
|
34
35
|
>
|
|
35
36
|
<Image
|
|
36
37
|
source={{ uri: url }}
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
wrapperStyle={styles.imageWrapper}
|
|
39
|
+
style={styles.image}
|
|
40
|
+
alt={title}
|
|
39
41
|
/>
|
|
40
42
|
<Text style={styles.link}>
|
|
41
43
|
<Text style={styles.tag}>/giphy</Text> {title}
|
|
@@ -58,12 +60,16 @@ const assertNumber = (value: string): number => {
|
|
|
58
60
|
return 0
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
const useStyles = () => {
|
|
63
|
+
const useStyles = ({ imageWidth, imageHeight }: { imageWidth: number; imageHeight: number }) => {
|
|
62
64
|
const { colors } = useTheme()
|
|
63
65
|
return StyleSheet.create({
|
|
64
66
|
container: {
|
|
65
67
|
gap: 4,
|
|
66
68
|
},
|
|
69
|
+
imageWrapper: {
|
|
70
|
+
width: '100%',
|
|
71
|
+
aspectRatio: imageWidth / imageHeight,
|
|
72
|
+
},
|
|
67
73
|
image: {
|
|
68
74
|
borderRadius: 8,
|
|
69
75
|
},
|
|
@@ -86,12 +86,9 @@ const useStyles = () => {
|
|
|
86
86
|
container: {
|
|
87
87
|
borderRadius: 8,
|
|
88
88
|
overflow: 'hidden',
|
|
89
|
-
maxWidth: 320,
|
|
90
|
-
maxHeight: 320,
|
|
91
89
|
},
|
|
92
90
|
video: {
|
|
93
91
|
width: '100%',
|
|
94
|
-
height: 'auto',
|
|
95
92
|
backgroundColor: colors.fillColorNeutral070,
|
|
96
93
|
},
|
|
97
94
|
thumbnailOverlay: {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
import { View, Pressable, StyleSheet } from 'react-native'
|
|
3
|
+
import Animated, {
|
|
4
|
+
useSharedValue,
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
interpolate,
|
|
7
|
+
Extrapolation,
|
|
8
|
+
ReduceMotion,
|
|
9
|
+
withSpring,
|
|
10
|
+
} from 'react-native-reanimated'
|
|
11
|
+
import { platformFontWeightMedium } from '../../utils'
|
|
12
|
+
import { useTheme } from '../../hooks'
|
|
13
|
+
import { Icon, Text } from '../display'
|
|
14
|
+
|
|
15
|
+
interface JumpToBottomButtonProps {
|
|
16
|
+
onPress: () => void
|
|
17
|
+
visible: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const JumpToBottomButton = ({ onPress, visible }: JumpToBottomButtonProps) => {
|
|
21
|
+
const styles = useStyles()
|
|
22
|
+
const progress = useSharedValue(0)
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
progress.value = withSpring(visible ? 1 : 0, {
|
|
26
|
+
mass: 1,
|
|
27
|
+
damping: 16,
|
|
28
|
+
stiffness: 170,
|
|
29
|
+
overshootClamping: false,
|
|
30
|
+
restDisplacementThreshold: 0.2,
|
|
31
|
+
restSpeedThreshold: 2,
|
|
32
|
+
reduceMotion: ReduceMotion.System,
|
|
33
|
+
})
|
|
34
|
+
}, [visible, progress])
|
|
35
|
+
|
|
36
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
37
|
+
return {
|
|
38
|
+
opacity: progress.value,
|
|
39
|
+
transform: [
|
|
40
|
+
{
|
|
41
|
+
translateY: interpolate(progress.value, [0, 1], [12, 0], Extrapolation.CLAMP),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
scale: interpolate(progress.value, [0, 1], [0.9, 1], Extrapolation.CLAMP),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<View>
|
|
52
|
+
<Animated.View style={[styles.container, animatedStyle]}>
|
|
53
|
+
<Pressable
|
|
54
|
+
onPress={onPress}
|
|
55
|
+
style={({ pressed }) => [styles.button, pressed && styles.pressed]}
|
|
56
|
+
>
|
|
57
|
+
<Icon name="general.downArrow" style={styles.icon} />
|
|
58
|
+
<Text variant="tertiary" style={styles.text}>
|
|
59
|
+
Jump to bottom
|
|
60
|
+
</Text>
|
|
61
|
+
</Pressable>
|
|
62
|
+
</Animated.View>
|
|
63
|
+
</View>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const useStyles = () => {
|
|
68
|
+
const { colors } = useTheme()
|
|
69
|
+
|
|
70
|
+
return StyleSheet.create({
|
|
71
|
+
container: {
|
|
72
|
+
alignSelf: 'center',
|
|
73
|
+
position: 'absolute',
|
|
74
|
+
bottom: 16,
|
|
75
|
+
zIndex: 2,
|
|
76
|
+
},
|
|
77
|
+
button: {
|
|
78
|
+
flexDirection: 'row',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
gap: 6,
|
|
81
|
+
paddingHorizontal: 16,
|
|
82
|
+
paddingVertical: 8,
|
|
83
|
+
borderRadius: 20,
|
|
84
|
+
backgroundColor: colors.fillColorNeutral020,
|
|
85
|
+
shadowColor: colors.fillColorNeutral000,
|
|
86
|
+
shadowOffset: {
|
|
87
|
+
width: 0,
|
|
88
|
+
height: 1,
|
|
89
|
+
},
|
|
90
|
+
shadowOpacity: 0.25,
|
|
91
|
+
shadowRadius: 2.84,
|
|
92
|
+
elevation: 5,
|
|
93
|
+
},
|
|
94
|
+
text: {
|
|
95
|
+
color: colors.fillColorNeutral100Inverted,
|
|
96
|
+
fontWeight: platformFontWeightMedium,
|
|
97
|
+
},
|
|
98
|
+
icon: {
|
|
99
|
+
color: colors.fillColorNeutral100Inverted,
|
|
100
|
+
fontSize: 14,
|
|
101
|
+
},
|
|
102
|
+
pressed: {
|
|
103
|
+
transform: [{ scale: 0.95 }],
|
|
104
|
+
},
|
|
105
|
+
})
|
|
106
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native'
|
|
2
2
|
import colorFunction from 'color'
|
|
3
3
|
import React from 'react'
|
|
4
|
-
import { Platform, Pressable, StyleSheet, View } from 'react-native'
|
|
4
|
+
import { Platform, Pressable, StyleSheet, useWindowDimensions, View } from 'react-native'
|
|
5
5
|
import { MessageReaction } from '../../components/conversation/message_reaction'
|
|
6
6
|
import { Avatar, Text } from '../../components/display'
|
|
7
7
|
import { useTheme } from '../../hooks'
|
|
@@ -167,6 +167,8 @@ const useMessageStyles = (props: MessageResource) => {
|
|
|
167
167
|
const { mine } = props
|
|
168
168
|
const { colors } = useTheme()
|
|
169
169
|
const activeColor = colorFunction(colors.interaction).alpha(0.2).string()
|
|
170
|
+
const { width } = useWindowDimensions()
|
|
171
|
+
const tabletWidth = width >= 744 // Smallest iPad Mini's width
|
|
170
172
|
|
|
171
173
|
return StyleSheet.create({
|
|
172
174
|
message: {
|
|
@@ -175,8 +177,8 @@ const useMessageStyles = (props: MessageResource) => {
|
|
|
175
177
|
paddingHorizontal: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,
|
|
176
178
|
},
|
|
177
179
|
messageContent: {
|
|
180
|
+
flex: 1,
|
|
178
181
|
gap: 4,
|
|
179
|
-
flexShrink: 1,
|
|
180
182
|
},
|
|
181
183
|
messageAuthor: {
|
|
182
184
|
flexDirection: 'row',
|
|
@@ -189,7 +191,7 @@ const useMessageStyles = (props: MessageResource) => {
|
|
|
189
191
|
messageBubble: {
|
|
190
192
|
backgroundColor: mine ? activeColor : colors.fillColorNeutral070,
|
|
191
193
|
borderRadius: 8,
|
|
192
|
-
maxWidth:
|
|
194
|
+
maxWidth: tabletWidth ? 360 : '80%',
|
|
193
195
|
alignSelf: mine ? 'flex-end' : 'flex-start',
|
|
194
196
|
},
|
|
195
197
|
messageText: {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
useRoute,
|
|
10
10
|
} from '@react-navigation/native'
|
|
11
11
|
import moment from 'moment'
|
|
12
|
-
import React, { useEffect } from 'react'
|
|
12
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
13
13
|
import { FlatList, Platform, StyleSheet, View } from 'react-native'
|
|
14
14
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
15
15
|
import { Badge, Icon, Text } from '../components'
|
|
@@ -32,6 +32,7 @@ import { getRelativeDateStatus } from '../utils/date'
|
|
|
32
32
|
import { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'
|
|
33
33
|
import { CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL } from '../utils/styles'
|
|
34
34
|
import { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'
|
|
35
|
+
import { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'
|
|
35
36
|
|
|
36
37
|
export type ConversationRouteProps = {
|
|
37
38
|
conversation_id: number
|
|
@@ -67,6 +68,20 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
|
|
|
67
68
|
const canDeleteNonAuthoredMessages = memberAbility?.canDeleteNonAuthoredMessages ?? false
|
|
68
69
|
const currentlyEditingMessage = messages.find(m => String(m.id) === String(editing_message_id))
|
|
69
70
|
|
|
71
|
+
const listRef = useRef<FlatList>(null)
|
|
72
|
+
const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)
|
|
73
|
+
|
|
74
|
+
const trackScroll = (event: any) => {
|
|
75
|
+
const offsetY = event.nativeEvent.contentOffset.y
|
|
76
|
+
setShowJumpToBottomButton(offsetY > 200)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const handleReturnToBottom = useCallback(() => {
|
|
80
|
+
listRef.current?.scrollToOffset({
|
|
81
|
+
offset: 0,
|
|
82
|
+
})
|
|
83
|
+
}, [])
|
|
84
|
+
|
|
70
85
|
useEffect(() => {
|
|
71
86
|
navigation.setParams({
|
|
72
87
|
title: title,
|
|
@@ -93,11 +108,14 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
|
|
|
93
108
|
) : (
|
|
94
109
|
<FlatList
|
|
95
110
|
inverted
|
|
111
|
+
ref={listRef}
|
|
96
112
|
contentContainerStyle={styles.listContainer}
|
|
97
113
|
refreshing={isRefetching}
|
|
98
114
|
onRefresh={refetch}
|
|
99
115
|
data={messagesWithSeparators}
|
|
100
116
|
keyExtractor={item => item.id}
|
|
117
|
+
onScroll={trackScroll}
|
|
118
|
+
scrollEventThrottle={10}
|
|
101
119
|
renderItem={({ item }) => {
|
|
102
120
|
if (item.type === 'DateSeparator') {
|
|
103
121
|
return <InlineDateSeparator {...item} />
|
|
@@ -116,6 +134,7 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
|
|
|
116
134
|
ListHeaderComponent={<View style={styles.listHeader} />}
|
|
117
135
|
/>
|
|
118
136
|
)}
|
|
137
|
+
<JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />
|
|
119
138
|
{!noMessages && <TypingIndicator conversationId={conversation_id} />}
|
|
120
139
|
{showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}
|
|
121
140
|
{canReply ? (
|