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

View File

@ -25,7 +25,8 @@ export const LOGIN = createRequestTypes('LOGIN', [
'CLOSE',
'SET_SERVICES',
'REMOVE_SERVICES',
'SET_PREFERENCE'
'SET_PREFERENCE',
'SET_SORT_PREFERENCE'
]);
export const FORGOT_PASSWORD = createRequestTypes('FORGOT_PASSWORD', [
...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 ROOM_FILES = createRequestTypes('ROOM_FILES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']);
export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN']);
export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']);
export const INCREMENT = 'INCREMENT';
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';
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 returnAnArray = obj => obj || [];
@ -772,6 +773,19 @@ const RocketChat = {
},
setAvatarFromService({ data, contentType = '', service = null }) {
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 snippetedMessages from './snippetedMessages';
import roomFiles from './roomFiles';
import sortPreferences from './sortPreferences';
export default combineReducers({
settings,
@ -38,5 +39,6 @@ export default combineReducers({
pinnedMessages,
mentionedMessages,
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 { selectServerRequest } from '../actions/server';
import { restoreToken, setUser } from '../actions/login';
import { setAllPreferences } from '../actions/sortPreferences';
import { APP } from '../actions/actionsTypes';
import RocketChat from '../lib/rocketchat';
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({}));
} catch (e) {
log('restore', e);

View File

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

View File

@ -39,31 +39,19 @@ if (Platform.OS === 'android') {
});
}
@connect((state) => {
let result = {
userId: state.login.user && state.login.user.id,
server: state.server.server,
Site_Url: state.settings.Site_Url,
searchText: state.rooms.searchText,
loadingServer: state.server.loading,
showServerDropdown: state.rooms.showServerDropdown,
showSortDropdown: state.rooms.showSortDropdown,
sidebarSortby: null,
sidebarGroupByType: null,
sidebarShowFavorites: null,
sidebarShowUnread: null
};
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 => ({
@connect(state => ({
userId: state.login.user && state.login.user.id,
server: state.server.server,
Site_Url: state.settings.Site_Url,
searchText: state.rooms.searchText,
loadingServer: state.server.loading,
showServerDropdown: state.rooms.showServerDropdown,
showSortDropdown: state.rooms.showSortDropdown,
sortBy: state.sortPreferences.sortBy,
groupByType: state.sortPreferences.groupByType,
showFavorites: state.sortPreferences.showFavorites,
showUnread: state.sortPreferences.showUnread
}), dispatch => ({
toggleSortDropdown: () => dispatch(toggleSortDropdown())
}))
/** @extends React.Component */
@ -88,10 +76,10 @@ export default class RoomsListView extends LoggedView {
loadingServer: PropTypes.bool,
showServerDropdown: PropTypes.bool,
showSortDropdown: PropTypes.bool,
sidebarSortby: PropTypes.string,
sidebarGroupByType: PropTypes.bool,
sidebarShowFavorites: PropTypes.bool,
sidebarShowUnread: PropTypes.bool,
sortBy: PropTypes.string,
groupByType: PropTypes.bool,
showFavorites: PropTypes.bool,
showUnread: PropTypes.bool,
toggleSortDropdown: PropTypes.func
}
@ -138,10 +126,10 @@ export default class RoomsListView extends LoggedView {
componentDidUpdate(prevProps) {
if (!(
(prevProps.sidebarSortby === this.props.sidebarSortby) &&
(prevProps.sidebarGroupByType === this.props.sidebarGroupByType) &&
(prevProps.sidebarShowFavorites === this.props.sidebarShowFavorites) &&
(prevProps.sidebarShowUnread === this.props.sidebarShowUnread)
(prevProps.sortBy === this.props.sortBy) &&
(prevProps.groupByType === this.props.groupByType) &&
(prevProps.showFavorites === this.props.showFavorites) &&
(prevProps.showUnread === this.props.showUnread)
)) {
this.getSubscriptions();
}
@ -195,7 +183,7 @@ export default class RoomsListView extends LoggedView {
getSubscriptions = () => {
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);
} else {
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 = [];
// 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)');
unread = this.unread.slice();
setTimeout(() => {
@ -220,7 +208,7 @@ export default class RoomsListView extends LoggedView {
this.removeListener(unread);
}
// favorites
if (this.props.sidebarShowFavorites) {
if (this.props.showFavorites) {
this.favorites = this.data.filtered('f == true');
favorites = this.favorites.slice();
setTimeout(() => {
@ -230,7 +218,7 @@ export default class RoomsListView extends LoggedView {
this.removeListener(favorites);
}
// type
if (this.props.sidebarGroupByType) {
if (this.props.groupByType) {
// channels
this.channels = this.data.filtered('t == $0', 'c');
channels = this.channels.slice();
@ -382,7 +370,7 @@ export default class RoomsListView extends LoggedView {
style={styles.dropdownContainerHeader}
>
<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' }} />
</View>
</Touch>
@ -496,7 +484,7 @@ export default class RoomsListView extends LoggedView {
render = () => {
const {
sidebarSortby, sidebarGroupByType, sidebarShowFavorites, sidebarShowUnread, showServerDropdown, showSortDropdown
sortBy, groupByType, showFavorites, showUnread, showServerDropdown, showSortDropdown
} = this.props;
return (
@ -505,10 +493,10 @@ export default class RoomsListView extends LoggedView {
{showSortDropdown ?
<SortDropdown
close={this.toggleSort}
sidebarSortby={sidebarSortby}
sidebarGroupByType={sidebarGroupByType}
sidebarShowFavorites={sidebarShowFavorites}
sidebarShowUnread={sidebarShowUnread}
sortBy={sortBy}
groupByType={groupByType}
showFavorites={showFavorites}
showUnread={showUnread}
/> :
null}
{showServerDropdown ? <ServerDropdown navigator={this.props.navigator} /> : null}