Select last channel viewed (#172)
* Select last channel viewed Now saving last channel id to local storage Reworked local storage saving * Feedback review
This commit is contained in:
parent
19c50379cd
commit
d180f324c5
10 changed files with 118 additions and 40 deletions
|
|
@ -3,19 +3,22 @@
|
|||
|
||||
import {AsyncStorage} from 'react-native';
|
||||
import {batchActions} from 'redux-batched-actions';
|
||||
import {GeneralTypes, TeamsTypes, UsersTypes} from 'service/constants';
|
||||
import Client from 'service/client';
|
||||
import {ChannelTypes, GeneralTypes, TeamsTypes, UsersTypes} from 'service/constants';
|
||||
|
||||
export function loadStorage() {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
const data = JSON.parse(await AsyncStorage.getItem('storage'));
|
||||
const {token, url, currentTeamId} = data;
|
||||
|
||||
const {token, url, currentTeamId, ...otherStorage} = data;
|
||||
const credentials = {token, url};
|
||||
|
||||
const currentChannelId = otherStorage[currentTeamId] ? otherStorage[currentTeamId].currentChannelId : '';
|
||||
|
||||
dispatch(batchActions([
|
||||
{type: GeneralTypes.RECEIVED_APP_CREDENTIALS, data: credentials},
|
||||
{type: TeamsTypes.SELECT_TEAM, data: currentTeamId}
|
||||
{type: TeamsTypes.SELECT_TEAM, data: currentTeamId},
|
||||
{type: ChannelTypes.SELECT_CHANNEL, data: currentChannelId}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
// Error loading data
|
||||
|
|
@ -24,23 +27,41 @@ export function loadStorage() {
|
|||
};
|
||||
}
|
||||
|
||||
export function saveStorage(data = {}) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
const clientData = {
|
||||
token: Client.getToken(),
|
||||
url: Client.getUrl()
|
||||
};
|
||||
// Passing in a blank key of null or '' merges the data into the current storage.
|
||||
// Could maybe use some rework
|
||||
export async function updateStorage(key, data) {
|
||||
try {
|
||||
const currentStorage = JSON.parse(await AsyncStorage.getItem('storage'));
|
||||
|
||||
const mergedStorageData = Object.assign({}, data, clientData);
|
||||
|
||||
await AsyncStorage.setItem('storage', JSON.stringify(mergedStorageData));
|
||||
dispatch({type: GeneralTypes.RECEIVED_APP_CREDENTIALS, data}, getState);
|
||||
} catch (error) {
|
||||
// Error saving data
|
||||
dispatch({type: GeneralTypes.REMOVED_APP_CREDENTIALS, error}, getState);
|
||||
let mergedData;
|
||||
if (key !== null && key.length > 0) {
|
||||
const keyData = currentStorage[key];
|
||||
if (typeof data === 'string') {
|
||||
mergedData = Object.assign({}, {[key]: data});
|
||||
} else if (typeof data === 'object') {
|
||||
mergedData = Object.assign({}, {[key]: {...keyData, ...data}});
|
||||
}
|
||||
} else {
|
||||
mergedData = data;
|
||||
}
|
||||
};
|
||||
|
||||
const mergedStorageData = Object.assign({}, currentStorage, mergedData);
|
||||
|
||||
await saveStorage(mergedStorageData);
|
||||
|
||||
return mergedStorageData;
|
||||
} catch (error) {
|
||||
// TODO: Need to handle this error
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function saveStorage(data) {
|
||||
try {
|
||||
await AsyncStorage.setItem('storage', JSON.stringify(data));
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function removeStorage() {
|
||||
|
|
@ -48,7 +69,7 @@ export function removeStorage() {
|
|||
try {
|
||||
await AsyncStorage.removeItem('storage');
|
||||
} catch (error) {
|
||||
// Error removing data
|
||||
// TODO: Error removing data
|
||||
}
|
||||
dispatch({type: UsersTypes.RESET_LOGOUT_STATE}, getState);
|
||||
};
|
||||
|
|
@ -56,6 +77,6 @@ export function removeStorage() {
|
|||
|
||||
export default {
|
||||
loadStorage,
|
||||
saveStorage,
|
||||
removeStorage
|
||||
removeStorage,
|
||||
updateStorage
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import {batchActions} from 'redux-batched-actions';
|
||||
|
||||
import {ViewTypes} from 'app/constants';
|
||||
import {updateStorage} from 'app/actions/storage';
|
||||
|
||||
import {fetchMyChannelsAndMembers, getMyChannelMembers, selectChannel} from 'service/actions/channels';
|
||||
import {getPosts} from 'service/actions/posts';
|
||||
|
|
@ -94,7 +95,14 @@ export function loadPostsIfNecessary(channel) {
|
|||
|
||||
export function selectInitialChannel(teamId) {
|
||||
return async (dispatch, getState) => {
|
||||
const channels = getState().entities.channels.channels;
|
||||
const state = getState();
|
||||
const channels = state.entities.channels.channels;
|
||||
const currentChannelId = state.entities.channels.currentId;
|
||||
|
||||
if (channels[currentChannelId] && channels[currentChannelId].team_id === teamId) {
|
||||
await selectChannel(currentChannelId)(dispatch, getState);
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = Object.values(channels).find((c) => c.team_id === teamId && c.name === Constants.DEFAULT_CHANNEL);
|
||||
if (channel) {
|
||||
|
|
@ -107,6 +115,14 @@ export function selectInitialChannel(teamId) {
|
|||
};
|
||||
}
|
||||
|
||||
export function handleSelectChannel(channelId) {
|
||||
return async (dispatch, getState) => {
|
||||
const currentTeamId = getState().entities.teams.currentId;
|
||||
await updateStorage(currentTeamId, {currentChannelId: channelId});
|
||||
await selectChannel(channelId)(dispatch, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export function handlePostDraftChanged(postDraft) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// See License.txt for license information.
|
||||
|
||||
import {ViewTypes} from 'app/constants';
|
||||
import {updateStorage} from 'app/actions/storage';
|
||||
import Client from 'service/client';
|
||||
|
||||
export function handleLoginIdChanged(loginId) {
|
||||
return async (dispatch, getState) => {
|
||||
|
|
@ -21,7 +23,17 @@ export function handlePasswordChanged(password) {
|
|||
};
|
||||
}
|
||||
|
||||
export function handleSuccessfulLogin() {
|
||||
return async () => {
|
||||
await updateStorage(null, {
|
||||
url: Client.getUrl(),
|
||||
token: Client.getToken()
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
handleLoginIdChanged,
|
||||
handlePasswordChanged
|
||||
handlePasswordChanged,
|
||||
handleSuccessfulLogin
|
||||
};
|
||||
|
|
|
|||
23
app/actions/views/select_team.js
Normal file
23
app/actions/views/select_team.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {batchActions} from 'redux-batched-actions';
|
||||
|
||||
import {ChannelTypes, TeamsTypes} from 'service/constants';
|
||||
import {updateStorage} from 'app/actions/storage';
|
||||
|
||||
export function handleTeamChange(team) {
|
||||
return async (dispatch, getState) => {
|
||||
const storage = await updateStorage('currentTeamId', team.id);
|
||||
const lastChannelForTeam = storage[team.id] ? storage[team.id].currentChannelId : '';
|
||||
|
||||
dispatch(batchActions([
|
||||
{type: TeamsTypes.SELECT_TEAM, data: team.id},
|
||||
{type: ChannelTypes.SELECT_CHANNEL, data: lastChannelForTeam}
|
||||
]), getState);
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
handleTeamChange
|
||||
};
|
||||
|
|
@ -12,7 +12,8 @@ export default class ChannelDrawer extends React.Component {
|
|||
static propTypes = {
|
||||
children: React.PropTypes.element.isRequired,
|
||||
actions: React.PropTypes.shape({
|
||||
selectChannel: React.PropTypes.func.isRequired,
|
||||
updateStorage: React.PropTypes.func.isRequired,
|
||||
handleSelectChannel: React.PropTypes.func.isRequired,
|
||||
viewChannel: React.PropTypes.func.isRequired,
|
||||
closeDMChannel: React.PropTypes.func.isRequired,
|
||||
closeChannelDrawer: React.PropTypes.func.isRequired
|
||||
|
|
@ -29,6 +30,7 @@ export default class ChannelDrawer extends React.Component {
|
|||
super(props);
|
||||
|
||||
this.handleBackButton = this.handleBackButton.bind(this);
|
||||
this.selectChannel = this.selectChannel.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
@ -62,6 +64,10 @@ export default class ChannelDrawer extends React.Component {
|
|||
return false;
|
||||
}
|
||||
|
||||
selectChannel(channelId) {
|
||||
this.props.actions.handleSelectChannel(channelId);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentChannel,
|
||||
|
|
@ -92,7 +98,7 @@ export default class ChannelDrawer extends React.Component {
|
|||
channels={channels}
|
||||
channelMembers={channelMembers}
|
||||
theme={theme}
|
||||
onSelectChannel={this.props.actions.selectChannel}
|
||||
onSelectChannel={this.selectChannel}
|
||||
onViewChannel={this.props.actions.viewChannel}
|
||||
handleCloseDM={this.props.actions.closeDMChannel}
|
||||
closeChannelDrawer={this.props.actions.closeChannelDrawer}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {selectChannel, viewChannel} from 'service/actions/channels';
|
||||
import {closeDMChannel} from 'app/actions/views/channel';
|
||||
import {viewChannel} from 'service/actions/channels';
|
||||
import {getChannelsByCategory} from 'service/selectors/entities/channels';
|
||||
import {closeDMChannel, handleSelectChannel} from 'app/actions/views/channel';
|
||||
import {closeChannelDrawer} from 'app/actions/views/drawer';
|
||||
import {updateStorage} from 'app/actions/storage';
|
||||
import ChannelDrawer from './channel_drawer';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
|
|
@ -24,7 +25,8 @@ function mapStateToProps(state, ownProps) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
selectChannel,
|
||||
updateStorage,
|
||||
handleSelectChannel,
|
||||
viewChannel,
|
||||
closeDMChannel,
|
||||
closeChannelDrawer
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class Login extends Component {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.loginRequest.status === RequestStatus.STARTED && nextProps.loginRequest.status === RequestStatus.SUCCESS) {
|
||||
this.props.actions.saveStorage().then(this.props.actions.goToSelectTeam);
|
||||
this.props.actions.handleSuccessfulLogin().then(this.props.actions.goToSelectTeam);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {connect} from 'react-redux';
|
|||
|
||||
import {getClientConfig, getLicenseConfig} from 'service/actions/general';
|
||||
import LoginActions from 'app/actions/views/login';
|
||||
import * as StorageActions from 'app/actions/storage';
|
||||
import {updateRootStorage} from 'app/actions/storage';
|
||||
import {goToSelectTeam} from 'app/actions/navigation';
|
||||
import {login} from 'service/actions/users';
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
...LoginActions,
|
||||
...StorageActions,
|
||||
updateRootStorage,
|
||||
login,
|
||||
getClientConfig,
|
||||
getLicenseConfig,
|
||||
|
|
|
|||
|
|
@ -55,10 +55,7 @@ export default class SelectTeam extends Component {
|
|||
}
|
||||
|
||||
onSelectTeam(team) {
|
||||
this.props.actions.selectTeam(team).then(() => {
|
||||
this.props.actions.saveStorage({currentTeamId: team.id}).
|
||||
then(this.props.actions.goToChannelView());
|
||||
});
|
||||
this.props.actions.handleTeamChange(team).then(this.props.actions.goToChannelView);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {selectTeam} from 'service/actions/teams';
|
||||
import {handleTeamChange} from 'app/actions/views/select_team';
|
||||
import {init as websocket} from 'service/actions/websocket';
|
||||
import {saveStorage} from 'app/actions/storage';
|
||||
import {updateRootStorage, loadTeamStorage} from 'app/actions/storage';
|
||||
import {goToChannelView} from 'app/actions/navigation';
|
||||
import {getCurrentTeam} from 'service/selectors/entities/teams';
|
||||
|
||||
|
|
@ -26,8 +26,9 @@ function mapDispatchToProps(dispatch) {
|
|||
return {
|
||||
actions: bindActionCreators({
|
||||
goToChannelView,
|
||||
saveStorage,
|
||||
selectTeam,
|
||||
updateRootStorage,
|
||||
loadTeamStorage,
|
||||
handleTeamChange,
|
||||
websocket
|
||||
}, dispatch)
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue