@ -60,7 +60,7 @@
|
||||
"@reach/popover": "^0.18.0",
|
||||
"@reach/rect": "^0.18.0",
|
||||
"@reach/tabs": "^0.18.0",
|
||||
"@reduxjs/toolkit": "^2.0.1",
|
||||
"@reduxjs/toolkit": "^2.2.7",
|
||||
"@sentry/browser": "^7.74.1",
|
||||
"@sentry/react": "^7.74.1",
|
||||
"@tabler/icons": "^3.18.0",
|
||||
@ -121,7 +121,7 @@
|
||||
"react-inlinesvg": "^4.0.0",
|
||||
"react-intl": "^6.7.0",
|
||||
"react-motion": "^0.5.2",
|
||||
"react-redux": "^9.0.4",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^5.3.4",
|
||||
"react-router-dom-v5-compat": "^6.24.1",
|
||||
"react-router-scroll-4": "^1.0.0-beta.2",
|
||||
@ -129,7 +129,7 @@
|
||||
"react-sparklines": "^1.7.0",
|
||||
"react-sticky-box": "^2.0.0",
|
||||
"react-swipeable-views": "^0.14.0",
|
||||
"redux": "^5.0.0",
|
||||
"redux": "^5.0.1",
|
||||
"redux-immutable": "^4.0.0",
|
||||
"redux-thunk": "^3.1.0",
|
||||
"reselect": "^5.0.0",
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import { PLEROMA, type UpdateNotificationSettingsParams, type Account, type CreateAccountParams, type PaginatedResponse, type Relationship } from 'pl-api';
|
||||
|
||||
import { importEntities } from 'pl-fe/entity-store/actions';
|
||||
import { Entities } from 'pl-fe/entity-store/entities';
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
import { selectAccount } from 'pl-fe/selectors';
|
||||
import { isLoggedIn } from 'pl-fe/utils/auth';
|
||||
|
||||
import { getClient, type PlfeResponse } from '../api';
|
||||
|
||||
import { importFetchedAccount, importFetchedAccounts } from './importer';
|
||||
|
||||
import type { Map as ImmutableMap } from 'immutable';
|
||||
import type { MinifiedStatus } from 'pl-fe/reducers/statuses';
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
@ -128,7 +125,7 @@ const fetchAccount = (accountId: string) =>
|
||||
|
||||
return getClient(getState()).accounts.getAccount(accountId)
|
||||
.then(response => {
|
||||
dispatch(importFetchedAccount(response));
|
||||
importEntities({ accounts: [response] });
|
||||
dispatch(fetchAccountSuccess(response));
|
||||
})
|
||||
.catch(error => {
|
||||
@ -143,8 +140,8 @@ const fetchAccountByUsername = (username: string, history?: History) =>
|
||||
|
||||
if (features.accountByUsername && (me || !features.accountLookup)) {
|
||||
return getClient(getState()).accounts.getAccount(username).then(response => {
|
||||
importEntities({ accounts: [response] });
|
||||
dispatch(fetchRelationships([response.id]));
|
||||
dispatch(importFetchedAccount(response));
|
||||
dispatch(fetchAccountSuccess(response));
|
||||
}).catch(error => {
|
||||
dispatch(fetchAccountFail(null, error));
|
||||
@ -198,7 +195,7 @@ const blockAccount = (accountId: string) =>
|
||||
|
||||
return getClient(getState).filtering.blockAccount(accountId)
|
||||
.then(response => {
|
||||
dispatch(importEntities([response], Entities.RELATIONSHIPS));
|
||||
importEntities({ relationships: [response] });
|
||||
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
||||
return dispatch(blockAccountSuccess(response, getState().statuses));
|
||||
}).catch(error => dispatch(blockAccountFail(error)));
|
||||
@ -212,7 +209,7 @@ const unblockAccount = (accountId: string) =>
|
||||
|
||||
return getClient(getState).filtering.unblockAccount(accountId)
|
||||
.then(response => {
|
||||
dispatch(importEntities([response], Entities.RELATIONSHIPS));
|
||||
importEntities({ relationships: [response] });
|
||||
return dispatch(unblockAccountSuccess(response));
|
||||
})
|
||||
.catch(error => dispatch(unblockAccountFail(error)));
|
||||
@ -273,7 +270,7 @@ const muteAccount = (accountId: string, notifications?: boolean, duration = 0) =
|
||||
|
||||
return client.filtering.muteAccount(accountId, params)
|
||||
.then(response => {
|
||||
dispatch(importEntities([response], Entities.RELATIONSHIPS));
|
||||
importEntities({ relationships: [response] });
|
||||
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
|
||||
return dispatch(muteAccountSuccess(response, getState().statuses));
|
||||
})
|
||||
@ -288,7 +285,7 @@ const unmuteAccount = (accountId: string) =>
|
||||
|
||||
return getClient(getState()).filtering.unmuteAccount(accountId)
|
||||
.then(response => {
|
||||
dispatch(importEntities([response], Entities.RELATIONSHIPS));
|
||||
importEntities({ relationships: [response] });
|
||||
return dispatch(unmuteAccountSuccess(response));
|
||||
})
|
||||
.catch(error => dispatch(unmuteAccountFail(accountId, error)));
|
||||
@ -369,7 +366,7 @@ const fetchRelationships = (accountIds: string[]) =>
|
||||
|
||||
return getClient(getState()).accounts.getRelationships(newAccountIds)
|
||||
.then(response => {
|
||||
dispatch(importEntities(response, Entities.RELATIONSHIPS));
|
||||
importEntities({ relationships: response });
|
||||
dispatch(fetchRelationshipsSuccess(response));
|
||||
})
|
||||
.catch(error => dispatch(fetchRelationshipsFail(error)));
|
||||
@ -398,7 +395,7 @@ const fetchFollowRequests = () =>
|
||||
|
||||
return getClient(getState()).myAccount.getFollowRequests()
|
||||
.then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(fetchFollowRequestsSuccess(response.items, response.next));
|
||||
})
|
||||
.catch(error => dispatch(fetchFollowRequestsFail(error)));
|
||||
@ -430,7 +427,7 @@ const expandFollowRequests = () =>
|
||||
dispatch(expandFollowRequestsRequest());
|
||||
|
||||
return next().then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(expandFollowRequestsSuccess(response.items, response.next));
|
||||
}).catch(error => dispatch(expandFollowRequestsFail(error)));
|
||||
};
|
||||
@ -576,7 +573,7 @@ const fetchPinnedAccounts = (accountId: string) =>
|
||||
dispatch(fetchPinnedAccountsRequest(accountId));
|
||||
|
||||
return getClient(getState).accounts.getAccountEndorsements(accountId).then(response => {
|
||||
dispatch(importFetchedAccounts(response));
|
||||
importEntities({ accounts: response });
|
||||
dispatch(fetchPinnedAccountsSuccess(accountId, response, null));
|
||||
}).catch(error => {
|
||||
dispatch(fetchPinnedAccountsFail(accountId, error));
|
||||
@ -604,10 +601,10 @@ const fetchPinnedAccountsFail = (accountId: string, error: unknown) => ({
|
||||
const accountSearch = (q: string, signal?: AbortSignal) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: ACCOUNT_SEARCH_REQUEST, params: { q } });
|
||||
return getClient(getState()).accounts.searchAccounts(q, { resolve: false, limit: 4, following: true }, { signal }).then((accounts) => {
|
||||
dispatch(importFetchedAccounts(accounts));
|
||||
dispatch({ type: ACCOUNT_SEARCH_SUCCESS, accounts });
|
||||
return accounts;
|
||||
return getClient(getState()).accounts.searchAccounts(q, { resolve: false, limit: 4, following: true }, { signal }).then((response) => {
|
||||
importEntities({ accounts: response });
|
||||
dispatch({ type: ACCOUNT_SEARCH_SUCCESS, accounts: response });
|
||||
return response;
|
||||
}).catch(error => {
|
||||
dispatch({ type: ACCOUNT_SEARCH_FAIL, skipAlert: true });
|
||||
throw error;
|
||||
@ -618,7 +615,7 @@ const accountLookup = (acct: string, signal?: AbortSignal) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: ACCOUNT_LOOKUP_REQUEST, acct });
|
||||
return getClient(getState()).accounts.lookupAccount(acct, { signal }).then((account) => {
|
||||
if (account && account.id) dispatch(importFetchedAccount(account));
|
||||
if (account && account.id) importEntities({ accounts: [account] });
|
||||
dispatch({ type: ACCOUNT_LOOKUP_SUCCESS, account });
|
||||
return account;
|
||||
}).catch(error => {
|
||||
@ -636,7 +633,7 @@ const fetchBirthdayReminders = (month: number, day: number) =>
|
||||
dispatch({ type: BIRTHDAY_REMINDERS_FETCH_REQUEST, day, month, accountId: me });
|
||||
|
||||
return getClient(getState).accounts.getBirthdays(day, month).then(response => {
|
||||
dispatch(importFetchedAccounts(response));
|
||||
importEntities({ accounts: response });
|
||||
dispatch({
|
||||
type: BIRTHDAY_REMINDERS_FETCH_SUCCESS,
|
||||
accounts: response,
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
|
||||
import { getClient } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
|
||||
import type { Account, ProfileDirectoryParams } from 'pl-api';
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
@ -19,7 +20,7 @@ const fetchDirectory = (params: ProfileDirectoryParams) =>
|
||||
dispatch(fetchDirectoryRequest());
|
||||
|
||||
return getClient(getState()).instance.profileDirectory({ ...params, limit: 20 }).then((data) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
importEntities({ accounts: data });
|
||||
dispatch(fetchDirectorySuccess(data));
|
||||
dispatch(fetchRelationships(data.map((x) => x.id)));
|
||||
}).catch(error => dispatch(fetchDirectoryFail(error)));
|
||||
@ -46,7 +47,7 @@ const expandDirectory = (params: Record<string, any>) =>
|
||||
const loadedItems = getState().user_lists.directory.items.size;
|
||||
|
||||
return getClient(getState()).instance.profileDirectory({ ...params, offset: loadedItems, limit: 20 }).then((data) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
importEntities({ accounts: data });
|
||||
dispatch(expandDirectorySuccess(data));
|
||||
dispatch(fetchRelationships(data.map((x) => x.id)));
|
||||
}).catch(error => dispatch(expandDirectoryFail(error)));
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
import { getClient } from 'pl-fe/api';
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
import { useModalsStore } from 'pl-fe/stores';
|
||||
import toast from 'pl-fe/toast';
|
||||
|
||||
import { importFetchedAccounts, importFetchedStatus, importFetchedStatuses } from './importer';
|
||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
||||
import { STATUS_FETCH_SOURCE_FAIL, STATUS_FETCH_SOURCE_REQUEST, STATUS_FETCH_SOURCE_SUCCESS } from './statuses';
|
||||
|
||||
import type { Account, CreateEventParams, Location, MediaAttachment, PaginatedResponse, Status } from 'pl-api';
|
||||
@ -241,7 +242,7 @@ const fetchEventParticipations = (statusId: string) =>
|
||||
dispatch(fetchEventParticipationsRequest(statusId));
|
||||
|
||||
return getClient(getState).events.getEventParticipations(statusId).then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
return dispatch(fetchEventParticipationsSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
dispatch(fetchEventParticipationsFail(statusId, error));
|
||||
@ -277,7 +278,7 @@ const expandEventParticipations = (statusId: string) =>
|
||||
dispatch(expandEventParticipationsRequest(statusId));
|
||||
|
||||
return next().then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
return dispatch(expandEventParticipationsSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
dispatch(expandEventParticipationsFail(statusId, error));
|
||||
@ -307,7 +308,7 @@ const fetchEventParticipationRequests = (statusId: string) =>
|
||||
dispatch(fetchEventParticipationRequestsRequest(statusId));
|
||||
|
||||
return getClient(getState).events.getEventParticipationRequests(statusId).then(response => {
|
||||
dispatch(importFetchedAccounts(response.items.map(({ account }) => account)));
|
||||
importEntities({ accounts: response.items.map(({ account }) => account) });
|
||||
return dispatch(fetchEventParticipationRequestsSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
dispatch(fetchEventParticipationRequestsFail(statusId, error));
|
||||
@ -346,7 +347,7 @@ const expandEventParticipationRequests = (statusId: string) =>
|
||||
dispatch(expandEventParticipationRequestsRequest(statusId));
|
||||
|
||||
return next().then(response => {
|
||||
dispatch(importFetchedAccounts(response.items.map(({ account }) => account)));
|
||||
importEntities({ accounts: response.items.map(({ account }) => account) });
|
||||
return dispatch(expandEventParticipationRequestsSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
dispatch(expandEventParticipationRequestsFail(statusId, error));
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
import { AppDispatch, RootState } from 'pl-fe/store';
|
||||
|
||||
import { getClient } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
|
||||
const FAMILIAR_FOLLOWERS_FETCH_REQUEST = 'FAMILIAR_FOLLOWERS_FETCH_REQUEST' as const;
|
||||
const FAMILIAR_FOLLOWERS_FETCH_SUCCESS = 'FAMILIAR_FOLLOWERS_FETCH_SUCCESS' as const;
|
||||
@ -19,7 +19,7 @@ const fetchAccountFamiliarFollowers = (accountId: string) => (dispatch: AppDispa
|
||||
.then((data) => {
|
||||
const accounts = data.find(({ id }: { id: string }) => id === accountId)!.accounts;
|
||||
|
||||
dispatch(importFetchedAccounts(accounts));
|
||||
importEntities({ accounts });
|
||||
dispatch(fetchRelationships(accounts.map((item) => item.id)));
|
||||
dispatch({
|
||||
type: FAMILIAR_FOLLOWERS_FETCH_SUCCESS,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getClient } from '../api';
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
|
||||
import { importFetchedAccounts } from './importer';
|
||||
import { getClient } from '../api';
|
||||
|
||||
import type { Account, PaginatedResponse } from 'pl-api';
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
@ -23,7 +23,7 @@ const fetchGroupBlocks = (groupId: string) =>
|
||||
dispatch(fetchGroupBlocksRequest(groupId));
|
||||
|
||||
return getClient(getState).experimental.groups.getGroupBlocks(groupId).then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(fetchGroupBlocksSuccess(groupId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
dispatch(fetchGroupBlocksFail(groupId, error));
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { getClient } from 'pl-fe/api';
|
||||
|
||||
import { importFetchedAccounts } from './importer';
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
|
||||
import type { StatusEdit } from 'pl-api';
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
@ -18,7 +17,7 @@ const fetchHistory = (statusId: string) =>
|
||||
dispatch(fetchHistoryRequest(statusId));
|
||||
|
||||
return getClient(getState()).statuses.getStatusHistory(statusId).then(data => {
|
||||
dispatch(importFetchedAccounts(data.map((x) => x.account)));
|
||||
importEntities({ accounts: data.map((x) => x.account) });
|
||||
dispatch(fetchHistorySuccess(statusId, data));
|
||||
}).catch(error => dispatch(fetchHistoryFail(statusId, error)));
|
||||
};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { importEntities } from 'pl-fe/entity-store/actions';
|
||||
import { Entities } from 'pl-fe/entity-store/entities';
|
||||
import { normalizeAccount, normalizeGroup } from 'pl-fe/normalizers';
|
||||
import { normalizeAccount, normalizeGroup, type Account, type Group } from 'pl-fe/normalizers';
|
||||
|
||||
import type { Account as BaseAccount, Group, Poll, Status as BaseStatus } from 'pl-api';
|
||||
import type { Account as BaseAccount, Group as BaseGroup, Poll, Status as BaseStatus } from 'pl-api';
|
||||
import type { AppDispatch } from 'pl-fe/store';
|
||||
|
||||
const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT';
|
||||
@ -13,25 +13,29 @@ const POLLS_IMPORT = 'POLLS_IMPORT';
|
||||
|
||||
const importAccount = (data: BaseAccount) => importAccounts([data]);
|
||||
|
||||
const importAccounts = (data: Array<BaseAccount>) => (dispatch: AppDispatch) => {
|
||||
dispatch({ type: ACCOUNTS_IMPORT, accounts: data });
|
||||
const importAccounts = (data: Array<BaseAccount>) => {
|
||||
let accounts: Array<Account> = [];
|
||||
|
||||
try {
|
||||
const accounts = data.map(normalizeAccount);
|
||||
dispatch(importEntities(accounts, Entities.ACCOUNTS));
|
||||
accounts = data.map(normalizeAccount);
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
|
||||
return importEntities(accounts, Entities.ACCOUNTS);
|
||||
};
|
||||
|
||||
const importGroup = (data: Group) => importGroups([data]);
|
||||
const importGroup = (data: BaseGroup) => importGroups([data]);
|
||||
|
||||
const importGroups = (data: Array<Group>) => (dispatch: AppDispatch) => {
|
||||
const importGroups = (data: Array<BaseGroup>) => {
|
||||
let groups: Array<Group> = [];
|
||||
try {
|
||||
const groups = data.map(normalizeGroup);
|
||||
dispatch(importEntities(groups, Entities.GROUPS));
|
||||
groups = data.map(normalizeGroup);
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
|
||||
return importEntities(groups, Entities.GROUPS);
|
||||
};
|
||||
|
||||
const importStatus = (status: BaseStatus & { expectsCard?: boolean }, idempotencyKey?: string) => ({ type: STATUS_IMPORT, status, idempotencyKey });
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
import { useModalsStore } from 'pl-fe/stores';
|
||||
import toast, { type IToastOptions } from 'pl-fe/toast';
|
||||
import { isLoggedIn } from 'pl-fe/utils/auth';
|
||||
@ -7,7 +8,6 @@ import { isLoggedIn } from 'pl-fe/utils/auth';
|
||||
import { getClient } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||
|
||||
import type { Account, EmojiReaction, PaginatedResponse, Status } from 'pl-api';
|
||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||
@ -97,7 +97,7 @@ const reblog = (status: Pick<Status, 'id'>) =>
|
||||
return getClient(getState()).statuses.reblogStatus(status.id).then((response) => {
|
||||
// The reblog API method returns a new status wrapped around the original. In this case we are only
|
||||
// interested in how the original is modified, hence passing it skipping the wrapper
|
||||
if (response.reblog) dispatch(importFetchedStatus(response.reblog as Status));
|
||||
if (response.reblog) importEntities({ statuses: [response] });
|
||||
dispatch(reblogSuccess(response));
|
||||
}).catch(error => {
|
||||
dispatch(reblogFail(status.id, error));
|
||||
@ -110,8 +110,8 @@ const unreblog = (status: Pick<Status, 'id'>) =>
|
||||
|
||||
dispatch(unreblogRequest(status.id));
|
||||
|
||||
return getClient(getState()).statuses.unreblogStatus(status.id).then((status) => {
|
||||
dispatch(unreblogSuccess(status));
|
||||
return getClient(getState()).statuses.unreblogStatus(status.id).then((response) => {
|
||||
dispatch(unreblogSuccess(response));
|
||||
}).catch(error => {
|
||||
dispatch(unreblogFail(status.id, error));
|
||||
});
|
||||
@ -306,9 +306,9 @@ const bookmark = (status: Pick<Status, 'id'>, folderId?: string) =>
|
||||
|
||||
dispatch(bookmarkRequest(status.id));
|
||||
|
||||
return getClient(getState()).statuses.bookmarkStatus(status.id, folderId).then((response) => {
|
||||
dispatch(importFetchedStatus(response));
|
||||
dispatch(bookmarkSuccess(response));
|
||||
return getClient(getState()).statuses.bookmarkStatus(status.id, folderId).then((status) => {
|
||||
importEntities({ statuses: [status] });
|
||||
dispatch(bookmarkSuccess(status));
|
||||
|
||||
let opts: IToastOptions = {
|
||||
actionLabel: messages.view,
|
||||
@ -335,7 +335,7 @@ const unbookmark = (status: Pick<Status, 'id'>) =>
|
||||
dispatch(unbookmarkRequest(status.id));
|
||||
|
||||
return getClient(getState()).statuses.unbookmarkStatus(status.id).then(response => {
|
||||
dispatch(importFetchedStatus(response));
|
||||
importEntities({ statuses: [response] });
|
||||
dispatch(unbookmarkSuccess(response));
|
||||
toast.success(messages.bookmarkRemoved);
|
||||
}).catch(error => {
|
||||
@ -391,7 +391,7 @@ const fetchReblogs = (statusId: string) =>
|
||||
dispatch(fetchReblogsRequest(statusId));
|
||||
|
||||
return getClient(getState()).statuses.getRebloggedBy(statusId).then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(fetchRelationships(response.items.map((item) => item.id)));
|
||||
dispatch(fetchReblogsSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
@ -420,7 +420,7 @@ const fetchReblogsFail = (statusId: string, error: unknown) => ({
|
||||
const expandReblogs = (statusId: string, next: AccountListLink) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
next().then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(fetchRelationships(response.items.map((item) => item.id)));
|
||||
dispatch(expandReblogsSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
@ -446,7 +446,7 @@ const fetchFavourites = (statusId: string) =>
|
||||
dispatch(fetchFavouritesRequest(statusId));
|
||||
|
||||
return getClient(getState()).statuses.getFavouritedBy(statusId).then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(fetchRelationships(response.items.map((item) => item.id)));
|
||||
dispatch(fetchFavouritesSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
@ -475,7 +475,7 @@ const fetchFavouritesFail = (statusId: string, error: unknown) => ({
|
||||
const expandFavourites = (statusId: string, next: AccountListLink) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
next().then(response => {
|
||||
dispatch(importFetchedAccounts(response.items));
|
||||
importEntities({ accounts: response.items });
|
||||
dispatch(fetchRelationships(response.items.map((item) => item.id)));
|
||||
dispatch(expandFavouritesSuccess(statusId, response.items, response.next));
|
||||
}).catch(error => {
|
||||
@ -501,7 +501,7 @@ const fetchDislikes = (statusId: string) =>
|
||||
dispatch(fetchDislikesRequest(statusId));
|
||||
|
||||
return getClient(getState).statuses.getDislikedBy(statusId).then(response => {
|
||||
dispatch(importFetchedAccounts(response));
|
||||
importEntities({ accounts: response });
|
||||
dispatch(fetchRelationships(response.map((item) => item.id)));
|
||||
dispatch(fetchDislikesSuccess(statusId, response));
|
||||
}).catch(error => {
|
||||
@ -531,7 +531,7 @@ const fetchReactions = (statusId: string) =>
|
||||
dispatch(fetchReactionsRequest(statusId));
|
||||
|
||||
return getClient(getState).statuses.getStatusReactions(statusId).then(response => {
|
||||
dispatch(importFetchedAccounts((response).map(({ accounts }) => accounts).flat()));
|
||||
importEntities({ accounts: (response).map(({ accounts }) => accounts).flat() });
|
||||
dispatch(fetchReactionsSuccess(statusId, response));
|
||||
}).catch(error => {
|
||||
dispatch(fetchReactionsFail(statusId, error));
|
||||
@ -562,7 +562,7 @@ const pin = (status: Pick<Status, 'id'>, accountId: string) =>
|
||||
dispatch(pinRequest(status.id, accountId));
|
||||
|
||||
return getClient(getState()).statuses.pinStatus(status.id).then(response => {
|
||||
dispatch(importFetchedStatus(response));
|
||||
importEntities({ statuses: [response] });
|
||||
dispatch(pinSuccess(response, accountId));
|
||||
}).catch(error => {
|
||||
dispatch(pinFail(status.id, error, accountId));
|
||||
@ -596,7 +596,7 @@ const unpin = (status: Pick<Status, 'id'>, accountId: string) =>
|
||||
dispatch(unpinRequest(status.id, accountId));
|
||||
|
||||
return getClient(getState()).statuses.unpinStatus(status.id).then(response => {
|
||||
dispatch(importFetchedStatus(response));
|
||||
importEntities({ statuses: [response] });
|
||||
dispatch(unpinSuccess(response, accountId));
|
||||
}).catch(error => {
|
||||
dispatch(unpinFail(status.id, error, accountId));
|
||||
|
||||
@ -34,7 +34,7 @@ const AccountTimeline: React.FC<IAccountTimeline> = ({ params, withReplies = fal
|
||||
const statusIds = useAppSelector(state => getStatusIds(state, { type: `account:${path}`, prefix: 'account_timeline' }));
|
||||
const featuredStatusIds = useAppSelector(state => getStatusIds(state, { type: `account:${account?.id}:with_replies:pinned`, prefix: 'account_timeline' }));
|
||||
|
||||
const isBlocked = useAppSelector(state => state.relationships.getIn([account?.id, 'blocked_by']) === true);
|
||||
const isBlocked = account?.relationship?.blocked_by;
|
||||
const unavailable = isBlocked && !features.blockersVisible;
|
||||
const isLoading = useAppSelector(state => state.timelines.get(`account:${path}`)?.isLoading === true);
|
||||
const hasMore = useAppSelector(state => state.timelines.get(`account:${path}`)?.hasMore === true);
|
||||
|
||||
@ -1,20 +1,16 @@
|
||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
||||
|
||||
import { importFetchedAccounts, importFetchedStatuses } from 'pl-fe/actions/importer';
|
||||
import { getNotificationStatus } from 'pl-fe/features/notifications/components/notification';
|
||||
import { useClient } from 'pl-fe/hooks';
|
||||
import { normalizeNotifications } from 'pl-fe/normalizers';
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
import { queryClient } from 'pl-fe/queries/client';
|
||||
import { AppDispatch, store } from 'pl-fe/store';
|
||||
import { flattenPages } from 'pl-fe/utils/queries';
|
||||
|
||||
import { importNotification, minifyNotification } from './useNotification';
|
||||
|
||||
import type {
|
||||
Account as BaseAccount,
|
||||
Notification as BaseNotification,
|
||||
PaginatedResponse,
|
||||
PlApiClient,
|
||||
Status as BaseStatus,
|
||||
} from 'pl-api';
|
||||
import type { NotificationType } from 'pl-fe/utils/notification';
|
||||
|
||||
@ -29,31 +25,59 @@ const getQueryKey = (params: UseNotificationParams) => [
|
||||
params.types ? params.types.join('|') : params.excludeTypes ? ('exclude:' + params.excludeTypes.join('|')) : 'all',
|
||||
];
|
||||
|
||||
const importNotifications = (response: PaginatedResponse<BaseNotification>) => {
|
||||
const accounts: Record<string, BaseAccount> = {};
|
||||
const statuses: Record<string, BaseStatus> = {};
|
||||
type DeduplicatedNotification = BaseNotification & {
|
||||
accounts: Array<BaseAccount>;
|
||||
duplicate?: boolean;
|
||||
}
|
||||
|
||||
response.items.forEach((notification) => {
|
||||
accounts[notification.account.id] = notification.account;
|
||||
const STATUS_NOTIFICATION_TYPES = [
|
||||
'favourite',
|
||||
'reblog',
|
||||
'emoji_reaction',
|
||||
'event_reminder',
|
||||
'participation_accepted',
|
||||
'participation_request',
|
||||
];
|
||||
|
||||
if (notification.type === 'move') accounts[notification.target.id] = notification.target;
|
||||
const deduplicateNotifications = (notifications: Array<BaseNotification>) => {
|
||||
const deduplicatedNotifications: DeduplicatedNotification[] = [];
|
||||
|
||||
// @ts-ignore
|
||||
if (notification.status?.id) {
|
||||
// @ts-ignore
|
||||
statuses[notification.status.id] = notification.status;
|
||||
for (const notification of notifications) {
|
||||
if (STATUS_NOTIFICATION_TYPES.includes(notification.type)) {
|
||||
const existingNotification = deduplicatedNotifications
|
||||
.find(deduplicated =>
|
||||
deduplicated.type === notification.type
|
||||
&& ((notification.type === 'emoji_reaction' && deduplicated.type === 'emoji_reaction') ? notification.emoji === deduplicated.emoji : true)
|
||||
&& getNotificationStatus(deduplicated)?.id === getNotificationStatus(notification)?.id,
|
||||
);
|
||||
|
||||
if (existingNotification) {
|
||||
existingNotification.accounts.push(notification.account);
|
||||
deduplicatedNotifications.push({ ...notification, accounts: [notification.account], duplicate: true });
|
||||
} else {
|
||||
deduplicatedNotifications.push({ ...notification, accounts: [notification.account], duplicate: false });
|
||||
}
|
||||
} else {
|
||||
deduplicatedNotifications.push({ ...notification, accounts: [notification.account], duplicate: false });
|
||||
}
|
||||
}
|
||||
|
||||
return deduplicatedNotifications;
|
||||
};
|
||||
|
||||
const importNotifications = (response: PaginatedResponse<BaseNotification>) => {
|
||||
const deduplicatedNotifications = deduplicateNotifications(response.items);
|
||||
|
||||
importEntities({
|
||||
notifications: deduplicatedNotifications,
|
||||
});
|
||||
|
||||
store.dispatch<AppDispatch>(importFetchedStatuses(Object.values(statuses)));
|
||||
store.dispatch<AppDispatch>(importFetchedAccounts(Object.values(accounts)));
|
||||
// const normalizedNotifications = normalizeNotifications(response.items);
|
||||
|
||||
const normalizedNotifications = normalizeNotifications(response.items);
|
||||
|
||||
normalizedNotifications.map(minifyNotification).forEach(importNotification);
|
||||
// normalizedNotifications.map(minifyNotification).forEach(importNotification);
|
||||
|
||||
return {
|
||||
items: normalizedNotifications.filter(({ duplicate }) => !duplicate).map(({ id }) => id),
|
||||
items: deduplicatedNotifications.filter(({ duplicate }) => !duplicate).map(({ id }) => id),
|
||||
previous: response.previous,
|
||||
next: response.next,
|
||||
};
|
||||
@ -91,4 +115,4 @@ const prefetchNotifications = (client: PlApiClient, params: UseNotificationParam
|
||||
getNextPageParam: (response) => response,
|
||||
});
|
||||
|
||||
export { useNotifications, prefetchNotifications };
|
||||
export { useNotifications, prefetchNotifications, type DeduplicatedNotification };
|
||||
|
||||
@ -1,28 +1,125 @@
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
import { importAccounts, importGroups, importPolls, importStatuses } from 'pl-fe/actions/importer';
|
||||
import { importEntities as importEntityStoreEntities } from 'pl-fe/entity-store/actions';
|
||||
import { Entities } from 'pl-fe/entity-store/entities';
|
||||
import { queryClient } from 'pl-fe/queries/client';
|
||||
import { store } from 'pl-fe/store';
|
||||
|
||||
import { DeduplicatedNotification } from './hooks/notifications/useNotifications';
|
||||
|
||||
import type {
|
||||
AccountWarning,
|
||||
Account as BaseAccount,
|
||||
Group as BaseGroup,
|
||||
Notification as BaseNotification,
|
||||
Poll as BasePoll,
|
||||
Relationship as BaseRelationship,
|
||||
Status as BaseStatus,
|
||||
RelationshipSeveranceEvent,
|
||||
} from 'pl-api';
|
||||
|
||||
|
||||
const minifyNotification = (notification: DeduplicatedNotification) => {
|
||||
// @ts-ignore
|
||||
const minifiedNotification: {
|
||||
duplicate: boolean;
|
||||
account_id: string;
|
||||
account_ids: string[];
|
||||
created_at: string;
|
||||
id: string;
|
||||
group_key: string;
|
||||
} & (
|
||||
| { type: 'follow' | 'follow_request' | 'admin.sign_up' | 'bite' }
|
||||
| {
|
||||
type: 'mention';
|
||||
subtype?: 'reply';
|
||||
status_id: string;
|
||||
}
|
||||
| {
|
||||
type: 'status' | 'reblog' | 'favourite' | 'poll' | 'update' | 'event_reminder';
|
||||
status_id: string;
|
||||
}
|
||||
| {
|
||||
type: 'admin.report';
|
||||
report: Report;
|
||||
}
|
||||
| {
|
||||
type: 'severed_relationships';
|
||||
relationship_severance_event: RelationshipSeveranceEvent;
|
||||
}
|
||||
| {
|
||||
type: 'moderation_warning';
|
||||
moderation_warning: AccountWarning;
|
||||
}
|
||||
| {
|
||||
type: 'move';
|
||||
target_id: string;
|
||||
}
|
||||
| {
|
||||
type: 'emoji_reaction';
|
||||
emoji: string;
|
||||
emoji_url: string | null;
|
||||
status_id: string;
|
||||
}
|
||||
| {
|
||||
type: 'chat_mention';
|
||||
chat_message_id: string;
|
||||
}
|
||||
| {
|
||||
type: 'participation_accepted' | 'participation_request';
|
||||
status_id: string;
|
||||
participation_message: string | null;
|
||||
}
|
||||
) = {
|
||||
...omit(notification, ['account', 'accounts', 'status', 'target', 'chat_message']),
|
||||
account_id: notification.account.id,
|
||||
account_ids: notification.accounts.map(({ id }) => id),
|
||||
created_at: notification.created_at,
|
||||
id: notification.id,
|
||||
type: notification.type,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
if (notification.status) minifiedNotification.status_id = notification.status.id;
|
||||
// @ts-ignore
|
||||
if (notification.target) minifiedNotification.target_id = notification.target.id;
|
||||
// @ts-ignore
|
||||
if (notification.chat_message) minifiedNotification.chat_message_id = notification.chat_message.id;
|
||||
|
||||
return minifiedNotification;
|
||||
};
|
||||
|
||||
type MinifiedNotification = ReturnType<typeof minifyNotification>;
|
||||
|
||||
const importNotification = (notification: DeduplicatedNotification) => {
|
||||
queryClient.setQueryData<MinifiedNotification>(
|
||||
['notifications', 'entities', notification.id],
|
||||
existingNotification => existingNotification?.duplicate ? existingNotification : minifyNotification(notification),
|
||||
);
|
||||
};
|
||||
|
||||
const importEntities = (entities: {
|
||||
accounts?: Array<BaseAccount>;
|
||||
notifications?: Array<BaseNotification>;
|
||||
notifications?: Array<DeduplicatedNotification>;
|
||||
statuses?: Array<BaseStatus>;
|
||||
relationships?: Array<BaseRelationship>;
|
||||
}) => {
|
||||
const { dispatch } = store;
|
||||
|
||||
const accounts: Record<string, BaseAccount> = {};
|
||||
const groups: Record<string, BaseGroup> = {};
|
||||
const notifications: Record<string, BaseNotification> = {};
|
||||
const notifications: Record<string, DeduplicatedNotification> = {};
|
||||
const polls: Record<string, BasePoll> = {};
|
||||
const relationships: Record<string, BaseRelationship> = {};
|
||||
const statuses: Record<string, BaseStatus> = {};
|
||||
|
||||
const processAccount = (account: BaseAccount) => {
|
||||
accounts[account.id] = account;
|
||||
if (account.moved) processAccount(account.moved);
|
||||
if (account.relationship) relationships[account.relationship.id] = account.relationship;
|
||||
};
|
||||
|
||||
const processNotification = (notification: BaseNotification) => {
|
||||
const processNotification = (notification: DeduplicatedNotification) => {
|
||||
notifications[notification.id] = notification;
|
||||
|
||||
processAccount(notification.account);
|
||||
@ -38,11 +135,20 @@ const importEntities = (entities: {
|
||||
|
||||
if (status.quote) processStatus(status.quote);
|
||||
if (status.reblog) processStatus(status.reblog);
|
||||
if (status.poll) polls[status.poll.id] = status.poll;
|
||||
if (status.group) groups[status.group.id] = status.group;
|
||||
};
|
||||
|
||||
entities.accounts?.forEach(processAccount);
|
||||
entities.notifications?.forEach(processNotification);
|
||||
entities.statuses?.forEach(processStatus);
|
||||
|
||||
dispatch(importAccounts(Object.values(accounts)));
|
||||
dispatch(importGroups(Object.values(groups)));
|
||||
Object.values(notifications).forEach(importNotification);
|
||||
dispatch(importPolls(Object.values(polls)));
|
||||
dispatch(importStatuses(Object.values(statuses)));
|
||||
dispatch(importEntityStoreEntities(Object.values(relationships), Entities.RELATIONSHIPS));
|
||||
};
|
||||
|
||||
export { importEntities };
|
||||
|
||||
@ -2,11 +2,11 @@ import { InfiniteData, keepPreviousData, useInfiniteQuery, useMutation, useQuery
|
||||
import sumBy from 'lodash/sumBy';
|
||||
import { type Chat, type ChatMessage as BaseChatMessage, type PaginatedResponse, chatMessageSchema } from 'pl-api';
|
||||
|
||||
import { importFetchedAccount, importFetchedAccounts } from 'pl-fe/actions/importer';
|
||||
import { ChatWidgetScreens, useChatContext } from 'pl-fe/contexts/chat-context';
|
||||
import { useStatContext } from 'pl-fe/contexts/stat-context';
|
||||
import { useAppDispatch, useAppSelector, useClient, useFeatures, useLoggedIn, useOwnAccount } from 'pl-fe/hooks';
|
||||
import { useAppSelector, useClient, useFeatures, useLoggedIn, useOwnAccount } from 'pl-fe/hooks';
|
||||
import { type ChatMessage, normalizeChatMessage } from 'pl-fe/normalizers';
|
||||
import { importEntities } from 'pl-fe/pl-hooks/importer';
|
||||
import { reOrderChatListItems } from 'pl-fe/utils/chats';
|
||||
import { flattenPages, updatePageItem } from 'pl-fe/utils/queries';
|
||||
|
||||
@ -51,7 +51,6 @@ const useChatMessages = (chat: Chat) => {
|
||||
|
||||
const useChats = () => {
|
||||
const client = useClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const features = useFeatures();
|
||||
const { setUnreadChatsCount } = useStatContext();
|
||||
const fetchRelationships = useFetchRelationships();
|
||||
@ -65,7 +64,7 @@ const useChats = () => {
|
||||
|
||||
// Set the relationships to these users in the redux store.
|
||||
fetchRelationships.mutate({ accountIds: items.map((item) => item.account.id) });
|
||||
dispatch(importFetchedAccounts(items.map((item) => item.account)));
|
||||
importEntities({ accounts: items.map((item) => item.account) });
|
||||
|
||||
return response;
|
||||
};
|
||||
@ -94,7 +93,6 @@ const useChats = () => {
|
||||
|
||||
const useChat = (chatId?: string) => {
|
||||
const client = useClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const fetchRelationships = useFetchRelationships();
|
||||
|
||||
const getChat = async () => {
|
||||
@ -102,7 +100,7 @@ const useChat = (chatId?: string) => {
|
||||
const data = await client.chats.getChat(chatId);
|
||||
|
||||
fetchRelationships.mutate({ accountIds: [data.account.id] });
|
||||
dispatch(importFetchedAccount(data.account));
|
||||
importEntities({ accounts: [data.account] });
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -2171,15 +2171,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.18.0.tgz#4f3cebe093dd436eeaff633809bf0f68f4f9d2ee"
|
||||
integrity sha512-KdVMdpTgDyK8FzdKO9SCpiibuy/kbv3pwgfXshTI6tEcQT1OOwj7BAksnzGC0rPz0UholwC+AgkqEl3EJX3M1A==
|
||||
|
||||
"@reduxjs/toolkit@^2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.0.1.tgz#0a5233c1e35c1941b03aece39cceade3467a1062"
|
||||
integrity sha512-fxIjrR9934cmS8YXIGd9e7s1XRsEU++aFc9DVNMFMRTM5Vtsg2DCRMj21eslGtDt43IUf9bJL3h5bwUlZleibA==
|
||||
"@reduxjs/toolkit@^2.2.7":
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.2.7.tgz#199e3d10ccb39267cb5aee92c0262fd9da7fdfb2"
|
||||
integrity sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==
|
||||
dependencies:
|
||||
immer "^10.0.3"
|
||||
redux "^5.0.0"
|
||||
redux "^5.0.1"
|
||||
redux-thunk "^3.1.0"
|
||||
reselect "^5.0.1"
|
||||
reselect "^5.1.0"
|
||||
|
||||
"@remix-run/router@1.18.0":
|
||||
version "1.18.0"
|
||||
@ -9713,10 +9713,10 @@ react-property@2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.2.tgz#d5ac9e244cef564880a610bc8d868bd6f60fdda6"
|
||||
integrity sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==
|
||||
|
||||
react-redux@^9.0.4:
|
||||
version "9.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.0.4.tgz#6892d465f086507a517d4b53eb589876e6bc8344"
|
||||
integrity sha512-9J1xh8sWO0vYq2sCxK2My/QO7MzUMRi3rpiILP/+tDr8krBHixC6JMM17fMK88+Oh3e4Ae6/sHIhNBgkUivwFA==
|
||||
react-redux@^9.1.2:
|
||||
version "9.1.2"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.2.tgz#deba38c64c3403e9abd0c3fbeab69ffd9d8a7e4b"
|
||||
integrity sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==
|
||||
dependencies:
|
||||
"@types/use-sync-external-store" "^0.0.3"
|
||||
use-sync-external-store "^1.0.0"
|
||||
@ -9908,10 +9908,10 @@ redux@^4.0.5:
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.2"
|
||||
|
||||
redux@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.0.tgz#29572e29a439e094ff8fec46883fc45053f6736d"
|
||||
integrity sha512-blLIYmYetpZMET6Q6uCY7Jtl/Im5OBldy+vNPauA8vvsdqyt66oep4EUpAMWNHauTC6xa9JuRPhRB72rY82QGA==
|
||||
redux@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b"
|
||||
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
||||
|
||||
reflect.getprototypeof@^1.0.4:
|
||||
version "1.0.4"
|
||||
@ -10051,11 +10051,16 @@ requires-port@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
|
||||
|
||||
reselect@^5.0.0, reselect@^5.0.1:
|
||||
reselect@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.0.1.tgz#587cdaaeb4e0e8927cff80ebe2bbef05f74b1648"
|
||||
integrity sha512-D72j2ubjgHpvuCiORWkOUxndHJrxDaSolheiz5CO+roz8ka97/4msh2E8F5qay4GawR5vzBt5MkbDHT+Rdy/Wg==
|
||||
|
||||
reselect@^5.1.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e"
|
||||
integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
|
||||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
|
||||
Reference in New Issue
Block a user