Merge pull request #32 from RocketChat/redux-saga
Replace redux-thunk with redux-saga and some major architecture changes
This commit is contained in:
commit
08bd566d9e
|
@ -114,7 +114,8 @@
|
||||||
"semi": [2, "always"],
|
"semi": [2, "always"],
|
||||||
"prefer-const": 2,
|
"prefer-const": 2,
|
||||||
"object-shorthand": 2,
|
"object-shorthand": 2,
|
||||||
"consistent-return": 0
|
"consistent-return": 0,
|
||||||
|
"global-require": "off"
|
||||||
},
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
"__DEV__": true
|
"__DEV__": true
|
||||||
|
|
|
@ -36,6 +36,8 @@ node_modules/
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
|
||||||
|
coverage/
|
||||||
|
|
||||||
# BUCK
|
# BUCK
|
||||||
buck-out/
|
buck-out/
|
||||||
\.buckd/
|
\.buckd/
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import 'react-native';
|
||||||
|
import React from 'react';
|
||||||
|
import RoomItem from '../app/components/RoomItem';
|
||||||
|
|
||||||
|
// Note: test renderer must be required after react-native.
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
jest.mock('react-native-img-cache', () => { return { CachedImage: 'View' } });
|
||||||
|
|
||||||
|
it('renders correctly', () => {
|
||||||
|
expect(renderer.create(<RoomItem type="d" name="name" />).toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('render unread', () => {
|
||||||
|
expect(renderer.create(<RoomItem type="d" name="name" unread={1} />).toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('render unread +999', () => {
|
||||||
|
expect(renderer.create(<RoomItem type="d" name="name" unread={1000} />).toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('render no icon', () => {
|
||||||
|
expect(renderer.create(<RoomItem type="X" name="name" />).toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('render private group', () => {
|
||||||
|
expect(renderer.create(<RoomItem type="g" name="private-group" /> ).toJSON()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('render channel', () => {
|
||||||
|
expect(renderer.create(<RoomItem type="c" name="general" />).toJSON()).toMatchSnapshot();
|
||||||
|
});
|
|
@ -0,0 +1,533 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`render channel 1`] = `
|
||||||
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
|
"paddingLeft": 16,
|
||||||
|
"paddingRight": 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"justifyContent": "center",
|
||||||
|
"overflow": "hidden",
|
||||||
|
"width": 40,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"backgroundColor": "#00BCD4",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={false}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"color": undefined,
|
||||||
|
"fontSize": 12,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"color": "#fff",
|
||||||
|
"fontSize": 20,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"fontFamily": "Material Design Icons",
|
||||||
|
"fontStyle": "normal",
|
||||||
|
"fontWeight": "normal",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#444",
|
||||||
|
"flex": 1,
|
||||||
|
"fontSize": 16,
|
||||||
|
"marginLeft": 16,
|
||||||
|
"marginRight": 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
general
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`render no icon 1`] = `
|
||||||
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
|
"paddingLeft": 16,
|
||||||
|
"paddingRight": 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#444",
|
||||||
|
"flex": 1,
|
||||||
|
"fontSize": 16,
|
||||||
|
"marginLeft": 16,
|
||||||
|
"marginRight": 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
name
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`render private group 1`] = `
|
||||||
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
|
"paddingLeft": 16,
|
||||||
|
"paddingRight": 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#444",
|
||||||
|
"flex": 1,
|
||||||
|
"fontSize": 16,
|
||||||
|
"marginLeft": 16,
|
||||||
|
"marginRight": 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
private-group
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`render unread +999 1`] = `
|
||||||
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
|
"paddingLeft": 16,
|
||||||
|
"paddingRight": 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"justifyContent": "center",
|
||||||
|
"overflow": "hidden",
|
||||||
|
"width": 40,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"backgroundColor": "#3F51B5",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#ffffff",
|
||||||
|
"fontSize": 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
NA
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
source={
|
||||||
|
Object {
|
||||||
|
"uri": "undefined/avatar/name",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"position": "absolute",
|
||||||
|
"width": 40,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#444",
|
||||||
|
"flex": 1,
|
||||||
|
"fontSize": 16,
|
||||||
|
"marginLeft": 16,
|
||||||
|
"marginRight": 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
name
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"backgroundColor": "#1d74f5",
|
||||||
|
"borderRadius": 5,
|
||||||
|
"color": "#fff",
|
||||||
|
"fontSize": 14,
|
||||||
|
"minWidth": 20,
|
||||||
|
"overflow": "hidden",
|
||||||
|
"paddingLeft": 5,
|
||||||
|
"paddingRight": 5,
|
||||||
|
"textAlign": "center",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
999+
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`render unread 1`] = `
|
||||||
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
|
"paddingLeft": 16,
|
||||||
|
"paddingRight": 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"justifyContent": "center",
|
||||||
|
"overflow": "hidden",
|
||||||
|
"width": 40,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"backgroundColor": "#3F51B5",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#ffffff",
|
||||||
|
"fontSize": 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
NA
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
source={
|
||||||
|
Object {
|
||||||
|
"uri": "undefined/avatar/name",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"position": "absolute",
|
||||||
|
"width": 40,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#444",
|
||||||
|
"flex": 1,
|
||||||
|
"fontSize": 16,
|
||||||
|
"marginLeft": 16,
|
||||||
|
"marginRight": 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
name
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"backgroundColor": "#1d74f5",
|
||||||
|
"borderRadius": 5,
|
||||||
|
"color": "#fff",
|
||||||
|
"fontSize": 14,
|
||||||
|
"minWidth": 20,
|
||||||
|
"overflow": "hidden",
|
||||||
|
"paddingLeft": 5,
|
||||||
|
"paddingRight": 5,
|
||||||
|
"textAlign": "center",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
1
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`renders correctly 1`] = `
|
||||||
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"flexDirection": "row",
|
||||||
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
|
"paddingLeft": 16,
|
||||||
|
"paddingRight": 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"alignItems": "center",
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"justifyContent": "center",
|
||||||
|
"overflow": "hidden",
|
||||||
|
"width": 40,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"backgroundColor": "#3F51B5",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#ffffff",
|
||||||
|
"fontSize": 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
NA
|
||||||
|
</Text>
|
||||||
|
<View
|
||||||
|
source={
|
||||||
|
Object {
|
||||||
|
"uri": "undefined/avatar/name",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"borderRadius": 20,
|
||||||
|
"height": 40,
|
||||||
|
"position": "absolute",
|
||||||
|
"width": 40,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<Text
|
||||||
|
accessible={true}
|
||||||
|
allowFontScaling={true}
|
||||||
|
disabled={false}
|
||||||
|
ellipsizeMode="tail"
|
||||||
|
numberOfLines={1}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"color": "#444",
|
||||||
|
"flex": 1,
|
||||||
|
"fontSize": 16,
|
||||||
|
"marginLeft": 16,
|
||||||
|
"marginRight": 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
name
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
`;
|
|
@ -4,15 +4,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
<RCTScrollView>
|
<RCTScrollView>
|
||||||
<View>
|
<View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -81,15 +99,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -158,15 +194,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -256,15 +310,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -354,15 +426,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -452,15 +542,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -550,15 +658,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -648,15 +774,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -725,15 +869,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
@ -802,15 +964,33 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
|
accessibilityComponentType={undefined}
|
||||||
|
accessibilityLabel={undefined}
|
||||||
|
accessibilityTraits={undefined}
|
||||||
|
accessible={true}
|
||||||
|
collapsable={undefined}
|
||||||
|
hitSlop={undefined}
|
||||||
|
isTVSelectable={true}
|
||||||
|
nativeID={undefined}
|
||||||
|
onLayout={undefined}
|
||||||
|
onResponderGrant={[Function]}
|
||||||
|
onResponderMove={[Function]}
|
||||||
|
onResponderRelease={[Function]}
|
||||||
|
onResponderTerminate={[Function]}
|
||||||
|
onResponderTerminationRequest={[Function]}
|
||||||
|
onStartShouldSetResponder={[Function]}
|
||||||
style={
|
style={
|
||||||
Object {
|
Object {
|
||||||
"alignItems": "center",
|
"alignItems": "center",
|
||||||
"flexDirection": "row",
|
"flexDirection": "row",
|
||||||
"height": 56,
|
"height": 56,
|
||||||
|
"opacity": 1,
|
||||||
"paddingLeft": 16,
|
"paddingLeft": 16,
|
||||||
"paddingRight": 16,
|
"paddingRight": 16,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
testID={undefined}
|
||||||
|
tvParallaxProperties={undefined}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={
|
style={
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
||||||
|
ÖŠ<EFBFBD>tùþ춥Z'ŸFöà.â°'
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
const REQUEST = 'REQUEST';
|
||||||
|
const SUCCESS = 'SUCCESS';
|
||||||
|
const FAILURE = 'FAILURE';
|
||||||
|
const defaultTypes = [REQUEST, SUCCESS, FAILURE];
|
||||||
|
function createRequestTypes(base, types = defaultTypes) {
|
||||||
|
const res = {};
|
||||||
|
types.forEach(type => res[type] = `${ base }_${ type }`);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login events
|
||||||
|
export const LOGIN = createRequestTypes('LOGIN', [...defaultTypes, 'SET_TOKEN', 'SUBMIT']);
|
||||||
|
export const ROOMS = createRequestTypes('ROOMS');
|
||||||
|
export const APP = createRequestTypes('APP', ['READY']);
|
||||||
|
export const MESSAGES = createRequestTypes('MESSAGES');
|
||||||
|
export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
|
||||||
|
export const SERVER = createRequestTypes('SERVER', ['SELECT', 'CHANGED']);
|
||||||
|
export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DISCONNECT']);
|
||||||
|
export const LOGOUT = 'LOGOUT'; // logout is always success
|
||||||
|
|
||||||
|
export const INCREMENT = 'INCREMENT';
|
||||||
|
export const DECREMENT = 'DECREMENT';
|
|
@ -0,0 +1,28 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export function connectRequest() {
|
||||||
|
return {
|
||||||
|
type: types.METEOR.REQUEST
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function connectSuccess() {
|
||||||
|
return {
|
||||||
|
type: types.METEOR.SUCCESS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function connectFailure(err) {
|
||||||
|
return {
|
||||||
|
type: types.METEOR.FAILURE,
|
||||||
|
err
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function disconnect(err) {
|
||||||
|
console.log('types.METEOR.DISCONNECT');
|
||||||
|
return {
|
||||||
|
type: types.METEOR.DISCONNECT,
|
||||||
|
err
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
import * as types from '../constants/types';
|
import * as types from '../constants/types';
|
||||||
|
import { APP } from './actionsTypes';
|
||||||
|
|
||||||
|
export function appReady() {
|
||||||
|
return {
|
||||||
|
type: APP.READY
|
||||||
|
};
|
||||||
|
}
|
||||||
export function setCurrentServer(server) {
|
export function setCurrentServer(server) {
|
||||||
return {
|
return {
|
||||||
type: types.SET_CURRENT_SERVER,
|
type: types.SET_CURRENT_SERVER,
|
||||||
|
@ -13,123 +19,8 @@ export function setAllSettings(settings) {
|
||||||
payload: settings
|
payload: settings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
export function login() {
|
||||||
// // GENRES
|
return {
|
||||||
// export function retrieveMoviesGenresSuccess(res) {
|
type: 'LOGIN'
|
||||||
// return {
|
};
|
||||||
// type: types.RETRIEVE_MOVIES_GENRES_SUCCESS,
|
}
|
||||||
// moviesGenres: res.data
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function retrieveMoviesGenres() {
|
|
||||||
// return function (dispatch) {
|
|
||||||
// return axios.get(`${TMDB_URL}/genre/movie/list?api_key=${TMDB_API_KEY}`)
|
|
||||||
// .then(res => {
|
|
||||||
// dispatch(retrieveMoviesGenresSuccess(res));
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log(error); //eslint-disable-line
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // POPULAR
|
|
||||||
// export function retrievePopularMoviesSuccess(res) {
|
|
||||||
// return {
|
|
||||||
// type: types.RETRIEVE_POPULAR_MOVIES_SUCCESS,
|
|
||||||
// popularMovies: res.data
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function retrievePopularMovies(page) {
|
|
||||||
// return function (dispatch) {
|
|
||||||
// return axios.get(`${TMDB_URL}/movie/popular?api_key=${TMDB_API_KEY}&page=${page}`)
|
|
||||||
// .then(res => {
|
|
||||||
// dispatch(retrievePopularMoviesSuccess(res));
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log('Popular', error); //eslint-disable-line
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // NOW PLAYING
|
|
||||||
// export function retrieveNowPlayingMoviesSuccess(res) {
|
|
||||||
// return {
|
|
||||||
// type: types.RETRIEVE_NOWPLAYING_MOVIES_SUCCESS,
|
|
||||||
// nowPlayingMovies: res.data
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function retrieveNowPlayingMovies(page) {
|
|
||||||
// return function (dispatch) {
|
|
||||||
// return axios.get(`${TMDB_URL}/movie/now_playing?api_key=${TMDB_API_KEY}&page=${page}`)
|
|
||||||
// .then(res => {
|
|
||||||
// dispatch(retrieveNowPlayingMoviesSuccess(res));
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log('Now Playing', error); //eslint-disable-line
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MOVIES LIST
|
|
||||||
// export function retrieveMoviesListSuccess(res) {
|
|
||||||
// return {
|
|
||||||
// type: types.RETRIEVE_MOVIES_LIST_SUCCESS,
|
|
||||||
// list: res.data
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function retrieveMoviesList(type, page) {
|
|
||||||
// return function (dispatch) {
|
|
||||||
// return axios.get(`${TMDB_URL}/movie/${type}?api_key=${TMDB_API_KEY}&page=${page}`)
|
|
||||||
// .then(res => {
|
|
||||||
// dispatch(retrieveMoviesListSuccess(res));
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log('Movies List', error); //eslint-disable-line
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // SEARCH RESULTS
|
|
||||||
// export function retrieveMoviesSearchResultsSuccess(res) {
|
|
||||||
// return {
|
|
||||||
// type: types.RETRIEVE_MOVIES_SEARCH_RESULT_SUCCESS,
|
|
||||||
// searchResults: res.data
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function retrieveMoviesSearchResults(query, page) {
|
|
||||||
// return function (dispatch) {
|
|
||||||
// return axios.get(`${TMDB_URL}/search/movie?api_key=${TMDB_API_KEY}&query=${query}&page=${page}`)
|
|
||||||
// .then(res => {
|
|
||||||
// dispatch(retrieveMoviesSearchResultsSuccess(res));
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log('Movies Search Results', error); //eslint-disable-line
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // MOVIE DETAILS
|
|
||||||
// export function retrieveMovieDetailsSuccess(res) {
|
|
||||||
// return {
|
|
||||||
// type: types.RETRIEVE_MOVIE_DETAILS_SUCCESS,
|
|
||||||
// details: res.data
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function retrieveMovieDetails(movieId) {
|
|
||||||
// return function (dispatch) {
|
|
||||||
// return axios.get(`${TMDB_URL}/movie/${movieId}?api_key=${TMDB_API_KEY}&append_to_response=casts,images,videos`)
|
|
||||||
// .then(res => {
|
|
||||||
// dispatch(retrieveMovieDetailsSuccess(res));
|
|
||||||
// })
|
|
||||||
// .catch(error => {
|
|
||||||
// console.log('Movie Details', error); //eslint-disable-line
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export function loginSubmit(credentials) {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SUBMIT,
|
||||||
|
credentials
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function loginRequest(credentials) {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.REQUEST,
|
||||||
|
credentials
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loginSuccess(user) {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SUCCESS,
|
||||||
|
user,
|
||||||
|
token: user.token
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loginFailure(err) {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.FAILURE,
|
||||||
|
err
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setToken(user) {
|
||||||
|
return {
|
||||||
|
type: types.LOGIN.SET_TOKEN,
|
||||||
|
token: user.token,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logout() {
|
||||||
|
return {
|
||||||
|
type: types.LOGOUT
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export function messagesRequest({ rid }) {
|
||||||
|
console.log(types.MESSAGES.REQUEST, rid);
|
||||||
|
return {
|
||||||
|
type: types.MESSAGES.REQUEST,
|
||||||
|
rid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function messagesSuccess() {
|
||||||
|
return {
|
||||||
|
type: types.MESSAGES.SUCCESS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function messagesFailure(err) {
|
||||||
|
return {
|
||||||
|
type: types.MESSAGES.FAILURE,
|
||||||
|
err
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export default function setNavigation(navigator = {}) {
|
||||||
|
return {
|
||||||
|
type: types.NAVIGATION.SET,
|
||||||
|
navigator
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import * as types from './actionsTypes';
|
||||||
|
|
||||||
|
export function roomsRequest() {
|
||||||
|
return {
|
||||||
|
type: types.ROOMS.REQUEST
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function roomsSuccess() {
|
||||||
|
return {
|
||||||
|
type: types.ROOMS.SUCCESS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function roomsFailure(err) {
|
||||||
|
return {
|
||||||
|
type: types.ROOMS.FAILURE,
|
||||||
|
err
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { SERVER } from './actionsTypes';
|
||||||
|
|
||||||
|
export function setServer(server) {
|
||||||
|
return {
|
||||||
|
type: SERVER.SELECT,
|
||||||
|
server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function changedServer(server) {
|
||||||
|
return {
|
||||||
|
type: SERVER.CHANGED,
|
||||||
|
server
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { Animated, Text } from 'react-native';
|
||||||
|
|
||||||
|
export default class Fade extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
visible: PropTypes.bool.isRequired,
|
||||||
|
style: Animated.View.propTypes.style,
|
||||||
|
children: PropTypes.oneOfType([
|
||||||
|
PropTypes.arrayOf(PropTypes.node),
|
||||||
|
PropTypes.node
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
visible: props.visible
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this._visibility = new Animated.Value(this.props.visible ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.visible) {
|
||||||
|
this.setState({ visible: true });
|
||||||
|
}
|
||||||
|
Animated.timing(this._visibility, {
|
||||||
|
toValue: nextProps.visible ? 1 : 0,
|
||||||
|
duration: 300
|
||||||
|
}).start(() => {
|
||||||
|
this.setState({ visible: nextProps.visible });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { style, children, ...rest } = this.props;
|
||||||
|
|
||||||
|
const containerStyle = {
|
||||||
|
opacity: this._visibility.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [0, 1]
|
||||||
|
}),
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
scale: this._visibility.interpolate({
|
||||||
|
inputRange: [0, 1],
|
||||||
|
outputRange: [1.1, 1]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const combinedStyle = [containerStyle, style];
|
||||||
|
return (
|
||||||
|
<Animated.View style={this.state.visible ? combinedStyle : containerStyle} {...rest}>
|
||||||
|
<Text>{this.state.visible ? children : null}</Text>
|
||||||
|
</Animated.View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,21 +36,14 @@ export default class MessageBox extends React.PureComponent {
|
||||||
rid: PropTypes.string.isRequired
|
rid: PropTypes.string.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
text: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
submit(message) {
|
submit(message) {
|
||||||
// console.log(this.state);
|
|
||||||
const text = message;
|
const text = message;
|
||||||
this.setState({ text: '' });
|
|
||||||
if (text.trim() === '') {
|
if (text.trim() === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.component) {
|
||||||
|
this.component.setNativeProps({ text: '' });
|
||||||
|
}
|
||||||
this.props.onSubmit(text);
|
this.props.onSubmit(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +55,6 @@ export default class MessageBox extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
ImagePicker.showImagePicker(options, (response) => {
|
ImagePicker.showImagePicker(options, (response) => {
|
||||||
// console.log('Response = ', response);
|
|
||||||
|
|
||||||
if (response.didCancel) {
|
if (response.didCancel) {
|
||||||
console.log('User cancelled image picker');
|
console.log('User cancelled image picker');
|
||||||
} else if (response.error) {
|
} else if (response.error) {
|
||||||
|
@ -90,13 +81,12 @@ export default class MessageBox extends React.PureComponent {
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={component => this.component = component}
|
ref={component => this.component = component}
|
||||||
style={styles.textBoxInput}
|
style={styles.textBoxInput}
|
||||||
value={this.state.text}
|
|
||||||
onChangeText={text => this.setState({ text })}
|
|
||||||
returnKeyType='send'
|
returnKeyType='send'
|
||||||
onSubmitEditing={event => this.submit(event.nativeEvent.text)}
|
onSubmitEditing={event => this.submit(event.nativeEvent.text)}
|
||||||
blurOnSubmit={false}
|
blurOnSubmit={false}
|
||||||
placeholder='New message'
|
placeholder='New message'
|
||||||
underlineColorAndroid='transparent'
|
underlineColorAndroid='transparent'
|
||||||
|
defaultValue={''}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { CachedImage } from 'react-native-img-cache';
|
import { CachedImage } from 'react-native-img-cache';
|
||||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { View, Text, StyleSheet } from 'react-native';
|
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
|
import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
|
||||||
|
|
||||||
|
@ -62,7 +62,8 @@ export default class RoomItem extends React.PureComponent {
|
||||||
type: PropTypes.string.isRequired,
|
type: PropTypes.string.isRequired,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
unread: PropTypes.number,
|
unread: PropTypes.number,
|
||||||
baseUrl: PropTypes.string
|
baseUrl: PropTypes.string,
|
||||||
|
onPress: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
get icon() {
|
get icon() {
|
||||||
|
@ -116,13 +117,12 @@ export default class RoomItem extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { unread, name } = this.props;
|
const { unread, name } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<TouchableOpacity onPress={this.props.onPress} style={styles.container}>
|
||||||
{this.icon}
|
{this.icon}
|
||||||
<Text style={styles.roomName} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text>
|
<Text style={styles.roomName} ellipsizeMode='tail' numberOfLines={1}>{ name }</Text>
|
||||||
{this.renderNumber(unread)}
|
{this.renderNumber(unread)}
|
||||||
</View>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { StyleSheet, View, Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
bannerContainer: {
|
||||||
|
backgroundColor: '#ddd',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '0%',
|
||||||
|
zIndex: 10,
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
bannerText: {
|
||||||
|
textAlign: 'center',
|
||||||
|
margin: 5
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@connect(state => ({
|
||||||
|
connecting: state.meteor.connecting,
|
||||||
|
authenticating: state.login.isFetching,
|
||||||
|
offline: !state.meteor.connected
|
||||||
|
}))
|
||||||
|
|
||||||
|
export default class Banner extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
connecting: PropTypes.bool,
|
||||||
|
authenticating: PropTypes.bool,
|
||||||
|
offline: PropTypes.bool
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { connecting, authenticating, offline } = this.props;
|
||||||
|
if (connecting) {
|
||||||
|
return (
|
||||||
|
<View style={[styles.bannerContainer, { backgroundColor: '#0d0' }]}>
|
||||||
|
<Text style={[styles.bannerText, { color: '#fff' }]}>Connecting...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authenticating) {
|
||||||
|
return (
|
||||||
|
<View style={[styles.bannerContainer, { backgroundColor: 'orange' }]}>
|
||||||
|
<Text style={[styles.bannerText, { color: '#a00' }]}>Authenticating...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (offline) {
|
||||||
|
return (
|
||||||
|
<View style={[styles.bannerContainer, { backgroundColor: 'red' }]}>
|
||||||
|
<Text style={[styles.bannerText, { color: '#a00' }]}>offline...</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Meteor from 'react-native-meteor';
|
import Meteor from 'react-native-meteor';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import { CachedImage } from 'react-native-img-cache';
|
import { CachedImage } from 'react-native-img-cache';
|
||||||
import { Text, TouchableOpacity } from 'react-native';
|
import { Text, TouchableOpacity } from 'react-native';
|
||||||
import { Navigation } from 'react-native-navigation';
|
import { Navigation } from 'react-native-navigation';
|
||||||
|
@ -29,16 +30,22 @@ CustomButton.propTypes = {
|
||||||
|
|
||||||
Navigation.registerComponent('CustomButton', () => CustomButton);
|
Navigation.registerComponent('CustomButton', () => CustomButton);
|
||||||
|
|
||||||
|
@connect(state => ({
|
||||||
|
base: state.settings.Site_Url,
|
||||||
|
canShowList: state.login.token.length || state.login.user.token
|
||||||
|
}))
|
||||||
|
|
||||||
export default class Cards extends React.PureComponent {
|
export default class Cards extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
data: PropTypes.object.isRequired
|
data: PropTypes.object.isRequired,
|
||||||
|
base: PropTypes.string
|
||||||
}
|
}
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
const user = Meteor.user();
|
const user = Meteor.user();
|
||||||
this.state = {};
|
this.state = {};
|
||||||
RocketChat.getUserToken().then((token) => {
|
RocketChat.getUserToken().then((token) => {
|
||||||
this.setState({ img: `${ RocketChat.currentServer }${ this.props.data.image_url }?rc_uid=${ user._id }&rc_token=${ token }` });
|
this.setState({ img: `${ this.props.base }${ this.props.data.image_url }?rc_uid=${ user._id }&rc_token=${ token }` });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_onPressButton() {
|
_onPressButton() {
|
||||||
|
|
|
@ -1,10 +1,2 @@
|
||||||
// export const RETRIEVE_MOVIES_GENRES_SUCCESS = 'RETRIEVE_MOVIES_GENRES_SUCCESS';
|
|
||||||
|
|
||||||
// export const RETRIEVE_POPULAR_MOVIES_SUCCESS = 'RETRIEVE_POPULAR_MOVIES_SUCCESS';
|
|
||||||
// export const RETRIEVE_NOWPLAYING_MOVIES_SUCCESS = 'RETRIEVE_NOWPLAYING_MOVIES_SUCCESS';
|
|
||||||
// export const RETRIEVE_MOVIES_LIST_SUCCESS = 'RETRIEVE_MOVIES_LIST_SUCCESS';
|
|
||||||
// export const RETRIEVE_MOVIE_DETAILS_SUCCESS = 'RETRIEVE_MOVIE_DETAILS_SUCCESS';
|
|
||||||
// export const RETRIEVE_MOVIES_SEARCH_RESULT_SUCCESS = 'RETRIEVE_MOVIES_SEARCH_RESULT_SUCCESS';
|
|
||||||
|
|
||||||
export const SET_CURRENT_SERVER = 'SET_CURRENT_SERVER';
|
export const SET_CURRENT_SERVER = 'SET_CURRENT_SERVER';
|
||||||
export const SET_ALL_SETTINGS = 'SET_ALL_SETTINGS';
|
export const SET_ALL_SETTINGS = 'SET_ALL_SETTINGS';
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
|
@ -0,0 +1,77 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="435.721px" height="85.242px" viewBox="62.402 -18.766 435.721 85.242"
|
||||||
|
enable-background="new 62.402 -18.766 435.721 85.242" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path fill="#F4F4F4" d="M205.456,22.207c0,4.297-1.603,7.119-4.681,8.465l4.425,16.803c0.192,0.771-0.192,1.154-0.898,1.154h-6.67
|
||||||
|
c-0.641,0-0.961-0.32-1.09-0.898l-4.297-16.289h-4.425v16.162c0,0.642-0.384,1.025-1.026,1.025h-6.67
|
||||||
|
c-0.641,0-1.026-0.385-1.026-1.025V-1.651c0-0.641,0.385-1.026,1.026-1.026h16.097c6.028,0,9.235,3.207,9.235,9.235V22.207
|
||||||
|
L205.456,22.207z M194.169,22.976c1.667,0,2.565-0.898,2.565-2.565V8.354c0-1.667-0.898-2.564-2.565-2.564h-6.349v17.187
|
||||||
|
L194.169,22.976L194.169,22.976z"/>
|
||||||
|
<path fill="#F4F4F4" d="M210.583,6.558c0-6.028,3.206-9.235,9.235-9.235h7.183c6.028,0,9.235,3.207,9.235,9.235v32.836
|
||||||
|
c0,6.027-3.207,9.234-9.235,9.234h-7.183c-6.029,0-9.235-3.207-9.235-9.234V6.558z M225.397,40.355
|
||||||
|
c1.667,0,2.565-0.834,2.565-2.565V8.162c0-1.667-0.898-2.565-2.565-2.565h-3.719c-1.667,0-2.565,0.898-2.565,2.565v29.629
|
||||||
|
c0,1.73,0.898,2.564,2.565,2.564H225.397L225.397,40.355z"/>
|
||||||
|
<path fill="#F4F4F4" d="M268.362,13.484c0,0.642-0.385,1.026-1.025,1.026h-6.413c-0.706,0-1.026-0.384-1.026-1.026v-5.13
|
||||||
|
c0-1.667-0.897-2.564-2.564-2.564h-3.335c-1.731,0-2.565,0.897-2.565,2.564V37.6c0,1.731,0.897,2.563,2.565,2.563h3.335
|
||||||
|
c1.667,0,2.564-0.833,2.564-2.563v-5.132c0-0.642,0.32-1.026,1.026-1.026h6.413c0.643,0,1.025,0.384,1.025,1.026v6.927
|
||||||
|
c0,6.027-3.271,9.234-9.234,9.234h-7.183c-6.028,0-9.299-3.207-9.299-9.234V6.558c0-6.028,3.271-9.235,9.299-9.235h7.183
|
||||||
|
c5.964,0,9.234,3.207,9.234,9.235V13.484z"/>
|
||||||
|
<path fill="#F4F4F4" d="M295.422,48.629c-0.771,0-1.218-0.32-1.476-0.961l-8.079-19.048l-2.374,4.554v14.172
|
||||||
|
c0,0.834-0.448,1.283-1.282,1.283h-6.157c-0.834,0-1.283-0.449-1.283-1.283v-48.74c0-0.833,0.449-1.283,1.283-1.283h6.157
|
||||||
|
c0.833,0,1.282,0.449,1.282,1.283v19.881l9.876-20.202c0.321-0.641,0.771-0.962,1.476-0.962h6.733c0.962,0,1.347,0.642,0.897,1.539
|
||||||
|
l-10.901,22.382l11.606,25.91c0.449,0.834,0.064,1.475-0.961,1.475H295.422z"/>
|
||||||
|
<path fill="#F4F4F4" d="M333.45,4.763c0,0.641-0.257,1.09-1.026,1.09h-16.033v12.826h12.249c0.643,0,1.026,0.385,1.026,1.09v6.349
|
||||||
|
c0,0.706-0.385,1.091-1.026,1.091h-12.249v12.954h16.033c0.771,0,1.026,0.321,1.026,1.026v6.414c0,0.641-0.257,1.024-1.026,1.024
|
||||||
|
h-23.6c-0.578,0-0.963-0.385-0.963-1.024V-1.651c0-0.641,0.385-1.026,0.963-1.026h23.6c0.771,0,1.026,0.385,1.026,1.026V4.763z"/>
|
||||||
|
<path fill="#F4F4F4" d="M363.204-2.677c0.705,0,1.026,0.385,1.026,1.026v6.414c0,0.641-0.321,1.026-1.026,1.026h-7.439v41.814
|
||||||
|
c0,0.705-0.32,1.024-1.025,1.024h-6.67c-0.643,0-1.026-0.319-1.026-1.024V5.789h-7.438c-0.643,0-1.026-0.385-1.026-1.026v-6.414
|
||||||
|
c0-0.641,0.385-1.026,1.026-1.026H363.204z"/>
|
||||||
|
<path fill="#F4F4F4" d="M363.585,41.445c0-0.834,0.449-1.282,1.283-1.282h5.836c0.834,0,1.282,0.448,1.282,1.282v5.899
|
||||||
|
c0,0.835-0.448,1.283-1.282,1.283h-5.836c-0.834,0-1.283-0.448-1.283-1.283V41.445z"/>
|
||||||
|
<path fill="#F4F4F4" d="M404.114,13.484c0,0.642-0.386,1.026-1.026,1.026h-6.413c-0.705,0-1.025-0.384-1.025-1.026v-5.13
|
||||||
|
c0-1.667-0.897-2.564-2.564-2.564h-3.335c-1.732,0-2.565,0.897-2.565,2.564V37.6c0,1.731,0.897,2.563,2.565,2.563h3.335
|
||||||
|
c1.667,0,2.564-0.833,2.564-2.563v-5.132c0-0.642,0.32-1.026,1.025-1.026h6.413c0.643,0,1.026,0.384,1.026,1.026v6.927
|
||||||
|
c0,6.027-3.271,9.234-9.235,9.234h-7.183c-6.028,0-9.299-3.207-9.299-9.234V6.558c0-6.028,3.271-9.235,9.299-9.235h7.183
|
||||||
|
c5.965,0,9.235,3.207,9.235,9.235V13.484z"/>
|
||||||
|
<path fill="#F4F4F4" d="M427.455-1.651c0-0.641,0.384-1.026,1.025-1.026h6.605c0.77,0,1.089,0.385,1.089,1.026v49.254
|
||||||
|
c0,0.641-0.32,1.024-1.089,1.024h-6.605c-0.643,0-1.025-0.385-1.025-1.024V27.209h-8.209v20.395c0,0.642-0.385,1.025-1.026,1.025
|
||||||
|
h-6.604c-0.771,0-1.091-0.385-1.091-1.025V-1.651c0-0.641,0.32-1.026,1.091-1.026h6.604c0.643,0,1.026,0.385,1.026,1.026v20.394
|
||||||
|
h8.209V-1.651L427.455-1.651z"/>
|
||||||
|
<path fill="#F4F4F4" d="M465.419,48.629c-0.577,0-0.897-0.32-1.026-0.898l-1.795-9.362h-11.416l-1.73,9.362
|
||||||
|
c-0.129,0.578-0.449,0.898-1.026,0.898h-6.861c-0.705,0-1.026-0.385-0.835-1.09l10.646-49.318c0.129-0.641,0.513-0.898,1.09-0.898
|
||||||
|
h8.915c0.577,0,0.962,0.257,1.09,0.898l10.646,49.318c0.129,0.705-0.128,1.09-0.897,1.09H465.419z M456.889,8.546l-4.104,22.382
|
||||||
|
h8.209L456.889,8.546z"/>
|
||||||
|
<path fill="#F4F4F4" d="M497.097-2.677c0.705,0,1.026,0.385,1.026,1.026v6.414c0,0.641-0.321,1.026-1.026,1.026h-7.438v41.814
|
||||||
|
c0,0.705-0.321,1.024-1.026,1.024h-6.67c-0.641,0-1.025-0.319-1.025-1.024V5.789h-7.438c-0.642,0-1.025-0.385-1.025-1.026v-6.414
|
||||||
|
c0-0.641,0.385-1.026,1.025-1.026H497.097z"/>
|
||||||
|
</g>
|
||||||
|
<path fill="#C1272D" d="M162.586,23.788c0-5.031-1.505-9.854-4.474-14.339c-2.666-4.025-6.401-7.588-11.1-10.591
|
||||||
|
c-9.074-5.796-21-8.989-33.579-8.989c-4.202,0-8.344,0.355-12.361,1.059c-2.492-2.333-5.41-4.432-8.497-6.091
|
||||||
|
c-16.494-7.994-30.172-0.188-30.172-0.188S75.12-4.904,73.052,4.253c-5.689,5.644-8.773,12.45-8.773,19.535
|
||||||
|
c0,0.022,0.001,0.045,0.001,0.068c0,0.022-0.001,0.044-0.001,0.068c0,7.085,3.083,13.891,8.773,19.534
|
||||||
|
c2.068,9.158-10.649,19.605-10.649,19.605s13.678,7.805,30.172-0.188c3.087-1.659,6.004-3.759,8.497-6.091
|
||||||
|
c4.018,0.703,8.159,1.058,12.361,1.058c12.58,0,24.505-3.191,33.579-8.987c4.699-3.003,8.434-6.565,11.1-10.592
|
||||||
|
c2.969-4.484,4.474-9.309,4.474-14.338c0-0.023-0.001-0.045-0.001-0.068S162.586,23.81,162.586,23.788z"/>
|
||||||
|
<path fill="#FFFFFF" d="M113.433-3.018c23.293,0,42.177,12.062,42.177,26.941c0,14.878-18.884,26.941-42.177,26.941
|
||||||
|
c-5.187,0-10.154-0.6-14.743-1.693c-4.664,5.61-14.924,13.411-24.891,10.89c3.242-3.482,8.045-9.366,7.017-19.058
|
||||||
|
c-5.974-4.648-9.56-10.597-9.56-17.08C71.255,9.043,90.139-3.018,113.433-3.018"/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<circle fill="#C1272D" cx="113.433" cy="24.79" r="5.603"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<circle fill="#C1272D" cx="132.913" cy="24.79" r="5.603"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<circle fill="#C1272D" cx="93.952" cy="24.79" r="5.602"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path fill="#CCCCCC" d="M113.433,47.319c-5.187,0-10.154-0.52-14.743-1.468c-4.118,4.294-12.6,10.066-21.39,9.854
|
||||||
|
c-1.158,1.755-2.417,3.19-3.501,4.355c9.967,2.521,20.227-5.279,24.891-10.89c4.589,1.094,9.557,1.693,14.743,1.693
|
||||||
|
c23.106,0,41.87-11.871,42.169-26.585C155.303,37.032,136.539,47.319,113.433,47.319z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.3 KiB |
|
@ -0,0 +1,63 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Text } from 'react-native';
|
||||||
|
import setNavigator from './actions/navigator';
|
||||||
|
import LoginView from './views/login';
|
||||||
|
import ListServerView from './views/serverList';
|
||||||
|
|
||||||
|
import store from './lib/createStore';
|
||||||
|
|
||||||
|
export const authenticated = WrappedComponent => class _p extends React.PureComponent {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.login = store.getState().login;
|
||||||
|
console.log('this.login.token', this.login.token);
|
||||||
|
if (!this.login.token || this.login.failure) {
|
||||||
|
return store.getState().navigator.resetTo({
|
||||||
|
screen: 'Login'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
// Wraps the input component in a container, without mutating it. Good!
|
||||||
|
return <WrappedComponent {...this.props} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//
|
||||||
|
export class PublicScreen extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
return !this.login.isAuthenticated || !this.login.user ? null : (<ListServerView {...this.props} />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@connect(null, dispatch => ({
|
||||||
|
setNavigator: navigator => dispatch(setNavigator(navigator))
|
||||||
|
}))
|
||||||
|
export class PrivateScreen extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
return (<LoginView {...this.props} />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@connect(() => ({
|
||||||
|
// logged: state.login.isAuthenticated
|
||||||
|
}), dispatch => ({
|
||||||
|
setNavigator: navigator => dispatch(setNavigator(navigator))
|
||||||
|
}))
|
||||||
|
export const HomeScreen = class extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
setNavigator: PropTypes.func.isRequired,
|
||||||
|
navigator: PropTypes.object.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.props.setNavigator(this.props.navigator);
|
||||||
|
this.props.navigator.resetTo({
|
||||||
|
screen: 'public'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (<Text>oieee</Text>);
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,20 +1,24 @@
|
||||||
import { createStore, applyMiddleware } from 'redux';
|
import 'babel-polyfill';
|
||||||
import thunk from 'redux-thunk';
|
import 'regenerator-runtime/runtime';
|
||||||
import logger from 'redux-logger';
|
|
||||||
import rootReducer from '../reducers/rootReducer';
|
|
||||||
|
|
||||||
let middleware = [thunk];
|
import { createStore, applyMiddleware } from 'redux';
|
||||||
|
import createSagaMiddleware from 'redux-saga';
|
||||||
|
import reducers from '../reducers';
|
||||||
|
import sagas from '../sagas';
|
||||||
|
|
||||||
|
const sagaMiddleware = createSagaMiddleware();
|
||||||
|
let middleware;
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
/* eslint-disable global-require */
|
/* eslint-disable global-require */
|
||||||
const reduxImmutableStateInvariant = require('redux-immutable-state-invariant').default();
|
const reduxImmutableStateInvariant = require('redux-immutable-state-invariant').default();
|
||||||
middleware = [...middleware, reduxImmutableStateInvariant, logger];
|
middleware = [sagaMiddleware, reduxImmutableStateInvariant];
|
||||||
} else {
|
} else {
|
||||||
middleware = [...middleware];
|
middleware = [sagaMiddleware];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createStore(
|
export default createStore(
|
||||||
rootReducer,
|
reducers,
|
||||||
undefined,
|
|
||||||
applyMiddleware(...middleware)
|
applyMiddleware(...middleware)
|
||||||
);
|
);
|
||||||
|
sagaMiddleware.run(sagas);
|
||||||
|
|
|
@ -33,7 +33,6 @@ const subscriptionSchema = {
|
||||||
name: 'string',
|
name: 'string',
|
||||||
fname: { type: 'string', optional: true },
|
fname: { type: 'string', optional: true },
|
||||||
rid: 'string',
|
rid: 'string',
|
||||||
// u: { _id: 'hKCY2XGzHYk89SAaM', username: 'rodrigo', name: null },
|
|
||||||
open: { type: 'bool', optional: true },
|
open: { type: 'bool', optional: true },
|
||||||
alert: { type: 'bool', optional: true },
|
alert: { type: 'bool', optional: true },
|
||||||
// roles: [ 'owner' ],
|
// roles: [ 'owner' ],
|
||||||
|
@ -153,9 +152,9 @@ const messagesSchema = {
|
||||||
// ]
|
// ]
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
//
|
||||||
// Realm.clearTestState();
|
// Realm.clearTestState();
|
||||||
|
// AsyncStorage.clear();
|
||||||
const realm = new Realm({
|
const realm = new Realm({
|
||||||
schema: [settingsSchema, serversSchema, subscriptionSchema, messagesSchema, usersSchema, attachment]
|
schema: [settingsSchema, serversSchema, subscriptionSchema, messagesSchema, usersSchema, attachment]
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ import reduxStore from '../lib/createStore';
|
||||||
import settingsType from '../constants/settings';
|
import settingsType from '../constants/settings';
|
||||||
import realm from './realm';
|
import realm from './realm';
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
|
import { disconnect, connectSuccess } from '../actions/connect';
|
||||||
|
|
||||||
export { Accounts } from 'react-native-meteor';
|
export { Accounts } from 'react-native-meteor';
|
||||||
|
|
||||||
|
@ -28,18 +28,6 @@ const RocketChat = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
get currentServer() {
|
|
||||||
const current = realm.objects('servers').filtered('current = true').slice(0, 1)[0];
|
|
||||||
return current && current.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
set currentServer(server) {
|
|
||||||
realm.write(() => {
|
|
||||||
realm.objects('servers').filtered('current = true').forEach(item => (item.current = false));
|
|
||||||
realm.create('servers', { id: server, current: true }, true);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async getUserToken() {
|
async getUserToken() {
|
||||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||||
try {
|
try {
|
||||||
|
@ -49,75 +37,82 @@ const RocketChat = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
connect(cb) {
|
connect(_url) {
|
||||||
const url = `${ RocketChat.currentServer }/websocket`;
|
return new Promise((resolve) => {
|
||||||
|
const url = `${ _url }/websocket`;
|
||||||
|
|
||||||
Meteor.connect(url);
|
Meteor.connect(url, { autoConnect: true, autoReconnect: true });
|
||||||
|
Meteor.ddp.on('disconnected', () => {
|
||||||
|
reduxStore.dispatch(disconnect());
|
||||||
|
});
|
||||||
|
Meteor.ddp.on('connected', () => {
|
||||||
|
reduxStore.dispatch(connectSuccess());
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
Meteor.ddp.on('connected', () => {
|
||||||
|
Meteor.call('public-settings/get', (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
Meteor.ddp.on('connected', () => {
|
const settings = {};
|
||||||
console.log('connected');
|
realm.write(() => {
|
||||||
|
data.forEach((item) => {
|
||||||
|
const setting = {
|
||||||
|
_id: item._id
|
||||||
|
};
|
||||||
|
setting._server = { id: reduxStore.getState().server };
|
||||||
|
if (settingsType[item.type]) {
|
||||||
|
setting[settingsType[item.type]] = item.value;
|
||||||
|
realm.create('settings', setting, true);
|
||||||
|
}
|
||||||
|
|
||||||
Meteor.call('public-settings/get', (err, data) => {
|
settings[item._id] = item.value;
|
||||||
if (err) {
|
});
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
const settings = {};
|
|
||||||
realm.write(() => {
|
|
||||||
data.forEach((item) => {
|
|
||||||
const setting = {
|
|
||||||
_id: item._id
|
|
||||||
};
|
|
||||||
setting._server = { id: RocketChat.currentServer };
|
|
||||||
if (settingsType[item.type]) {
|
|
||||||
setting[settingsType[item.type]] = item.value;
|
|
||||||
realm.create('settings', setting, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
settings[item._id] = item.value;
|
|
||||||
});
|
});
|
||||||
|
reduxStore.dispatch(actions.setAllSettings(settings));
|
||||||
});
|
});
|
||||||
reduxStore.dispatch(actions.setAllSettings(settings));
|
|
||||||
|
|
||||||
if (cb) {
|
Meteor.ddp.on('changed', (ddbMessage) => {
|
||||||
cb();
|
if (ddbMessage.collection === 'stream-room-messages') {
|
||||||
}
|
realm.write(() => {
|
||||||
|
const message = ddbMessage.fields.args[0];
|
||||||
|
message.temp = false;
|
||||||
|
message._server = { id: reduxStore.getState().server };
|
||||||
|
realm.create('messages', message, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ddbMessage.collection === 'stream-notify-user') {
|
||||||
|
realm.write(() => {
|
||||||
|
const data = ddbMessage.fields.args[1];
|
||||||
|
data._server = { id: reduxStore.getState().server };
|
||||||
|
realm.create('subscriptions', data, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
})
|
||||||
Meteor.ddp.on('changed', (ddbMessage) => {
|
.catch(e => console.error(e));
|
||||||
// console.log('changed', ddbMessage);
|
|
||||||
if (ddbMessage.collection === 'stream-room-messages') {
|
|
||||||
realm.write(() => {
|
|
||||||
const message = ddbMessage.fields.args[0];
|
|
||||||
message.temp = false;
|
|
||||||
message._server = { id: RocketChat.currentServer };
|
|
||||||
// write('messages', message);
|
|
||||||
realm.create('messages', message, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ddbMessage.collection === 'stream-notify-user') {
|
|
||||||
// console.log(ddbMessage);
|
|
||||||
realm.write(() => {
|
|
||||||
const data = ddbMessage.fields.args[1];
|
|
||||||
data._server = { id: RocketChat.currentServer };
|
|
||||||
realm.create('subscriptions', data, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
login(params, callback) {
|
login(params, callback) {
|
||||||
Meteor._startLoggingIn();
|
console.log('login(params, callback)');
|
||||||
Meteor.call('login', params, (err, result) => {
|
return new Promise((resolve, reject) => {
|
||||||
Meteor._endLoggingIn();
|
Meteor._startLoggingIn();
|
||||||
|
return Meteor.call('login', params, (err, result) => {
|
||||||
Meteor._handleLoginCallback(err, result);
|
Meteor._endLoggingIn();
|
||||||
|
Meteor._handleLoginCallback(err, result);
|
||||||
if (typeof callback === 'function') {
|
console.log('login(params, callback)asdas', err, result);
|
||||||
callback(err);
|
if (err) {
|
||||||
}
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback(err, result);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -146,10 +141,8 @@ const RocketChat = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof username === 'string') {
|
if (typeof username === 'string' && username.indexOf('@') !== -1) {
|
||||||
if (username.indexOf('@') !== -1) {
|
params.user = { email: username };
|
||||||
params.user = { email: username };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +155,7 @@ const RocketChat = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.login(params, callback);
|
return this.login(params, callback);
|
||||||
},
|
},
|
||||||
|
|
||||||
loadSubscriptions(cb) {
|
loadSubscriptions(cb) {
|
||||||
|
@ -179,7 +172,7 @@ const RocketChat = {
|
||||||
// if (typeof item.value === 'string') {
|
// if (typeof item.value === 'string') {
|
||||||
// subscription.value = item.value;
|
// subscription.value = item.value;
|
||||||
// }
|
// }
|
||||||
subscription._server = { id: RocketChat.currentServer };
|
subscription._server = { id: reduxStore.getState().server };
|
||||||
// write('subscriptions', subscription);
|
// write('subscriptions', subscription);
|
||||||
realm.create('subscriptions', subscription, true);
|
realm.create('subscriptions', subscription, true);
|
||||||
});
|
});
|
||||||
|
@ -191,40 +184,41 @@ const RocketChat = {
|
||||||
},
|
},
|
||||||
|
|
||||||
loadMessagesForRoom(rid, end, cb) {
|
loadMessagesForRoom(rid, end, cb) {
|
||||||
Meteor.call('loadHistory', rid, end, 20, (err, data) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (err) {
|
Meteor.call('loadHistory', rid, end, 20, (err, data) => {
|
||||||
console.error(err);
|
if (err) {
|
||||||
if (cb) {
|
if (cb) {
|
||||||
cb({ end: true });
|
cb({ end: true });
|
||||||
|
}
|
||||||
|
return reject(err);
|
||||||
}
|
}
|
||||||
return;
|
if (data && data.messages.length) {
|
||||||
}
|
realm.write(() => {
|
||||||
if (data.messages.length) {
|
data.messages.forEach((message) => {
|
||||||
realm.write(() => {
|
message.temp = false;
|
||||||
data.messages.forEach((message) => {
|
message._server = { id: reduxStore.getState().server };
|
||||||
message.temp = false;
|
// write('messages', message);
|
||||||
message._server = { id: RocketChat.currentServer };
|
realm.create('messages', message, true);
|
||||||
// write('messages', message);
|
});
|
||||||
realm.create('messages', message, true);
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cb) {
|
|
||||||
if (data.messages.length < 20) {
|
|
||||||
cb({ end: true });
|
|
||||||
} else {
|
|
||||||
cb({ end: false });
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Meteor.subscribe('stream-room-messages', rid, false);
|
if (cb) {
|
||||||
|
if (data && data.messages.length < 20) {
|
||||||
|
cb({ end: true });
|
||||||
|
} else {
|
||||||
|
cb({ end: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
Meteor.subscribe('stream-room-messages', rid, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getMessage(rid, msg = {}) {
|
getMessage(rid, msg = {}) {
|
||||||
const _id = Random.id();
|
const _id = Random.id();
|
||||||
const user = Meteor.user();
|
// console.log('reduxStore.getState().login.id ', reduxStore.getState().login);
|
||||||
const message = {
|
const message = {
|
||||||
_id,
|
_id,
|
||||||
rid,
|
rid,
|
||||||
|
@ -232,10 +226,10 @@ const RocketChat = {
|
||||||
ts: new Date(),
|
ts: new Date(),
|
||||||
_updatedAt: new Date(),
|
_updatedAt: new Date(),
|
||||||
temp: true,
|
temp: true,
|
||||||
_server: { id: RocketChat.currentServer },
|
_server: { id: reduxStore.getState().server },
|
||||||
u: {
|
u: {
|
||||||
_id: user._id,
|
_id: reduxStore.getState().login.user.id || '1',
|
||||||
username: user.username
|
username: reduxStore.getState().login.user.id
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -365,45 +359,39 @@ const RocketChat = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getRooms() {
|
||||||
|
// Meteor.Accounts.onLogin(() => {
|
||||||
|
return Promise.all([call('subscriptions/get'), call('rooms/get')]).then(([subscriptions, rooms]) => {
|
||||||
|
// console.log('getRooms resolved', reduxStore.getState().server, subscriptions);
|
||||||
|
subscriptions = subscriptions.sort((s1, s2) => (s1.rid > s2.rid ? 1 : -1));
|
||||||
|
rooms = rooms.sort((s1, s2) => (s1._id > s2._id ? 1 : -1));
|
||||||
|
const data = subscriptions.map((subscription, index) => {
|
||||||
|
subscription._updatedAt = rooms[index]._updatedAt;
|
||||||
|
return subscription;
|
||||||
|
});
|
||||||
|
// Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/rooms-changed`, false);
|
||||||
|
console.log('getRooms resolved', reduxStore.getState().server, data);
|
||||||
|
realm.write(() => {
|
||||||
|
data.forEach((subscription) => {
|
||||||
|
// const subscription = {
|
||||||
|
// _id: item._id
|
||||||
|
// };
|
||||||
|
// if (typeof item.value === 'string') {
|
||||||
|
// subscription.value = item.value;
|
||||||
|
// }
|
||||||
|
subscription._server = { id: reduxStore.getState().server };
|
||||||
|
// write('subscriptions', subscription);
|
||||||
|
realm.create('subscriptions', subscription, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Meteor.subscribe('stream-notify-user', `${ reduxStore.getState().user.id }/subscriptions-changed`, false);
|
||||||
|
return data;
|
||||||
|
}).then(data => data);
|
||||||
|
// });
|
||||||
|
},
|
||||||
logout() {
|
logout() {
|
||||||
return AsyncStorage.clear();
|
return AsyncStorage.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RocketChat;
|
export default RocketChat;
|
||||||
|
|
||||||
if (RocketChat.currentServer) {
|
|
||||||
reduxStore.dispatch(actions.setCurrentServer(RocketChat.currentServer));
|
|
||||||
}
|
|
||||||
|
|
||||||
Meteor.Accounts.onLogin(() => {
|
|
||||||
Promise.all([call('subscriptions/get'), call('rooms/get')]).then(([subscriptions, rooms]) => {
|
|
||||||
subscriptions = subscriptions.sort((s1, s2) => (s1.rid > s2.rid ? 1 : -1));
|
|
||||||
rooms = rooms.sort((s1, s2) => (s1._id > s2._id ? 1 : -1));
|
|
||||||
const data = subscriptions.map((subscription, index) => {
|
|
||||||
subscription._updatedAt = rooms[index]._updatedAt;
|
|
||||||
return subscription;
|
|
||||||
});
|
|
||||||
Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/subscriptions-changed`, false);
|
|
||||||
// Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/rooms-changed`, false);
|
|
||||||
realm.write(() => {
|
|
||||||
data.forEach((subscription) => {
|
|
||||||
// const subscription = {
|
|
||||||
// _id: item._id
|
|
||||||
// };
|
|
||||||
// if (typeof item.value === 'string') {
|
|
||||||
// subscription.value = item.value;
|
|
||||||
// }
|
|
||||||
subscription._server = { id: RocketChat.currentServer };
|
|
||||||
// write('subscriptions', subscription);
|
|
||||||
realm.create('subscriptions', subscription, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
console.log('subscriptions done.');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Use for logout
|
|
||||||
// AsyncStorage.clear();
|
|
||||||
|
|
|
@ -9,8 +9,13 @@ import RoomView from './views/room';
|
||||||
import PhotoView from './views/Photo';
|
import PhotoView from './views/Photo';
|
||||||
import CreateChannel from './views/CreateChannel';
|
import CreateChannel from './views/CreateChannel';
|
||||||
import store from './lib/createStore';
|
import store from './lib/createStore';
|
||||||
|
import { PrivateScreen, HomeScreen, authenticated } from './index';
|
||||||
|
|
||||||
Navigation.registerComponent('Rooms', () => RoomsListView, store, Provider);
|
// console.log('fisateile/', PublicRoute(PublicScreen));
|
||||||
|
Navigation.registerComponent('home', () => HomeScreen, store, Provider);
|
||||||
|
Navigation.registerComponent('private', () => PrivateScreen, store, Provider);
|
||||||
|
Navigation.registerComponent('public', () => ListServerView, store, Provider);
|
||||||
|
Navigation.registerComponent('Rooms', () => authenticated(RoomsListView), store, Provider);
|
||||||
Navigation.registerComponent('Room', () => RoomView, store, Provider);
|
Navigation.registerComponent('Room', () => RoomView, store, Provider);
|
||||||
Navigation.registerComponent('Photo', () => PhotoView, store, Provider);
|
Navigation.registerComponent('Photo', () => PhotoView, store, Provider);
|
||||||
Navigation.registerComponent('ListServer', () => ListServerView, store, Provider);
|
Navigation.registerComponent('ListServer', () => ListServerView, store, Provider);
|
||||||
|
@ -20,8 +25,8 @@ Navigation.registerComponent('CreateChannel', () => CreateChannel, store, Provid
|
||||||
|
|
||||||
Navigation.startSingleScreenApp({
|
Navigation.startSingleScreenApp({
|
||||||
screen: {
|
screen: {
|
||||||
screen: 'Rooms',
|
screen: 'home',
|
||||||
title: 'Channels'
|
title: 'private'
|
||||||
},
|
},
|
||||||
animationType: 'none'
|
animationType: 'slide-up'
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { METEOR } from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
connecting: false,
|
||||||
|
connected: false,
|
||||||
|
errorMessage: '',
|
||||||
|
failure: false
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function connect(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case METEOR.REQUEST:
|
||||||
|
return { ...state,
|
||||||
|
connecting: true
|
||||||
|
};
|
||||||
|
case METEOR.SUCCESS:
|
||||||
|
return { ...state,
|
||||||
|
connecting: false,
|
||||||
|
connected: true,
|
||||||
|
failure: false
|
||||||
|
};
|
||||||
|
case METEOR.FAILURE:
|
||||||
|
return { ...state,
|
||||||
|
connecting: false,
|
||||||
|
connected: false,
|
||||||
|
failure: true,
|
||||||
|
errorMessage: action.err
|
||||||
|
};
|
||||||
|
case METEOR.DISCONNECT:
|
||||||
|
return initialState;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { combineReducers } from 'redux';
|
||||||
|
import settings from './reducers';
|
||||||
|
import login from './login';
|
||||||
|
import meteor from './connect';
|
||||||
|
import messages from './messages';
|
||||||
|
import server from './server';
|
||||||
|
import navigator from './navigator';
|
||||||
|
|
||||||
|
|
||||||
|
export default combineReducers({
|
||||||
|
settings, login, meteor, messages, server, navigator
|
||||||
|
});
|
|
@ -0,0 +1,46 @@
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
isAuthenticated: false,
|
||||||
|
isFetching: false,
|
||||||
|
token: '',
|
||||||
|
user: {},
|
||||||
|
errorMessage: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function login(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case types.LOGIN.REQUEST:
|
||||||
|
console.log('types.LOGIN.REQUEST', action);
|
||||||
|
return { ...state,
|
||||||
|
isFetching: true,
|
||||||
|
isAuthenticated: false,
|
||||||
|
failure: false
|
||||||
|
};
|
||||||
|
case types.LOGIN.SUCCESS:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: false,
|
||||||
|
isAuthenticated: true,
|
||||||
|
user: action.user,
|
||||||
|
token: action.user.token,
|
||||||
|
failure: false
|
||||||
|
// user: action.user
|
||||||
|
};
|
||||||
|
case types.LOGIN.FAILURE:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: false,
|
||||||
|
isAuthenticated: false,
|
||||||
|
failure: true,
|
||||||
|
errorMessage: action.err
|
||||||
|
};
|
||||||
|
case types.LOGOUT:
|
||||||
|
return initialState;
|
||||||
|
case types.LOGIN.SET_TOKEN:
|
||||||
|
return { ...state,
|
||||||
|
token: action.token,
|
||||||
|
user: action.user
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
isFetching: false,
|
||||||
|
failure: false
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function messages(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case types.MESSAGES.REQUEST:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: true
|
||||||
|
};
|
||||||
|
case types.MESSAGES.SUCCESS:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: false
|
||||||
|
};
|
||||||
|
case types.LOGIN.FAILURE:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: false,
|
||||||
|
failure: true,
|
||||||
|
errorMessage: action.err
|
||||||
|
};
|
||||||
|
// case types.LOGOUT:
|
||||||
|
// return initialState;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {};
|
||||||
|
|
||||||
|
export default function navigations(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case types.NAVIGATION.SET:
|
||||||
|
return action.navigator
|
||||||
|
;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,9 @@
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import * as types from '../constants/types';
|
import * as types from '../constants/types';
|
||||||
import initialState from './initialState';
|
import initialState from './initialState';
|
||||||
|
|
||||||
export function server(state = initialState.server, action) {
|
export default function settings(state = initialState.settings, action) {
|
||||||
if (action.type === types.SET_CURRENT_SERVER) {
|
|
||||||
RocketChat.currentServer = action.payload;
|
|
||||||
return action.payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function settings(state = initialState.settings, action) {
|
|
||||||
if (action.type === types.SET_ALL_SETTINGS) {
|
if (action.type === types.SET_ALL_SETTINGS) {
|
||||||
return {
|
return { ...state,
|
||||||
...action.payload
|
...action.payload
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
isFetching: false,
|
||||||
|
failure: false
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function login(state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case types.ROOMS.REQUEST:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: true
|
||||||
|
};
|
||||||
|
case types.ROOMS.SUCCESS:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: false
|
||||||
|
};
|
||||||
|
case types.ROOMS.FAILURE:
|
||||||
|
return { ...state,
|
||||||
|
isFetching: false,
|
||||||
|
failure: true,
|
||||||
|
errorMessage: action.err
|
||||||
|
};
|
||||||
|
// case types.LOGOUT:
|
||||||
|
// return initialState;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
import * as reducers from './reducers';
|
import * as reducers from './reducers';
|
||||||
|
import * as login from './login';
|
||||||
|
import * as connect from './connect';
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
...reducers
|
...reducers, ...login, ...connect
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rootReducer;
|
export default rootReducer;
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { SERVER } from '../actions/actionsTypes';
|
||||||
|
|
||||||
|
export default function server(state = '', action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case SERVER.SELECT:
|
||||||
|
return action.server;
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Scene,
|
||||||
|
Router
|
||||||
|
// Actions,
|
||||||
|
// Reducer,
|
||||||
|
// ActionConst,
|
||||||
|
// Tabs,
|
||||||
|
// Modal,
|
||||||
|
// Drawer,
|
||||||
|
// Stack,
|
||||||
|
// Lightbox
|
||||||
|
} from 'react-native-router-flux';
|
||||||
|
// import { Navigation } from 'react-native-navigation';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
|
import LoginView from '../views/login';
|
||||||
|
import NewServerView from '../views/serverNew';
|
||||||
|
import ListServerView from '../views/serverList';
|
||||||
|
import RoomsListView from '../views/roomsList';
|
||||||
|
import RoomView from '../views/room';
|
||||||
|
// import PhotoView from '../views/Photo';
|
||||||
|
// import CreateChannel from '../views/CreateChannel';
|
||||||
|
import store from '../lib/createStore';
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<Provider store={store}>
|
||||||
|
<Router>
|
||||||
|
<Scene key='root'>
|
||||||
|
<Scene key='listServer' component={ListServerView} title='Servers' />
|
||||||
|
<Scene key='newServer' component={NewServerView} title='New Server' />
|
||||||
|
<Scene key='login' component={LoginView} title='Login' />
|
||||||
|
<Scene key='roomList' component={RoomsListView} />
|
||||||
|
<Scene key='room' component={RoomView} initial />
|
||||||
|
</Scene>
|
||||||
|
</Router>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
// <Scene key='register' component={Register} title='Register' />
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { take, put, call, fork, takeLatest, select } from 'redux-saga/effects';
|
||||||
|
import { METEOR } from '../actions/actionsTypes';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
|
import { connectSuccess, connectFailure } from '../actions/connect';
|
||||||
|
|
||||||
|
const getServer = ({ server }) => server;
|
||||||
|
|
||||||
|
|
||||||
|
const connect = url => RocketChat.connect(url);
|
||||||
|
const test = function* test() {
|
||||||
|
try {
|
||||||
|
const server = yield select(getServer);
|
||||||
|
const response = yield call(connect, server);
|
||||||
|
yield put(connectSuccess(response));
|
||||||
|
} catch (err) {
|
||||||
|
yield put(connectFailure(err.status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const watchConnect = function* watchConnect() {
|
||||||
|
yield takeLatest(METEOR.REQUEST, test);
|
||||||
|
while (true) {
|
||||||
|
yield take(METEOR.DISCONNECT);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const root = function* root() {
|
||||||
|
yield fork(watchConnect);
|
||||||
|
// yield fork(auto);
|
||||||
|
};
|
||||||
|
export default root;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { take, fork } from 'redux-saga/effects';
|
||||||
|
|
||||||
|
const foreverAlone = function* foreverAlone() {
|
||||||
|
yield take('FOI');
|
||||||
|
console.log('FOIIIIIII');
|
||||||
|
yield take('voa');
|
||||||
|
console.log('o');
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = function* root() {
|
||||||
|
yield fork(foreverAlone);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default root;
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { fork, take } from 'redux-saga/effects';
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
import hello from './hello';
|
||||||
|
import login from './login';
|
||||||
|
import connect from './connect';
|
||||||
|
import rooms from './rooms';
|
||||||
|
import messages from './messages';
|
||||||
|
import selectServer from './selectServer';
|
||||||
|
import init from './init';
|
||||||
|
|
||||||
|
const root = function* root() {
|
||||||
|
yield fork(init);
|
||||||
|
yield take(types.APP.READY);
|
||||||
|
yield fork(hello);
|
||||||
|
yield fork(rooms);
|
||||||
|
yield fork(login);
|
||||||
|
yield fork(connect);
|
||||||
|
yield fork(messages);
|
||||||
|
yield fork(selectServer);
|
||||||
|
};
|
||||||
|
// Consider using takeEvery
|
||||||
|
export default root;
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { AsyncStorage } from 'react-native';
|
||||||
|
import { call, put } from 'redux-saga/effects';
|
||||||
|
import * as actions from '../actions';
|
||||||
|
import { setServer } from '../actions/server';
|
||||||
|
|
||||||
|
const restore = function* restore() {
|
||||||
|
try {
|
||||||
|
const currentServer = yield call([AsyncStorage, 'getItem'], 'currentServer');
|
||||||
|
yield put(actions.appReady({}));
|
||||||
|
if (currentServer) { yield put(setServer(currentServer)); }
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export default restore;
|
|
@ -0,0 +1,102 @@
|
||||||
|
import { AsyncStorage } from 'react-native';
|
||||||
|
import { take, put, call, takeEvery, fork, select, all, race } from 'redux-saga/effects';
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
import { loginRequest, loginSuccess, loginFailure, setToken } from '../actions/login';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
|
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||||
|
const getUser = state => state.login;
|
||||||
|
const getServer = state => state.server;
|
||||||
|
const loginCall = args => (args.resume ? RocketChat.login(args) : RocketChat.loginWithPassword(args));
|
||||||
|
|
||||||
|
const getToken = function* getToken() {
|
||||||
|
const currentServer = yield select(getServer);
|
||||||
|
const user = yield call([AsyncStorage, 'getItem'], `${ TOKEN_KEY }-${ currentServer }`);
|
||||||
|
if (user) {
|
||||||
|
try {
|
||||||
|
yield put(setToken(JSON.parse(user)));
|
||||||
|
yield call([AsyncStorage, 'setItem'], TOKEN_KEY, JSON.parse(user).token || '');
|
||||||
|
return JSON.parse(user);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('getTokenerr', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoginWhenServerChanges = function* handleLoginWhenServerChanges() {
|
||||||
|
// do {
|
||||||
|
try {
|
||||||
|
yield take(types.METEOR.SUCCESS);
|
||||||
|
const { navigator } = yield select(state => state);
|
||||||
|
navigator.resetTo({
|
||||||
|
screen: 'Rooms'
|
||||||
|
});
|
||||||
|
const user = yield select(getUser);
|
||||||
|
if (user.token) {
|
||||||
|
yield put(loginRequest({ resume: user.token }));
|
||||||
|
// console.log('AEEEEEEEEOOOOO');
|
||||||
|
// // wait for a response
|
||||||
|
// const { error } = yield race({
|
||||||
|
// success: take(types.LOGIN.SUCCESS),
|
||||||
|
// error: take(types.LOGIN.FAILURE)
|
||||||
|
// });
|
||||||
|
// console.log('AEEEEEEEEOOOOO', error);
|
||||||
|
// if (!error) {
|
||||||
|
// navigator.resetTo({
|
||||||
|
// screen: 'Rooms'
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
// } while (true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveToken = function* saveToken() {
|
||||||
|
const [server, user] = yield all([select(getServer), select(getUser)]);
|
||||||
|
yield AsyncStorage.setItem(TOKEN_KEY, user.token);
|
||||||
|
yield AsyncStorage.setItem(`${ TOKEN_KEY }-${ server }`, JSON.stringify(user));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoginRequest = function* handleLoginRequest() {
|
||||||
|
while (true) {
|
||||||
|
const { credentials } = yield take(types.LOGIN.REQUEST);
|
||||||
|
try {
|
||||||
|
const response = yield call(loginCall, credentials);
|
||||||
|
yield put(loginSuccess(response));
|
||||||
|
} catch (err) {
|
||||||
|
// console.log('login failed');
|
||||||
|
yield put(loginFailure(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLoginSubmit = function* handleLoginSubmit() {
|
||||||
|
while (true) {
|
||||||
|
const { credentials } = yield take(types.LOGIN.SUBMIT);
|
||||||
|
// put a login request
|
||||||
|
yield put(loginRequest(credentials));
|
||||||
|
// wait for a response
|
||||||
|
const { error } = yield race({
|
||||||
|
success: take(types.LOGIN.SUCCESS),
|
||||||
|
error: take(types.LOGIN.FAILURE)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
const { navigator } = yield select(state => state);
|
||||||
|
navigator.resetTo({
|
||||||
|
screen: 'Rooms'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = function* root() {
|
||||||
|
yield takeEvery(types.SERVER.CHANGED, getToken);
|
||||||
|
yield takeEvery(types.SERVER.CHANGED, handleLoginWhenServerChanges);
|
||||||
|
yield fork(handleLoginRequest);
|
||||||
|
yield takeEvery(types.LOGIN.SUCCESS, saveToken);
|
||||||
|
yield fork(handleLoginSubmit);
|
||||||
|
};
|
||||||
|
export default root;
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { takeLatest, select, take, put } from 'redux-saga/effects';
|
||||||
|
import { MESSAGES, LOGIN } from '../actions/actionsTypes';
|
||||||
|
import { messagesSuccess, messagesFailure } from '../actions/messages';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
|
const get = function* get({ rid }) {
|
||||||
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
|
console.log('hey now', yield select(state => state.login));
|
||||||
|
if (!auth) {
|
||||||
|
yield take(LOGIN.SUCCESS);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
yield RocketChat.loadMessagesForRoom(rid, null);
|
||||||
|
yield put(messagesSuccess());
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
yield put(messagesFailure(err.status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getData = function* getData() {
|
||||||
|
yield takeLatest(MESSAGES.REQUEST, get);
|
||||||
|
};
|
||||||
|
export default getData;
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { put, call, takeEvery } from 'redux-saga/effects';
|
||||||
|
import * as types from '../actions/actionsTypes';
|
||||||
|
import { roomsSuccess, roomsFailure } from '../actions/rooms';
|
||||||
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
|
||||||
|
const getRooms = function* getRooms() {
|
||||||
|
return yield RocketChat.getRooms();
|
||||||
|
};
|
||||||
|
|
||||||
|
const watchRoomsRequest = function* watchRoomsRequest() {
|
||||||
|
try {
|
||||||
|
console.log('getRooms');
|
||||||
|
yield call(getRooms);
|
||||||
|
yield put(roomsSuccess());
|
||||||
|
} catch (err) {
|
||||||
|
yield put(roomsFailure(err.status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const root = function* root() {
|
||||||
|
yield takeEvery(types.LOGIN.SUCCESS, watchRoomsRequest);
|
||||||
|
};
|
||||||
|
export default root;
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { put, takeEvery, call } from 'redux-saga/effects';
|
||||||
|
import { AsyncStorage } from 'react-native';
|
||||||
|
import { SERVER } from '../actions/actionsTypes';
|
||||||
|
import { connectRequest, disconnect } from '../actions/connect';
|
||||||
|
import { changedServer } from '../actions/server';
|
||||||
|
|
||||||
|
const selectServer = function* selectServer({ server }) {
|
||||||
|
yield put(disconnect());
|
||||||
|
yield put(changedServer(server));
|
||||||
|
yield console.log('SERVER->', server);
|
||||||
|
yield call([AsyncStorage, 'setItem'], 'currentServer', server);
|
||||||
|
yield put(connectRequest(server));
|
||||||
|
};
|
||||||
|
const root = function* root() {
|
||||||
|
yield takeEvery(SERVER.SELECT, selectServer);
|
||||||
|
};
|
||||||
|
export default root;
|
|
@ -1,51 +1,82 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import Spinner from 'react-native-loading-spinner-overlay';
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Text, TextInput, StyleSheet } from 'react-native';
|
import { Keyboard, Text, TextInput, StyleSheet, View, Image, TouchableOpacity } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
// import * as actions from '../actions';
|
||||||
import * as actions from '../actions';
|
import * as loginActions from '../actions/login';
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import KeyboardView from '../components/KeyboardView';
|
import KeyboardView from '../components/KeyboardView';
|
||||||
|
// import { Keyboard } from 'react-native'
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
view: {
|
view: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
padding: 20,
|
||||||
alignItems: 'stretch',
|
alignItems: 'stretch',
|
||||||
backgroundColor: '#fff'
|
backgroundColor: '#2f343d'
|
||||||
|
},
|
||||||
|
logoContainer: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
flexGrow: 1,
|
||||||
|
justifyContent: 'center'
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
width: 150,
|
||||||
|
// backgroundColor: 'red'
|
||||||
|
// height: 150,
|
||||||
|
resizeMode: 'contain'
|
||||||
|
},
|
||||||
|
formContainer: {
|
||||||
|
// marginBottom: 20
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
height: 40,
|
height: 40,
|
||||||
borderColor: '#aaa',
|
marginBottom: 20,
|
||||||
marginLeft: 20,
|
borderRadius: 2,
|
||||||
marginRight: 20,
|
paddingHorizontal: 10,
|
||||||
marginTop: 10,
|
|
||||||
padding: 5,
|
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
backgroundColor: '#f6f6f6'
|
backgroundColor: 'rgba(255,255,255,.2)',
|
||||||
|
color: 'white'
|
||||||
|
},
|
||||||
|
buttonContainer: {
|
||||||
|
paddingVertical: 15,
|
||||||
|
backgroundColor: '#414852',
|
||||||
|
marginBottom: 20
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'white',
|
||||||
|
borderRadius: 2,
|
||||||
|
fontWeight: '700'
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
color: 'red',
|
color: 'red',
|
||||||
paddingTop: 5
|
paddingTop: 5
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
flex: 1,
|
||||||
|
position: 'absolute',
|
||||||
|
backgroundColor: 'rgba(255,255,255,.2)',
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@connect(state => ({
|
class LoginView extends React.Component {
|
||||||
server: state.server,
|
|
||||||
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
|
|
||||||
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder
|
|
||||||
}), dispatch => ({
|
|
||||||
actions: bindActionCreators(actions, dispatch)
|
|
||||||
}))
|
|
||||||
export default class LoginView extends React.Component {
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigator: PropTypes.object.isRequired,
|
navigator: PropTypes.object.isRequired,
|
||||||
|
loginSubmit: PropTypes.func.isRequired,
|
||||||
server: PropTypes.string.isRequired,
|
server: PropTypes.string.isRequired,
|
||||||
Accounts_EmailOrUsernamePlaceholder: PropTypes.string,
|
Accounts_EmailOrUsernamePlaceholder: PropTypes.string,
|
||||||
Accounts_PasswordPlaceholder: PropTypes.string
|
Accounts_PasswordPlaceholder: PropTypes.string,
|
||||||
|
login: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
static navigationOptions = () => ({
|
static navigationOptions = () => ({
|
||||||
|
@ -70,36 +101,14 @@ export default class LoginView extends React.Component {
|
||||||
subtitle: nextProps.server
|
subtitle: nextProps.server
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
submit = () => {
|
submit = () => {
|
||||||
this.setState({
|
const { username, password, code } = this.state;
|
||||||
error: undefined
|
this.props.loginSubmit({ username, password, code });
|
||||||
});
|
Keyboard.dismiss();
|
||||||
|
|
||||||
const credentials = {
|
|
||||||
username: this.state.username,
|
|
||||||
password: this.state.password,
|
|
||||||
code: this.state.code
|
|
||||||
};
|
|
||||||
|
|
||||||
RocketChat.loginWithPassword(credentials, (error) => {
|
|
||||||
if (error) {
|
|
||||||
if (error.error === 'totp-required') {
|
|
||||||
this.setState({ totp: true });
|
|
||||||
this.codeInput.focus();
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
error: error.reason
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.props.navigator.dismissModal();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTOTP = () => {
|
renderTOTP = () => {
|
||||||
if (this.state.totp) {
|
if (this.props.login.errorMessage && this.props.login.errorMessage.error === 'totp-required') {
|
||||||
return (
|
return (
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={ref => this.codeInput = ref}
|
ref={ref => this.codeInput = ref}
|
||||||
|
@ -116,33 +125,65 @@ export default class LoginView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// {this.props.login.isFetching && <Text> LOGANDO</Text>}
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<KeyboardView style={styles.view} keyboardVerticalOffset={64}>
|
<KeyboardView style={styles.view} keyboardVerticalOffset={64}>
|
||||||
<TextInput
|
<View style={styles.logoContainer}>
|
||||||
style={styles.input}
|
<Image style={styles.logo} source={require('../images/logo.png')} />
|
||||||
onChangeText={username => this.setState({ username })}
|
</View>
|
||||||
keyboardType='email-address'
|
<View style={styles.formContainer}>
|
||||||
autoCorrect={false}
|
<TextInput
|
||||||
returnKeyType='done'
|
placeholderTextColor={'rgba(255,255,255,.2)'}
|
||||||
autoCapitalize='none'
|
style={styles.input}
|
||||||
autoFocus
|
onChangeText={username => this.setState({ username })}
|
||||||
onSubmitEditing={this.submit}
|
keyboardType='email-address'
|
||||||
placeholder={this.props.Accounts_EmailOrUsernamePlaceholder || 'Email or username'}
|
autoCorrect={false}
|
||||||
/>
|
returnKeyType='done'
|
||||||
<TextInput
|
autoCapitalize='none'
|
||||||
style={styles.input}
|
autoFocus
|
||||||
onChangeText={password => this.setState({ password })}
|
|
||||||
secureTextEntry
|
underlineColorAndroid='transparent'
|
||||||
autoCorrect={false}
|
onSubmitEditing={this.submit}
|
||||||
returnKeyType='done'
|
placeholder={this.props.Accounts_EmailOrUsernamePlaceholder || 'Email or username'}
|
||||||
autoCapitalize='none'
|
/>
|
||||||
onSubmitEditing={this.submit}
|
<TextInput
|
||||||
placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'}
|
placeholderTextColor={'rgba(255,255,255,.2)'}
|
||||||
/>
|
style={styles.input}
|
||||||
{this.renderTOTP()}
|
onChangeText={password => this.setState({ password })}
|
||||||
<Text style={styles.error}>{this.state.error}</Text>
|
secureTextEntry
|
||||||
|
autoCorrect={false}
|
||||||
|
returnKeyType='done'
|
||||||
|
autoCapitalize='none'
|
||||||
|
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
|
onSubmitEditing={this.submit}
|
||||||
|
placeholder={this.props.Accounts_PasswordPlaceholder || 'Password'}
|
||||||
|
/>
|
||||||
|
{this.renderTOTP()}
|
||||||
|
<TouchableOpacity style={styles.buttonContainer}>
|
||||||
|
<Text style={styles.button} onPress={this.submit}>LOGIN</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
{this.props.login.error && <Text style={styles.error}>{this.props.login.error}</Text>}
|
||||||
|
</View>
|
||||||
|
<Spinner visible={this.props.login.isFetching} textContent={'Loading...'} textStyle={{ color: '#FFF' }} />
|
||||||
</KeyboardView>
|
</KeyboardView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
// console.log(Object.keys(state));
|
||||||
|
return {
|
||||||
|
server: state.server,
|
||||||
|
Accounts_EmailOrUsernamePlaceholder: state.settings.Accounts_EmailOrUsernamePlaceholder,
|
||||||
|
Accounts_PasswordPlaceholder: state.settings.Accounts_PasswordPlaceholder,
|
||||||
|
login: state.login
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps(dispatch) {
|
||||||
|
return bindActionCreators(loginActions, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(LoginView);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
|
import { messagesRequest } from '../actions/messages';
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import debounce from '../utils/throttle';
|
import debounce from '../utils/throttle';
|
||||||
|
@ -47,19 +48,23 @@ const styles = StyleSheet.create({
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
server: state.server,
|
server: state.server,
|
||||||
Site_Url: state.settings.Site_Url,
|
Site_Url: state.settings.Site_Url,
|
||||||
Message_TimeFormat: state.settings.Message_TimeFormat
|
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||||
|
loading: state.messages.isFetching
|
||||||
}), dispatch => ({
|
}), dispatch => ({
|
||||||
actions: bindActionCreators(actions, dispatch)
|
actions: bindActionCreators(actions, dispatch),
|
||||||
|
getMessages: rid => dispatch(messagesRequest({ rid }))
|
||||||
}))
|
}))
|
||||||
export default class RoomView extends React.Component {
|
export default class RoomView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigator: PropTypes.object.isRequired,
|
navigator: PropTypes.object.isRequired,
|
||||||
|
getMessages: PropTypes.func.isRequired,
|
||||||
rid: PropTypes.string,
|
rid: PropTypes.string,
|
||||||
sid: PropTypes.string,
|
sid: PropTypes.string,
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
Site_Url: PropTypes.string,
|
Site_Url: PropTypes.string,
|
||||||
Message_TimeFormat: PropTypes.string
|
Message_TimeFormat: PropTypes.string,
|
||||||
|
loading: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -69,7 +74,7 @@ export default class RoomView extends React.Component {
|
||||||
|
|
||||||
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', this.props.server, this.rid).sorted('ts', true);
|
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', this.props.server, this.rid).sorted('ts', true);
|
||||||
this.state = {
|
this.state = {
|
||||||
dataSource: ds.cloneWithRows(this.data.slice(0, 10)),
|
dataSource: ds.cloneWithRows(this.data),
|
||||||
loaded: true,
|
loaded: true,
|
||||||
joined: typeof props.rid === 'undefined'
|
joined: typeof props.rid === 'undefined'
|
||||||
};
|
};
|
||||||
|
@ -80,17 +85,18 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const late = setTimeout(() => this.setState({
|
this.props.getMessages(this.rid);
|
||||||
loaded: false
|
// const late = setTimeout(() => this.setState({
|
||||||
}), 1000);
|
// loaded: false
|
||||||
RocketChat.loadMessagesForRoom(this.rid, null, () => {
|
// }), 1000);
|
||||||
clearTimeout(late);
|
// RocketChat.loadMessagesForRoom(this.rid, null, () => {
|
||||||
this.setState({
|
// clearTimeout(late);
|
||||||
loaded: true
|
// this.setState({
|
||||||
});
|
// loaded: true
|
||||||
this.data.addListener(this.updateState);
|
// });
|
||||||
});
|
this.data.addListener(this.updateState);
|
||||||
this.updateState();
|
// });
|
||||||
|
// this.updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -141,15 +147,13 @@ export default class RoomView extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
renderBanner = () => {
|
renderBanner = () => (this.props.loading ?
|
||||||
if (this.state.loaded === false) {
|
(
|
||||||
return (
|
<View style={styles.bannerContainer}>
|
||||||
<View style={styles.bannerContainer}>
|
<Text style={styles.bannerText}>Loading new messages...</Text>
|
||||||
<Text style={styles.bannerText}>Loading new messages...</Text>
|
</View>
|
||||||
</View>
|
) : null)
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
renderItem = ({ item }) => (
|
renderItem = ({ item }) => (
|
||||||
<Message
|
<Message
|
||||||
|
@ -193,11 +197,6 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// data={this.state.dataSource}
|
|
||||||
// extraData={this.state}
|
|
||||||
// renderItem={this.renderItem}
|
|
||||||
// keyExtractor={item => item._id}
|
|
||||||
//
|
|
||||||
return (
|
return (
|
||||||
<KeyboardView style={styles.container} keyboardVerticalOffset={64}>
|
<KeyboardView style={styles.container} keyboardVerticalOffset={64}>
|
||||||
{this.renderBanner()}
|
{this.renderBanner()}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
import ActionButton from 'react-native-action-button';
|
import ActionButton from 'react-native-action-button';
|
||||||
import { Navigation } from 'react-native-navigation';
|
import { Navigation } from 'react-native-navigation';
|
||||||
import { ListView } from 'realm/react-native';
|
import { ListView } from 'realm/react-native';
|
||||||
import Icon from 'react-native-vector-icons/Ionicons';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Text, View, StyleSheet, TouchableOpacity, Platform, TextInput } from 'react-native';
|
import { View, StyleSheet, TextInput, Platform } from 'react-native';
|
||||||
import Meteor from 'react-native-meteor';
|
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
|
import * as server from '../actions/connect';
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import RoomItem from '../components/RoomItem';
|
import RoomItem from '../components/RoomItem';
|
||||||
import debounce from '../utils/debounce';
|
import Banner from '../components/banner';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -38,13 +35,6 @@ const styles = StyleSheet.create({
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: '#ccc'
|
color: '#ccc'
|
||||||
},
|
},
|
||||||
bannerContainer: {
|
|
||||||
backgroundColor: '#ddd'
|
|
||||||
},
|
|
||||||
bannerText: {
|
|
||||||
textAlign: 'center',
|
|
||||||
margin: 5
|
|
||||||
},
|
|
||||||
actionButtonIcon: {
|
actionButtonIcon: {
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
height: 22,
|
height: 22,
|
||||||
|
@ -63,65 +53,47 @@ const styles = StyleSheet.create({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Meteor.Accounts.onLogin(() => {
|
|
||||||
console.log('onLogin');
|
|
||||||
});
|
|
||||||
|
|
||||||
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
||||||
class RoomsListItem extends React.PureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
item: PropTypes.object.isRequired,
|
|
||||||
onPress: PropTypes.func.isRequired,
|
|
||||||
baseUrl: PropTypes.string
|
|
||||||
}
|
|
||||||
_onPress = (...args) => {
|
|
||||||
this.props.onPress(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { item } = this.props;
|
|
||||||
return (
|
|
||||||
<TouchableOpacity key={item._id} onPress={() => this.props.onPress(item._id, item)}>
|
|
||||||
<RoomItem
|
|
||||||
id={item._id}
|
|
||||||
type={item.t}
|
|
||||||
name={item.name}
|
|
||||||
unread={item.unread}
|
|
||||||
baseUrl={this.props.baseUrl}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
server: state.server,
|
server: state.server,
|
||||||
Site_Url: state.settings.Site_Url
|
login: state.login,
|
||||||
|
Site_Url: state.settings.Site_Url,
|
||||||
|
canShowList: state.login.token.length || state.login.user.token
|
||||||
}), dispatch => ({
|
}), dispatch => ({
|
||||||
actions: bindActionCreators(actions, dispatch)
|
login: () => dispatch(actions.login()),
|
||||||
|
connect: () => dispatch(server.connectRequest())
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export default class RoomsListView extends React.Component {
|
export default class RoomsListView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigator: PropTypes.object.isRequired,
|
navigator: PropTypes.object.isRequired,
|
||||||
server: PropTypes.string,
|
Site_Url: PropTypes.string,
|
||||||
Site_Url: PropTypes.string
|
server: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server);
|
||||||
// this.data = realm.objects('subscriptions').filtered('_server.id = $0', this.props.server);
|
|
||||||
this.state = {
|
this.state = {
|
||||||
dataSource: ds.cloneWithRows([]),
|
dataSource: ds.cloneWithRows(this.data),
|
||||||
searching: false,
|
searching: false,
|
||||||
searchDataSource: [],
|
searchDataSource: [],
|
||||||
searchText: ''
|
searchText: '',
|
||||||
|
login: false
|
||||||
};
|
};
|
||||||
|
this.data.addListener(this.updateState);
|
||||||
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
this.props.navigator.setOnNavigatorEvent(event => event.type === 'NavBarButtonPress' && event.id === 'servers' &&
|
||||||
|
Navigation.showModal({
|
||||||
|
screen: 'ListServer',
|
||||||
|
passProps: {},
|
||||||
|
navigatorStyle: {},
|
||||||
|
navigatorButtons: {},
|
||||||
|
animationType: 'slide-up'
|
||||||
|
}));
|
||||||
|
this.props.navigator.setSubTitle({
|
||||||
|
subtitle: this.props.server
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const button = Platform.OS === 'ios' ? 'leftButtons' : 'rightButtons';
|
const button = Platform.OS === 'ios' ? 'leftButtons' : 'rightButtons';
|
||||||
this.props.navigator.setButtons({
|
this.props.navigator.setButtons({
|
||||||
|
@ -131,43 +103,9 @@ export default class RoomsListView extends React.Component {
|
||||||
}],
|
}],
|
||||||
animated: true
|
animated: true
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.props.server) {
|
|
||||||
this.setInitialData();
|
|
||||||
} else {
|
|
||||||
Navigation.showModal({
|
|
||||||
screen: 'ListServer',
|
|
||||||
passProps: {},
|
|
||||||
navigatorStyle: {},
|
|
||||||
navigatorButtons: {},
|
|
||||||
animationType: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if (nextProps.server !== this.props.server) {
|
|
||||||
this.setInitialData(nextProps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.state.data.removeListener(this.updateState);
|
this.data.removeListener(this.updateState);
|
||||||
}
|
|
||||||
|
|
||||||
onNavigatorEvent = (event) => {
|
|
||||||
if (event.type === 'NavBarButtonPress') {
|
|
||||||
if (event.id === 'servers') {
|
|
||||||
Navigation.showModal({
|
|
||||||
screen: 'ListServer',
|
|
||||||
passProps: {},
|
|
||||||
navigatorStyle: {},
|
|
||||||
navigatorButtons: {},
|
|
||||||
animationType: 'slide-up'
|
|
||||||
// animationType: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchChangeText = (text) => {
|
onSearchChangeText = (text) => {
|
||||||
|
@ -178,11 +116,11 @@ export default class RoomsListView extends React.Component {
|
||||||
});
|
});
|
||||||
if (searchText === '') {
|
if (searchText === '') {
|
||||||
return this.setState({
|
return this.setState({
|
||||||
dataSource: ds.cloneWithRows(this.state.data)
|
dataSource: ds.cloneWithRows(this.data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = this.state.data.filtered('name CONTAINS[c] $0', searchText).slice();
|
const data = this.data.filtered('name CONTAINS[c] $0', searchText).slice();
|
||||||
|
|
||||||
const usernames = [];
|
const usernames = [];
|
||||||
const dataSource = data.map((sub) => {
|
const dataSource = data.map((sub) => {
|
||||||
|
@ -228,36 +166,12 @@ export default class RoomsListView extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setInitialData = (props = this.props) => {
|
|
||||||
props.navigator.setSubTitle({
|
|
||||||
subtitle: props.server
|
|
||||||
});
|
|
||||||
|
|
||||||
RocketChat.getUserToken().then((token) => {
|
updateState = () => {
|
||||||
if (!token) {
|
|
||||||
Navigation.showModal({
|
|
||||||
screen: 'Login',
|
|
||||||
animationType: 'slide-up'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
RocketChat.connect();
|
|
||||||
|
|
||||||
const data = realm.objects('subscriptions').filtered('_server.id = $0', props.server).sorted('_updatedAt', true);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
dataSource: ds.cloneWithRows(data),
|
|
||||||
data
|
|
||||||
});
|
|
||||||
|
|
||||||
data.addListener(this.updateState);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateState = debounce(() => {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
dataSource: ds.cloneWithRows(this.state.data)
|
dataSource: ds.cloneWithRows(this.data)
|
||||||
});
|
});
|
||||||
}, 500);
|
};
|
||||||
|
|
||||||
_onPressItem = (id, item = {}) => {
|
_onPressItem = (id, item = {}) => {
|
||||||
const navigateToRoom = (room) => {
|
const navigateToRoom = (room) => {
|
||||||
|
@ -306,47 +220,10 @@ export default class RoomsListView extends React.Component {
|
||||||
clearSearch();
|
clearSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
_createChannel = () => {
|
|
||||||
this.props.navigator.showModal({
|
|
||||||
screen: 'CreateChannel'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBanner = () => {
|
|
||||||
const status = Meteor.getData() && Meteor.getData().ddp && Meteor.getData().ddp.status;
|
|
||||||
|
|
||||||
if (status === 'disconnected') {
|
|
||||||
return (
|
|
||||||
<View style={[styles.bannerContainer, { backgroundColor: '#0d0' }]}>
|
|
||||||
<Text style={[styles.bannerText, { color: '#fff' }]}>Connecting...</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status === 'connected' && Meteor._isLoggingIn) {
|
|
||||||
return (
|
|
||||||
<View style={[styles.bannerContainer, { backgroundColor: 'orange' }]}>
|
|
||||||
<Text style={[styles.bannerText, { color: '#a00' }]}>Authenticating...</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderItem = ({ item }) => (
|
|
||||||
<RoomsListItem
|
|
||||||
item={item}
|
|
||||||
onPress={() => this._onPressItem(item._id, item)}
|
|
||||||
baseUrl={this.props.Site_Url}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
renderSeparator = () => (
|
|
||||||
<View style={styles.separator} />
|
|
||||||
);
|
|
||||||
|
|
||||||
renderSearchBar = () => (
|
renderSearchBar = () => (
|
||||||
<View style={styles.searchBoxView}>
|
<View style={styles.searchBoxView}>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
style={styles.searchBox}
|
style={styles.searchBox}
|
||||||
value={this.state.searchText}
|
value={this.state.searchText}
|
||||||
onChangeText={this.onSearchChangeText}
|
onChangeText={this.onSearchChangeText}
|
||||||
|
@ -358,44 +235,32 @@ export default class RoomsListView extends React.Component {
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
// if (!this.state.searching && !this.state.dataSource.length) {
|
renderItem = item => (
|
||||||
// return (
|
<RoomItem
|
||||||
// <View style={styles.emptyView}>
|
key={item._id}
|
||||||
// <Text style={styles.emptyText}>No rooms</Text>
|
name={item.name}
|
||||||
// </View>
|
type={item.t}
|
||||||
// );
|
baseUrl={this.props.Site_Url}
|
||||||
// }
|
onPress={() => this._onPressItem(item._id, item)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
renderList = () => (
|
renderList = () => (
|
||||||
// data={this.state.searching ? this.state.searchDataSource : this.state.dataSource}
|
|
||||||
// keyExtractor={item => item._id}
|
|
||||||
// ItemSeparatorComponent={this.renderSeparator}
|
|
||||||
// renderItem={this.renderItem}
|
|
||||||
<ListView
|
<ListView
|
||||||
dataSource={this.state.dataSource}
|
dataSource={this.state.dataSource}
|
||||||
style={styles.list}
|
style={styles.list}
|
||||||
renderRow={item => this.renderItem({ item })}
|
renderRow={this.renderItem}
|
||||||
renderHeader={this.renderSearchBar}
|
renderHeader={this.renderSearchBar}
|
||||||
contentOffset={{ x: 0, y: 20 }}
|
contentOffset={{ x: 0, y: 20 }}
|
||||||
enableEmptySections
|
enableEmptySections
|
||||||
keyboardShouldPersistTaps='always'
|
keyboardShouldPersistTaps='always'
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
renderCreateButtons = () => (
|
||||||
renderCreateButtons() {
|
<ActionButton buttonColor='rgba(231,76,60,1)' />);
|
||||||
return (
|
render= () => (
|
||||||
<ActionButton buttonColor='rgba(231,76,60,1)'>
|
<View style={styles.container}>
|
||||||
<ActionButton.Item buttonColor='#9b59b6' title='Create Channel' onPress={() => { this._createChannel(); }} >
|
<Banner />
|
||||||
<Icon name='md-chatbubbles' style={styles.actionButtonIcon} />
|
{this.renderList()}
|
||||||
</ActionButton.Item>
|
{this.renderCreateButtons()}
|
||||||
</ActionButton>);
|
</View>)
|
||||||
}
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<View style={styles.container}>
|
|
||||||
{this.renderBanner()}
|
|
||||||
{this.renderList()}
|
|
||||||
{this.renderCreateButtons()}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import Icon from 'react-native-vector-icons/Ionicons';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Navigation } from 'react-native-navigation';
|
import { Navigation } from 'react-native-navigation';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import Zeroconf from 'react-native-zeroconf';
|
import Zeroconf from 'react-native-zeroconf';
|
||||||
import { View, Text, SectionList, Platform, StyleSheet } from 'react-native';
|
import { View, Text, SectionList, Platform, StyleSheet } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { setServer } from '../actions/server';
|
||||||
import * as actions from '../actions';
|
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import Fade from '../animations/fade';
|
||||||
|
import Banner from '../components/banner';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
view: {
|
view: {
|
||||||
|
@ -30,11 +31,6 @@ const styles = StyleSheet.create({
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
color: '#888'
|
color: '#888'
|
||||||
},
|
},
|
||||||
listItem: {
|
|
||||||
lineHeight: 18,
|
|
||||||
color: '#666',
|
|
||||||
padding: 14
|
|
||||||
},
|
|
||||||
container: {
|
container: {
|
||||||
flex: 1
|
flex: 1
|
||||||
},
|
},
|
||||||
|
@ -47,6 +43,21 @@ const styles = StyleSheet.create({
|
||||||
lineHeight: 24,
|
lineHeight: 24,
|
||||||
paddingLeft: 14,
|
paddingLeft: 14,
|
||||||
color: '#888'
|
color: '#888'
|
||||||
|
},
|
||||||
|
serverItem: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
// justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
padding: 14
|
||||||
|
},
|
||||||
|
|
||||||
|
listItem: {
|
||||||
|
color: '#666', flexGrow: 1, lineHeight: 30
|
||||||
|
},
|
||||||
|
serverChecked: {
|
||||||
|
flexGrow: 0
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -56,11 +67,12 @@ const zeroconf = new Zeroconf();
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
server: state.server
|
server: state.server
|
||||||
}), dispatch => ({
|
}), dispatch => ({
|
||||||
actions: bindActionCreators(actions, dispatch)
|
selectServer: server => dispatch(setServer(server))
|
||||||
}))
|
}))
|
||||||
export default class ListServerView extends React.Component {
|
export default class ListServerView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigator: PropTypes.object.isRequired,
|
navigator: PropTypes.object.isRequired,
|
||||||
|
selectServer: PropTypes.func.isRequired,
|
||||||
actions: PropTypes.object,
|
actions: PropTypes.object,
|
||||||
server: PropTypes.string
|
server: PropTypes.string
|
||||||
}
|
}
|
||||||
|
@ -131,14 +143,7 @@ export default class ListServerView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressItem = (item) => {
|
onPressItem = (item) => {
|
||||||
RocketChat.logout();
|
this.props.selectServer(item.id);
|
||||||
Navigation.dismissModal({
|
|
||||||
animationType: 'slide-down'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
server: item.id
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getState = () => {
|
getState = () => {
|
||||||
|
@ -176,12 +181,16 @@ export default class ListServerView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem = ({ item }) => (
|
renderItem = ({ item }) => (
|
||||||
<Text
|
|
||||||
style={styles.listItem}
|
<View style={styles.serverItem}>
|
||||||
onPress={() => { this.onPressItem(item); }}
|
<Text
|
||||||
>
|
style={[styles.listItem]}
|
||||||
{item.id}
|
onPress={() => { this.onPressItem(item); }}
|
||||||
</Text>
|
>
|
||||||
|
{item.id}
|
||||||
|
</Text>
|
||||||
|
<Fade visible={this.props.server === item.id}><Icon iconSize={24} size={24} style={styles.serverChecked} name='ios-checkmark-circle-outline' /> </Fade>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
renderSectionHeader = ({ section }) => (
|
renderSectionHeader = ({ section }) => (
|
||||||
|
@ -195,6 +204,7 @@ export default class ListServerView extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={styles.view}>
|
<View style={styles.view}>
|
||||||
|
<Banner />
|
||||||
<SectionList
|
<SectionList
|
||||||
style={styles.list}
|
style={styles.list}
|
||||||
sections={this.state.sections}
|
sections={this.state.sections}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
import './app/navigation';
|
import './index.ios';
|
||||||
|
|
|
@ -1 +1,7 @@
|
||||||
|
import 'babel-polyfill';
|
||||||
|
import 'regenerator-runtime/runtime';
|
||||||
import './app/navigation';
|
import './app/navigation';
|
||||||
|
// import { AppRegistry } from 'react-native';
|
||||||
|
// import Routes from './app/routes';
|
||||||
|
//
|
||||||
|
// AppRegistry.registerComponent('RocketChatRN', () => Routes);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
"babel-plugin-transform-decorators-legacy": "^1.3.4",
|
||||||
|
"babel-polyfill": "^6.26.0",
|
||||||
"moment": "^2.18.1",
|
"moment": "^2.18.1",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
"react": "16.0.0-alpha.12",
|
"react": "16.0.0-alpha.12",
|
||||||
|
@ -31,9 +32,12 @@
|
||||||
"react-native-form-generator": "^0.9.9",
|
"react-native-form-generator": "^0.9.9",
|
||||||
"react-native-image-picker": "^0.26.3",
|
"react-native-image-picker": "^0.26.3",
|
||||||
"react-native-img-cache": "^1.4.0",
|
"react-native-img-cache": "^1.4.0",
|
||||||
|
"react-native-loader": "^1.1.0",
|
||||||
|
"react-native-loading-spinner-overlay": "^0.5.1",
|
||||||
"react-native-meteor": "^1.1.0",
|
"react-native-meteor": "^1.1.0",
|
||||||
"react-native-navigation": "^1.1.193",
|
"react-native-navigation": "^1.1.193",
|
||||||
"react-native-optimized-flatlist": "^1.0.1",
|
"react-native-optimized-flatlist": "^1.0.1",
|
||||||
|
"react-native-router-flux": "^4.0.0-beta.18",
|
||||||
"react-native-svg": "^5.4.1",
|
"react-native-svg": "^5.4.1",
|
||||||
"react-native-svg-image": "^1.1.4",
|
"react-native-svg-image": "^1.1.4",
|
||||||
"react-native-vector-icons": "^4.3.0",
|
"react-native-vector-icons": "^4.3.0",
|
||||||
|
@ -44,7 +48,8 @@
|
||||||
"redux": "^3.7.2",
|
"redux": "^3.7.2",
|
||||||
"redux-immutable-state-invariant": "^2.0.0",
|
"redux-immutable-state-invariant": "^2.0.0",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"redux-thunk": "^2.2.0",
|
"redux-saga": "^0.15.6",
|
||||||
|
"regenerator-runtime": "^0.11.0",
|
||||||
"strip-ansi": "^4.0.0",
|
"strip-ansi": "^4.0.0",
|
||||||
"underscore": "^1.8.3"
|
"underscore": "^1.8.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -7417,4 +7417,4 @@ yauzl@2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"
|
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"
|
||||||
dependencies:
|
dependencies:
|
||||||
fd-slicer "~1.0.1"
|
fd-slicer "~1.0.1"
|
Loading…
Reference in New Issue