From ddcf85c672e948aac337a043c99c6608487253d0 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Tue, 9 Jun 2020 16:47:12 -0400 Subject: [PATCH] Updated user lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Updated: - user lists - follow_requests, followers, following, mutes, blocks --- app/javascript/gabsocial/actions/accounts.js | 23 ++--- app/javascript/gabsocial/actions/blocks.js | 87 +++++++++---------- app/javascript/gabsocial/actions/groups.js | 12 ++- app/javascript/gabsocial/actions/mutes.js | 7 +- .../gabsocial/features/blocked_accounts.js | 63 +++++++++----- .../gabsocial/features/follow_requests.js | 6 +- .../gabsocial/features/followers.js | 2 +- .../gabsocial/features/following.js | 2 +- app/javascript/gabsocial/features/mutes.js | 67 +++++++++----- .../gabsocial/reducers/user_lists.js | 57 ++++++++---- 10 files changed, 190 insertions(+), 136 deletions(-) diff --git a/app/javascript/gabsocial/actions/accounts.js b/app/javascript/gabsocial/actions/accounts.js index 4f2d70bb..8742073b 100644 --- a/app/javascript/gabsocial/actions/accounts.js +++ b/app/javascript/gabsocial/actions/accounts.js @@ -441,10 +441,9 @@ export function expandFollowers(id) { if (!me) return; const url = getState().getIn(['user_lists', 'followers', id, 'next']); + const isLoading = getState().getIn(['user_lists', 'followers', id, 'isLoading']); - if (url === null) { - return; - } + if (url === null || isLoading) return dispatch(expandFollowersRequest(id)); @@ -454,7 +453,8 @@ export function expandFollowers(id) { dispatch(importFetchedAccounts(response.data)); dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null)); dispatch(fetchRelationships(response.data.map(item => item.id))); - }).catch(error => { + }).catch((error) => { + console.log("error:", error) dispatch(expandFollowersFail(id, error)); }); }; @@ -531,10 +531,9 @@ export function expandFollowing(id) { if (!me) return; const url = getState().getIn(['user_lists', 'following', id, 'next']); + const isLoading = getState().getIn(['user_lists', 'following', id, 'isLoading']); - if (url === null) { - return; - } + if (url === null || isLoading) return dispatch(expandFollowingRequest(id)); @@ -583,6 +582,9 @@ export function fetchRelationships(accountIds) { if (newAccountIds.length === 0) { return; + } else if (newAccountIds.length == 1) { + const firstId = newAccountIds[0] + if (me === firstId) return; } dispatch(fetchRelationshipsRequest(newAccountIds)); @@ -658,11 +660,10 @@ export function expandFollowRequests() { return (dispatch, getState) => { if (!me) return; - const url = getState().getIn(['user_lists', 'follow_requests', 'next']); + const url = getState().getIn(['user_lists', 'follow_requests', me, 'next']); + const isLoading = getState().getIn(['user_lists', 'follow_requests', me, 'isLoading']); - if (url === null) { - return; - } + if (url === null || isLoading) return dispatch(expandFollowRequestsRequest()); diff --git a/app/javascript/gabsocial/actions/blocks.js b/app/javascript/gabsocial/actions/blocks.js index 6a055753..f241eef7 100644 --- a/app/javascript/gabsocial/actions/blocks.js +++ b/app/javascript/gabsocial/actions/blocks.js @@ -1,90 +1,89 @@ -import api, { getLinks } from '../api'; -import { fetchRelationships } from './accounts'; -import { importFetchedAccounts } from './importer'; -import { me } from '../initial_state'; +import api, { getLinks } from '../api' +import { fetchRelationships } from './accounts' +import { importFetchedAccounts } from './importer' +import { me } from '../initial_state' -export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST'; -export const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS'; -export const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL'; +export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST' +export const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS' +export const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL' -export const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST'; -export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS'; -export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL'; +export const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST' +export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS' +export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL' export function fetchBlocks() { return (dispatch, getState) => { - if (!me) return; + if (!me) return - dispatch(fetchBlocksRequest()); + dispatch(fetchBlocksRequest()) api(getState).get('/api/v1/blocks').then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null)); - dispatch(fetchRelationships(response.data.map(item => item.id))); - }).catch(error => dispatch(fetchBlocksFail(error))); - }; -}; + const next = getLinks(response).refs.find(link => link.rel === 'next') + dispatch(importFetchedAccounts(response.data)) + dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null)) + dispatch(fetchRelationships(response.data.map(item => item.id))) + }).catch(error => dispatch(fetchBlocksFail(error))) + } +} export function fetchBlocksRequest() { return { type: BLOCKS_FETCH_REQUEST, - }; -}; + } +} export function fetchBlocksSuccess(accounts, next) { return { type: BLOCKS_FETCH_SUCCESS, accounts, next, - }; -}; + } +} export function fetchBlocksFail(error) { return { type: BLOCKS_FETCH_FAIL, error, - }; -}; + } +} export function expandBlocks() { return (dispatch, getState) => { - if (!me) return; + if (!me) return - const url = getState().getIn(['user_lists', 'blocks', 'next']); + const url = getState().getIn(['user_lists', 'blocks', me, 'next']) + const isLoading = getState().getIn(['user_lists', 'blocks', me, 'isLoading']) - if (url === null) { - return; - } + if (url === null || isLoading) return - dispatch(expandBlocksRequest()); + dispatch(expandBlocksRequest()) api(getState).get(url).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(expandBlocksSuccess(response.data, next ? next.uri : null)); - dispatch(fetchRelationships(response.data.map(item => item.id))); - }).catch(error => dispatch(expandBlocksFail(error))); - }; -}; + const next = getLinks(response).refs.find(link => link.rel === 'next') + dispatch(importFetchedAccounts(response.data)) + dispatch(expandBlocksSuccess(response.data, next ? next.uri : null)) + dispatch(fetchRelationships(response.data.map(item => item.id))) + }).catch(error => dispatch(expandBlocksFail(error))) + } +} export function expandBlocksRequest() { return { type: BLOCKS_EXPAND_REQUEST, - }; -}; + } +} export function expandBlocksSuccess(accounts, next) { return { type: BLOCKS_EXPAND_SUCCESS, accounts, next, - }; -}; + } +} export function expandBlocksFail(error) { return { type: BLOCKS_EXPAND_FAIL, error, - }; -}; + } +} diff --git a/app/javascript/gabsocial/actions/groups.js b/app/javascript/gabsocial/actions/groups.js index e7068681..8855d2f7 100644 --- a/app/javascript/gabsocial/actions/groups.js +++ b/app/javascript/gabsocial/actions/groups.js @@ -284,11 +284,10 @@ export function expandMembers(id) { return (dispatch, getState) => { if (!me) return; - const url = getState().getIn(['user_lists', 'groups', id, 'next']); + const url = getState().getIn(['user_lists', 'groups', id, 'next']) + const isLoading = getState().getIn(['user_lists', 'groups', id, 'isLoading']) - if (url === null) { - return; - } + if (url === null || isLoading) return dispatch(expandMembersRequest(id)); @@ -375,10 +374,9 @@ export function expandRemovedAccounts(id) { if (!me) return; const url = getState().getIn(['user_lists', 'groups_removed_accounts', id, 'next']); + const isLoading = getState().getIn(['user_lists', 'groups_removed_accounts', id, 'isLoading']) - if (url === null) { - return; - } + if (url === null || isLoading) return dispatch(expandRemovedAccountsRequest(id)); diff --git a/app/javascript/gabsocial/actions/mutes.js b/app/javascript/gabsocial/actions/mutes.js index e02a37a7..31276a77 100644 --- a/app/javascript/gabsocial/actions/mutes.js +++ b/app/javascript/gabsocial/actions/mutes.js @@ -54,11 +54,10 @@ export function expandMutes() { return (dispatch, getState) => { if (!me) return; - const url = getState().getIn(['user_lists', 'mutes', 'next']); + const url = getState().getIn(['user_lists', 'mutes', me, 'next']); + const isLoading = getState().getIn(['user_lists', 'mutes', me, 'isLoading']); - if (url === null) { - return; - } + if (url === null || isLoading) return dispatch(expandMutesRequest()); diff --git a/app/javascript/gabsocial/features/blocked_accounts.js b/app/javascript/gabsocial/features/blocked_accounts.js index ee31ea69..a9ef3a8f 100644 --- a/app/javascript/gabsocial/features/blocked_accounts.js +++ b/app/javascript/gabsocial/features/blocked_accounts.js @@ -2,8 +2,10 @@ import { defineMessages, injectIntl } from 'react-intl' import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePropTypes from 'react-immutable-proptypes' import debounce from 'lodash.debounce' +import { me } from '../initial_state' import { fetchBlocks, expandBlocks } from '../actions/blocks' import Account from '../components/account' +import Block from '../components/block' import ScrollableList from '../components/scrollable_list' const messages = defineMessages({ @@ -11,31 +13,40 @@ const messages = defineMessages({ }) const mapStateToProps = (state) => ({ - accountIds: state.getIn(['user_lists', 'blocks', 'items']), - hasMore: !!state.getIn(['user_lists', 'blocks', 'next']), - isLoading: state.getIn(['user_lists', 'blocks', 'isLoading'], true), + accountIds: state.getIn(['user_lists', 'blocks', me, 'items']), + hasMore: !!state.getIn(['user_lists', 'blocks', me, 'next']), + isLoading: state.getIn(['user_lists', 'blocks', me, 'isLoading']), +}) + +const mapDispatchToProps = (dispatch) => ({ + onFetchBlocks() { + dispatch(fetchBlocks()) + }, + onExpandBlocks() { + dispatch(expandBlocks()) + }, }) export default -@connect(mapStateToProps) +@connect(mapStateToProps, mapDispatchToProps) @injectIntl class Blocks extends ImmutablePureComponent { static propTypes = { - params: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, accountIds: ImmutablePropTypes.list, hasMore: PropTypes.bool, - isLoading: PropTypes.bool, intl: PropTypes.object.isRequired, + isLoading: PropTypes.bool, + onExpandBlocks: PropTypes.func.isRequired, + onFetchBlocks: PropTypes.func.isRequired, } - componentWillMount() { - this.props.dispatch(fetchBlocks()) + componentDidMount() { + this.props.onFetchBlocks() } handleLoadMore = debounce(() => { - this.props.dispatch(expandBlocks()) + this.props.onExpandBlocks() }, 300, { leading: true }) render() { @@ -49,19 +60,25 @@ class Blocks extends ImmutablePureComponent { const emptyMessage = intl.formatMessage(messages.empty) return ( - - { - !!accountIds && accountIds.map(id => - - ) - } - + + + { + !!accountIds && accountIds.map((id) => + + ) + } + + ) } diff --git a/app/javascript/gabsocial/features/follow_requests.js b/app/javascript/gabsocial/features/follow_requests.js index 07b40f97..cd57b627 100644 --- a/app/javascript/gabsocial/features/follow_requests.js +++ b/app/javascript/gabsocial/features/follow_requests.js @@ -10,9 +10,9 @@ import ScrollableList from '../components/scrollable_list' import Text from '../components/text' const mapStateToProps = (state) => ({ - accountIds: state.getIn(['user_lists', 'follow_requests', 'items']), - isLoading: state.getIn(['user_lists', 'follow_requests', 'isLoading'], true), - hasMore: !!state.getIn(['user_lists', 'follow_requests', 'next']), + accountIds: state.getIn(['user_lists', 'follow_requests', me, 'items']), + isLoading: state.getIn(['user_lists', 'follow_requests', me, 'isLoading']), + hasMore: !!state.getIn(['user_lists', 'follow_requests', me, 'next']), locked: !!state.getIn(['accounts', me, 'locked']), }) diff --git a/app/javascript/gabsocial/features/followers.js b/app/javascript/gabsocial/features/followers.js index a24c45ea..d6f1d19d 100644 --- a/app/javascript/gabsocial/features/followers.js +++ b/app/javascript/gabsocial/features/followers.js @@ -18,7 +18,7 @@ const mapStateToProps = (state, { account }) => { accountId, accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']), - isLoading: state.getIn(['user_lists', 'followers', accountId, 'isLoading'], true), + isLoading: state.getIn(['user_lists', 'followers', accountId, 'isLoading']), } } diff --git a/app/javascript/gabsocial/features/following.js b/app/javascript/gabsocial/features/following.js index aa0586bc..c3d305d5 100644 --- a/app/javascript/gabsocial/features/following.js +++ b/app/javascript/gabsocial/features/following.js @@ -18,7 +18,7 @@ const mapStateToProps = (state, { account }) => { accountId, accountIds: state.getIn(['user_lists', 'following', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']), - isLoading: state.getIn(['user_lists', 'following', accountId, 'isLoading'], true), + isLoading: state.getIn(['user_lists', 'following', accountId, 'isLoading']), } } diff --git a/app/javascript/gabsocial/features/mutes.js b/app/javascript/gabsocial/features/mutes.js index 8db82323..fdaf1d90 100644 --- a/app/javascript/gabsocial/features/mutes.js +++ b/app/javascript/gabsocial/features/mutes.js @@ -2,54 +2,75 @@ import { injectIntl, FormattedMessage } from 'react-intl' import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePropTypes from 'react-immutable-proptypes' import debounce from 'lodash.debounce' +import { me } from '../initial_state' import { fetchMutes, expandMutes } from '../actions/mutes' import Account from '../components/account' +import Block from '../components/block' import ScrollableList from '../components/scrollable_list' const mapStateToProps = (state) => ({ - accountIds: state.getIn(['user_lists', 'mutes', 'items']), - hasMore: !!state.getIn(['user_lists', 'mutes', 'next']), - isLoading: state.getIn(['user_lists', 'mutes', 'isLoading'], true), + accountIds: state.getIn(['user_lists', 'mutes', me, 'items']), + hasMore: !!state.getIn(['user_lists', 'mutes', me, 'next']), + isLoading: state.getIn(['user_lists', 'mutes', me, 'isLoading']), +}) + +const mapDispatchToProps = (dispatch) => ({ + onFetchMutes() { + dispatch(fetchMutes()) + }, + onExpandMutes() { + dispatch(expandMutes()) + }, }) export default -@connect(mapStateToProps) +@connect(mapStateToProps, mapDispatchToProps) @injectIntl class Mutes extends ImmutablePureComponent { static propTypes = { - params: PropTypes.object.isRequired, - dispatch: PropTypes.func.isRequired, - hasMore: PropTypes.bool, accountIds: ImmutablePropTypes.list, + hasMore: PropTypes.bool, isLoading: PropTypes.bool, + onExpandMutes: PropTypes.func.isRequired, + onFetchMutes: PropTypes.func.isRequired, } componentWillMount() { - this.props.dispatch(fetchMutes()) + this.props.onFetchMutes() } handleLoadMore = debounce(() => { - this.props.dispatch(expandMutes()) + this.props.onExpandMutes() }, 300, { leading: true }) render() { - const { hasMore, accountIds, isLoading } = this.props + const { + accountIds, + hasMore, + isLoading, + } = this.props return ( - } - > - { - accountIds && accountIds.map(id => - - ) - } - + + } + > + { + !!accountIds && accountIds.map((id) => + + ) + } + + ) } diff --git a/app/javascript/gabsocial/reducers/user_lists.js b/app/javascript/gabsocial/reducers/user_lists.js index dc47bffe..83dc4f6a 100644 --- a/app/javascript/gabsocial/reducers/user_lists.js +++ b/app/javascript/gabsocial/reducers/user_lists.js @@ -1,4 +1,5 @@ import { Map as ImmutableMap, List as ImmutableList } from 'immutable' +import { me } from '../initial_state' import { FOLLOWERS_FETCH_REQUEST, FOLLOWERS_FETCH_SUCCESS, @@ -61,27 +62,36 @@ const initialState = ImmutableMap({ groups_removed_accounts: ImmutableMap(), }); +const setListFailed = (state, type, id) => { + return state.setIn([type, id], ImmutableMap({ + next: null, + items: ImmutableList(), + isLoading: false, + })) +} + const normalizeList = (state, type, id, accounts, next) => { return state.setIn([type, id], ImmutableMap({ next, items: ImmutableList(accounts.map(item => item.id)), isLoading: false, - })); -}; + })) +} const appendToList = (state, type, id, accounts, next) => { - return state.updateIn([type, id], map => { + return state.updateIn([type, id], (map) => { return map .set('next', next) .set('isLoading', false) .update('items', (list) => { - list.concat(accounts.map(item => item.id)) + return list.concat(accounts.map(item => item.id)) }) - }); -}; + }) +} export default function userLists(state = initialState, action) { switch(action.type) { + case FOLLOWERS_FETCH_SUCCESS: return normalizeList(state, 'followers', action.id, action.accounts, action.next); case FOLLOWERS_EXPAND_SUCCESS: @@ -91,7 +101,8 @@ export default function userLists(state = initialState, action) { return state.setIn(['followers', action.id, 'isLoading'], true); case FOLLOWERS_FETCH_FAIL: case FOLLOWERS_EXPAND_FAIL: - return state.setIn(['followers', action.id, 'isLoading'], false); + return setListFailed(state, 'followers', action.id) + case FOLLOWING_FETCH_SUCCESS: return normalizeList(state, 'following', action.id, action.accounts, action.next); case FOLLOWING_EXPAND_SUCCESS: @@ -102,10 +113,13 @@ export default function userLists(state = initialState, action) { case FOLLOWING_FETCH_FAIL: case FOLLOWING_EXPAND_FAIL: return state.setIn(['following', action.id, 'isLoading'], false); + case REPOSTS_FETCH_SUCCESS: return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id))); + case LIKES_FETCH_SUCCESS: return state.setIn(['liked_by', action.id], ImmutableList(action.accounts.map(item => item.id))); + case FOLLOW_REQUESTS_FETCH_SUCCESS: return state.setIn(['follow_requests', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next).setIn(['follow_requests', 'isLoading'], false); case FOLLOW_REQUESTS_EXPAND_SUCCESS: @@ -119,36 +133,41 @@ export default function userLists(state = initialState, action) { case FOLLOW_REQUEST_AUTHORIZE_SUCCESS: case FOLLOW_REQUEST_REJECT_SUCCESS: return state.updateIn(['follow_requests', 'items'], list => list.filterNot(item => item === action.id)); - case BLOCKS_FETCH_SUCCESS: - return state.setIn(['blocks', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['blocks', 'next'], action.next); - case BLOCKS_EXPAND_SUCCESS: - return state.updateIn(['blocks', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['blocks', 'next'], action.next); + case BLOCKS_FETCH_REQUEST: case BLOCKS_EXPAND_REQUEST: - return state.setIn(['blocks', 'isLoading'], true); + return state.setIn(['blocks', me, 'isLoading'], true) + case BLOCKS_FETCH_SUCCESS: + return normalizeList(state, 'blocks', me, action.accounts, action.next) + case BLOCKS_EXPAND_SUCCESS: + return appendToList(state, 'blocks', me, action.accounts, action.next) case BLOCKS_FETCH_FAIL: case BLOCKS_EXPAND_FAIL: - return state.setIn(['blocks', 'isLoading'], false); - case MUTES_FETCH_SUCCESS: - return state.setIn(['mutes', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next); - case MUTES_EXPAND_SUCCESS: - return state.updateIn(['mutes', 'items'], list => list.concat(action.accounts.map(item => item.id))).setIn(['mutes', 'next'], action.next); + return setListFailed(state, 'blocks', me) + case MUTES_FETCH_REQUEST: case MUTES_EXPAND_REQUEST: - return state.setIn(['mutes', 'isLoading'], true); + return state.setIn(['mutes', me, 'isLoading'], true) + case MUTES_FETCH_SUCCESS: + return normalizeList(state, 'mutes', me, action.accounts, action.next) + case MUTES_EXPAND_SUCCESS: + return appendToList(state, 'mutes', me, action.accounts, action.next) case MUTES_FETCH_FAIL: case MUTES_EXPAND_FAIL: - return state.setIn(['mutes', 'isLoading'], false); + return setListFailed(state, 'mutes', me) + case GROUP_MEMBERS_FETCH_SUCCESS: return normalizeList(state, 'groups', action.id, action.accounts, action.next); case GROUP_MEMBERS_EXPAND_SUCCESS: return appendToList(state, 'groups', action.id, action.accounts, action.next); + case GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS: return normalizeList(state, 'groups_removed_accounts', action.id, action.accounts, action.next); case GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS: return appendToList(state, 'groups_removed_accounts', action.id, action.accounts, action.next); case GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS: return state.updateIn(['groups_removed_accounts', action.groupId, 'items'], list => list.filterNot(item => item === action.id)); + default: return state; }