movius-chats 1.3.0 → 1.3.2
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/README.md +605 -197
- package/lib/commonjs/index.js +3 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +3 -3
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/assets/Icons/CheckAllIcon.d.ts +5 -2
- package/lib/typescript/assets/Icons/CheckIcon.d.ts +5 -2
- package/lib/typescript/components/ChatInput/TruncateFileName.d.ts +2 -2
- package/lib/typescript/hooks/useKeyboardInset.d.ts +5 -0
- package/lib/typescript/types/index.d.ts +13 -0
- package/lib/typescript/utils/theme.d.ts +6 -0
- package/package.json +1 -1
- package/src/assets/Icons/CheckAllIcon.tsx +6 -1
- package/src/assets/Icons/CheckIcon.tsx +6 -2
- package/src/components/AudioPlayer/AudioPlayer.tsx +8 -4
- package/src/components/ChatBubble/ChatBubble.tsx +15 -8
- package/src/components/ChatBubble/MessageContent.tsx +23 -10
- package/src/components/ChatBubble/MessageStatus.tsx +19 -12
- package/src/components/ChatInput/ChatInput.tsx +26 -22
- package/src/components/ChatInput/FilePreview.tsx +9 -1
- package/src/components/ChatInput/TruncateFileName.tsx +9 -3
- package/src/components/MediaViewer/MediaViewer.tsx +9 -1
- package/src/components/TypingComponent/TypingIndicator.tsx +18 -9
- package/src/hooks/useKeyboardInset.ts +42 -0
- package/src/index.tsx +35 -3
- package/src/types/index.ts +14 -0
- package/src/utils/theme.ts +37 -0
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { FlatList, View } from 'react-native';
|
|
2
|
+
import { FlatList, KeyboardAvoidingView, Platform, View } from 'react-native';
|
|
3
3
|
import tw from 'twrnc';
|
|
4
4
|
import ChatBubble from './components/ChatBubble/ChatBubble';
|
|
5
5
|
import ChatInput from './components/ChatInput/ChatInput';
|
|
@@ -7,6 +7,7 @@ import MediaViewer from './components/MediaViewer/MediaViewer';
|
|
|
7
7
|
import { TypingIndicator } from './components/TypingComponent/TypingIndicator';
|
|
8
8
|
import { AudioProvider } from './context/AudioContext';
|
|
9
9
|
import { ChatProvider, useChatContext } from './context/ChatContext';
|
|
10
|
+
import { useKeyboardInset } from './hooks/useKeyboardInset';
|
|
10
11
|
import { ChatScreenProps } from './types';
|
|
11
12
|
|
|
12
13
|
const ChatScreenContent = () => {
|
|
@@ -34,11 +35,26 @@ const ChatScreenContent = () => {
|
|
|
34
35
|
CustomFileIcon,
|
|
35
36
|
CustomImagePreview,
|
|
36
37
|
CustomVideoPreview,
|
|
38
|
+
keyboardVerticalOffset = 0,
|
|
39
|
+
disableKeyboardAvoiding = false,
|
|
37
40
|
} = useChatContext();
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
const keyboardInset = useKeyboardInset(
|
|
43
|
+
keyboardVerticalOffset,
|
|
44
|
+
!disableKeyboardAvoiding
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const content = (
|
|
48
|
+
<View
|
|
49
|
+
style={[
|
|
50
|
+
tw`flex-1 px-2 pb-4 gap-2 relative`,
|
|
51
|
+
!disableKeyboardAvoiding && keyboardInset > 0
|
|
52
|
+
? { paddingBottom: keyboardInset + 16 }
|
|
53
|
+
: undefined,
|
|
54
|
+
]}
|
|
55
|
+
>
|
|
41
56
|
<FlatList
|
|
57
|
+
style={tw`flex-1`}
|
|
42
58
|
data={messages}
|
|
43
59
|
keyExtractor={(item) => item.id}
|
|
44
60
|
renderItem={({ item, index }) => (
|
|
@@ -60,6 +76,8 @@ const ChatScreenContent = () => {
|
|
|
60
76
|
}
|
|
61
77
|
showsVerticalScrollIndicator={false}
|
|
62
78
|
inverted
|
|
79
|
+
keyboardShouldPersistTaps="handled"
|
|
80
|
+
keyboardDismissMode="interactive"
|
|
63
81
|
/>
|
|
64
82
|
|
|
65
83
|
{renderCustomInput ? (
|
|
@@ -94,6 +112,20 @@ const ChatScreenContent = () => {
|
|
|
94
112
|
/>
|
|
95
113
|
</View>
|
|
96
114
|
);
|
|
115
|
+
|
|
116
|
+
if (disableKeyboardAvoiding) {
|
|
117
|
+
return <View style={tw`flex-1`}>{content}</View>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<KeyboardAvoidingView
|
|
122
|
+
style={tw`flex-1`}
|
|
123
|
+
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
|
|
124
|
+
keyboardVerticalOffset={keyboardVerticalOffset}
|
|
125
|
+
>
|
|
126
|
+
{content}
|
|
127
|
+
</KeyboardAvoidingView>
|
|
128
|
+
);
|
|
97
129
|
};
|
|
98
130
|
|
|
99
131
|
const ChatScreen: React.FC<ChatScreenProps> = (props) => {
|
package/src/types/index.ts
CHANGED
|
@@ -24,6 +24,11 @@ export interface ChatScreenProps {
|
|
|
24
24
|
onAudioRecordStart?: () => void;
|
|
25
25
|
onCameraPress?: () => void;
|
|
26
26
|
|
|
27
|
+
/** Extra space subtracted from keyboard height (header, tab bar, safe area). */
|
|
28
|
+
keyboardVerticalOffset?: number;
|
|
29
|
+
/** Set true if your screen already handles keyboard insets. */
|
|
30
|
+
disableKeyboardAvoiding?: boolean;
|
|
31
|
+
|
|
27
32
|
// Typing indicators and input
|
|
28
33
|
typingUsers?: Array<{ id: string; avatar: string; name: string }>;
|
|
29
34
|
onTypingStart?: () => void;
|
|
@@ -37,6 +42,7 @@ export interface ChatScreenProps {
|
|
|
37
42
|
|
|
38
43
|
// UI Customization
|
|
39
44
|
theme?: {
|
|
45
|
+
fontFamily?: string;
|
|
40
46
|
colors?: {
|
|
41
47
|
sentMessageTailColor?: string;
|
|
42
48
|
receivedMessageTailColor?: string;
|
|
@@ -47,6 +53,14 @@ export interface ChatScreenProps {
|
|
|
47
53
|
audioPlayIconColor?: string;
|
|
48
54
|
audioPauseIconColor?: string;
|
|
49
55
|
videoPlayIconColor?: string;
|
|
56
|
+
inputTextColor?: string;
|
|
57
|
+
sentIconColor?: string;
|
|
58
|
+
deliveredIconColor?: string;
|
|
59
|
+
readIconColor?: string;
|
|
60
|
+
};
|
|
61
|
+
sizes?: {
|
|
62
|
+
/** Twrnc classes (e.g. `"h-8 w-8"`) or pixel size (e.g. `28`). */
|
|
63
|
+
inputIconSize?: string | number;
|
|
50
64
|
};
|
|
51
65
|
bubbleStyle?: {
|
|
52
66
|
sent?: ViewStyle;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Platform, StyleProp, TextStyle, ViewStyle } from 'react-native';
|
|
2
|
+
import tw from 'twrnc';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_INPUT_ICON_CLASS =
|
|
5
|
+
Platform.OS === 'ios' ? 'h-6 w-6' : 'w-6 h-6';
|
|
6
|
+
|
|
7
|
+
/** Resolves theme.sizes.inputIconSize (twrnc class string or pixel number). */
|
|
8
|
+
export function getInputIconStyle(
|
|
9
|
+
size?: string | number,
|
|
10
|
+
extraClass?: string
|
|
11
|
+
): ViewStyle {
|
|
12
|
+
if (typeof size === 'number' && size > 0) {
|
|
13
|
+
return { width: size, height: size };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const sizeClass =
|
|
17
|
+
typeof size === 'string' && size.trim().length > 0
|
|
18
|
+
? size.trim()
|
|
19
|
+
: DEFAULT_INPUT_ICON_CLASS;
|
|
20
|
+
|
|
21
|
+
return tw.style(sizeClass, extraClass);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Applies theme.fontFamily to any Text / ParsedText style array. */
|
|
25
|
+
export function withFontFamily(
|
|
26
|
+
style: StyleProp<TextStyle>,
|
|
27
|
+
fontFamily?: string
|
|
28
|
+
): StyleProp<TextStyle> {
|
|
29
|
+
if (!fontFamily) {
|
|
30
|
+
return style;
|
|
31
|
+
}
|
|
32
|
+
return [style, { fontFamily }];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getFontFamilyStyle(fontFamily?: string): TextStyle | undefined {
|
|
36
|
+
return fontFamily ? { fontFamily } : undefined;
|
|
37
|
+
}
|