Changeset View
Changeset View
Standalone View
Standalone View
native/chat/chat-input-bar.react.js
Show All 37 Lines | import { | ||||
threadHasPermission, | threadHasPermission, | ||||
viewerIsMember, | viewerIsMember, | ||||
threadFrozenDueToViewerBlock, | threadFrozenDueToViewerBlock, | ||||
threadActualMembers, | threadActualMembers, | ||||
checkIfDefaultMembersAreVoiced, | checkIfDefaultMembersAreVoiced, | ||||
draftKeyFromThreadID, | draftKeyFromThreadID, | ||||
colorIsDark, | colorIsDark, | ||||
} from 'lib/shared/thread-utils'; | } from 'lib/shared/thread-utils'; | ||||
import type { Selection } from 'lib/shared/typeahead-utils'; | |||||
import type { CalendarQuery } from 'lib/types/entry-types'; | import type { CalendarQuery } from 'lib/types/entry-types'; | ||||
import type { LoadingStatus } from 'lib/types/loading-types'; | import type { LoadingStatus } from 'lib/types/loading-types'; | ||||
import type { PhotoPaste } from 'lib/types/media-types'; | import type { PhotoPaste } from 'lib/types/media-types'; | ||||
import { messageTypes } from 'lib/types/message-types'; | import { messageTypes } from 'lib/types/message-types'; | ||||
import type { Dispatch } from 'lib/types/redux-types'; | import type { Dispatch } from 'lib/types/redux-types'; | ||||
import { | import { | ||||
type ThreadInfo, | type ThreadInfo, | ||||
threadPermissions, | threadPermissions, | ||||
Show All 25 Lines | |||||
import { NavContext } from '../navigation/navigation-context'; | import { NavContext } from '../navigation/navigation-context'; | ||||
import { | import { | ||||
type NavigationRoute, | type NavigationRoute, | ||||
CameraModalRouteName, | CameraModalRouteName, | ||||
ImagePasteModalRouteName, | ImagePasteModalRouteName, | ||||
} from '../navigation/route-names'; | } from '../navigation/route-names'; | ||||
import { useSelector } from '../redux/redux-utils'; | import { useSelector } from '../redux/redux-utils'; | ||||
import { type Colors, useStyles, useColors } from '../themes/colors'; | import { type Colors, useStyles, useColors } from '../themes/colors'; | ||||
import type { LayoutEvent } from '../types/react-native'; | import type { LayoutEvent, SelectionChangeEvent } from '../types/react-native'; | ||||
import { type AnimatedViewStyle, AnimatedView } from '../types/styles'; | import { type AnimatedViewStyle, AnimatedView } from '../types/styles'; | ||||
import { runTiming } from '../utils/animation-utils'; | import { runTiming } from '../utils/animation-utils'; | ||||
import { ChatContext } from './chat-context'; | import { ChatContext } from './chat-context'; | ||||
import type { ChatNavigationProp } from './chat.react'; | import type { ChatNavigationProp } from './chat.react'; | ||||
/* eslint-disable import/no-named-as-default-member */ | /* eslint-disable import/no-named-as-default-member */ | ||||
const { | const { | ||||
Value, | Value, | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | type Props = { | ||||
+inputState: ?InputState, | +inputState: ?InputState, | ||||
+userSearchIndex: SearchIndex, | +userSearchIndex: SearchIndex, | ||||
+threadMembers: $ReadOnlyArray<RelativeMemberInfo>, | +threadMembers: $ReadOnlyArray<RelativeMemberInfo>, | ||||
}; | }; | ||||
type State = { | type State = { | ||||
+text: string, | +text: string, | ||||
+textEdited: boolean, | +textEdited: boolean, | ||||
+buttonsExpanded: boolean, | +buttonsExpanded: boolean, | ||||
+selection: Selection, | |||||
}; | }; | ||||
class ChatInputBar extends React.PureComponent<Props, State> { | class ChatInputBar extends React.PureComponent<Props, State> { | ||||
textInput: ?React.ElementRef<typeof TextInput>; | textInput: ?React.ElementRef<typeof TextInput>; | ||||
clearableTextInput: ?ClearableTextInput; | clearableTextInput: ?ClearableTextInput; | ||||
expandoButtonsOpen: Value; | expandoButtonsOpen: Value; | ||||
targetExpandoButtonsOpen: Value; | targetExpandoButtonsOpen: Value; | ||||
expandoButtonsStyle: AnimatedViewStyle; | expandoButtonsStyle: AnimatedViewStyle; | ||||
cameraRollIconStyle: AnimatedViewStyle; | cameraRollIconStyle: AnimatedViewStyle; | ||||
cameraIconStyle: AnimatedViewStyle; | cameraIconStyle: AnimatedViewStyle; | ||||
expandIconStyle: AnimatedViewStyle; | expandIconStyle: AnimatedViewStyle; | ||||
sendButtonContainerOpen: Value; | sendButtonContainerOpen: Value; | ||||
targetSendButtonContainerOpen: Value; | targetSendButtonContainerOpen: Value; | ||||
sendButtonContainerStyle: AnimatedViewStyle; | sendButtonContainerStyle: AnimatedViewStyle; | ||||
constructor(props: Props) { | constructor(props: Props) { | ||||
super(props); | super(props); | ||||
this.state = { | this.state = { | ||||
text: props.draft, | text: props.draft, | ||||
textEdited: false, | textEdited: false, | ||||
buttonsExpanded: true, | buttonsExpanded: true, | ||||
selection: { start: 0, end: 0 }, | |||||
}; | }; | ||||
this.setUpActionIconAnimations(); | this.setUpActionIconAnimations(); | ||||
this.setUpSendIconAnimations(); | this.setUpSendIconAnimations(); | ||||
} | } | ||||
setUpActionIconAnimations() { | setUpActionIconAnimations() { | ||||
this.expandoButtonsOpen = new Value(1); | this.expandoButtonsOpen = new Value(1); | ||||
▲ Show 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | return ( | ||||
</TouchableOpacity> | </TouchableOpacity> | ||||
{this.state.buttonsExpanded ? null : expandoButton} | {this.state.buttonsExpanded ? null : expandoButton} | ||||
</View> | </View> | ||||
</AnimatedView> | </AnimatedView> | ||||
<ClearableTextInput | <ClearableTextInput | ||||
allowImagePasteForThreadID={this.props.threadInfo.id} | allowImagePasteForThreadID={this.props.threadInfo.id} | ||||
value={this.state.text} | value={this.state.text} | ||||
onChangeText={this.updateText} | onChangeText={this.updateText} | ||||
selection={this.state.selection} | |||||
onSelectionChange={this.updateSelection} | |||||
placeholder="Send a message..." | placeholder="Send a message..." | ||||
placeholderTextColor={this.props.colors.listInputButton} | placeholderTextColor={this.props.colors.listInputButton} | ||||
multiline={true} | multiline={true} | ||||
style={this.props.styles.textInput} | style={this.props.styles.textInput} | ||||
textInputRef={this.textInputRef} | textInputRef={this.textInputRef} | ||||
ref={this.clearableTextInputRef} | ref={this.clearableTextInputRef} | ||||
selectionColor={`#${this.props.threadInfo.color}`} | selectionColor={`#${this.props.threadInfo.color}`} | ||||
/> | /> | ||||
Show All 25 Lines | clearableTextInputRef = (clearableTextInput: ?ClearableTextInput) => { | ||||
this.clearableTextInput = clearableTextInput; | this.clearableTextInput = clearableTextInput; | ||||
}; | }; | ||||
updateText = (text: string) => { | updateText = (text: string) => { | ||||
this.setState({ text, textEdited: true }); | this.setState({ text, textEdited: true }); | ||||
this.saveDraft(text); | this.saveDraft(text); | ||||
}; | }; | ||||
updateSelection: (event: SelectionChangeEvent) => void = event => { | |||||
this.setState({ selection: event.nativeEvent.selection }); | |||||
}; | |||||
saveDraft = _throttle(text => { | saveDraft = _throttle(text => { | ||||
this.props.dispatch({ | this.props.dispatch({ | ||||
type: updateDraftActionType, | type: updateDraftActionType, | ||||
payload: { | payload: { | ||||
key: draftKeyFromThreadID(this.props.threadInfo.id), | key: draftKeyFromThreadID(this.props.threadInfo.id), | ||||
text, | text, | ||||
}, | }, | ||||
}); | }); | ||||
▲ Show 20 Lines • Show All 398 Lines • Show Last 20 Lines |