1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
import React from 'react'
import {Pressable, StyleSheet, View} from 'react-native'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import Graphemer from 'graphemer'
import TextareaAutosize from 'react-textarea-autosize'
import {MAX_DM_GRAPHEME_LENGTH} from '#/lib/constants'
import {
useMessageDraft,
useSaveMessageDraft,
} from '#/state/messages/message-drafts'
import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useTheme} from '#/alf'
import {useSharedInputStyles} from '#/components/forms/TextField'
import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlane} from '#/components/icons/PaperPlane'
export function MessageInput({
onSendMessage,
}: {
onSendMessage: (message: string) => void
}) {
const {_} = useLingui()
const t = useTheme()
const {getDraft, clearDraft} = useMessageDraft()
const [message, setMessage] = React.useState(getDraft)
const inputStyles = useSharedInputStyles()
const [isFocused, setIsFocused] = React.useState(false)
const [isHovered, setIsHovered] = React.useState(false)
const onSubmit = React.useCallback(() => {
if (message.trim() === '') {
return
}
if (new Graphemer().countGraphemes(message) > MAX_DM_GRAPHEME_LENGTH) {
Toast.show(_(msg`Message is too long`))
return
}
clearDraft()
onSendMessage(message.trimEnd())
setMessage('')
}, [message, onSendMessage, _, clearDraft])
const onKeyDown = React.useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter') {
if (e.shiftKey) return
e.preventDefault()
onSubmit()
}
},
[onSubmit],
)
const onChange = React.useCallback(
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
setMessage(e.target.value)
},
[],
)
useSaveMessageDraft(message)
return (
<View style={a.p_sm}>
<View
style={[
a.flex_row,
t.atoms.bg_contrast_25,
{
paddingHorizontal: a.p_sm.padding - 2,
paddingLeft: a.p_md.padding - 2,
borderWidth: 2,
borderRadius: 23,
borderColor: 'transparent',
},
isHovered && inputStyles.chromeHover,
isFocused && inputStyles.chromeFocus,
]}
// @ts-expect-error web only
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}>
<TextareaAutosize
style={StyleSheet.flatten([
a.flex_1,
a.px_sm,
a.border_0,
t.atoms.text,
{
paddingTop: 10,
paddingBottom: 12,
backgroundColor: 'transparent',
resize: 'none',
},
])}
maxRows={12}
placeholder={_(msg`Write a message`)}
defaultValue=""
value={message}
dirName="ltr"
autoFocus={true}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onChange={onChange}
onKeyDown={onKeyDown}
/>
<Pressable
accessibilityRole="button"
accessibilityLabel={_(msg`Send message`)}
accessibilityHint=""
style={[
a.rounded_full,
a.align_center,
a.justify_center,
{
height: 30,
width: 30,
marginTop: 5,
backgroundColor: t.palette.primary_500,
},
]}
onPress={onSubmit}>
<PaperPlane fill={t.palette.white} style={[a.relative, {left: 1}]} />
</Pressable>
</View>
</View>
)
}
|