Sort/group rooms local only (#425)

* Update android api from ci

* Sort local only
This commit is contained in:
Diego Mello 2018-09-04 11:29:20 -03:00 committed by GitHub
parent a283d96228
commit 101d4c727c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 126 additions and 75 deletions

View File

@ -84,7 +84,7 @@ jobs:
android-build: android-build:
<<: *defaults <<: *defaults
docker: docker:
- image: circleci/android:api-26-alpha - image: circleci/android:api-27-node8-alpha
environment: environment:
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError" GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError"
@ -95,12 +95,12 @@ jobs:
steps: steps:
- checkout - checkout
- run: # - run:
name: Install Node 8 # name: Install Node 8
command: | # command: |
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash # curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash
source ~/.nvm/nvm.sh # source ~/.nvm/nvm.sh
nvm install 8 # nvm install 8
- restore_cache: - restore_cache:
key: node-modules-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }} key: node-modules-{{ checksum ".circleci/config.yml" }}-{{ checksum "package.json" }}

View File

@ -25,7 +25,8 @@ export const LOGIN = createRequestTypes('LOGIN', [
'CLOSE', 'CLOSE',
'SET_SERVICES', 'SET_SERVICES',
'REMOVE_SERVICES', 'REMOVE_SERVICES',
'SET_PREFERENCE' 'SET_PREFERENCE',
'SET_SORT_PREFERENCE'
]); ]);
export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [ export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [
...defaultTypes, ...defaultTypes,
@ -98,6 +99,7 @@ export const MENTIONED_MESSAGES = createRequestTypes('MENTIONED_MESSAGES', ['OPE
export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']); export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']);
export const ROOM_FILES = createRequestTypes('ROOM_FILES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']); export const ROOM_FILES = createRequestTypes('ROOM_FILES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']);
export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']); export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']);
export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']);
export const INCREMENT = 'INCREMENT'; export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT'; export const DECREMENT = 'DECREMENT';

View File

@ -0,0 +1,15 @@
import * as types from './actionsTypes';
export function setAllPreferences(preferences) {
return {
type: types.SORT_PREFERENCES.SET_ALL,
preferences
};
}
export function setPreference(preference) {
return {
type: types.SORT_PREFERENCES.SET,
preference
};
}

View File

@ -44,6 +44,7 @@ import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFil
import { getDeviceToken } from '../push'; import { getDeviceToken } from '../push';
const TOKEN_KEY = 'reactnativemeteor_usertoken'; const TOKEN_KEY = 'reactnativemeteor_usertoken';
const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY';
const call = (method, ...params) => RocketChat.ddp.call(method, ...params); // eslint-disable-line const call = (method, ...params) => RocketChat.ddp.call(method, ...params); // eslint-disable-line
const returnAnArray = obj => obj || []; const returnAnArray = obj => obj || [];
@ -772,6 +773,19 @@ const RocketChat = {
}, },
setAvatarFromService({ data, contentType = '', service = null }) { setAvatarFromService({ data, contentType = '', service = null }) {
return call('setAvatarFromService', data, contentType, service); return call('setAvatarFromService', data, contentType, service);
},
async getSortPreferences() {
const prefs = await AsyncStorage.getItem(SORT_PREFS_KEY);
return JSON.parse(prefs);
},
async saveSortPreference(param) {
try {
let prefs = await RocketChat.getSortPreferences();
prefs = { ...prefs, ...param };
return await AsyncStorage.setItem(SORT_PREFS_KEY, JSON.stringify(prefs));
} catch (error) {
console.warn(error);
}
} }
}; };

View File

