diff --git a/app/presentation/RoomItem/index.js b/app/presentation/RoomItem/index.js
index b93c9f1d..b9e2639b 100644
--- a/app/presentation/RoomItem/index.js
+++ b/app/presentation/RoomItem/index.js
@@ -1,9 +1,7 @@
import React from 'react';
import moment from 'moment';
import PropTypes from 'prop-types';
-import {
- View, Text, Dimensions, Animated
-} from 'react-native';
+import { View, Text, Animated } from 'react-native';
import { connect } from 'react-redux';
import { RectButton, PanGestureHandler, State } from 'react-native-gesture-handler';
@@ -18,9 +16,8 @@ import { CustomIcon } from '../../lib/Icons';
export { ROW_HEIGHT };
const OPTION_WIDTH = 80;
-const SMALL_SWIPE = 80;
-const ACTION_OFFSET = 220;
-const attrs = ['name', 'unread', 'userMentions', 'showLastMessage', 'alert', 'type'];
+const SMALL_SWIPE = 40;
+const attrs = ['name', 'unread', 'userMentions', 'showLastMessage', 'alert', 'type', 'width'];
@connect(state => ({
userId: state.login.user && state.login.user.id,
username: state.login.user && state.login.user.username,
@@ -45,6 +42,7 @@ export default class RoomItem extends React.Component {
token: PropTypes.string,
avatarSize: PropTypes.number,
testID: PropTypes.string,
+ width: PropTypes.number,
height: PropTypes.number,
favorite: PropTypes.bool,
isRead: PropTypes.bool,
@@ -71,9 +69,7 @@ export default class RoomItem extends React.Component {
this.state = {
dragX,
rowOffSet,
- rowState: 0, // 0: closed, 1: right opened, -1: left opened
- leftWidth: undefined,
- rightOffset: undefined
+ rowState: 0 // 0: closed, 1: right opened, -1: left opened
};
this._onGestureEvent = Animated.event(
[{ nativeEvent: { translationX: dragX } }]
@@ -104,43 +100,30 @@ export default class RoomItem extends React.Component {
this.rowTranslation.removeAllListeners();
}
- close = () => {
- this.swipeableRow.close();
- };
-
_onHandlerStateChange = ({ nativeEvent }) => {
if (nativeEvent.oldState === State.ACTIVE) {
this._handleRelease(nativeEvent);
}
};
- _currentOffset = () => {
- const { leftWidth = 0, rowState } = this.state;
- const { rightOffset } = this.state;
- if (rowState === 1) {
- return leftWidth;
- } else if (rowState === -1) {
- return rightOffset;
- }
- return 0;
- };
-
_handleRelease = (nativeEvent) => {
const { translationX } = nativeEvent;
const { rowState } = this.state;
+ const { width } = this.props;
+ const halfScreen = width / 2;
let toValue = 0;
if (rowState === 0) { // if no option is opened
- if (translationX > 0 && translationX < ACTION_OFFSET) {
+ if (translationX > 0 && translationX < halfScreen) {
toValue = OPTION_WIDTH; // open left option if he swipe right but not enough to trigger action
this.setState({ rowState: -1 });
- } else if (translationX > ACTION_OFFSET) {
+ } else if (translationX >= halfScreen) {
toValue = 0;
this.toggleRead();
- } else if (translationX < 0 && translationX > -ACTION_OFFSET) {
+ } else if (translationX < 0 && translationX > -halfScreen) {
toValue = -2 * OPTION_WIDTH; // open right option if he swipe left
this.setState({ rowState: 1 });
- } else if (translationX < -ACTION_OFFSET) {
- toValue = 0;
+ } else if (translationX <= -halfScreen) {
+ toValue = -width;
this.hideChannel();
} else {
toValue = 0;
@@ -151,7 +134,7 @@ export default class RoomItem extends React.Component {
if (this._value < SMALL_SWIPE) {
toValue = 0;
this.setState({ rowState: 0 });
- } else if (this._value > ACTION_OFFSET) {
+ } else if (this._value > halfScreen) {
toValue = 0;
this.setState({ rowState: 0 });
this.toggleRead();
@@ -164,7 +147,7 @@ export default class RoomItem extends React.Component {
if (this._value > -2 * SMALL_SWIPE) {
toValue = 0;
this.setState({ rowState: 0 });
- } else if (this._value < -ACTION_OFFSET) {
+ } else if (this._value < -halfScreen) {
toValue = 0;
this.setState({ rowState: 0 });
this.hideChannel();
@@ -181,7 +164,7 @@ export default class RoomItem extends React.Component {
dragX.setValue(0);
Animated.spring(rowOffSet, {
toValue,
- bounciness: 5
+ bounciness: 0
}).start();
}
@@ -191,6 +174,7 @@ export default class RoomItem extends React.Component {
}
close = () => {
+ this.setState({ rowState: 0 });
this._animateRow(0);
}
@@ -221,16 +205,28 @@ export default class RoomItem extends React.Component {
}
}
+ onPress = () => {
+ const { rowState } = this.state;
+ if (rowState !== 0) {
+ this.close();
+ return;
+ }
+ const { onPress } = this.props;
+ if (onPress) {
+ onPress();
+ }
+ }
+
renderLeftActions = () => {
- const { isRead } = this.props;
- const { width } = Dimensions.get('window');
+ const { isRead, width } = this.props;
+ const halfWidth = width / 2;
const trans = this.rowTranslation.interpolate({
inputRange: [0, OPTION_WIDTH],
outputRange: [-width, -width + OPTION_WIDTH]
});
const iconTrans = this.rowTranslation.interpolate({
- inputRange: [0, OPTION_WIDTH, ACTION_OFFSET - 20, ACTION_OFFSET, width],
+ inputRange: [0, OPTION_WIDTH, halfWidth - 1, halfWidth, width],
outputRange: [0, 0, -(OPTION_WIDTH + 10), 0, 0]
});
return (
@@ -246,12 +242,12 @@ export default class RoomItem extends React.Component {
>
{isRead ? (
-
+
{I18n.t('Unread')}
) : (
-
+
{I18n.t('Read')}
)}
@@ -262,23 +258,24 @@ export default class RoomItem extends React.Component {
};
renderRightActions = () => {
- const { favorite } = this.props;
- const { width } = Dimensions.get('window');
+ const { favorite, width } = this.props;
+ const halfWidth = width / 2;
const trans = this.rowTranslation.interpolate({
inputRange: [-OPTION_WIDTH, 0],
outputRange: [width - OPTION_WIDTH, width]
});
const iconHideTrans = this.rowTranslation.interpolate({
- inputRange: [-(ACTION_OFFSET - 20), -2 * OPTION_WIDTH, 0],
+ inputRange: [-(halfWidth - 20), -2 * OPTION_WIDTH, 0],
outputRange: [0, 0, -OPTION_WIDTH]
});
const iconFavWidth = this.rowTranslation.interpolate({
- inputRange: [-(ACTION_OFFSET + 1), -ACTION_OFFSET, -(ACTION_OFFSET - 20), -2 * OPTION_WIDTH, 0],
- outputRange: [0, 0, OPTION_WIDTH + 20, OPTION_WIDTH, OPTION_WIDTH]
+ inputRange: [-halfWidth, -2 * OPTION_WIDTH, 0],
+ outputRange: [0, OPTION_WIDTH, OPTION_WIDTH],
+ extrapolate: 'clamp'
});
const iconHideWidth = this.rowTranslation.interpolate({
- inputRange: [-(ACTION_OFFSET + 1), -ACTION_OFFSET, -(ACTION_OFFSET - 20), -2 * OPTION_WIDTH, 0],
- outputRange: [(ACTION_OFFSET + 1), ACTION_OFFSET, OPTION_WIDTH + 20, OPTION_WIDTH, OPTION_WIDTH]
+ inputRange: [-width, -halfWidth, -2 * OPTION_WIDTH, 0],
+ outputRange: [width, halfWidth, OPTION_WIDTH, OPTION_WIDTH]
});
return (
{favorite ? (
-
+
{I18n.t('Unfavorite')}
) : (
-
+
{I18n.t('Favorite')}
)}
@@ -314,7 +311,7 @@ export default class RoomItem extends React.Component {
onPress={this.handleHideButtonPress}
>
-
+
{I18n.t('Hide')}
@@ -332,7 +329,7 @@ export default class RoomItem extends React.Component {
render() {
const {
- unread, userMentions, name, _updatedAt, alert, testID, height, type, avatarSize, baseUrl, userId, username, token, onPress, id, prid, showLastMessage, lastMessage
+ unread, userMentions, name, _updatedAt, alert, testID, height, type, avatarSize, baseUrl, userId, username, token, id, prid, showLastMessage, lastMessage
} = this.props;
const date = this.formatDate(_updatedAt);
@@ -358,7 +355,7 @@ export default class RoomItem extends React.Component {
onGestureEvent={this._onGestureEvent}
onHandlerStateChange={this._onHandlerStateChange}
>
-
+
{this.renderLeftActions()}
{this.renderRightActions()}
-
+
);
}
diff --git a/app/presentation/RoomItem/styles.js b/app/presentation/RoomItem/styles.js
index fba962e7..a39a1037 100644
--- a/app/presentation/RoomItem/styles.js
+++ b/app/presentation/RoomItem/styles.js
@@ -9,12 +9,14 @@ export const ROW_HEIGHT = 75 * PixelRatio.getFontScale();
export default StyleSheet.create({
container: {
- backgroundColor: COLOR_WHITE,
flexDirection: 'row',
alignItems: 'center',
paddingLeft: 14,
height: ROW_HEIGHT
},
+ button: {
+ backgroundColor: COLOR_WHITE
+ },
centerContainer: {
flex: 1,
paddingVertical: 10,
@@ -96,10 +98,12 @@ export default StyleSheet.create({
marginRight: 10
},
actionText: {
- color: 'white',
- fontSize: 14,
+ color: COLOR_WHITE,
+ fontSize: 15,
backgroundColor: 'transparent',
- justifyContent: 'center'
+ justifyContent: 'center',
+ marginTop: 4,
+ ...sharedStyles.textSemibold
},
actionButtonLeft: {
flex: 1,
diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js
index f8901afc..fbb9c169 100644
--- a/app/views/RoomsListView/index.js
+++ b/app/views/RoomsListView/index.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
- View, FlatList, BackHandler, ActivityIndicator, Text, ScrollView, Keyboard, LayoutAnimation, InteractionManager
+ View, FlatList, BackHandler, ActivityIndicator, Text, ScrollView, Keyboard, LayoutAnimation, InteractionManager, Dimensions
} from 'react-native';
import { connect } from 'react-redux';
import { isEqual } from 'lodash';
@@ -121,6 +121,7 @@ export default class RoomsListView extends React.Component {
console.time(`${ this.constructor.name } init`);
console.time(`${ this.constructor.name } mount`);
+ const { width } = Dimensions.get('window');
this.data = [];
this.state = {
searching: false,
@@ -133,7 +134,8 @@ export default class RoomsListView extends React.Component {
channels: [],
privateGroup: [],
direct: [],
- livechat: []
+ livechat: [],
+ width
};
Orientation.unlockAllOrientations();
this.didFocusListener = props.navigation.addListener('didFocus', () => BackHandler.addEventListener('hardwareBackPress', this.handleBackPress));
@@ -148,6 +150,7 @@ export default class RoomsListView extends React.Component {
initSearchingAndroid: this.initSearchingAndroid,
cancelSearchingAndroid: this.cancelSearchingAndroid
});
+ Dimensions.addEventListener('change', this.onDimensionsChange);
console.timeEnd(`${ this.constructor.name } mount`);
}
@@ -172,7 +175,7 @@ export default class RoomsListView extends React.Component {
return true;
}
- const { loading, searching } = this.state;
+ const { loading, searching, width } = this.state;
if (nextState.loading !== loading) {
return true;
}
@@ -180,6 +183,10 @@ export default class RoomsListView extends React.Component {
return true;
}
+ if (nextState.width !== width) {
+ return true;
+ }
+
const { search } = this.state;
if (!isEqual(nextState.search, search)) {
return true;
@@ -220,9 +227,12 @@ export default class RoomsListView extends React.Component {
if (this.willBlurListener && this.willBlurListener.remove) {
this.willBlurListener.remove();
}
+ Dimensions.removeEventListener('change', this.onDimensionsChange);
console.countReset(`${ this.constructor.name }.render calls`);
}
+ onDimensionsChange = ({ window: { width } }) => this.setState({ width })
+
// eslint-disable-next-line react/sort-comp
internalSetState = (...args) => {
const { navigation } = this.props;
@@ -393,7 +403,15 @@ export default class RoomsListView extends React.Component {
toggleRead = async(rid, isRead) => {
try {
- await RocketChat.toggleRead(isRead, rid);
+ const result = await RocketChat.toggleRead(isRead, rid);
+ if (result.success) {
+ database.write(() => {
+ const sub = database.objects('subscriptions').filtered('rid == $0', rid)[0];
+ if (sub) {
+ sub.alert = isRead;
+ }
+ });
+ }
} catch (e) {
log('error_toggle_read', e);
}
@@ -401,7 +419,13 @@ export default class RoomsListView extends React.Component {
hideChannel = async(rid, type) => {
try {
- await RocketChat.hideRoom(rid, type);
+ const result = await RocketChat.hideRoom(rid, type);
+ if (result.success) {
+ database.write(() => {
+ const sub = database.objects('subscriptions').filtered('rid == $0', rid)[0];
+ database.delete(sub);
+ });
+ }
} catch (e) {
log('error_hide_channel', e);
}
@@ -435,6 +459,7 @@ export default class RoomsListView extends React.Component {
}
renderItem = ({ item }) => {
+ const { width } = this.state;
const {
userId, baseUrl, StoreLastMessage
} = this.props;
@@ -460,6 +485,7 @@ export default class RoomsListView extends React.Component {
showLastMessage={StoreLastMessage}
onPress={() => this._onPressItem(item)}
testID={`rooms-list-view-item-${ item.name }`}
+ width={width}
height={ROW_HEIGHT}
toggleFav={this.toggleFav}
toggleRead={this.toggleRead}
diff --git a/storybook/stories/RoomItem.js b/storybook/stories/RoomItem.js
index 48fddcb1..dd22e393 100644
--- a/storybook/stories/RoomItem.js
+++ b/storybook/stories/RoomItem.js
@@ -1,5 +1,5 @@
import React from 'react';
-import { ScrollView } from 'react-native';
+import { ScrollView, Dimensions } from 'react-native';
// import moment from 'moment';
import RoomItemComponent from '../../app/presentation/RoomItem';
@@ -7,6 +7,7 @@ import StoriesSeparator from './StoriesSeparator';
const date = '2017-10-10T10:00:00Z';
const baseUrl = 'https://open.rocket.chat';
+const { width } = Dimensions.get('window');
const RoomItem = props => (
(
name='rocket.cat'
_updatedAt={date}
baseUrl={baseUrl}
+ width={width}
{...props}
/>
);