pl-hooks works

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-10-07 23:53:05 +02:00
parent 90c729ff71
commit bd73697628
17 changed files with 208 additions and 144 deletions

View File

@ -6,6 +6,26 @@ import { relationshipSchema } from './relationship';
import { roleSchema } from './role';
import { coerceObject, dateSchema, filteredArray } from './utils';
const getDomainFromURL = (account: Pick<Account, 'url'>): string => {
try {
const url = account.url;
return new URL(url).host;
} catch {
return '';
}
};
const guessFqn = (account: Pick<Account, 'acct' | 'url'>): string => {
const acct = account.acct;
const [user, domain] = acct.split('@');
if (domain) {
return acct;
} else {
return [user, getDomainFromURL(account)].join('@');
}
};
const filterBadges = (tags?: string[]) =>
tags?.filter(tag => tag.startsWith('badge:')).map(tag => roleSchema.parse({ id: tag, name: tag.replace(/^badge:/, '') }));
@ -13,9 +33,12 @@ const preprocessAccount = (account: any) => {
if (!account?.acct) return null;
const username = account.username || account.acct.split('@')[0];
const fqn = guessFqn(account);
return {
username,
fqn,
domain: fqn.split('@')[1] || '',
avatar_static: account.avatar_static || account.avatar,
header_static: account.header_static || account.header,
local: typeof account.pleroma?.is_local === 'boolean' ? account.pleroma.is_local : account.acct.split('@')[1] === undefined,
@ -120,6 +143,7 @@ const baseAccountSchema = z.object({
header_description: z.string().catch(''),
verified: z.boolean().optional().catch(undefined),
domain: z.string().catch(''),
__meta: coerceObject({
pleroma: z.any().optional().catch(undefined),

View File

@ -1,7 +1,8 @@
import { makeGetAccount } from 'pl-fe/selectors';
import { queryClient } from 'pl-fe/queries/client';
import KVStore from 'pl-fe/storage/kv-store';
import type { MinifiedAccount } from 'pl-fe/pl-hooks/minifiers/minifyAccount';
import type { AppDispatch, RootState } from 'pl-fe/store';
const DRAFT_STATUSES_FETCH_SUCCESS = 'DRAFT_STATUSES_FETCH_SUCCESS' as const;
@ -9,12 +10,10 @@ const DRAFT_STATUSES_FETCH_SUCCESS = 'DRAFT_STATUSES_FETCH_SUCCESS' as const;
const PERSIST_DRAFT_STATUS = 'PERSIST_DRAFT_STATUS' as const;
const CANCEL_DRAFT_STATUS = 'DELETE_DRAFT_STATUS' as const;
const getAccount = makeGetAccount();
const fetchDraftStatuses = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const accountUrl = getAccount(state, state.me as string)!.url;
const accountUrl = queryClient.getQueryData<MinifiedAccount>(['accounts', 'entities', state.me])!.url;
return KVStore.getItem(`drafts:${accountUrl}`).then((statuses) => {
dispatch({
@ -27,7 +26,7 @@ const fetchDraftStatuses = () =>
const saveDraftStatus = (composeId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const accountUrl = getAccount(state, state.me as string)!.url;
const accountUrl = queryClient.getQueryData<MinifiedAccount>(['accounts', 'entities', state.me])!.url;
const compose = state.compose.get(composeId)!;
@ -46,7 +45,7 @@ const saveDraftStatus = (composeId: string) =>
const cancelDraftStatus = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const accountUrl = getAccount(state, state.me as string)!.url;
const accountUrl = queryClient.getQueryData<MinifiedAccount>(['accounts', 'entities', state.me])!.url;
dispatch({
type: CANCEL_DRAFT_STATUS,

View File

@ -7,7 +7,7 @@ import { getNotificationStatus } from 'pl-fe/features/notifications/components/n
import { normalizeNotification } from 'pl-fe/normalizers';
import { importEntities } from 'pl-fe/pl-hooks/importer';
import { queryClient } from 'pl-fe/queries/client';
import { getFilters, regexFromFilters } from 'pl-fe/selectors';
// import { getFilters, regexFromFilters } from 'pl-fe/selectors';
import { useSettingsStore } from 'pl-fe/stores/settings';
import { unescapeHTML } from 'pl-fe/utils/html';
import { joinPublicPath } from 'pl-fe/utils/static';
@ -60,26 +60,27 @@ const updateNotificationsQueue = (notification: Notification, intlMessages: Reco
if (!notification.type) return; // drop invalid notifications
if (notification.type === 'chat_mention') return; // Drop chat notifications, handle them per-chat
const filters = getFilters(getState(), { contextType: 'notifications' });
// TODO: Restore filtering
// const filters = getFilters(getState(), { contextType: 'notifications' });
const status = getNotificationStatus(notification);
let filtered: boolean | null = false;
// let filtered: boolean | null = false;
const isOnNotificationsPage = curPath === '/notifications';
if (notification.type === 'mention' || notification.type === 'status') {
const regex = regexFromFilters(filters);
const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content);
filtered = regex && regex.test(searchIndex);
}
// if (notification.type === 'mention' || notification.type === 'status') {
// const regex = regexFromFilters(filters);
// const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content);
// filtered = regex && regex.test(searchIndex);
// }
// Desktop notifications
try {
// eslint-disable-next-line compat/compat
const isNotificationsEnabled = window.Notification?.permission === 'granted';
if (!filtered && isNotificationsEnabled) {
if (/* !filtered && */ isNotificationsEnabled) {
const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username }) as string;
const body = (status && status.spoiler_text.length > 0) ? status.spoiler_text : unescapeHTML(status ? status.content : '');

View File

@ -3,7 +3,8 @@ import { defineMessage } from 'react-intl';
import { patchMe } from 'pl-fe/actions/me';
import { getClient } from 'pl-fe/api';
import messages from 'pl-fe/messages';
import { makeGetAccount } from 'pl-fe/selectors';
import { MinifiedAccount } from 'pl-fe/pl-hooks/minifiers/minifyAccount';
import { queryClient } from 'pl-fe/queries/client';
import KVStore from 'pl-fe/storage/kv-store';
import { useSettingsStore } from 'pl-fe/stores/settings';
import toast from 'pl-fe/toast';
@ -13,8 +14,6 @@ import type { AppDispatch, RootState } from 'pl-fe/store';
const FE_NAME = 'pl_fe';
const getAccount = makeGetAccount();
/** Options when changing/saving settings. */
type SettingOpts = {
/** Whether to display an alert when settings are saved. */
@ -71,7 +70,7 @@ const updateSettingsStore = (settings: any) =>
},
}));
} else {
const accountUrl = getAccount(state, state.me as string)!.url;
const accountUrl = queryClient.getQueryData<MinifiedAccount>(['accounts', 'entities', state.me])!.url;
return updateAuthAccount(accountUrl, settings);
}

View File

@ -80,7 +80,6 @@ const StatusHoverCard: React.FC<IStatusHoverCard> = ({ visible = true }) => {
if (!statusId) return null;
const renderStatus = (statusId: string) => (
// @ts-ignore
<StatusContainer
key={statusId}
id={statusId}

View File

@ -1,5 +1,5 @@
import clsx from 'clsx';
import React, { useCallback, useEffect, useRef } from 'react';
import React, { useEffect, useRef } from 'react';
import { defineMessages, useIntl, FormattedList, FormattedMessage } from 'react-intl';
import { Link, useHistory } from 'react-router-dom';
@ -11,8 +11,8 @@ import AccountContainer from 'pl-fe/containers/account-container';
import StatusTypeIcon from 'pl-fe/features/status/components/status-type-icon';
import QuotedStatus from 'pl-fe/features/status/containers/quoted-status-container';
import { HotKeys } from 'pl-fe/features/ui/components/hotkeys';
import { useAppDispatch, useAppSelector, useSettings } from 'pl-fe/hooks';
import { makeGetStatus, type SelectedStatus } from 'pl-fe/selectors';
import { useAppDispatch, useSettings } from 'pl-fe/hooks';
import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import { useModalsStore } from 'pl-fe/stores';
import { textForScreenReader } from 'pl-fe/utils/status';
@ -27,6 +27,8 @@ import SensitiveContentOverlay from './statuses/sensitive-content-overlay';
import StatusInfo from './statuses/status-info';
import { Card, Icon, Stack, Text } from './ui';
import type { SelectedStatus } from 'pl-fe/selectors';
const messages = defineMessages({
reblogged_by: { id: 'status.reblogged_by', defaultMessage: '{name} reposted' },
});
@ -80,8 +82,7 @@ const Status: React.FC<IStatus> = (props) => {
const didShowCard = useRef(false);
const node = useRef<HTMLDivElement>(null);
const getStatus = useCallback(makeGetStatus(), []);
const actualStatus = useAppSelector(state => status.reblog_id && getStatus(state, { id: status.reblog_id }) || status)!;
const actualStatus = useStatus(status.reblog_id || undefined).data || status;
const isReblog = status.reblog_id;
const statusUrl = `/@${actualStatus.account.acct}/posts/${actualStatus.id}`;

View File

@ -1,8 +1,7 @@
import React, { useCallback } from 'react';
import React from 'react';
import Status, { IStatus } from 'pl-fe/components/status';
import { useAppSelector } from 'pl-fe/hooks';
import { makeGetStatus } from 'pl-fe/selectors';
import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IStatusContainer extends Omit<IStatus, 'status'> {
id: string;
@ -12,14 +11,12 @@ interface IStatusContainer extends Omit<IStatus, 'status'> {
}
/**
* Legacy Status wrapper accepting a status ID instead of the full entity.
* @deprecated Use the Status component directly.
* Status wrapper accepting a status ID instead of the full entity.
*/
const StatusContainer: React.FC<IStatusContainer> = (props) => {
const { id, contextType, ...rest } = props;
const getStatus = useCallback(makeGetStatus(), []);
const status = useAppSelector(state => getStatus(state, { id, contextType }));
const { data: status } = useStatus(id);
if (status) {
return <Status status={status} {...rest} />;

View File

@ -47,7 +47,6 @@ const Conversation: React.FC<IConversation> = ({ conversationId, onMoveUp, onMov
}
return (
// @ts-ignore
<StatusContainer
id={lastStatusId}
unread={unread}

View File

@ -141,7 +141,6 @@ const SearchResults = () => {
if (results.statuses && results.statuses.length > 0) {
searchResults = results.statuses.map((statusId: string) => (
// @ts-ignore
<StatusContainer
key={statusId}
id={statusId}
@ -152,7 +151,6 @@ const SearchResults = () => {
resultsIds = results.statuses;
} else if (!submitted && !filterByAccount && trendingStatuses && trendingStatuses.length !== 0) {
searchResults = trendingStatuses.map((statusId: string) => (
// @ts-ignore
<StatusContainer
key={statusId}
id={statusId}

View File

@ -42,7 +42,6 @@ const ThreadStatus: React.FC<IThreadStatus> = (props): JSX.Element => {
<div className='thread__status relative pb-4'>
{renderConnector()}
{isLoaded ? (
// @ts-ignore FIXME
<StatusContainer {...props} showGroup={false} />
) : (
<PlaceholderStatus variant='default' />

View File

@ -1,7 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import { useRelationship } from 'pl-fe/api/hooks/accounts/useRelationship';
import { useAppSelector, useClient } from 'pl-fe/hooks';
import { useClient } from 'pl-fe/hooks';
import { type MinifiedAccount, minifyAccount } from 'pl-fe/pl-hooks/minifiers/minifyAccount';
import { normalizeAccount } from 'pl-fe/pl-hooks/normalizers/normalizeAccount';
import { queryClient } from 'pl-fe/queries/client';
interface UseAccountOpts {
withRelationship?: boolean;
@ -24,19 +27,14 @@ const useAccount = (accountId?: string, opts: UseAccountOpts = {}) => {
enabled: opts.withRelationship,
});
const movedQuery = useAccount(opts.withMoveTarget && accountQuery.data?.moved_id || undefined);
const data: Account | null = useAppSelector((state) => {
const account = accountQuery.data;
if (!account) return null;
return {
...account,
account,
let data;
if (accountQuery.data) {
data = {
...accountQuery.data,
relationship: relationshipQuery.relationship,
moved: movedQuery.data || null,
moved: opts.withMoveTarget && queryClient.getQueryData(['accounts', 'entities', accountQuery.data?.moved_id]) as MinifiedAccount || null,
};
});
} else data = null;
return { ...accountQuery, data };
};

View File

@ -3,6 +3,7 @@ import { useIntl } from 'react-intl';
import { useAccount, useGroup } from 'pl-fe/api/hooks';
import { useAppSelector, useClient } from 'pl-fe/hooks';
import { importEntities } from 'pl-fe/pl-hooks/importer';
import { queryClient } from 'pl-fe/queries/client';
import { selectAccount, selectAccounts } from 'pl-fe/selectors';
@ -13,6 +14,76 @@ import { normalizeStatus } from '../../normalizers/normalizeStatus';
type Account = ReturnType<typeof selectAccount>;
// const toServerSideType = (columnType: string): Filter['context'][0] => {
// switch (columnType) {
// case 'home':
// case 'notifications':
// case 'public':
// case 'thread':
// return columnType;
// default:
// if (columnType.includes('list:')) {
// return 'home';
// } else {
// return 'public'; // community, account, hashtag
// }
// }
// };
// type FilterContext = { contextType?: string };
// const getFilters = (state: RootState, query: FilterContext) =>
// state.filters.filter((filter) =>
// (!query?.contextType || filter.context.includes(toServerSideType(query.contextType)))
// && (filter.expires_at === null || Date.parse(filter.expires_at) > new Date().getTime()),
// );
// const escapeRegExp = (string: string) =>
// string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
// const regexFromFilters = (filters: ImmutableList<Filter>) => {
// if (filters.size === 0) return null;
// return new RegExp(filters.map(filter =>
// filter.keywords.map(keyword => {
// let expr = escapeRegExp(keyword.keyword);
// if (keyword.whole_word) {
// if (/^[\w]/.test(expr)) {
// expr = `\\b${expr}`;
// }
// if (/[\w]$/.test(expr)) {
// expr = `${expr}\\b`;
// }
// }
// return expr;
// }).join('|'),
// ).join('|'), 'i');
// };
// const checkFiltered = (index: string, filters: ImmutableList<Filter>) =>
// filters.reduce((result: Array<string>, filter) =>
// result.concat(filter.keywords.reduce((result: Array<string>, keyword) => {
// let expr = escapeRegExp(keyword.keyword);
// if (keyword.whole_word) {
// if (/^[\w]/.test(expr)) {
// expr = `\\b${expr}`;
// }
// if (/[\w]$/.test(expr)) {
// expr = `${expr}\\b`;
// }
// }
// const regex = new RegExp(expr);
// if (regex.test(index)) return result.concat(filter.title);
// return result;
// }, [])), []);
const importStatus = (status: MinifiedStatus) => {
queryClient.setQueryData<MinifiedStatus>(
['statuses', 'entities', status.id],
@ -29,6 +100,7 @@ const useStatus = (statusId?: string) => {
queryFn: () => client.statuses.getStatus(statusId!, {
language: intl.locale,
})
.then(status => (importEntities({ statuses: [status] }, { withParents: false }), status))
.then(normalizeStatus)
.then(minifyStatus),
enabled: !!statusId,
@ -51,9 +123,13 @@ const useStatus = (statusId?: string) => {
return {
...status,
account,
account: account!,
accounts,
group,
// quote,
// reblog,
// poll
};
});

View File

@ -47,6 +47,8 @@ const importEntities = (entities: {
polls?: Array<BasePoll>;
statuses?: Array<BaseStatus>;
relationships?: Array<BaseRelationship>;
}, options = {
withParents: true,
}) => {
const accounts: Record<string, BaseAccount> = {};
const groups: Record<string, BaseGroup> = {};
@ -55,14 +57,15 @@ const importEntities = (entities: {
const relationships: Record<string, BaseRelationship> = {};
const statuses: Record<string, BaseStatus> = {};
const processAccount = (account: BaseAccount) => {
accounts[account.id] = account;
const processAccount = (account: BaseAccount, withParent = true) => {
if (withParent) accounts[account.id] = account;
if (account.moved) processAccount(account.moved);
if (account.relationship) relationships[account.relationship.id] = account.relationship;
};
const processNotification = (notification: DeduplicatedNotification) => {
notifications[notification.id] = notification;
const processNotification = (notification: DeduplicatedNotification, withParent = true) => {
if (withParent) notifications[notification.id] = notification;
processAccount(notification.account);
if (notification.type === 'move') processAccount(notification.target);
@ -72,9 +75,9 @@ const importEntities = (entities: {
processStatus(notification.status);
};
const processStatus = (status: BaseStatus) => {
const processStatus = (status: BaseStatus, withParent = true) => {
if (status.account) {
statuses[status.id] = status;
if (withParent) statuses[status.id] = status;
processAccount(status.account);
}
@ -84,12 +87,15 @@ const importEntities = (entities: {
if (status.group) groups[status.group.id] = status.group;
};
entities.accounts?.forEach(processAccount);
entities.groups?.forEach(group => groups[group.id] = group);
entities.notifications?.forEach(processNotification);
entities.polls?.forEach(poll => polls[poll.id] = poll);
entities.relationships?.forEach(relationship => relationships[relationship.id] = relationship);
entities.statuses?.forEach(processStatus);
if (options.withParents) {
entities.groups?.forEach(group => groups[group.id] = group);
entities.polls?.forEach(poll => polls[poll.id] = poll);
entities.relationships?.forEach(relationship => relationships[relationship.id] = relationship);
}
entities.accounts?.forEach((account) => processAccount(account, options.withParents));
entities.notifications?.forEach((notification) => processNotification(notification, options.withParents));
entities.statuses?.forEach((status) => processStatus(status, options.withParents));
if (!isEmpty(accounts)) dispatch(importAccounts(Object.values(accounts)));
if (!isEmpty(groups)) dispatch(importGroups(Object.values(groups)));

View File

@ -0,0 +1,10 @@
import type { Account } from '../normalizers/normalizeAccount';
const minifyAccount = ({ moved, ...account }: Account) => ({
...account,
moved_id: moved?.id || null,
});
type MinifiedAccount = ReturnType<typeof minifyAccount>;
export { minifyAccount, type MinifiedAccount };

View File

@ -0,0 +1,37 @@
import escapeTextContentForBrowser from 'escape-html';
import emojify from 'pl-fe/features/emoji';
import { unescapeHTML } from 'pl-fe/utils/html';
import { makeEmojiMap } from 'pl-fe/utils/normalizers';
import type { Account as BaseAccount } from 'pl-api';
const normalizeAccount = (account: BaseAccount) => {
const missingAvatar = require('pl-fe/assets/images/avatar-missing.png');
const missingHeader = require('pl-fe/assets/images/header-missing.png');
const note = account.note === '<p></p>' ? '' : account.note;
const emojiMap = makeEmojiMap(account.emojis);
return {
...account,
avatar: account.avatar || account.avatar_static || missingAvatar,
avatar_static: account.avatar_static || account.avatar || missingAvatar,
header: account.header || account.header_static || missingHeader,
header_static: account.header_static || account.header || missingHeader,
note,
display_name_html: emojify(escapeTextContentForBrowser(account.display_name), emojiMap),
note_emojified: emojify(account.note, emojiMap),
note_plain: unescapeHTML(account.note),
fields: account.fields.map(field => ({
...field,
name_emojified: emojify(escapeTextContentForBrowser(field.name), emojiMap),
value_emojified: emojify(field.value, emojiMap),
value_plain: unescapeHTML(field.value),
})),
};
};
type Account = ReturnType<typeof normalizeAccount>;
export { normalizeAccount, type Account };

View File

@ -8,7 +8,7 @@ import DOMPurify from 'isomorphic-dompurify';
import { type Account as BaseAccount, type Status as BaseStatus, type MediaAttachment, mentionSchema, type Translation } from 'pl-api';
import emojify from 'pl-fe/features/emoji';
import { stripCompatibilityFeatures, unescapeHTML } from 'pl-fe/utils/html';
import { unescapeHTML } from 'pl-fe/utils/html';
import { makeEmojiMap } from 'pl-fe/utils/normalizers';
const domParser = new DOMParser();
@ -58,7 +58,7 @@ const buildSearchContent = (status: Pick<BaseStatus, 'poll' | 'mentions' | 'spoi
return unescapeHTML(fields.join('\n\n')) || '';
};
const calculateContent = (text: string, emojiMap: any, hasQuote?: boolean) => DOMPurify.sanitize(stripCompatibilityFeatures(emojify(text, emojiMap), hasQuote), { USE_PROFILES: { html: true } });
const calculateContent = (text: string, emojiMap: any, hasQuote?: boolean) => emojify(text, emojiMap);
const calculateSpoiler = (text: string, emojiMap: any) => DOMPurify.sanitize(emojify(escapeTextContentForBrowser(text), emojiMap), { USE_PROFILES: { html: true } });
const calculateStatus = (status: BaseStatus, oldStatus?: OldStatus): CalculatedValues => {

View File

@ -13,7 +13,7 @@ import { validId } from 'pl-fe/utils/auth';
import ConfigDB from 'pl-fe/utils/config-db';
import { shouldFilter } from 'pl-fe/utils/timelines';
import type { Account as BaseAccount, Filter, MediaAttachment, Relationship } from 'pl-api';
import type { Account as BaseAccount, MediaAttachment, Relationship } from 'pl-api';
import type { EntityStore } from 'pl-fe/entity-store/types';
import type { Account, Group } from 'pl-fe/normalizers';
import type { MinifiedStatus } from 'pl-fe/reducers/statuses';
@ -49,76 +49,6 @@ const makeGetAccount = () => createSelector([
};
});
const toServerSideType = (columnType: string): Filter['context'][0] => {
switch (columnType) {
case 'home':
case 'notifications':
case 'public':
case 'thread':
return columnType;
default:
if (columnType.includes('list:')) {
return 'home';
} else {
return 'public'; // community, account, hashtag
}
}
};
type FilterContext = { contextType?: string };
const getFilters = (state: RootState, query: FilterContext) =>
state.filters.filter((filter) =>
(!query?.contextType || filter.context.includes(toServerSideType(query.contextType)))
&& (filter.expires_at === null || Date.parse(filter.expires_at) > new Date().getTime()),
);
const escapeRegExp = (string: string) =>
string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
const regexFromFilters = (filters: ImmutableList<Filter>) => {
if (filters.size === 0) return null;
return new RegExp(filters.map(filter =>
filter.keywords.map(keyword => {
let expr = escapeRegExp(keyword.keyword);
if (keyword.whole_word) {
if (/^[\w]/.test(expr)) {
expr = `\\b${expr}`;
}
if (/[\w]$/.test(expr)) {
expr = `${expr}\\b`;
}
}
return expr;
}).join('|'),
).join('|'), 'i');
};
const checkFiltered = (index: string, filters: ImmutableList<Filter>) =>
filters.reduce((result: Array<string>, filter) =>
result.concat(filter.keywords.reduce((result: Array<string>, keyword) => {
let expr = escapeRegExp(keyword.keyword);
if (keyword.whole_word) {
if (/^[\w]/.test(expr)) {
expr = `\\b${expr}`;
}
if (/[\w]$/.test(expr)) {
expr = `${expr}\\b`;
}
}
const regex = new RegExp(expr);
if (regex.test(index)) return result.concat(filter.title);
return result;
}, [])), []);
type APIStatus = { id: string; username?: string };
const makeGetStatus = () => createSelector(
@ -133,13 +63,12 @@ const makeGetStatus = () => createSelector(
},
(state: RootState, { id }: APIStatus) => state.polls.get(id) || null,
(_state: RootState, { username }: APIStatus) => username,
getFilters,
(state: RootState) => state.me,
(state: RootState) => state.auth.client.features,
(state: RootState) => getLocale('en'),
],
(statusBase, statusReblog, statusQuote, statusGroup, poll, username, filters, me, features, locale) => {
(statusBase, statusReblog, statusQuote, statusGroup, poll, username, me, features, locale) => {
if (!statusBase) return null;
const { account } = statusBase;
const accountUsername = account.acct;
@ -149,17 +78,12 @@ const makeGetStatus = () => createSelector(
return null;
}
const filtered = features.filtersV2
? statusBase.filtered
: features.filters && account.id !== me && checkFiltered(statusReblog?.search_index || statusBase.search_index || '', filters) || [];
return {
...statusBase,
reblog: statusReblog || null,
quote: statusQuote || null,
group: statusGroup || null,
poll,
filtered,
};
// if (map.currentLanguage === null && map.content_map?.size) {
// let currentLanguage: string | null = null;
@ -329,9 +253,6 @@ export {
selectAccounts,
selectOwnAccount,
makeGetAccount,
getFilters,
regexFromFilters,
makeGetStatus,
type SelectedStatus,
type AccountGalleryAttachment,
getAccountGallery,