@ -18,6 +18,7 @@ import pinnedMessages from './pinnedMessages';
import mentionedMessages from './mentionedMessages'; import mentionedMessages from './mentionedMessages';
import snippetedMessages from './snippetedMessages'; import snippetedMessages from './snippetedMessages';
import roomFiles from './roomFiles'; import roomFiles from './roomFiles';
import sortPreferences from './sortPreferences';
export default combineReducers({ export default combineReducers({
settings, settings,
@ -38,5 +39,6 @@ export default combineReducers({
pinnedMessages, pinnedMessages,
mentionedMessages, mentionedMessages,
snippetedMessages, snippetedMessages,
roomFiles roomFiles,
sortPreferences
}); });

View File

@ -0,0 +1,26 @@
import { SORT_PREFERENCES } from '../actions/actionsTypes';
const initialState = {
sortBy: 'activity',
groupByType: true,
showFavorites: true,
showUnread: true
};
export default (state = initialState, action) => {
switch (action.type) {
case SORT_PREFERENCES.SET_ALL:
return {
...state,
...action.preferences
};
case SORT_PREFERENCES.SET:
return {
...state,
...action.preference
};
default:
return state;
}
};

View File

@ -4,6 +4,7 @@ import { call, put, takeLatest } from 'redux-saga/effects';
import * as actions from '../actions'; import * as actions from '../actions';
import { selectServerRequest } from '../actions/server'; import { selectServerRequest } from '../actions/server';
import { restoreToken, setUser } from '../actions/login'; import { restoreToken, setUser } from '../actions/login';
import { setAllPreferences } from '../actions/sortPreferences';
import { APP } from '../actions/actionsTypes'; import { APP } from '../actions/actionsTypes';
import RocketChat from '../lib/rocketchat'; import RocketChat from '../lib/rocketchat';
import log from '../utils/log'; import log from '../utils/log';
@ -27,6 +28,9 @@ const restore = function* restore() {
} }
} }
const sortPreferences = yield RocketChat.getSortPreferences();
yield put(setAllPreferences(sortPreferences));
yield put(actions.appReady({})); yield put(actions.appReady({}));
} catch (e) { } catch (e) {
log('restore', e); log('restore', e);

View File

@ -6,7 +6,7 @@ import { connect } from 'react-redux';
import Touch from '../../utils/touch'; import Touch from '../../utils/touch';
import styles from './styles'; import styles from './styles';
import RocketChat from '../../lib/rocketchat'; import RocketChat from '../../lib/rocketchat';
import { setPreference } from '../../actions/login'; import { setPreference } from '../../actions/sortPreferences';
import log from '../../utils/log'; import log from '../../utils/log';
import I18n from '../../i18n'; import I18n from '../../i18n';
@ -15,17 +15,17 @@ const ANIMATION_DURATION = 200;
@connect(state => ({ @connect(state => ({
closeSortDropdown: state.rooms.closeSortDropdown closeSortDropdown: state.rooms.closeSortDropdown
}), dispatch => ({ }), dispatch => ({
setPreference: preference => dispatch(setPreference(preference)) setSortPreference: preference => dispatch(setPreference(preference))
})) }))
export default class Sort extends Component { export default class Sort extends Component {
static propTypes = { static propTypes = {
closeSortDropdown: PropTypes.bool, closeSortDropdown: PropTypes.bool,
close: PropTypes.func, close: PropTypes.func,
sidebarSortby: PropTypes.string, sortBy: PropTypes.string,
sidebarGroupByType: PropTypes.bool, groupByType: PropTypes.bool,
sidebarShowFavorites: PropTypes.bool, showFavorites: PropTypes.bool,
sidebarShowUnread: PropTypes.bool, showUnread: PropTypes.bool,
setPreference: PropTypes.func setSortPreference: PropTypes.func
} }
constructor(props) { constructor(props) {
@ -51,33 +51,33 @@ export default class Sort extends Component {
} }
} }
saveUserPreference = async(param) => { setSortPreference = async(param) => {
try { try {
this.props.setPreference(param); this.props.setSortPreference(param);
await RocketChat.saveUserPreferences(param); RocketChat.saveSortPreference(param);
} catch (e) { } catch (e) {
log('RoomsListView.saveUserPreference', e); log('RoomsListView.setSortPreference', e);
} }
} }
sortByName = () => { sortByName = () => {
this.saveUserPreference({ sidebarSortby: 'alphabetical' }); this.setSortPreference({ sortBy: 'alphabetical' });
} }
sortByActivity = () => { sortByActivity = () => {
this.saveUserPreference({ sidebarSortby: 'activity' }); this.setSortPreference({ sortBy: 'activity' });
} }
toggleGroupByType = () => { toggleGroupByType = () => {
this.saveUserPreference({ sidebarGroupByType: !this.props.sidebarGroupByType }); this.setSortPreference({ groupByType: !this.props.groupByType });
} }
toggleGroupByFavorites = () => { toggleGroupByFavorites = () => {
this.saveUserPreference({ sidebarShowFavorites: !this.props.sidebarShowFavorites }); this.setSortPreference({ showFavorites: !this.props.showFavorites });
} }
toggleUnread = () => { toggleUnread = () => {
this.saveUserPreference({ sidebarShowUnread: !this.props.sidebarShowUnread }); this.setSortPreference({ showUnread: !this.props.showUnread });
} }
close = () => { close = () => {
@ -102,7 +102,7 @@ export default class Sort extends Component {
outputRange: [0, 0.3] outputRange: [0, 0.3]
}); });
const { const {
sidebarSortby, sidebarGroupByType, sidebarShowFavorites, sidebarShowUnread sortBy, groupByType, showFavorites, showUnread
} = this.props; } = this.props;
return ( return (
[ [
@ -117,14 +117,14 @@ export default class Sort extends Component {
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Image style={styles.sortIcon} source={{ uri: 'sort_alphabetically' }} /> <Image style={styles.sortIcon} source={{ uri: 'sort_alphabetically' }} />
<Text style={styles.sortItemText}>{I18n.t('Alphabetical')}</Text> <Text style={styles.sortItemText}>{I18n.t('Alphabetical')}</Text>
{sidebarSortby === 'alphabetical' ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null} {sortBy === 'alphabetical' ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null}
</View> </View>
</Touch> </Touch>
<Touch key='sort-activity' style={styles.sortItemButton} onPress={this.sortByActivity}> <Touch key='sort-activity' style={styles.sortItemButton} onPress={this.sortByActivity}>
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Image style={styles.sortIcon} source={{ uri: 'sort_activity' }} /> <Image style={styles.sortIcon} source={{ uri: 'sort_activity' }} />
<Text style={styles.sortItemText}>{I18n.t('Activity')}</Text> <Text style={styles.sortItemText}>{I18n.t('Activity')}</Text>
{sidebarSortby === 'activity' ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null} {sortBy === 'activity' ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null}
</View> </View>
</Touch> </Touch>
<View style={styles.sortSeparator} /> <View style={styles.sortSeparator} />
@ -132,21 +132,21 @@ export default class Sort extends Component {
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Image style={styles.sortIcon} source={{ uri: 'group_type' }} /> <Image style={styles.sortIcon} source={{ uri: 'group_type' }} />
<Text style={styles.sortItemText}>{I18n.t('Group_by_type')}</Text> <Text style={styles.sortItemText}>{I18n.t('Group_by_type')}</Text>
{sidebarGroupByType ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null} {groupByType ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null}
</View> </View>
</Touch> </Touch>
<Touch key='group-favorites' style={styles.sortItemButton} onPress={this.toggleGroupByFavorites}> <Touch key='group-favorites' style={styles.sortItemButton} onPress={this.toggleGroupByFavorites}>
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Image style={styles.sortIcon} source={{ uri: 'group_favorites' }} /> <Image style={styles.sortIcon} source={{ uri: 'group_favorites' }} />
<Text style={styles.sortItemText}>{I18n.t('Group_by_favorites')}</Text> <Text style={styles.sortItemText}>{I18n.t('Group_by_favorites')}</Text>
{sidebarShowFavorites ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null} {showFavorites ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null}
</View> </View>
</Touch> </Touch>
<Touch key='group-unread' style={styles.sortItemButton} onPress={this.toggleUnread}> <Touch key='group-unread' style={styles.sortItemButton} onPress={this.toggleUnread}>
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Image style={styles.sortIcon} source={{ uri: 'group_unread' }} /> <Image style={styles.sortIcon} source={{ uri: 'group_unread' }} />
<Text style={styles.sortItemText}>{I18n.t('Unread_on_top')}</Text> <Text style={styles.sortItemText}>{I18n.t('Unread_on_top')}</Text>
{sidebarShowUnread ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null} {showUnread ? <Image style={styles.sortIcon} source={{ uri: 'check' }} /> : null}
</View> </View>
</Touch> </Touch>
</Animated.View>, </Animated.View>,
@ -156,7 +156,7 @@ export default class Sort extends Component {
style={[styles.dropdownContainerHeader, styles.sortToggleContainerClose]} style={[styles.dropdownContainerHeader, styles.sortToggleContainerClose]}
> >
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Text style={styles.sortToggleText}>{I18n.t('Sorting_by', { key: I18n.t(this.props.sidebarSortby === 'alphabetical' ? 'name' : 'activity') })}</Text> <Text style={styles.sortToggleText}>{I18n.t('Sorting_by', { key: I18n.t(this.props.sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
<Image style={styles.sortIcon} source={{ uri: 'group_type' }} /> <Image style={styles.sortIcon} source={{ uri: 'group_type' }} />
</View> </View>
</Touch> </Touch>

View File

@ -39,31 +39,19 @@ if (Platform.OS === 'android') {
}); });
} }
@connect((state) => { @connect(state => ({
let result = { userId: state.login.user && state.login.user.id,
userId: state.login.user && state.login.user.id, server: state.server.server,
server: state.server.server, Site_Url: state.settings.Site_Url,
Site_Url: state.settings.Site_Url, searchText: state.rooms.searchText,
searchText: state.rooms.searchText, loadingServer: state.server.loading,
loadingServer: state.server.loading, showServerDropdown: state.rooms.showServerDropdown,
showServerDropdown: state.rooms.showServerDropdown, showSortDropdown: state.rooms.showSortDropdown,
showSortDropdown: state.rooms.showSortDropdown, sortBy: state.sortPreferences.sortBy,
sidebarSortby: null, groupByType: state.sortPreferences.groupByType,
sidebarGroupByType: null, showFavorites: state.sortPreferences.showFavorites,
sidebarShowFavorites: null, showUnread: state.sortPreferences.showUnread
sidebarShowUnread: null }), dispatch => ({
};
if (state.login && state.login.user && state.login.user.settings && state.login.user.settings.preferences) {
result = {
...result,
sidebarSortby: state.login.user.settings.preferences.sidebarSortby,
sidebarGroupByType: state.login.user.settings.preferences.sidebarGroupByType,
sidebarShowFavorites: state.login.user.settings.preferences.sidebarShowFavorites,
sidebarShowUnread: state.login.user.settings.preferences.sidebarShowUnread
};
}
return result;
}, dispatch => ({
toggleSortDropdown: () => dispatch(toggleSortDropdown()) toggleSortDropdown: () => dispatch(toggleSortDropdown())
})) }))
/** @extends React.Component */ /** @extends React.Component */
@ -88,10 +76,10 @@ export default class RoomsListView extends LoggedView {
loadingServer: PropTypes.bool, loadingServer: PropTypes.bool,
showServerDropdown: PropTypes.bool, showServerDropdown: PropTypes.bool,
showSortDropdown: PropTypes.bool, showSortDropdown: PropTypes.bool,
sidebarSortby: PropTypes.string, sortBy: PropTypes.string,
sidebarGroupByType: PropTypes.bool, groupByType: PropTypes.bool,
sidebarShowFavorites: PropTypes.bool, showFavorites: PropTypes.bool,
sidebarShowUnread: PropTypes.bool, showUnread: PropTypes.bool,
toggleSortDropdown: PropTypes.func toggleSortDropdown: PropTypes.func
} }
@ -138,10 +126,10 @@ export default class RoomsListView extends LoggedView {
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
if (!( if (!(
(prevProps.sidebarSortby === this.props.sidebarSortby) && (prevProps.sortBy === this.props.sortBy) &&
(prevProps.sidebarGroupByType === this.props.sidebarGroupByType) && (prevProps.groupByType === this.props.groupByType) &&
(prevProps.sidebarShowFavorites === this.props.sidebarShowFavorites) && (prevProps.showFavorites === this.props.showFavorites) &&
(prevProps.sidebarShowUnread === this.props.sidebarShowUnread) (prevProps.showUnread === this.props.showUnread)
)) { )) {
this.getSubscriptions(); this.getSubscriptions();
} }
@ -195,7 +183,7 @@ export default class RoomsListView extends LoggedView {
getSubscriptions = () => { getSubscriptions = () => {
if (this.props.server && this.hasActiveDB()) { if (this.props.server && this.hasActiveDB()) {
if (this.props.sidebarSortby === 'alphabetical') { if (this.props.sortBy === 'alphabetical') {
this.data = database.objects('subscriptions').filtered('archived != true && open == true').sorted('name', false); this.data = database.objects('subscriptions').filtered('archived != true && open == true').sorted('name', false);
} else { } else {
this.data = database.objects('subscriptions').filtered('archived != true && open == true').sorted('roomUpdatedAt', true); this.data = database.objects('subscriptions').filtered('archived != true && open == true').sorted('roomUpdatedAt', true);
@ -210,7 +198,7 @@ export default class RoomsListView extends LoggedView {
let livechat = []; let livechat = [];
// unread // unread
if (this.props.sidebarShowUnread) { if (this.props.showUnread) {
this.unread = this.data.filtered('archived != true && open == true').sorted('name', false).filtered('(unread > 0 || alert == true)'); this.unread = this.data.filtered('archived != true && open == true').sorted('name', false).filtered('(unread > 0 || alert == true)');
unread = this.unread.slice(); unread = this.unread.slice();
setTimeout(() => { setTimeout(() => {
@ -220,7 +208,7 @@ export default class RoomsListView extends LoggedView {
this.removeListener(unread); this.removeListener(unread);
} }
// favorites // favorites
if (this.props.sidebarShowFavorites) { if (this.props.showFavorites) {
this.favorites = this.data.filtered('f == true'); this.favorites = this.data.filtered('f == true');
favorites = this.favorites.slice(); favorites = this.favorites.slice();
setTimeout(() => { setTimeout(() => {
@ -230,7 +218,7 @@ export default class RoomsListView extends LoggedView {
this.removeListener(favorites); this.removeListener(favorites);
} }
// type // type
if (this.props.sidebarGroupByType) { if (this.props.groupByType) {
// channels // channels
this.channels = this.data.filtered('t == $0', 'c'); this.channels = this.data.filtered('t == $0', 'c');
channels = this.channels.slice(); channels = this.channels.slice();
@ -382,7 +370,7 @@ export default class RoomsListView extends LoggedView {
style={styles.dropdownContainerHeader} style={styles.dropdownContainerHeader}
> >
<View style={styles.sortItemContainer}> <View style={styles.sortItemContainer}>
<Text style={styles.sortToggleText}>{I18n.t('Sorting_by', { key: I18n.t(this.props.sidebarSortby === 'alphabetical' ? 'name' : 'activity') })}</Text> <Text style={styles.sortToggleText}>{I18n.t('Sorting_by', { key: I18n.t(this.props.sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
<Image style={styles.sortIcon} source={{ uri: 'group_type' }} /> <Image style={styles.sortIcon} source={{ uri: 'group_type' }} />
</View> </View>
</Touch> </Touch>
@ -496,7 +484,7 @@ export default class RoomsListView extends LoggedView {
render = () => { render = () => {
const { const {
sidebarSortby, sidebarGroupByType, sidebarShowFavorites, sidebarShowUnread, showServerDropdown, showSortDropdown sortBy, groupByType, showFavorites, showUnread, showServerDropdown, showSortDropdown
} = this.props; } = this.props;
return ( return (
@ -505,10 +493,10 @@ export default class RoomsListView extends LoggedView {
{showSortDropdown ? {showSortDropdown ?
<SortDropdown <SortDropdown
close={this.toggleSort} close={this.toggleSort}
sidebarSortby={sidebarSortby} sortBy={sortBy}
sidebarGroupByType={sidebarGroupByType} groupByType={groupByType}
sidebarShowFavorites={sidebarShowFavorites} showFavorites={showFavorites}
sidebarShowUnread={sidebarShowUnread} showUnread={showUnread}
/> : /> :
null} null}
{showServerDropdown ? <ServerDropdown navigator={this.props.navigator} /> : null} {showServerDropdown ? <ServerDropdown navigator={this.props.navigator} /> : null}