Add fetch for emoji-reacted accounts

This commit is contained in:
noellabo 2021-09-13 01:26:16 +09:00
parent eb941f5b01
commit d10dd36386
11 changed files with 148 additions and 33 deletions

View file

@ -96,7 +96,7 @@ class Api::V1::AccountsController < Api::BaseController
end end
def account_ids def account_ids
Array(params[:id]).map(&:to_i) Array(params[:id]).uniq.map(&:to_i)
end end
def account_params def account_params

View file

@ -8,13 +8,18 @@ class Api::V1::Statuses::EmojiReactionsController < Api::BaseController
before_action :set_status before_action :set_status
def update def update
EmojiReactionService.new.call(current_account, @status, params[:id]) if EmojiReactionService.new.call(current_account, @status, params[:id]).present?
@status = Status.include_expired.find(params[:status_id])
end
render json: @status, serializer: REST::StatusSerializer render json: @status, serializer: REST::StatusSerializer
end end
def destroy def destroy
#UnEmojiReactionWorker.perform_async(current_account.id, @status.id) #UnEmojiReactionWorker.perform_async(current_account.id, @status.id)
UnEmojiReactionService.new.call(current_account, @status) if UnEmojiReactionService.new.call(current_account, @status).present?
@status = Status.include_expired.find(params[:status_id])
end
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, emoji_reactions_map: { @status.id => false }) render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, emoji_reactions_map: { @status.id => false })
end end

View file

