weechatRN

Weechat relay client for iOS using websockets https://github.com/mhoran/weechatRN
git clone http://git.hanabi.in/repos/weechatRN.git
Log | Files | Refs | README | LICENSE

commit 3153891340d06f298f2e444547b3cc4a63747fca
parent 17bc93dc1d5ecba400692593e0d85bdafa68c43b
Author: Johan Lindskogen <johan.lindskogen@gmail.com>
Date:   Thu,  5 Apr 2018 17:54:46 +0200

Autocomplete nicks

Diffstat:
Msrc/usecase/buffers/ui/Buffer.tsx | 8+-------
Msrc/usecase/buffers/ui/BufferContainer.tsx | 61++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Asrc/usecase/icons/long-arrow-right.png | 0
Asrc/usecase/icons/long-arrow-right@2x.png | 0
4 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/src/usecase/buffers/ui/Buffer.tsx b/src/usecase/buffers/ui/Buffer.tsx @@ -7,11 +7,9 @@ import { View, ListRenderItem } from "react-native"; -import { connect } from "react-redux"; import * as _ from "lodash"; import BufferLine from "./BufferLine"; -import { StoreState } from "../../../store"; interface Props { lines: WeechatLine[]; @@ -23,7 +21,7 @@ interface Props { const keyExtractor = (line: WeechatLine, index: number) => _.last(line.pointers); -class Buffer extends React.PureComponent<Props> { +export default class Buffer extends React.PureComponent<Props> { renderBuffer: ListRenderItem<WeechatLine> = ({ item }) => { const { onLongPress, parseArgs } = this.props; @@ -45,10 +43,6 @@ class Buffer extends React.PureComponent<Props> { } } -export default connect((state: StoreState, { bufferId }: Props) => ({ - lines: state.lines[bufferId] || [] -}))(Buffer); - const styles = StyleSheet.create({ topbar: { height: 20, diff --git a/src/usecase/buffers/ui/BufferContainer.tsx b/src/usecase/buffers/ui/BufferContainer.tsx @@ -8,13 +8,16 @@ import { Animated, Keyboard, TextInput, + Image, Easing, View, Text, - EmitterSubscription + EmitterSubscription, + TouchableOpacity } from "react-native"; import { connect } from "react-redux"; +import * as _ from "lodash"; import ParsedText from "react-native-parsed-text"; import { changeCurrentBuffer } from "../actions/BufferActions"; @@ -24,22 +27,26 @@ import Buffer from "./Buffer"; import { getParseArgs } from "../../../lib/helpers/parse-text-args"; import { formatUrl } from "../../../lib/helpers/url-formatter"; import { renderWeechatFormat } from "../../../lib/weechat/color-formatter"; +import { StoreState } from "../../../store"; interface Props { buffer: WeechatBuffer | null; + lines: WeechatLine[]; + nicklist: WeechatNicklist[]; bufferId: string; showTopic: boolean; - fetchLinesForBuffer: (bufferId: string) => void; sendMessage: (message: string) => void; } interface State { + showTabButton: boolean; inputWidth: Animated.Value; textValue: string; } -export default class BufferContainer extends React.Component<Props, State> { +class BufferContainer extends React.Component<Props, State> { state = { + showTabButton: false, inputWidth: new Animated.Value(350), textValue: "" }; @@ -51,6 +58,9 @@ export default class BufferContainer extends React.Component<Props, State> { ); handleOnFocus() { + this.setState({ + showTabButton: true + }); Animated.timing(this.state.inputWidth, { toValue: 310, duration: 250, @@ -58,6 +68,9 @@ export default class BufferContainer extends React.Component<Props, State> { }).start(); } handleOnBlur() { + this.setState({ + showTabButton: false + }); Animated.timing(this.state.inputWidth, { toValue: 350, duration: 250, @@ -97,11 +110,29 @@ export default class BufferContainer extends React.Component<Props, State> { }); }; - onLongPress = (line: WeechatLine) => {}; + tabCompleteNick = () => { + const tokens = this.state.textValue.split(" "); + const lastIndex = tokens.length - 1; + const nickcomplete = tokens[lastIndex].toLowerCase(); + + const alternatives = this.props.nicklist.filter(nick => + nick.name.toLowerCase().startsWith(nickcomplete) + ); + + if (alternatives[0]) { + tokens[lastIndex] = alternatives[0].name + ": "; + + this.setState({ + textValue: tokens.join(" ") + }); + } + }; + + onLongPress = () => {}; render() { - const { bufferId, buffer, showTopic } = this.props; - const { textValue } = this.state; + const { bufferId, buffer, showTopic, lines } = this.props; + const { textValue, showTabButton } = this.state; if (!bufferId) { return <View style={styles.container} />; @@ -120,6 +151,7 @@ export default class BufferContainer extends React.Component<Props, State> { )} <Buffer bufferId={bufferId} + lines={lines} onLongPress={this.onLongPress} parseArgs={this.parseArgs} /> @@ -136,12 +168,25 @@ export default class BufferContainer extends React.Component<Props, State> { onSubmitEditing={this.handleSubmit} /> </Animated.View> + {showTabButton && ( + <TouchableOpacity + style={{ alignItems: "center", width: 40 }} + onPress={this.tabCompleteNick} + > + <Image source={require("../../icons/long-arrow-right.png")} /> + </TouchableOpacity> + )} </View> </KeyboardAvoidingView> ); } } +export default connect((state: StoreState, { bufferId }: Props) => ({ + lines: state.lines[bufferId] || [], + nicklist: state.nicklists[bufferId] || [] +}))(BufferContainer); + const styles = StyleSheet.create({ topbar: { height: 20, @@ -164,7 +209,9 @@ const styles = StyleSheet.create({ bottomBox: { height: 40, paddingHorizontal: 10, - justifyContent: "center", + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", backgroundColor: "#333" }, inputBox: { diff --git a/src/usecase/icons/long-arrow-right.png b/src/usecase/icons/long-arrow-right.png Binary files differ. diff --git a/src/usecase/icons/long-arrow-right@2x.png b/src/usecase/icons/long-arrow-right@2x.png Binary files differ.