Updated user lists

• Updated:
- user lists
- follow_requests, followers, following, mutes, blocks
This commit is contained in:
mgabdev 2020-06-09 16:47:12 -04:00
parent 26829507fc
commit ddcf85c672
10 changed files with 190 additions and 136 deletions

View File

@ -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());

View File

@ -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,
};
};
}
}

View File

@ -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));

View File

@ -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());

View File

@ -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 (
<ScrollableList
scrollKey='blocks'
onLoadMore={this.handleLoadMore}
hasMore={hasMore}
emptyMessage={emptyMessage}
isLoading={isLoading}
>
{
!!accountIds && accountIds.map(id =>
<Account key={`blocked-${id}`} id={id} compact />
)
}
</ScrollableList>
<Block>
<ScrollableList
scrollKey='blocked_accounts'
onLoadMore={this.handleLoadMore}
hasMore={hasMore}
isLoading={isLoading}
emptyMessage={emptyMessage}
>
{
!!accountIds && accountIds.map((id) =>
<Account
key={`blocked-accounts-${id}`}
id={id}
compact
/>
)
}
</ScrollableList>
</Block>
)
}

View File

@ -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']),
})

View File

@ -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']),
}
}

View File

@ -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']),
}
}

View File

@ -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 (
<ScrollableList
scrollKey='mutes'
onLoadMore={this.handleLoadMore}
hasMore={hasMore}
isLoading={isLoading}
emptyMessage={<FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />}
>
{
accountIds && accountIds.map(id =>
<Account key={`mutes-${id}`} id={id} compact />
)
}
</ScrollableList>
<Block>
<ScrollableList
scrollKey='mutes'
onLoadMore={this.handleLoadMore}
hasMore={hasMore}
isLoading={isLoading}
emptyMessage={<FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />}
>
{
!!accountIds && accountIds.map((id) =>
<Account
key={`mutes-${id}`}
id={id}
compact
/>
)
}
</ScrollableList>
</Block>
)
}

View File

@ -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;
}