@ -1,10 +1,15 @@
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import { importFetchedAccount, importFetchedAccounts } from './importer'; import { importFetchedAccount, importFetchedAccounts } from './importer';
import { uniq } from '../utils/uniq';
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST'; export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS'; export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';
export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL'; export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL';
export const ACCOUNTS_FETCH_REQUEST = 'ACCOUNTS_FETCH_REQUEST';
export const ACCOUNTS_FETCH_SUCCESS = 'ACCOUNTS_FETCH_SUCCESS';
export const ACCOUNTS_FETCH_FAIL = 'ACCOUNTS_FETCH_FAIL';
export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST'; export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST';
export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS'; export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS';
export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL'; export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL';
@ -125,6 +130,65 @@ export function fetchAccountFail(id, error) {
}; };
}; };
export function fetchAccountsFromStatus(status) {
return fetchAccountsFromStatuses([status]);
};
export function fetchAccountsFromStatuses(statuses) {
return fetchAccounts(
uniq(
statuses
.flatMap(item => item.emoji_reactions)
.flatMap(emoji_reaction => emoji_reaction.account_ids)
)
);
};
export function fetchAccounts(accountIds) {
return (dispatch, getState) => {
dispatch(fetchRelationships(accountIds));
const loadedAccounts = getState().get('accounts', new Map());
const newAccountIds = Array.from(new Set(accountIds)).filter(id => loadedAccounts.get(id, null) === null);
if (newAccountIds.length === 0) {
return;
}
dispatch(fetchAccountsRequest(accountIds));
api(getState).get(`/api/v1/accounts?${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
dispatch(importFetchedAccounts(response.data));
dispatch(fetchAccountsSuccess());
}).catch(error => {
dispatch(fetchAccountsFail(accountIds, error));
});
};
};
export function fetchAccountsRequest(accountIds) {
return {
type: ACCOUNTS_FETCH_REQUEST,
accountIds,
};
};
export function fetchAccountsSuccess() {
return {
type: ACCOUNTS_FETCH_SUCCESS,
};
};
export function fetchAccountsFail(accountIds, error) {
return {
type: ACCOUNTS_FETCH_FAIL,
accountIds,
error,
skipAlert: true,
skipNotFound: true,
};
};
export function followAccount(id, options = { reblogs: true, delivery: true }) { export function followAccount(id, options = { reblogs: true, delivery: true }) {
return (dispatch, getState) => { return (dispatch, getState) => {
const alreadyFollowing = getState().getIn(['relationships', id, 'following']); const alreadyFollowing = getState().getIn(['relationships', id, 'following']);
@ -681,6 +745,24 @@ export function expandSubscribeFail(id, error) {
}; };
}; };
export function fetchRelationshipsFromStatus(status) {
return fetchRelationshipsFromStatuses([status]);
};
export function fetchRelationshipsFromStatuses(statuses) {
return fetchRelationships(
uniq(
statuses
.map(status => status.reblog ? status.reblog.account.id : status.account.id)
.concat(
statuses
.map(status => status.quote ? status.quote.account.id : null)
)
.filter(e => !!e)
)
);
};
export function fetchRelationships(accountIds) { export function fetchRelationships(accountIds) {
return (dispatch, getState) => { return (dispatch, getState) => {
const loadedRelationships = getState().get('relationships'); const loadedRelationships = getState().get('relationships');

View file

@ -1,4 +1,4 @@
import { fetchRelationships } from './accounts'; import { fetchRelationshipsFromStatuses, fetchAccountsFromStatuses } from './accounts';
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import { importFetchedStatuses } from './importer'; import { importFetchedStatuses } from './importer';
import { uniq } from '../utils/uniq'; import { uniq } from '../utils/uniq';
@ -21,9 +21,11 @@ export function fetchBookmarkedStatuses() {
api(getState).get('/api/v1/bookmarks').then(response => { api(getState).get('/api/v1/bookmarks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id)))); dispatch(importFetchedStatuses(statuses));
dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(fetchBookmarkedStatusesSuccess(statuses, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(fetchBookmarkedStatusesFail(error)); dispatch(fetchBookmarkedStatusesFail(error));
}); });
@ -63,9 +65,11 @@ export function expandBookmarkedStatuses() {
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id)))); dispatch(importFetchedStatuses(statuses));
dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(expandBookmarkedStatusesSuccess(statuses, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(expandBookmarkedStatusesFail(error)); dispatch(expandBookmarkedStatusesFail(error));
}); });

View file

@ -1,4 +1,4 @@
import { fetchRelationships } from './accounts'; import { fetchRelationshipsFromStatuses, fetchAccountsFromStatuses } from './accounts';
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import { importFetchedStatuses } from './importer'; import { importFetchedStatuses } from './importer';
import { uniq } from '../utils/uniq'; import { uniq } from '../utils/uniq';
@ -21,9 +21,11 @@ export function fetchEmojiReactionedStatuses() {
api(getState).get('/api/v1/emoji_reactions').then(response => { api(getState).get('/api/v1/emoji_reactions').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id)))); dispatch(importFetchedStatuses(statuses));
dispatch(fetchEmojiReactionedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(fetchEmojiReactionedStatusesSuccess(statuses, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(fetchEmojiReactionedStatusesFail(error)); dispatch(fetchEmojiReactionedStatusesFail(error));
}); });
@ -63,9 +65,11 @@ export function expandEmojiReactionedStatuses() {
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id)))); dispatch(importFetchedStatuses(statuses));
dispatch(expandEmojiReactionedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(expandEmojiReactionedStatusesSuccess(statuses, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(expandEmojiReactionedStatusesFail(error)); dispatch(expandEmojiReactionedStatusesFail(error));
}); });

View file

@ -1,4 +1,4 @@
import { fetchRelationships } from './accounts'; import { fetchRelationshipsFromStatuses, fetchAccountsFromStatuses } from './accounts';
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import { importFetchedStatuses } from './importer'; import { importFetchedStatuses } from './importer';
import { uniq } from '../utils/uniq'; import { uniq } from '../utils/uniq';
@ -21,9 +21,11 @@ export function fetchFavouritedStatuses() {
api(getState).get('/api/v1/favourites').then(response => { api(getState).get('/api/v1/favourites').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id)))); dispatch(importFetchedStatuses(statuses));
dispatch(fetchFavouritedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(fetchFavouritedStatusesSuccess(statuses, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(fetchFavouritedStatusesFail(error)); dispatch(fetchFavouritedStatusesFail(error));
}); });
@ -66,9 +68,11 @@ export function expandFavouritedStatuses() {
api(getState).get(url).then(response => { api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id)))); dispatch(importFetchedStatuses(statuses));
dispatch(expandFavouritedStatusesSuccess(response.data, next ? next.uri : null)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(expandFavouritedStatusesSuccess(statuses, next ? next.uri : null));
}).catch(error => { }).catch(error => {
dispatch(expandFavouritedStatusesFail(error)); dispatch(expandFavouritedStatusesFail(error));
}); });

View file

@ -1,6 +1,6 @@
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import IntlMessageFormat from 'intl-messageformat'; import IntlMessageFormat from 'intl-messageformat';
import { fetchRelationships } from './accounts'; import { fetchRelationships, fetchAccounts, fetchAccountsFromStatuses } from './accounts';
import { import {
importFetchedAccount, importFetchedAccount,
importFetchedAccounts, importFetchedAccounts,
@ -85,6 +85,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
if (notification.status) { if (notification.status) {
dispatch(importFetchedStatus(notification.status)); dispatch(importFetchedStatus(notification.status));
dispatch(fetchAccounts(notification.status.emoji_reactions.map(emoji_reaction => emoji_reaction.account_ids).flat()));
} }
dispatch({ dispatch({
@ -169,6 +170,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems)); dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore, isLoadingRecent, isLoadingRecent && preferPendingItems));
fetchRelatedRelationships(dispatch, response.data); fetchRelatedRelationships(dispatch, response.data);
dispatch(fetchAccountsFromStatuses(response.data.map(item => item.status).filter(status => !!status)));
dispatch(submitMarkers()); dispatch(submitMarkers());
}).catch(error => { }).catch(error => {
dispatch(expandNotificationsFail(error, isLoadingMore)); dispatch(expandNotificationsFail(error, isLoadingMore));

View file

@ -1,4 +1,5 @@
import api from '../api'; import api from '../api';
import { fetchAccountsFromStatuses } from './accounts';
import { importFetchedStatuses } from './importer'; import { importFetchedStatuses } from './importer';
export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST'; export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST';
@ -13,6 +14,7 @@ export function fetchPinnedStatuses() {
api(getState).get(`/api/v1/accounts/${me}/statuses`, { params: { pinned: true } }).then(response => { api(getState).get(`/api/v1/accounts/${me}/statuses`, { params: { pinned: true } }).then(response => {
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(fetchAccountsFromStatuses(response.data));
dispatch(fetchPinnedStatusesSuccess(response.data, null)); dispatch(fetchPinnedStatusesSuccess(response.data, null));
}).catch(error => { }).catch(error => {
dispatch(fetchPinnedStatusesFail(error)); dispatch(fetchPinnedStatusesFail(error));

View file

@ -1,5 +1,5 @@
import api from '../api'; import api from '../api';
import { fetchRelationships } from './accounts'; import { fetchRelationships, fetchAccountsFromStatuses } from './accounts';
import { importFetchedAccounts, importFetchedStatuses } from './importer'; import { importFetchedAccounts, importFetchedStatuses } from './importer';
export const SEARCH_CHANGE = 'SEARCH_CHANGE'; export const SEARCH_CHANGE = 'SEARCH_CHANGE';
@ -51,6 +51,7 @@ export function submitSearch() {
if (response.data.statuses) { if (response.data.statuses) {
dispatch(importFetchedStatuses(response.data.statuses)); dispatch(importFetchedStatuses(response.data.statuses));
dispatch(fetchAccountsFromStatuses(response.data.statuses));
} }
dispatch(fetchSearchSuccess(response.data, value)); dispatch(fetchSearchSuccess(response.data, value));
@ -101,6 +102,7 @@ export const expandSearch = type => (dispatch, getState) => {
if (data.statuses) { if (data.statuses) {
dispatch(importFetchedStatuses(data.statuses)); dispatch(importFetchedStatuses(data.statuses));
dispatch(fetchAccountsFromStatuses(data.statuses));
} }
dispatch(expandSearchSuccess(data, value, type)); dispatch(expandSearchSuccess(data, value, type));

View file

@ -1,6 +1,7 @@
import api from '../api'; import api from '../api';
import { deleteFromTimelines } from './timelines'; import { deleteFromTimelines } from './timelines';
import { fetchRelationshipsFromStatus, fetchAccountsFromStatus, fetchRelationshipsFromStatuses, fetchAccountsFromStatuses } from './accounts';
import { importFetchedStatus, importFetchedStatuses, importFetchedAccount } from './importer'; import { importFetchedStatus, importFetchedStatuses, importFetchedAccount } from './importer';
import { ensureComposeIsVisible } from './compose'; import { ensureComposeIsVisible } from './compose';
@ -54,7 +55,10 @@ export function fetchStatus(id) {
dispatch(fetchStatusRequest(id, skipLoading)); dispatch(fetchStatusRequest(id, skipLoading));
api(getState).get(`/api/v1/statuses/${id}`).then(response => { api(getState).get(`/api/v1/statuses/${id}`).then(response => {
dispatch(importFetchedStatus(response.data)); const status = response.data;
dispatch(importFetchedStatus(status));
dispatch(fetchRelationshipsFromStatus(status));
dispatch(fetchAccountsFromStatus(status));
dispatch(fetchStatusSuccess(skipLoading)); dispatch(fetchStatusSuccess(skipLoading));
}).catch(error => { }).catch(error => {
dispatch(fetchStatusFail(id, error, skipLoading)); dispatch(fetchStatusFail(id, error, skipLoading));
@ -141,7 +145,10 @@ export function fetchContext(id) {
dispatch(fetchContextRequest(id)); dispatch(fetchContextRequest(id));
api(getState).get(`/api/v1/statuses/${id}/context`).then(response => { api(getState).get(`/api/v1/statuses/${id}/context`).then(response => {
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants))); const statuses = response.data.ancestors.concat(response.data.descendants);
dispatch(importFetchedStatuses(statuses));
dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants)); dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants));
}).catch(error => { }).catch(error => {

View file

@ -1,4 +1,4 @@
import { fetchRelationships } from './accounts'; import { fetchRelationshipsFromStatus, fetchAccountsFromStatus, fetchRelationshipsFromStatuses, fetchAccountsFromStatuses } from './accounts';
import { importFetchedStatus, importFetchedStatuses } from './importer'; import { importFetchedStatus, importFetchedStatuses } from './importer';
import { submitMarkers } from './markers'; import { submitMarkers } from './markers';
import api, { getLinks } from 'mastodon/api'; import api, { getLinks } from 'mastodon/api';
@ -43,7 +43,8 @@ export function updateTimeline(timeline, status, accept) {
} }
dispatch(importFetchedStatus(status)); dispatch(importFetchedStatus(status));
dispatch(fetchRelationships([status.reblog ? status.reblog.account.id : status.account.id, status.quote ? status.quote.account.id : null].filter(function(e){return e}))); dispatch(fetchRelationshipsFromStatus(status));
dispatch(fetchAccountsFromStatus(status));
const insertTimeline = timeline => { const insertTimeline = timeline => {
dispatch({ dispatch({
@ -146,9 +147,11 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
api(getState).get(path, { params }).then(response => { api(getState).get(path, { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); const statuses = response.data;
dispatch(fetchRelationships(uniq(response.data.map(item => item.reblog ? item.reblog.account.id : item.account.id).concat(response.data.map(item => item.quote ? item.quote.account.id : null)).filter(function(e){return e})))); dispatch(importFetchedStatuses(statuses));
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems)); dispatch(fetchRelationshipsFromStatuses(statuses));
dispatch(fetchAccountsFromStatuses(statuses));
dispatch(expandTimelineSuccess(timelineId, statuses, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
if (timelineId === 'home') { if (timelineId === 'home') {
dispatch(submitMarkers()); dispatch(submitMarkers());