Normalized data in Redux, fix for asset URLs when rendered outside request

This commit is contained in:
Eugen Rochko
2016-09-04 14:04:26 +02:00
parent 7939a216ff
commit 1022d682dc
9 changed files with 71 additions and 27 deletions

View File

@ -7,9 +7,15 @@ const DisplayName = React.createClass({
},
render () {
let displayName = this.props.account.get('display_name');
if (displayName.length === 0) {
displayName = this.props.account.get('username');
}
return (
<span style={{ display: 'block', maxWidth: '100%', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
<strong style={{ fontWeight: 'bold' }}>{this.props.account.get('display_name')}</strong> <span style={{ fontSize: '14px' }}>@{this.props.account.get('acct')}</span>
<strong style={{ fontWeight: 'bold' }}>{displayName}</strong> <span style={{ fontSize: '14px' }}>@{this.props.account.get('acct')}</span>
</span>
);
}

View File

@ -3,9 +3,21 @@ import StatusList from '../components/status_list';
import { replyCompose } from '../actions/compose';
import { reblog, favourite } from '../actions/interactions';
function selectStatus(state, id) {
let status = state.getIn(['timelines', 'statuses', id]);
status = status.set('account', state.getIn(['timelines', 'accounts', status.get('account')]));
if (status.get('reblog') !== null) {
status = status.set('reblog', selectStatus(state, status.get('reblog')));
}
return status;
};
const mapStateToProps = function (state, props) {
return {
statuses: state.getIn(['timelines', props.type])
statuses: state.getIn(['timelines', props.type]).map(id => selectStatus(state, id))
};
};

View File

@ -2,31 +2,57 @@ import { TIMELINE_SET, TIMELINE_UPDATE } from '../actions/timelines';
import { REBLOG_SUCCESS, FAVOURITE_SUCCESS } from '../actions/interactions';
import Immutable from 'immutable';
const initialState = Immutable.Map();
const initialState = Immutable.Map({
home: Immutable.List(),
mentions: Immutable.List(),
statuses: Immutable.Map(),
accounts: Immutable.Map()
});
function updateMatchingStatuses(state, needle, callback) {
return state.map(function (list) {
return list.map(function (status) {
if (status.get('id') === needle.get('id')) {
return callback(status);
} else if (status.getIn(['reblog', 'id'], null) === needle.get('id')) {
return status.set('reblog', callback(status.get('reblog')));
}
function statusToMaps(state, status) {
// Separate account
let account = status.get('account');
status = status.set('account', account.get('id'));
return status;
});
// Separate reblog, repeat for reblog
let reblog = status.get('reblog');
if (reblog !== null) {
status = status.set('reblog', reblog.get('id'));
state = statusToMaps(state, reblog);
}
return state.withMutations(map => {
map.setIn(['accounts', account.get('id')], account);
map.setIn(['statuses', status.get('id')], status);
});
};
function timelineToMaps(state, timeline, statuses) {
statuses.forEach((status, i) => {
state = statusToMaps(state, status);
state = state.setIn([timeline, i], status.get('id'));
});
return state;
};
function updateTimelineWithMaps(state, timeline, status) {
state = statusToMaps(state, status);
state = state.update(timeline, list => list.unshift(status.get('id')));
return state;
};
export default function timelines(state = initialState, action) {
switch(action.type) {
case TIMELINE_SET:
return state.set(action.timeline, Immutable.fromJS(action.statuses));
return timelineToMaps(state, action.timeline, Immutable.fromJS(action.statuses));
case TIMELINE_UPDATE:
return state.update(action.timeline, list => list.unshift(Immutable.fromJS(action.status)));
return updateTimelineWithMaps(state, action.timeline,Immutable.fromJS(action.status));
case REBLOG_SUCCESS:
case FAVOURITE_SUCCESS:
return updateMatchingStatuses(state, action.status, () => Immutable.fromJS(action.response));
return statusToMaps(state, Immutable.fromJS(action.response));
default:
return state;
}