sectionReducer.js 6.3 KB
/**
 * # guideReducer.js
 *
 * The reducer for all the actions from the various log states
 */
'use strict';
/**
 * ## Imports
 *
 * InitialState
 */
import InitialState from './sectionInitialState';
import Immutable, {Map, List} from 'immutable';

const {
	SECTION_HEADER_REQUEST,
    SECTION_HEADER_SUCCESS,
    SECTION_HEADER_FAILURE,

    SECTION_NEW_POST_REQUEST,
    SECTION_NEW_POST_SUCCESS,
    SECTION_NEW_POST_FAILURE,

    SECTION_HOT_POST_REQUEST,
    SECTION_HOT_POST_SUCCESS,
    SECTION_HOT_POST_FAILURE,

	SECTION_SET_ACTIVE_TAB,
	SECTION_CLEAN,
	GO_TO_SECTION,

	POST_LIKE_REQUEST,
    POST_UNLIKE_REQUEST,
} = require('../../constants/actionTypes').default;

const initialState = new InitialState;

/**
 * ## guideReducer function
 * @param {Object} state - initialState
 * @param {Object} action - type and payload
 */
export default function sectionReducer(state = initialState, action) {
    if (!(state instanceof InitialState)) return initialState.merge(state);

    switch (action.type) {

		case GO_TO_SECTION: {

			let currentSid = state.sid;
			let newItems = state.items;
			let newSid = currentSid;
			// componentWillUnmount未调用,导致clean操作未进行
			if (currentSid == -1) {
                newItems = List();
            }
			
			if (action.payload.tryToClean && currentSid > -1 && !state.cleaned) {
				newItems = newItems.pop();
				newSid = newSid - 1;
			}

			let sid = newSid + 1;
			// 获取新的初始状态item
			let item = initialState.item;
			// 设置item的value
			item = item.set('id', action.payload.id)
				.set('name', action.payload.name);
			// items新增item
			let items = newItems.push(item);
			let nextState =  state.set('sid', sid)
				.set('items', items)
				.set('cleaned', false);
			return nextState;
		}

		case SECTION_HEADER_REQUEST: {
			let sid = action.payload;
			let nextState =  state.setIn(['items', sid, 'isFetching'], true)
				.setIn(['items', sid, 'error'], null)
				.setIn(['items', sid, 'ptr'], true);
			return nextState;
		}

		case SECTION_HEADER_SUCCESS: {
			let {sid, json} = action.payload;
			let {notice, header} = json;
			let item = state.items.get(sid);
			item = item.set('isFetching', false)
				.set('error', null)
				.set('ptr', false)
				.setIn(['header', 'uri'], header.uri)
				.setIn(['header', 'title'], header.title)
				.setIn(['header', 'desc'], header.desc)
				.setIn(['header', 'post'], header.post)
				.setIn(['header', 'comment'], header.comment)
				.setIn(['header', 'like'], header.like)
				.setIn(['notice', 'duration'], notice.duration)
				.setIn(['notice', 'open'], notice.open)
				.setIn(['notice', 'list'], Immutable.fromJS(notice.list));
			let nextState = state.setIn(['items', sid], item);
			return nextState;
		}

		case SECTION_HEADER_FAILURE: {
			let {sid, error} = action.payload;
			let nextState =  state.setIn(['items', sid, 'isFetching'], false)
				.setIn(['items', sid, 'error'], error)
				.setIn(['items', sid, 'ptr'], false);
			return nextState;
		}

		case SECTION_HOT_POST_REQUEST: {
			let {sid, ptr} = action.payload;
			let nextState =  state.setIn(['items', sid, 'hot', 'isFetching'], true)
				.setIn(['items', sid, 'hot', 'error'], null);
			return nextState;
		}

		case SECTION_HOT_POST_SUCCESS: {
			let {sid, json} = action.payload;
			let {lastedTime, list, endReached} = json;
			let item = state.items.get(sid);
			item = item.setIn(['hot', 'isFetching'], false)
				.setIn(['hot', 'error'], null)
				.setIn(['hot', 'lastedTime'], lastedTime)
				.setIn(['hot', 'endReached'], endReached)
				.setIn(['hot', 'list'], Immutable.fromJS(list));
			let nextState = state.setIn(['items', sid], item);
			return nextState;
		}

		case SECTION_HOT_POST_FAILURE: {
			let {sid, error} = action.payload;
			let nextState =  state.setIn(['items', sid, 'hot', 'isFetching'], false)
				.setIn(['items', sid, 'hot', 'error'], error);
			return nextState;
		}

		case SECTION_NEW_POST_REQUEST: {
			let {sid, ptr} = action.payload;
			let nextState =  state.setIn(['items', sid, 'new', 'isFetching'], true)
				.setIn(['items', sid, 'new', 'error'], null);
			return nextState;
		}

		case SECTION_NEW_POST_SUCCESS: {
			let {sid, json} = action.payload;
			let {lastedTime, list, endReached} = json;
			let item = state.items.get(sid);
			item = item.setIn(['new', 'isFetching'], false)
				.setIn(['new', 'error'], null)
				.setIn(['new', 'lastedTime'], lastedTime)
				.setIn(['new', 'endReached'], endReached)
				.setIn(['new', 'list'], Immutable.fromJS(list));
			let nextState = state.setIn(['items', sid], item);
			return nextState;
		}

		case SECTION_NEW_POST_FAILURE: {
			let {sid, error} = action.payload;
			let nextState =  state.setIn(['items', sid, 'new', 'isFetching'], false)
				.setIn(['items', sid, 'new', 'error'], error);
			return nextState;
		}

		case SECTION_SET_ACTIVE_TAB: {
			let {sid, tab} = action.payload;
			let item = state.items.get(sid);
			if (item) {
				item = item.set('activeTab', tab);
				let nextState =  state.setIn(['items', sid], item);
				return nextState;
			}
		}

		case POST_LIKE_REQUEST: {
			return sectionNewLikeState(state, action.payload, true);
		}

		case POST_UNLIKE_REQUEST: {
			return sectionNewLikeState(state, action.payload, false);
		}

		case SECTION_CLEAN: {
			let sid = action.payload;
			if (state.items.size > sid) {
				let items = state.items.pop();
				let nextState =  state.set('sid', sid - 1)
					.set('items', items)
					.set('cleaned', true);
				return nextState;
			}
			return state;
		}
    }

    return state;
}

function sectionNewLikeState(state, postId, like) {

	let likeState = (list, postId, like) => {
		let index = list.findIndex((item) => {
			return item.get('id') == postId;
		})
		if (index == -1) {
			return list;
		}

		let likeCount = 0;
		if (like) {
			likeCount = list.get(index).get('likeCount') + 1;
		} else {
			likeCount = list.get(index).get('likeCount') - 1;
			likeCount = likeCount < 0 ? 0 : likeCount;
		}

		let nextList =  list.setIn([index, 'isLike'], like)
			.setIn([index, 'likeCount'], likeCount);
		return nextList;
	};

	let nextState = state;
	state.items.map((item, i) => {
		let hotList = likeState(item.hot.list, postId, like);
		let newList = likeState(item.new.list, postId, like);

		item = item.setIn(['hot', 'list'], hotList)
			.setIn(['new', 'list'], newList);
		nextState = nextState.setIn(['items', i], item);
	});

	return nextState;
}