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 c46cc161346263ed0d7614f1357438d12a847c0c
parent dc02dd4c05cd6ffac286b11e91ccc0bb8b9124ec
Author: Johan Lindskogen <johan.lindskogen@gmail.com>
Date:   Mon,  2 Apr 2018 22:05:29 +0200

Persist connection info

Diffstat:
Mpackage.json | 1+
Msrc/lib/weechat/connection.ts | 17++++++++++++++---
Msrc/store/connection-info.ts | 7+++++--
Msrc/store/index.ts | 12+++++++++++-
Msrc/usecase/ConnectionGate.tsx | 5+++--
Msrc/usecase/Root.tsx | 25++++++++++++++-----------
Msrc/usecase/login/LoginForm.tsx | 30++++++++++++++++++++++++------
Myarn.lock | 4++++
8 files changed, 76 insertions(+), 25 deletions(-)

diff --git a/package.json b/package.json @@ -18,6 +18,7 @@ "react-native-parsed-text": "^0.0.20", "react-redux": "^5.0.7", "redux": "^3.7.2", + "redux-persist": "^5.9.1", "redux-thunk": "^2.2.0" }, "devDependencies": { diff --git a/src/lib/weechat/connection.ts b/src/lib/weechat/connection.ts @@ -7,6 +7,7 @@ export default class WeechatConnection { dispatch: any; hostname: string; password: string; + ssl: boolean; compressed: boolean; websocket: WebSocket; @@ -15,11 +16,20 @@ export default class WeechatConnection { this.websocket = null; } - connect(host, password = "", onSuccess, onError) { + connect( + host: string, + password: string = "", + ssl: boolean, + onSuccess: (conn: WeechatConnection) => any, + onError: (event: Event) => any + ) { this.hostname = host; this.password = password; + this.ssl = ssl; - this.websocket = new WebSocket(this.hostname); + this.websocket = new WebSocket( + `${this.ssl ? "wss" : "ws"}://${this.hostname}/weechat` + ); this.websocket.onopen = () => this.onopen(onSuccess); this.websocket.onmessage = event => this.onmessage(event); @@ -30,7 +40,8 @@ export default class WeechatConnection { this.dispatch({ type: "SET_CONNECTION_INFO", hostname: this.hostname, - password: this.password + password: this.password, + ssl: this.ssl }); this.send( `init password=${this.password},compression=${ diff --git a/src/store/connection-info.ts b/src/store/connection-info.ts @@ -1,11 +1,13 @@ export type ConnectionInfo = { hostname: string | null; password: string | null; + ssl: boolean; }; const initialState: ConnectionInfo = { hostname: null, - password: null + password: null, + ssl: false }; export default (state: ConnectionInfo = initialState, action) => { @@ -13,7 +15,8 @@ export default (state: ConnectionInfo = initialState, action) => { case "SET_CONNECTION_INFO": return { hostname: action.hostname, - password: action.password + password: action.password, + ssl: action.ssl }; case "CLEAR_CONNECTION_INFO": return initialState; diff --git a/src/store/index.ts b/src/store/index.ts @@ -1,9 +1,12 @@ import { compose, combineReducers, createStore, applyMiddleware } from "redux"; import thunk from "redux-thunk"; +import { persistStore, persistReducer } from "redux-persist"; +import storage from "redux-persist/lib/storage"; import buffers, { BufferState } from "./buffers"; import lines, { LineState } from "./lines"; import hotlists, { HotListState } from "./hotlists"; +import connection, { ConnectionInfo } from "./connection-info"; type AppState = { connected: boolean; @@ -12,6 +15,7 @@ type AppState = { export type StoreState = { app: AppState; + connection: ConnectionInfo; buffers: BufferState; lines: LineState; hotlists: HotListState; @@ -43,10 +47,16 @@ const reducer = combineReducers({ app, buffers, lines, + connection, hotlists }); const composeEnhancers = (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; -export default createStore(reducer, composeEnhancers(applyMiddleware(thunk))); +export const store = createStore( + persistReducer({ storage, key: "state", whitelist: ["connection"] }, reducer), + composeEnhancers(applyMiddleware(thunk)) +); + +export const persistor = persistStore(store); diff --git a/src/usecase/ConnectionGate.tsx b/src/usecase/ConnectionGate.tsx @@ -1,11 +1,12 @@ import * as React from "react"; import { connect } from "react-redux"; import LoginForm from "./login/LoginForm"; +import { StoreState } from "../store"; interface Props { connecting: boolean; connected: boolean; - onConnect: (hostname: string, password: string) => void; + onConnect: (hostname: string, password: string, ssl: boolean) => void; } class ConnectionGate extends React.Component<Props> { @@ -19,6 +20,6 @@ class ConnectionGate extends React.Component<Props> { } } -export default connect(state => ({ +export default connect((state: StoreState) => ({ connected: state.app.connected }))(ConnectionGate); diff --git a/src/usecase/Root.tsx b/src/usecase/Root.tsx @@ -1,9 +1,10 @@ import * as React from "react"; import { StatusBar } from "react-native"; import { Provider } from "react-redux"; +import { PersistGate } from "redux-persist/integration/react"; import WeechatConnection from "../lib/weechat/connection"; -import store from "../store"; +import { store, persistor } from "../store"; import App from "./App"; import ConnectionGate from "./ConnectionGate"; @@ -39,12 +40,12 @@ export default class WeechatNative extends React.Component<{}, State> { console.log(error); }; - onConnect = (hostname: string, password: string) => { - console.log(hostname, password); + onConnect = (hostname: string, password: string, ssl: boolean) => { this.setState({ connecting: true }); this.connection.connect( hostname, password, + ssl, this.onConnectionSuccess, this.onConnectionError ); @@ -72,14 +73,16 @@ export default class WeechatNative extends React.Component<{}, State> { return ( <Provider store={store}> - <ConnectionGate connecting={connecting} onConnect={this.onConnect}> - <StatusBar barStyle="light-content" /> - <App - clearHotlistForBuffer={this.clearHotlistForBuffer} - sendMessageToBuffer={this.sendMessageToBuffer} - fetchLinesForBuffer={this.fetchLines} - /> - </ConnectionGate> + <PersistGate loading={null} persistor={persistor}> + <ConnectionGate connecting={connecting} onConnect={this.onConnect}> + <StatusBar barStyle="light-content" /> + <App + clearHotlistForBuffer={this.clearHotlistForBuffer} + sendMessageToBuffer={this.sendMessageToBuffer} + fetchLinesForBuffer={this.fetchLines} + /> + </ConnectionGate> + </PersistGate> </Provider> ); } diff --git a/src/usecase/login/LoginForm.tsx b/src/usecase/login/LoginForm.tsx @@ -10,10 +10,14 @@ import { TouchableOpacity } from "react-native"; import { connect } from "react-redux"; +import { StoreState } from "../../store"; interface Props { - onConnect: (hostname: string, password: string) => void; + onConnect: (hostname: string, password: string, ssl: boolean) => void; connecting: boolean; + hostname: string; + password: string; + ssl: boolean; } interface State { hostname: string; @@ -21,21 +25,30 @@ interface State { ssl: boolean; } -export default class LoginForm extends React.Component<Props, State> { +class LoginForm extends React.Component<Props, State> { state: State = { hostname: "", password: "", ssl: true }; + static getDerivedStateFromProps(nextProps: Props, prevState: State) { + if (!prevState.hostname && !prevState.password) { + return { + ...prevState, + hostname: nextProps.hostname, + password: nextProps.password + }; + } else { + return null; + } + } + onPress = () => { const { hostname, password, ssl } = this.state; - this.props.onConnect(this.getFullWebsocketUrl(hostname, ssl), password); + this.props.onConnect(hostname, password, ssl); }; - getFullWebsocketUrl = (hostname: string, ssl: boolean) => - `${ssl ? "wss" : "ws"}://${hostname}/weechat`; - setHostname = (hostname: string) => { this.setState({ hostname }); }; @@ -101,6 +114,11 @@ export default class LoginForm extends React.Component<Props, State> { } } +export default connect((state: StoreState) => ({ + hostname: state.connection.hostname, + password: state.connection.password +}))(LoginForm); + const styles = StyleSheet.create({ container: { backgroundColor: "#f8f8f8", diff --git a/yarn.lock b/yarn.lock @@ -4485,6 +4485,10 @@ realpath-native@^1.0.0: dependencies: util.promisify "^1.0.0" +redux-persist@^5.9.1: + version "5.9.1" + resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-5.9.1.tgz#83bd4abd526ef768f63fceee338fa9d8ed6552d6" + redux-thunk@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"