diff --git a/packages/pl-api/lib/entities/account.ts b/packages/pl-api/lib/entities/account.ts
index 269d74d5f..e13843263 100644
--- a/packages/pl-api/lib/entities/account.ts
+++ b/packages/pl-api/lib/entities/account.ts
@@ -96,7 +96,7 @@ const baseAccountSchema = z.object({
acct: z.string().catch(''),
url: z.string().url(),
display_name: z.string().catch(''),
- note: z.string().catch(''),
+ note: z.string().transform(note => note === '
' ? '' : note).catch(''),
avatar: z.string().catch(''),
avatar_static: z.string().url().catch(''),
header: z.string().url().catch(''),
diff --git a/packages/pl-api/lib/entities/status.ts b/packages/pl-api/lib/entities/status.ts
index 69dc9e2b4..e6cd32770 100644
--- a/packages/pl-api/lib/entities/status.ts
+++ b/packages/pl-api/lib/entities/status.ts
@@ -41,7 +41,7 @@ const baseStatusSchema = z.object({
uri: z.string().url().catch(''),
created_at: dateSchema,
account: accountSchema,
- content: z.string().catch(''),
+ content: z.string().transform(note => note === '' ? '' : note).catch(''),
visibility: z.string().catch('public'),
sensitive: z.coerce.boolean(),
spoiler_text: z.string().catch(''),
diff --git a/packages/pl-fe/src/actions/accounts.ts b/packages/pl-fe/src/actions/accounts.ts
index 7022cfff6..bea1397b1 100644
--- a/packages/pl-fe/src/actions/accounts.ts
+++ b/packages/pl-fe/src/actions/accounts.ts
@@ -1,10 +1,10 @@
import { PLEROMA, type UpdateNotificationSettingsParams, type Account, type CreateAccountParams, type PaginatedResponse, type Relationship } from 'pl-api';
+import { importEntities } from 'pl-hooks/importer';
import { getClient, type PlfeResponse } from 'pl-fe/api';
import { Entities } from 'pl-fe/entity-store/entities';
import { selectAccount } from 'pl-fe/selectors';
import { isLoggedIn } from 'pl-fe/utils/auth';
-import { importEntities } from 'pl-hooks/importer';
import type { Map as ImmutableMap } from 'immutable';
import type { MinifiedStatus } from 'pl-fe/reducers/statuses';
diff --git a/packages/pl-fe/src/actions/admin.ts b/packages/pl-fe/src/actions/admin.ts
index 47795cea0..2ea917a98 100644
--- a/packages/pl-fe/src/actions/admin.ts
+++ b/packages/pl-fe/src/actions/admin.ts
@@ -1,7 +1,8 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { fetchRelationships } from 'pl-fe/actions/accounts';
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { filterBadges, getTagDiff } from 'pl-fe/utils/badges';
import { deleteFromTimelines } from './timelines';
diff --git a/packages/pl-fe/src/actions/aliases.ts b/packages/pl-fe/src/actions/aliases.ts
index aad1dc396..3b914eb01 100644
--- a/packages/pl-fe/src/actions/aliases.ts
+++ b/packages/pl-fe/src/actions/aliases.ts
@@ -1,7 +1,7 @@
+import { importEntities } from 'pl-hooks/importer';
import { defineMessages } from 'react-intl';
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import toast from 'pl-fe/toast';
import { isLoggedIn } from 'pl-fe/utils/auth';
diff --git a/packages/pl-fe/src/actions/auth.ts b/packages/pl-fe/src/actions/auth.ts
index efb65ec74..5584a754f 100644
--- a/packages/pl-fe/src/actions/auth.ts
+++ b/packages/pl-fe/src/actions/auth.ts
@@ -7,6 +7,7 @@
* @see module:pl-fe/actions/security
*/
import { credentialAccountSchema, PlApiClient, type CreateAccountParams, type Token } from 'pl-api';
+import { importEntities } from 'pl-hooks/importer';
import { defineMessages } from 'react-intl';
import { createAccount } from 'pl-fe/actions/accounts';
@@ -17,7 +18,6 @@ import { startOnboarding } from 'pl-fe/actions/onboarding';
import { type PlfeResponse, getClient } from 'pl-fe/api';
import * as BuildConfig from 'pl-fe/build-config';
import { custom } from 'pl-fe/custom';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { queryClient } from 'pl-fe/queries/client';
import { selectAccount } from 'pl-fe/selectors';
import { unsetSentryAccount } from 'pl-fe/sentry';
diff --git a/packages/pl-fe/src/actions/bookmarks.ts b/packages/pl-fe/src/actions/bookmarks.ts
index 13cc43d06..87f371dd7 100644
--- a/packages/pl-fe/src/actions/bookmarks.ts
+++ b/packages/pl-fe/src/actions/bookmarks.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import type { PaginatedResponse, Status } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/compose.ts b/packages/pl-fe/src/actions/compose.ts
index 0089cc814..775f915b6 100644
--- a/packages/pl-fe/src/actions/compose.ts
+++ b/packages/pl-fe/src/actions/compose.ts
@@ -1,11 +1,11 @@
import throttle from 'lodash/throttle';
+import { importEntities } from 'pl-hooks/importer';
import { defineMessages, IntlShape } from 'react-intl';
import { getClient } from 'pl-fe/api';
import { isNativeEmoji } from 'pl-fe/features/emoji';
import emojiSearch from 'pl-fe/features/emoji/search';
import { Language } from 'pl-fe/features/preferences';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { selectAccount, selectOwnAccount, makeGetAccount } from 'pl-fe/selectors';
import { tagHistory } from 'pl-fe/settings';
import { useModalsStore, useSettingsStore } from 'pl-fe/stores';
diff --git a/packages/pl-fe/src/actions/conversations.ts b/packages/pl-fe/src/actions/conversations.ts
index adac3b19f..c74bd11c0 100644
--- a/packages/pl-fe/src/actions/conversations.ts
+++ b/packages/pl-fe/src/actions/conversations.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { isLoggedIn } from 'pl-fe/utils/auth';
import type { Account, Conversation, PaginatedResponse, Status } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/directory.ts b/packages/pl-fe/src/actions/directory.ts
index 7e9fc983e..674c69063 100644
--- a/packages/pl-fe/src/actions/directory.ts
+++ b/packages/pl-fe/src/actions/directory.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { fetchRelationships } from './accounts';
diff --git a/packages/pl-fe/src/actions/draft-statuses.ts b/packages/pl-fe/src/actions/draft-statuses.ts
index d79d9fb45..7ed4ca2b2 100644
--- a/packages/pl-fe/src/actions/draft-statuses.ts
+++ b/packages/pl-fe/src/actions/draft-statuses.ts
@@ -1,8 +1,8 @@
import { queryClient } from 'pl-fe/queries/client';
import KVStore from 'pl-fe/storage/kv-store';
-import type { Account } from 'pl-fe/pl-hooks/normalizers/normalizeAccount';
import type { AppDispatch, RootState } from 'pl-fe/store';
+import type { Account } from 'pl-hooks/normalizers/normalizeAccount';
const DRAFT_STATUSES_FETCH_SUCCESS = 'DRAFT_STATUSES_FETCH_SUCCESS' as const;
diff --git a/packages/pl-fe/src/actions/emoji-reacts.ts b/packages/pl-fe/src/actions/emoji-reacts.ts
index 54bc4899d..01beefc25 100644
--- a/packages/pl-fe/src/actions/emoji-reacts.ts
+++ b/packages/pl-fe/src/actions/emoji-reacts.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { isLoggedIn } from 'pl-fe/utils/auth';
import type { Status } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/events.ts b/packages/pl-fe/src/actions/events.ts
index 515646a71..13f4a07ba 100644
--- a/packages/pl-fe/src/actions/events.ts
+++ b/packages/pl-fe/src/actions/events.ts
@@ -1,8 +1,8 @@
+import { importEntities } from 'pl-hooks/importer';
import { defineMessages } from 'react-intl';
import { STATUS_FETCH_SOURCE_FAIL, STATUS_FETCH_SOURCE_REQUEST, STATUS_FETCH_SOURCE_SUCCESS } from 'pl-fe/actions/statuses';
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';
diff --git a/packages/pl-fe/src/actions/familiar-followers.ts b/packages/pl-fe/src/actions/familiar-followers.ts
index 404a99259..bf28b7a30 100644
--- a/packages/pl-fe/src/actions/familiar-followers.ts
+++ b/packages/pl-fe/src/actions/familiar-followers.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { AppDispatch, RootState } from 'pl-fe/store';
import { fetchRelationships } from './accounts';
diff --git a/packages/pl-fe/src/actions/favourites.ts b/packages/pl-fe/src/actions/favourites.ts
index 2ba10fcd5..0edef7438 100644
--- a/packages/pl-fe/src/actions/favourites.ts
+++ b/packages/pl-fe/src/actions/favourites.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { isLoggedIn } from 'pl-fe/utils/auth';
import type { PaginatedResponse, Status } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/groups.ts b/packages/pl-fe/src/actions/groups.ts
index e5aef02e7..116e98325 100644
--- a/packages/pl-fe/src/actions/groups.ts
+++ b/packages/pl-fe/src/actions/groups.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import type { Account, PaginatedResponse } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/history.ts b/packages/pl-fe/src/actions/history.ts
index ae46fa8bd..8a0eb0665 100644
--- a/packages/pl-fe/src/actions/history.ts
+++ b/packages/pl-fe/src/actions/history.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import type { StatusEdit } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/interactions.ts b/packages/pl-fe/src/actions/interactions.ts
index 81a36c9c8..c5010096b 100644
--- a/packages/pl-fe/src/actions/interactions.ts
+++ b/packages/pl-fe/src/actions/interactions.ts
@@ -1,7 +1,7 @@
+import { importEntities } from 'pl-hooks/importer';
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, { type IToastOptions } from 'pl-fe/toast';
import { isLoggedIn } from 'pl-fe/utils/auth';
diff --git a/packages/pl-fe/src/actions/lists.ts b/packages/pl-fe/src/actions/lists.ts
index 502a363a9..2ec70deb3 100644
--- a/packages/pl-fe/src/actions/lists.ts
+++ b/packages/pl-fe/src/actions/lists.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { selectAccount } from 'pl-fe/selectors';
import toast from 'pl-fe/toast';
import { isLoggedIn } from 'pl-fe/utils/auth';
diff --git a/packages/pl-fe/src/actions/me.ts b/packages/pl-fe/src/actions/me.ts
index 27f7b10df..462004e8c 100644
--- a/packages/pl-fe/src/actions/me.ts
+++ b/packages/pl-fe/src/actions/me.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { selectAccount } from 'pl-fe/selectors';
import { setSentryAccount } from 'pl-fe/sentry';
import KVStore from 'pl-fe/storage/kv-store';
diff --git a/packages/pl-fe/src/actions/notifications.ts b/packages/pl-fe/src/actions/notifications.ts
index 3c7b2be1d..df82c8508 100644
--- a/packages/pl-fe/src/actions/notifications.ts
+++ b/packages/pl-fe/src/actions/notifications.ts
@@ -1,11 +1,11 @@
import IntlMessageFormat from 'intl-messageformat';
import 'intl-pluralrules';
+import { importEntities } from 'pl-hooks/importer';
import { defineMessages } from 'react-intl';
import { FILTER_TYPES, type FilterType } from 'pl-fe/features/notifications';
import { getNotificationStatus } from 'pl-fe/features/notifications/components/notification';
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 { useSettingsStore } from 'pl-fe/stores';
diff --git a/packages/pl-fe/src/actions/pin-statuses.ts b/packages/pl-fe/src/actions/pin-statuses.ts
index f4968f194..9ee169a10 100644
--- a/packages/pl-fe/src/actions/pin-statuses.ts
+++ b/packages/pl-fe/src/actions/pin-statuses.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { isLoggedIn } from 'pl-fe/utils/auth';
import type { Status } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/polls.ts b/packages/pl-fe/src/actions/polls.ts
index 132d5fcd9..601cc63c5 100644
--- a/packages/pl-fe/src/actions/polls.ts
+++ b/packages/pl-fe/src/actions/polls.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import type { Poll } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/preload.ts b/packages/pl-fe/src/actions/preload.ts
index 7925046ea..3fbab4a6e 100644
--- a/packages/pl-fe/src/actions/preload.ts
+++ b/packages/pl-fe/src/actions/preload.ts
@@ -1,6 +1,5 @@
import mapValues from 'lodash/mapValues';
-
-import { importEntities } from 'pl-fe/pl-hooks/importer';
+import { importEntities } from 'pl-hooks/importer';
import { verifyCredentials } from './auth';
diff --git a/packages/pl-fe/src/actions/search.ts b/packages/pl-fe/src/actions/search.ts
index ef7d8d12c..49d933c1b 100644
--- a/packages/pl-fe/src/actions/search.ts
+++ b/packages/pl-fe/src/actions/search.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { useSettingsStore } from 'pl-fe/stores';
import { fetchRelationships } from './accounts';
diff --git a/packages/pl-fe/src/actions/settings.ts b/packages/pl-fe/src/actions/settings.ts
index ddf9e8e3c..61003930c 100644
--- a/packages/pl-fe/src/actions/settings.ts
+++ b/packages/pl-fe/src/actions/settings.ts
@@ -1,9 +1,9 @@
+import { Account } from 'pl-hooks/normalizers/normalizeAccount';
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 { Account } from 'pl-fe/pl-hooks/normalizers/normalizeAccount';
import { queryClient } from 'pl-fe/queries/client';
import KVStore from 'pl-fe/storage/kv-store';
import { useSettingsStore } from 'pl-fe/stores';
diff --git a/packages/pl-fe/src/actions/status-quotes.ts b/packages/pl-fe/src/actions/status-quotes.ts
index 8aa0cad43..a40dbc437 100644
--- a/packages/pl-fe/src/actions/status-quotes.ts
+++ b/packages/pl-fe/src/actions/status-quotes.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import type { Status as BaseStatus, PaginatedResponse } from 'pl-api';
diff --git a/packages/pl-fe/src/actions/statuses.ts b/packages/pl-fe/src/actions/statuses.ts
index bc9064538..cec4f6927 100644
--- a/packages/pl-fe/src/actions/statuses.ts
+++ b/packages/pl-fe/src/actions/statuses.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { useModalsStore, useSettingsStore } from 'pl-fe/stores';
import { isLoggedIn } from 'pl-fe/utils/auth';
import { shouldHaveCard } from 'pl-fe/utils/status';
diff --git a/packages/pl-fe/src/actions/suggestions.ts b/packages/pl-fe/src/actions/suggestions.ts
index 10d052e6f..109c5fcc9 100644
--- a/packages/pl-fe/src/actions/suggestions.ts
+++ b/packages/pl-fe/src/actions/suggestions.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { fetchRelationships } from './accounts';
diff --git a/packages/pl-fe/src/actions/timelines.ts b/packages/pl-fe/src/actions/timelines.ts
index 0dd14251c..8f0af94fc 100644
--- a/packages/pl-fe/src/actions/timelines.ts
+++ b/packages/pl-fe/src/actions/timelines.ts
@@ -1,9 +1,8 @@
import { Map as ImmutableMap } from 'immutable';
-
+import { importEntities } from 'pl-hooks/importer';
import { getLocale } from 'pl-fe/actions/settings';
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { useSettingsStore } from 'pl-fe/stores';
import { shouldFilter } from 'pl-fe/utils/timelines';
diff --git a/packages/pl-fe/src/actions/trending-statuses.ts b/packages/pl-fe/src/actions/trending-statuses.ts
index 0cd76b090..5c41d8734 100644
--- a/packages/pl-fe/src/actions/trending-statuses.ts
+++ b/packages/pl-fe/src/actions/trending-statuses.ts
@@ -1,5 +1,6 @@
+import { importEntities } from 'pl-hooks/importer';
+
import { getClient } from 'pl-fe/api';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import type { AppDispatch, RootState } from 'pl-fe/store';
diff --git a/packages/pl-fe/src/components/quoted-status-indicator.tsx b/packages/pl-fe/src/components/quoted-status-indicator.tsx
index ee150fab4..34f3e7f7f 100644
--- a/packages/pl-fe/src/components/quoted-status-indicator.tsx
+++ b/packages/pl-fe/src/components/quoted-status-indicator.tsx
@@ -1,7 +1,7 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { HStack, Icon, Text } from 'pl-fe/components/ui';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IQuotedStatusIndicator {
/** The quoted status id. */
diff --git a/packages/pl-fe/src/components/status.tsx b/packages/pl-fe/src/components/status.tsx
index 2a68df1a4..c3a1529be 100644
--- a/packages/pl-fe/src/components/status.tsx
+++ b/packages/pl-fe/src/components/status.tsx
@@ -1,4 +1,5 @@
import clsx from 'clsx';
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect, useRef } from 'react';
import { defineMessages, useIntl, FormattedList, FormattedMessage } from 'react-intl';
import { Link, useHistory } from 'react-router-dom';
@@ -12,7 +13,6 @@ 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, 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';
diff --git a/packages/pl-fe/src/containers/status-container.tsx b/packages/pl-fe/src/containers/status-container.tsx
index 32ad7e395..cc1ae14df 100644
--- a/packages/pl-fe/src/containers/status-container.tsx
+++ b/packages/pl-fe/src/containers/status-container.tsx
@@ -1,7 +1,7 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import Status, { IStatus } from 'pl-fe/components/status';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IStatusContainer extends Omit {
id: string;
diff --git a/packages/pl-fe/src/features/compose/components/reply-group-indicator.tsx b/packages/pl-fe/src/features/compose/components/reply-group-indicator.tsx
index 47ab97940..d3d900a80 100644
--- a/packages/pl-fe/src/features/compose/components/reply-group-indicator.tsx
+++ b/packages/pl-fe/src/features/compose/components/reply-group-indicator.tsx
@@ -1,10 +1,10 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Link from 'pl-fe/components/link';
import { Text } from 'pl-fe/components/ui';
import { useCompose } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IReplyGroupIndicator {
composeId: string;
diff --git a/packages/pl-fe/src/features/compose/components/reply-mentions.tsx b/packages/pl-fe/src/features/compose/components/reply-mentions.tsx
index 942fbe3ae..1d08a899b 100644
--- a/packages/pl-fe/src/features/compose/components/reply-mentions.tsx
+++ b/packages/pl-fe/src/features/compose/components/reply-mentions.tsx
@@ -1,8 +1,8 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { FormattedList, FormattedMessage } from 'react-intl';
import { useCompose, useFeatures } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import { useModalsStore } from 'pl-fe/stores';
interface IReplyMentions {
diff --git a/packages/pl-fe/src/features/compose/containers/quoted-status-container.tsx b/packages/pl-fe/src/features/compose/containers/quoted-status-container.tsx
index 3dbf2461c..bbcff3515 100644
--- a/packages/pl-fe/src/features/compose/containers/quoted-status-container.tsx
+++ b/packages/pl-fe/src/features/compose/containers/quoted-status-container.tsx
@@ -1,9 +1,9 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { cancelQuoteCompose } from 'pl-fe/actions/compose';
import QuotedStatus from 'pl-fe/components/quoted-status';
import { useAppDispatch, useCompose } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IQuotedStatusContainer {
composeId: string;
diff --git a/packages/pl-fe/src/features/compose/containers/reply-indicator-container.tsx b/packages/pl-fe/src/features/compose/containers/reply-indicator-container.tsx
index 142667542..338ca170f 100644
--- a/packages/pl-fe/src/features/compose/containers/reply-indicator-container.tsx
+++ b/packages/pl-fe/src/features/compose/containers/reply-indicator-container.tsx
@@ -1,8 +1,8 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { cancelReplyCompose } from 'pl-fe/actions/compose';
import { useAppDispatch, useCompose } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import ReplyIndicator from '../components/reply-indicator';
diff --git a/packages/pl-fe/src/features/embedded-status/index.tsx b/packages/pl-fe/src/features/embedded-status/index.tsx
index ba8f4479d..6d310fb78 100644
--- a/packages/pl-fe/src/features/embedded-status/index.tsx
+++ b/packages/pl-fe/src/features/embedded-status/index.tsx
@@ -1,3 +1,4 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
@@ -7,7 +8,6 @@ import Status from 'pl-fe/components/status';
import { Spinner } from 'pl-fe/components/ui';
import { useLogo } from 'pl-fe/hooks';
import { iframeId } from 'pl-fe/iframe';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IEmbeddedStatus {
params: {
diff --git a/packages/pl-fe/src/features/event/event-discussion.tsx b/packages/pl-fe/src/features/event/event-discussion.tsx
index dffa4528f..fc1d243cd 100644
--- a/packages/pl-fe/src/features/event/event-discussion.tsx
+++ b/packages/pl-fe/src/features/event/event-discussion.tsx
@@ -1,4 +1,5 @@
import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable';
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect, useRef, useState } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
@@ -11,7 +12,6 @@ import { Stack } from 'pl-fe/components/ui';
import PlaceholderStatus from 'pl-fe/features/placeholder/components/placeholder-status';
import PendingStatus from 'pl-fe/features/ui/components/pending-status';
import { useAppDispatch, useAppSelector } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import ComposeForm from '../compose/components/compose-form';
import { getDescendantsIds } from '../status/components/thread';
diff --git a/packages/pl-fe/src/features/event/event-information.tsx b/packages/pl-fe/src/features/event/event-information.tsx
index 44ed5c835..c90b1c48e 100644
--- a/packages/pl-fe/src/features/event/event-information.tsx
+++ b/packages/pl-fe/src/features/event/event-information.tsx
@@ -1,3 +1,4 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useCallback } from 'react';
import { FormattedDate, FormattedMessage } from 'react-intl';
@@ -8,7 +9,6 @@ import TranslateButton from 'pl-fe/components/translate-button';
import { HStack, Icon, Stack, Text } from 'pl-fe/components/ui';
import QuotedStatus from 'pl-fe/features/status/containers/quoted-status-container';
import { usePlFeConfig } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import { useModalsStore } from 'pl-fe/stores';
type RouteParams = { statusId: string };
diff --git a/packages/pl-fe/src/features/events/components/event-carousel.tsx b/packages/pl-fe/src/features/events/components/event-carousel.tsx
index d40479986..a8c9910e8 100644
--- a/packages/pl-fe/src/features/events/components/event-carousel.tsx
+++ b/packages/pl-fe/src/features/events/components/event-carousel.tsx
@@ -1,10 +1,10 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import ReactSwipeableViews from 'react-swipeable-views';
import EventPreview from 'pl-fe/components/event-preview';
import { Card, Icon } from 'pl-fe/components/ui';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import PlaceholderEventPreview from '../../placeholder/components/placeholder-event-preview';
diff --git a/packages/pl-fe/src/features/notifications/components/notification.tsx b/packages/pl-fe/src/features/notifications/components/notification.tsx
index 7b2e80200..47cdefd27 100644
--- a/packages/pl-fe/src/features/notifications/components/notification.tsx
+++ b/packages/pl-fe/src/features/notifications/components/notification.tsx
@@ -1,3 +1,4 @@
+import { useNotification } from 'pl-hooks/hooks/notifications/useNotification';
import React, { useCallback } from 'react';
import { defineMessages, useIntl, FormattedList, FormattedMessage, IntlShape, MessageDescriptor } from 'react-intl';
import { Link, useHistory } from 'react-router-dom';
@@ -13,7 +14,6 @@ import AccountContainer from 'pl-fe/containers/account-container';
import StatusContainer from 'pl-fe/containers/status-container';
import { HotKeys } from 'pl-fe/features/ui/components/hotkeys';
import { useAppDispatch, useInstance, useLoggedIn } from 'pl-fe/hooks';
-import { useNotification } from 'pl-fe/pl-hooks/hooks/notifications/useNotification';
import { useModalsStore, useSettingsStore } from 'pl-fe/stores';
import { NotificationType } from 'pl-fe/utils/notification';
diff --git a/packages/pl-fe/src/features/notifications/index.tsx b/packages/pl-fe/src/features/notifications/index.tsx
index 2e1307b67..6526ea704 100644
--- a/packages/pl-fe/src/features/notifications/index.tsx
+++ b/packages/pl-fe/src/features/notifications/index.tsx
@@ -1,5 +1,8 @@
import clsx from 'clsx';
import debounce from 'lodash/debounce';
+import { useMarker } from 'pl-hooks/hooks/markers/useMarkers';
+import { useUpdateMarkerMutation } from 'pl-hooks/hooks/markers/useUpdateMarkerMutation';
+import { useNotificationList } from 'pl-hooks/hooks/notifications/useNotificationList';
import React, { useCallback, useEffect, useRef } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
@@ -10,9 +13,6 @@ import ScrollableList from 'pl-fe/components/scrollable-list';
import { Column, Portal } from 'pl-fe/components/ui';
import PlaceholderNotification from 'pl-fe/features/placeholder/components/placeholder-notification';
import { useAppDispatch, useAppSelector, useSettings } from 'pl-fe/hooks';
-import { useMarker } from 'pl-fe/pl-hooks/hooks/markers/useMarkers';
-import { useUpdateMarkerMutation } from 'pl-fe/pl-hooks/hooks/markers/useUpdateMarkerMutation';
-import { useNotificationList } from 'pl-fe/pl-hooks/hooks/notifications/useNotificationList';
import { compareId } from 'pl-fe/utils/comparators';
import { NotificationType } from 'pl-fe/utils/notification';
diff --git a/packages/pl-fe/src/features/status/containers/quoted-status-container.tsx b/packages/pl-fe/src/features/status/containers/quoted-status-container.tsx
index 9b3ac1ffa..6c28326a5 100644
--- a/packages/pl-fe/src/features/status/containers/quoted-status-container.tsx
+++ b/packages/pl-fe/src/features/status/containers/quoted-status-container.tsx
@@ -1,7 +1,7 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import QuotedStatus from 'pl-fe/components/quoted-status';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IQuotedStatusContainer {
/** Status ID to the quoted status. */
diff --git a/packages/pl-fe/src/features/status/index.tsx b/packages/pl-fe/src/features/status/index.tsx
index 7acb44d1f..00f0c0cb0 100644
--- a/packages/pl-fe/src/features/status/index.tsx
+++ b/packages/pl-fe/src/features/status/index.tsx
@@ -1,3 +1,4 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Redirect } from 'react-router-dom';
@@ -8,7 +9,6 @@ import PullToRefresh from 'pl-fe/components/pull-to-refresh';
import { Column, Stack } from 'pl-fe/components/ui';
import PlaceholderStatus from 'pl-fe/features/placeholder/components/placeholder-status';
import { useAppDispatch, useLoggedIn } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import Thread from './components/thread';
import ThreadLoginCta from './components/thread-login-cta';
diff --git a/packages/pl-fe/src/features/test-timeline/index.tsx b/packages/pl-fe/src/features/test-timeline/index.tsx
index ac7a8c8e2..c81c2c692 100644
--- a/packages/pl-fe/src/features/test-timeline/index.tsx
+++ b/packages/pl-fe/src/features/test-timeline/index.tsx
@@ -1,10 +1,10 @@
+import { importEntities } from 'pl-hooks/importer';
import React from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { expandTimelineSuccess } from 'pl-fe/actions/timelines';
import { useAppDispatch, useTheme } from 'pl-fe/hooks';
import { useIsMobile } from 'pl-fe/hooks/useIsMobile';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { Column } from '../../components/ui';
import Timeline from '../ui/components/timeline';
diff --git a/packages/pl-fe/src/features/ui/components/modals/boost-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/boost-modal.tsx
index 50a65e4ae..5f1a798b0 100644
--- a/packages/pl-fe/src/features/ui/components/modals/boost-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/boost-modal.tsx
@@ -1,10 +1,10 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import Icon from 'pl-fe/components/icon';
import { Modal, Stack, Text } from 'pl-fe/components/ui';
import ReplyIndicator from 'pl-fe/features/compose/components/reply-indicator';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import type { BaseModalProps } from '../modal-root';
import type { Status as StatusEntity } from 'pl-fe/normalizers';
diff --git a/packages/pl-fe/src/features/ui/components/modals/event-map-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/event-map-modal.tsx
index 98608021d..8f651218e 100644
--- a/packages/pl-fe/src/features/ui/components/modals/event-map-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/event-map-modal.tsx
@@ -1,10 +1,10 @@
import L from 'leaflet';
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect, useRef } from 'react';
import { FormattedMessage } from 'react-intl';
import { Button, Modal, Stack } from 'pl-fe/components/ui';
import { usePlFeConfig } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import type { BaseModalProps } from '../modal-root';
diff --git a/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx
index c55943aad..a18d82454 100644
--- a/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/media-modal.tsx
@@ -1,4 +1,5 @@
import clsx from 'clsx';
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect, useState } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
@@ -15,7 +16,6 @@ import Thread from 'pl-fe/features/status/components/thread';
import Video from 'pl-fe/features/video';
import { useAppDispatch } from 'pl-fe/hooks';
import { userTouching } from 'pl-fe/is-mobile';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import ImageLoader from '../image-loader';
diff --git a/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx
index 76a2578c4..4d97e1c22 100644
--- a/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/mentions-modal.tsx
@@ -1,3 +1,4 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useEffect, useRef } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
@@ -6,7 +7,6 @@ import ScrollableList from 'pl-fe/components/scrollable-list';
import { Modal, Spinner } from 'pl-fe/components/ui';
import AccountContainer from 'pl-fe/containers/account-container';
import { useAppDispatch } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import type { BaseModalProps } from '../modal-root';
diff --git a/packages/pl-fe/src/features/ui/components/modals/reply-mentions-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/reply-mentions-modal.tsx
index 40838ae2d..0a8b78a0b 100644
--- a/packages/pl-fe/src/features/ui/components/modals/reply-mentions-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/reply-mentions-modal.tsx
@@ -1,10 +1,10 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Modal } from 'pl-fe/components/ui';
import Account from 'pl-fe/features/reply-mentions/account';
import { useCompose, useOwnAccount } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import { statusToMentionsAccountIdsArray } from 'pl-fe/reducers/compose';
import type { BaseModalProps } from '../modal-root';
diff --git a/packages/pl-fe/src/features/ui/components/modals/select-bookmark-folder-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/select-bookmark-folder-modal.tsx
index 91f1a27c7..76bd3b89e 100644
--- a/packages/pl-fe/src/features/ui/components/modals/select-bookmark-folder-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/select-bookmark-folder-modal.tsx
@@ -1,3 +1,4 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
@@ -7,7 +8,6 @@ import { RadioGroup, RadioItem } from 'pl-fe/components/radio';
import { Emoji, HStack, Icon, Modal, Spinner, Stack } from 'pl-fe/components/ui';
import NewFolderForm from 'pl-fe/features/bookmark-folders/components/new-folder-form';
import { useAppDispatch } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import type { BaseModalProps } from '../modal-root';
diff --git a/packages/pl-fe/src/features/ui/components/modals/video-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/video-modal.tsx
index a65e84569..b8f052aac 100644
--- a/packages/pl-fe/src/features/ui/components/modals/video-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/video-modal.tsx
@@ -1,9 +1,9 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import Video from 'pl-fe/features/video';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
import type { BaseModalProps } from '../modal-root';
import type { MediaAttachment } from 'pl-api';
diff --git a/packages/pl-fe/src/features/ui/index.tsx b/packages/pl-fe/src/features/ui/index.tsx
index 914e9400e..12ea70c4c 100644
--- a/packages/pl-fe/src/features/ui/index.tsx
+++ b/packages/pl-fe/src/features/ui/index.tsx
@@ -1,4 +1,6 @@
import clsx from 'clsx';
+import { prefetchMarker } from 'pl-hooks/hooks/markers/useMarkers';
+import { prefetchNotifications } from 'pl-hooks/hooks/notifications/useNotificationList';
import React, { Suspense, lazy, useEffect, useRef } from 'react';
import { Switch, useHistory, useLocation, Redirect } from 'react-router-dom';
@@ -33,8 +35,6 @@ import ProfileLayout from 'pl-fe/layouts/profile-layout';
import RemoteInstanceLayout from 'pl-fe/layouts/remote-instance-layout';
import SearchLayout from 'pl-fe/layouts/search-layout';
import StatusLayout from 'pl-fe/layouts/status-layout';
-import { prefetchMarker } from 'pl-fe/pl-hooks/hooks/markers/useMarkers';
-import { prefetchNotifications } from 'pl-fe/pl-hooks/hooks/notifications/useNotificationList';
import { useUiStore } from 'pl-fe/stores';
import { getVapidKey } from 'pl-fe/utils/auth';
import { isStandalone } from 'pl-fe/utils/state';
diff --git a/packages/pl-fe/src/layouts/event-layout.tsx b/packages/pl-fe/src/layouts/event-layout.tsx
index deafb6003..a7e3a9af6 100644
--- a/packages/pl-fe/src/layouts/event-layout.tsx
+++ b/packages/pl-fe/src/layouts/event-layout.tsx
@@ -1,3 +1,4 @@
+import { useStatus } from 'pl-hooks/hooks/statuses/useStatus';
import React from 'react';
import { Helmet } from 'react-helmet-async';
import { FormattedMessage } from 'react-intl';
@@ -13,7 +14,6 @@ import {
WhoToFollowPanel,
} from 'pl-fe/features/ui/util/async-components';
import { useAppSelector, useFeatures } from 'pl-fe/hooks';
-import { useStatus } from 'pl-fe/pl-hooks/hooks/statuses/useStatus';
interface IEventLayout {
params?: {
diff --git a/packages/pl-fe/src/queries/chats.ts b/packages/pl-fe/src/queries/chats.ts
index 1c3125a98..a0dc540f8 100644
--- a/packages/pl-fe/src/queries/chats.ts
+++ b/packages/pl-fe/src/queries/chats.ts
@@ -1,14 +1,13 @@
import { InfiniteData, keepPreviousData, useInfiniteQuery, useMutation, useQuery } from '@tanstack/react-query';
import sumBy from 'lodash/sumBy';
import { type Chat, type ChatMessage as BaseChatMessage, type PaginatedResponse, chatMessageSchema, type Relationship } from 'pl-api';
-
+import { importEntities } from 'pl-hooks/importer';
import { ChatWidgetScreens, useChatContext } from 'pl-fe/contexts/chat-context';
import { useStatContext } from 'pl-fe/contexts/stat-context';
import { Entities } from 'pl-fe/entity-store/entities';
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';
diff --git a/packages/pl-fe/src/queries/suggestions.ts b/packages/pl-fe/src/queries/suggestions.ts
index 267916557..096abcd98 100644
--- a/packages/pl-fe/src/queries/suggestions.ts
+++ b/packages/pl-fe/src/queries/suggestions.ts
@@ -1,9 +1,8 @@
import { useMutation, keepPreviousData, useQuery } from '@tanstack/react-query';
-
+import { importEntities } from 'pl-hooks/importer';
import { fetchRelationships } from 'pl-fe/actions/accounts';
import { useAppDispatch, useClient } from 'pl-fe/hooks';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
import { removePageItem } from '../utils/queries';
diff --git a/packages/pl-fe/tsconfig.json b/packages/pl-fe/tsconfig.json
index e34f118dc..6ecfb0520 100644
--- a/packages/pl-fe/tsconfig.json
+++ b/packages/pl-fe/tsconfig.json
@@ -15,7 +15,6 @@
"skipLibCheck": true,
"paths": {
"pl-fe/*": ["src/*"],
- "pl-hooks/*": ["src/pl-hooks/*"],
},
"typeRoots": [
"./src/types",
diff --git a/packages/pl-fe/vite.config.ts b/packages/pl-fe/vite.config.ts
index 3148f4143..26a59eedf 100644
--- a/packages/pl-fe/vite.config.ts
+++ b/packages/pl-fe/vite.config.ts
@@ -154,7 +154,6 @@ const config = defineConfig(({ command }) => ({
resolve: {
alias: [
{ find: 'pl-fe', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
- { find: 'pl-hooks', replacement: fileURLToPath(new URL('./src/pl-hooks', import.meta.url)) },
],
},
test: {
diff --git a/packages/pl-hooks/lib/client.ts b/packages/pl-hooks/lib/client.ts
new file mode 100644
index 000000000..e11ce296c
--- /dev/null
+++ b/packages/pl-hooks/lib/client.ts
@@ -0,0 +1,14 @@
+import { QueryClient } from '@tanstack/react-query';
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnWindowFocus: false,
+ staleTime: 60000, // 1 minute
+ gcTime: Infinity,
+ retry: false,
+ },
+ },
+});
+
+export { queryClient };
diff --git a/packages/pl-hooks/lib/hooks/accounts/useAccount.ts b/packages/pl-hooks/lib/hooks/accounts/useAccount.ts
index 80f44e259..6ff3f807f 100644
--- a/packages/pl-hooks/lib/hooks/accounts/useAccount.ts
+++ b/packages/pl-hooks/lib/hooks/accounts/useAccount.ts
@@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query';
-
import { useRelationship } from 'pl-fe/api/hooks/accounts/useRelationship';
import { useClient } from 'pl-fe/hooks';
-import { normalizeAccount } from 'pl-fe/pl-hooks/normalizers/normalizeAccount';
-import { queryClient } from 'pl-fe/queries/client';
+
+import { queryClient } from 'pl-hooks/client';
+import { normalizeAccount } from 'pl-hooks/normalizers/normalizeAccount';
interface UseAccountOpts {
withRelationship?: boolean;
diff --git a/packages/pl-hooks/lib/hooks/markers/useMarkers.ts b/packages/pl-hooks/lib/hooks/markers/useMarkers.ts
index 576e33d53..54c2e9a08 100644
--- a/packages/pl-hooks/lib/hooks/markers/useMarkers.ts
+++ b/packages/pl-hooks/lib/hooks/markers/useMarkers.ts
@@ -1,7 +1,7 @@
import { useQuery } from '@tanstack/react-query';
-
import { useClient } from 'pl-fe/hooks';
-import { queryClient } from 'pl-fe/queries/client';
+
+import { queryClient } from 'pl-hooks/client';
import type { PlApiClient } from 'pl-api';
diff --git a/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts b/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts
index e2296c1b0..7fc27389f 100644
--- a/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts
+++ b/packages/pl-hooks/lib/hooks/markers/useUpdateMarkerMutation.ts
@@ -1,7 +1,7 @@
import { useMutation } from '@tanstack/react-query';
-
import { useClient } from 'pl-fe/hooks';
-import { queryClient } from 'pl-fe/queries/client';
+
+import { queryClient } from 'pl-hooks/client';
import type { Timeline } from './useMarkers';
import type { Marker } from 'pl-api';
diff --git a/packages/pl-hooks/lib/hooks/notifications/useNotification.ts b/packages/pl-hooks/lib/hooks/notifications/useNotification.ts
index 9571dae30..4b7224288 100644
--- a/packages/pl-hooks/lib/hooks/notifications/useNotification.ts
+++ b/packages/pl-hooks/lib/hooks/notifications/useNotification.ts
@@ -1,16 +1,16 @@
import { useQuery } from '@tanstack/react-query';
-
-
import { useAppSelector, useClient } from 'pl-fe/hooks';
-import { normalizeNotification, type Notification } from 'pl-fe/normalizers';
-import { type MinifiedNotification, minifyNotification } from 'pl-fe/pl-hooks/minifiers/minifyNotification';
-import { queryClient } from 'pl-fe/queries/client';
import { selectAccount, selectAccounts } from 'pl-fe/selectors';
+import { queryClient } from 'pl-hooks/client';
+import { type NormalizedNotification, normalizeNotification } from 'pl-hooks/normalizers/normalizeNotifications';
+
+import { useAccount } from '../accounts/useAccount';
+import { useStatus } from '../statuses/useStatus';
type Account = ReturnType;
-const importNotification = (notification: MinifiedNotification) => {
- queryClient.setQueryData(
+const importNotification = (notification: NormalizedNotification) => {
+ queryClient.setQueryData(
['notifications', 'entities', notification.id],
existingNotification => existingNotification?.duplicate ? existingNotification : notification,
);
@@ -22,25 +22,24 @@ const useNotification = (notificationId: string) => {
const notificationQuery = useQuery({
queryKey: ['notifications', 'entities', notificationId],
queryFn: () => client.notifications.getNotification(notificationId)
- .then(normalizeNotification)
- .then(minifyNotification),
+ .then(normalizeNotification),
});
+ const notification = notificationQuery.data;
+
+ const accountQuery = useAccount(notification?.account_id);
+ const moveTargetAccountQuery = useAccount(notification?.target_id);
+ const statusQuery = useStatus(notification?.status_id);
+
const data: Notification | null = useAppSelector((state) => {
- const notification = notificationQuery.data;
if (!notification) return null;
- const account = selectAccount(state, notification.account_id)!;
- // @ts-ignore
- const target = selectAccount(state, notification.target_id)!;
- // @ts-ignore
- const status = state.statuses.get(notification.status_id)!;
const accounts = selectAccounts(state, notification.account_ids).filter((account): account is Account => account !== undefined);
return {
...notification,
- account,
- target,
- status,
+ account: accountQuery.data,
+ target: moveTargetAccountQuery.data,
+ status: statusQuery.data,
accounts,
};
});
diff --git a/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts b/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts
index 9d1ac3c2f..44bfc4a4a 100644
--- a/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts
+++ b/packages/pl-hooks/lib/hooks/notifications/useNotificationList.ts
@@ -1,17 +1,16 @@
import { useInfiniteQuery } from '@tanstack/react-query';
-
import { useClient } from 'pl-fe/hooks';
-import { importEntities } from 'pl-fe/pl-hooks/importer';
-import { deduplicateNotifications } from 'pl-fe/pl-hooks/normalizers/deduplicateNotifications';
-import { queryClient } from 'pl-fe/queries/client';
-import { flattenPages } from 'pl-fe/utils/queries';
+
+import { queryClient } from 'pl-hooks/client';
+import { importEntities } from 'pl-hooks/importer';
+import { deduplicateNotifications } from 'pl-hooks/normalizers/deduplicateNotifications';
+import { flattenPages } from 'pl-hooks/utils/queries';
import type { Notification as BaseNotification, PaginatedResponse, PlApiClient } from 'pl-api';
-import type { NotificationType } from 'pl-fe/utils/notification';
type UseNotificationParams = {
- types?: Array;
- excludeTypes?: Array;
+ types?: Array;
+ excludeTypes?: Array;
}
const getQueryKey = (params: UseNotificationParams) => [
diff --git a/packages/pl-hooks/lib/hooks/statuses/useStatus.ts b/packages/pl-hooks/lib/hooks/statuses/useStatus.ts
index 64d5a0cdf..110268602 100644
--- a/packages/pl-hooks/lib/hooks/statuses/useStatus.ts
+++ b/packages/pl-hooks/lib/hooks/statuses/useStatus.ts
@@ -1,11 +1,11 @@
import { useQuery } from '@tanstack/react-query';
+import { useAppSelector, useClient } from 'pl-fe/hooks';
+import { selectAccount, selectAccounts } from 'pl-fe/selectors';
import { useIntl } from 'react-intl';
-import { useAccount } 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';
+import { queryClient } from 'pl-hooks/client';
+import { useAccount } from 'pl-hooks/hooks/accounts/useAccount';
+import { importEntities } from 'pl-hooks/importer';
import { normalizeStatus, type Status } from '../../normalizers/normalizeStatus';
@@ -106,7 +106,7 @@ const useStatus = (statusId?: string) => {
const status = statusQuery.data;
- const { account } = useAccount(status?.account_id || undefined);
+ const { data: account } = useAccount(status?.account_id || undefined);
// : (Status & {
// account: Account;
diff --git a/packages/pl-hooks/lib/importer.ts b/packages/pl-hooks/lib/importer.ts
index 17abfcfae..69d8d6797 100644
--- a/packages/pl-hooks/lib/importer.ts
+++ b/packages/pl-hooks/lib/importer.ts
@@ -1,10 +1,7 @@
-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 { queryClient } from 'pl-hooks/client';
-import { minifyNotification, type MinifiedNotification } from './minifiers/minifyNotification';
-import { DeduplicatedNotification } from './normalizers/deduplicateNotifications';
+import { type MinifiedNotification, minifyNotification } from './minifiers/minifyNotification';
+import { DeduplicatedNotification } from './normalizers/normalizeNotifications';
import { normalizeStatus, type Status } from './normalizers/normalizeStatus';
import type {
@@ -14,30 +11,34 @@ import type {
Relationship as BaseRelationship,
Status as BaseStatus,
} from 'pl-api';
-import type { AppDispatch } from 'pl-fe/store';
-let dispatch: AppDispatch;
+const importAccount = (account: BaseAccount) => queryClient.setQueryData(
+ ['accounts', 'entities', account.id], account,
+);
-import('pl-fe/store').then(value => dispatch = value.store.dispatch).catch(() => {});
+const importGroup = (group: BaseGroup) => queryClient.setQueryData(
+ ['groups', 'entities', group.id], group,
+);
-const importNotification = (notification: DeduplicatedNotification) => {
- queryClient.setQueryData(
- ['notifications', 'entities', notification.id],
- existingNotification => existingNotification?.duplicate ? existingNotification : minifyNotification(notification),
- );
-};
+const importNotification = (notification: DeduplicatedNotification) => queryClient.setQueryData(
+ ['notifications', 'entities', notification.id],
+ existingNotification => existingNotification?.duplicate ? existingNotification : minifyNotification(notification),
+);
-const importStatus = (status: BaseStatus) => {
- queryClient.setQueryData(
- ['statuses', 'entities', status.id],
- _ => normalizeStatus(status),
- );
-};
+const importPoll = (poll: BasePoll) => queryClient.setQueryData(
+ ['polls', 'entities', poll.id], poll,
+);
-const isEmpty = (object: Record) => {
- for (const i in object) return false;
- return true;
-};
+const importRelationship = (relationship: BaseRelationship) => queryClient.setQueryData(
+ ['relationships', 'entities', relationship.id], relationship,
+);
+
+const importStatus = (status: BaseStatus) => queryClient.setQueryData(
+ ['statuses', 'entities', status.id],
+ _ => normalizeStatus(status),
+);
+
+const isEmpty = (object: Record) => !Object.values(object).some(value => value);
const importEntities = (entities: {
accounts?: Array;
@@ -56,16 +57,12 @@ const importEntities = (entities: {
const relationships: Record = {};
const statuses: Record = {};
- const processAccount = (account: BaseAccount, withParent = true) => {
- if (withParent) accounts[account.id] = account;
-
+ const processAccount = (account: BaseAccount) => {
if (account.moved) processAccount(account.moved);
if (account.relationship) relationships[account.relationship.id] = account.relationship;
};
- const processNotification = (notification: DeduplicatedNotification, withParent = true) => {
- if (withParent) notifications[notification.id] = notification;
-
+ const processNotification = (notification: DeduplicatedNotification) => {
processAccount(notification.account);
if (notification.type === 'move') processAccount(notification.target);
@@ -74,9 +71,8 @@ const importEntities = (entities: {
processStatus(notification.status);
};
- const processStatus = (status: BaseStatus, withParent = true) => {
+ const processStatus = (status: BaseStatus) => {
if (status.account) {
- if (withParent) statuses[status.id] = status;
processAccount(status.account);
}
@@ -87,21 +83,23 @@ const importEntities = (entities: {
};
if (options.withParents) {
+ entities.accounts?.forEach(account => accounts[account.id] = account);
entities.groups?.forEach(group => groups[group.id] = group);
+ entities.notifications?.forEach(notification => notifications[notification.id] = notification);
entities.polls?.forEach(poll => polls[poll.id] = poll);
entities.relationships?.forEach(relationship => relationships[relationship.id] = relationship);
+ entities.statuses?.forEach(status => statuses[status.id] = status);
}
- entities.accounts?.forEach((account) => processAccount(account, options.withParents));
- entities.notifications?.forEach((notification) => processNotification(notification, options.withParents));
- entities.statuses?.forEach((status) => processStatus(status, options.withParents));
+ entities.accounts?.forEach((account) => processAccount(account));
+ entities.notifications?.forEach((notification) => processNotification(notification));
+ entities.statuses?.forEach((status) => processStatus(status));
- if (!isEmpty(accounts)) dispatch(importAccounts(Object.values(accounts)));
- if (!isEmpty(groups)) dispatch(importGroups(Object.values(groups)));
+ if (!isEmpty(accounts)) Object.values(accounts).forEach(importAccount);
+ if (!isEmpty(groups)) Object.values(groups).forEach(importGroup);
if (!isEmpty(notifications)) Object.values(notifications).forEach(importNotification);
- if (!isEmpty(polls)) dispatch(importPolls(Object.values(polls)));
- if (!isEmpty(relationships)) dispatch(importEntityStoreEntities(Object.values(relationships), Entities.RELATIONSHIPS));
- if (!isEmpty(statuses)) dispatch(importStatuses(Object.values(statuses)));
+ if (!isEmpty(polls)) Object.values(polls).forEach(importPoll);
+ if (!isEmpty(relationships)) Object.values(relationships).forEach(importRelationship);
if (!isEmpty(statuses)) Object.values(statuses).forEach(importStatus);
};
diff --git a/packages/pl-hooks/lib/minifiers/minifyNotification.ts b/packages/pl-hooks/lib/minifiers/minifyNotification.ts
index 3a972088c..ba0f01ae4 100644
--- a/packages/pl-hooks/lib/minifiers/minifyNotification.ts
+++ b/packages/pl-hooks/lib/minifiers/minifyNotification.ts
@@ -1,6 +1,6 @@
import omit from 'lodash/omit';
-import { DeduplicatedNotification } from '../normalizers/deduplicateNotifications';
+import { DeduplicatedNotification } from '../normalizers/normalizeNotifications';
import type { AccountWarning, RelationshipSeveranceEvent } from 'pl-api';
diff --git a/packages/pl-hooks/lib/normalizers/deduplicateNotifications.ts b/packages/pl-hooks/lib/normalizers/deduplicateNotifications.ts
deleted file mode 100644
index 41e0d7cfd..000000000
--- a/packages/pl-hooks/lib/normalizers/deduplicateNotifications.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { getNotificationStatus } from 'pl-fe/features/notifications/components/notification';
-
-import type { Account as BaseAccount, Notification as BaseNotification } from 'pl-api';
-
-type DeduplicatedNotification = BaseNotification & {
- accounts: Array;
- duplicate?: boolean;
-}
-
-const STATUS_NOTIFICATION_TYPES = [
- 'favourite',
- 'reblog',
- 'emoji_reaction',
- 'event_reminder',
- 'participation_accepted',
- 'participation_request',
-];
-
-const deduplicateNotifications = (notifications: Array) => {
- const deduplicatedNotifications: DeduplicatedNotification[] = [];
-
- 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;
-};
-
-export { deduplicateNotifications, type DeduplicatedNotification };
diff --git a/packages/pl-hooks/lib/normalizers/normalizeAccount.ts b/packages/pl-hooks/lib/normalizers/normalizeAccount.ts
index de583a430..2fca21d28 100644
--- a/packages/pl-hooks/lib/normalizers/normalizeAccount.ts
+++ b/packages/pl-hooks/lib/normalizers/normalizeAccount.ts
@@ -1,37 +1,9 @@
-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 = ({ moved, ...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 === '' ? '' : account.note;
-
- const emojiMap = makeEmojiMap(account.emojis);
-
- return {
- ...account,
- moved_id: moved?.id || null,
- 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),
- })),
- };
-};
+const normalizeAccount = ({ moved, ...account }: BaseAccount) => ({
+ ...account,
+ moved_id: moved?.id || null,
+});
type Account = ReturnType;
diff --git a/packages/pl-hooks/lib/normalizers/normalizeNotifications.ts b/packages/pl-hooks/lib/normalizers/normalizeNotifications.ts
new file mode 100644
index 000000000..0e7c5ba5c
--- /dev/null
+++ b/packages/pl-hooks/lib/normalizers/normalizeNotifications.ts
@@ -0,0 +1,131 @@
+import omit from 'lodash/omit';
+
+import type { AccountWarning, Account as BaseAccount, Notification as BaseNotification, RelationshipSeveranceEvent } from 'pl-api';
+
+type DeduplicatedNotification = BaseNotification & {
+ accounts: Array;
+ duplicate?: boolean;
+}
+
+const STATUS_NOTIFICATION_TYPES = [
+ 'mention',
+ 'status',
+ 'reblog',
+ 'favourite',
+ 'poll',
+ 'update',
+ 'emoji_reaction',
+ 'event_reminder',
+ 'participation_accepted',
+ 'participation_request',
+];
+
+const getNotificationStatus = (n: Pick) => {
+ if (STATUS_NOTIFICATION_TYPES.includes(n.type))
+ // @ts-ignore
+ return n.status;
+ return null;
+};
+
+const normalizeNotifications = (notifications: Array): Array => {
+ const deduplicatedNotifications: DeduplicatedNotification[] = [];
+
+ 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.map(normalizeNotification);
+};
+
+
+const normalizeNotification = (notification: BaseNotification | 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;
+ }
+ ) = {
+ duplicate: false,
+ ...omit(notification, ['account', 'accounts', 'status', 'target', 'chat_message']),
+ account_id: notification.account.id,
+ account_ids: ('accounts' in notification) ? notification.accounts.map(({ id }) => id) : [notification.account.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 NormalizedNotification = ReturnType;
+
+
+export { normalizeNotifications, normalizeNotification, type NormalizedNotification };
diff --git a/packages/pl-hooks/lib/normalizers/normalizeStatus.ts b/packages/pl-hooks/lib/normalizers/normalizeStatus.ts
index 4dbee8d69..aa5666483 100644
--- a/packages/pl-hooks/lib/normalizers/normalizeStatus.ts
+++ b/packages/pl-hooks/lib/normalizers/normalizeStatus.ts
@@ -3,96 +3,12 @@
* Converts API statuses into our internal format.
* @see {@link https://docs.joinmastodon.org/entities/status/}
*/
-import escapeTextContentForBrowser from 'escape-html';
-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 { queryClient } from 'pl-fe/queries/client';
-import { unescapeHTML } from 'pl-fe/utils/html';
-import { makeEmojiMap } from 'pl-fe/utils/normalizers';
-
-const domParser = new DOMParser();
+import { type Account as BaseAccount, type Status as BaseStatus, type MediaAttachment, mentionSchema } from 'pl-api';
type StatusApprovalStatus = Exclude;
type StatusVisibility = 'public' | 'unlisted' | 'private' | 'direct' | 'group' | 'mutuals_only' | 'local';
-type CalculatedValues = {
- search_index: string;
- contentHtml: string;
- spoilerHtml: string;
- contentMapHtml?: Record;
- spoilerMapHtml?: Record;
- expanded?: boolean | null;
- hidden?: boolean | null;
- translation?: Translation | null | false;
- currentLanguage?: string;
-};
-
-type OldStatus = Pick & CalculatedValues;
-
-// Gets titles of poll options from status
-const getPollOptionTitles = ({ poll }: Pick): readonly string[] => {
- if (poll && typeof poll === 'object') {
- return poll.options.map(({ title }) => title);
- } else {
- return [];
- }
-};
-
-// Gets usernames of mentioned users from status
-const getMentionedUsernames = (status: Pick): Array =>
- status.mentions.map(({ acct }) => `@${acct}`);
-
-// Creates search text from the status
-const buildSearchContent = (status: Pick): string => {
- const pollOptionTitles = getPollOptionTitles(status);
- const mentionedUsernames = getMentionedUsernames(status);
-
- const fields = [
- status.spoiler_text,
- status.content,
- ...pollOptionTitles,
- ...mentionedUsernames,
- ];
-
- return unescapeHTML(fields.join('\n\n')) || '';
-};
-
-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 => {
- if (oldStatus && oldStatus.content === status.content && oldStatus.spoiler_text === status.spoiler_text) {
- const {
- search_index, contentHtml, spoilerHtml, contentMapHtml, spoilerMapHtml, hidden, expanded, translation, currentLanguage,
- } = oldStatus;
-
- return {
- search_index, contentHtml, spoilerHtml, contentMapHtml, spoilerMapHtml, hidden, expanded, translation, currentLanguage,
- };
- } else {
- const searchContent = buildSearchContent(status);
- const emojiMap = makeEmojiMap(status.emojis);
-
- return {
- search_index: domParser.parseFromString(searchContent, 'text/html').documentElement.textContent || '',
- contentHtml: calculateContent(status.content, emojiMap, !!status.quote),
- spoilerHtml: calculateSpoiler(status.spoiler_text, emojiMap),
- contentMapHtml: status.content_map
- ? Object.fromEntries(Object.entries(status.content_map)?.map(([key, value]) => [key, calculateContent(value, emojiMap, !!status.quote)]))
- : undefined,
- spoilerMapHtml: status.spoiler_text_map
- ? Object.fromEntries(Object.entries(status.spoiler_text_map).map(([key, value]) => [key, calculateSpoiler(value, emojiMap)]))
- : undefined,
- };
- }
-};
-
const normalizeStatus = ({ account, accounts, reblog, poll, group, quote, ...status }: BaseStatus & { accounts?: Array }) => {
- const oldStatus = queryClient.getQueryData(['statuses', 'entities', status.id]);
- const calculated = calculateStatus(status, oldStatus);
-
// Sort the replied-to mention to the top
let mentions = status.mentions.toSorted((a, _b) => {
if (a.id === status.in_reply_to_account_id) {
@@ -107,7 +23,7 @@ const normalizeStatus = ({ account, accounts, reblog, poll, group, quote, ...sta
const hasSelfMention = status.mentions.some(mention => account.id === mention.id);
if (isSelfReply && !hasSelfMention) {
- const selfMention = mentionSchema.parse(status.account);
+ const selfMention = mentionSchema.parse(account);
mentions = [selfMention, ...mentions];
}
@@ -151,13 +67,9 @@ const normalizeStatus = ({ account, accounts, reblog, poll, group, quote, ...sta
mentions,
expanded: null,
hidden: null,
- /** Rewrite `` to empty string. */
- content: status.content === '' ? '' : status.content,
filtered: status.filtered?.map(result => result.filter.title),
event,
media_attachments,
- ...calculated,
- translation: (status.translation || calculated.translation || null) as Translation | null | false,
};
};
diff --git a/packages/pl-hooks/lib/utils/queries.ts b/packages/pl-hooks/lib/utils/queries.ts
new file mode 100644
index 000000000..80b3e262b
--- /dev/null
+++ b/packages/pl-hooks/lib/utils/queries.ts
@@ -0,0 +1,12 @@
+import type { InfiniteData } from '@tanstack/react-query';
+import type { PaginatedResponse } from 'pl-api';
+
+/** Flatten paginated results into a single array. */
+const flattenPages = (queryData: InfiniteData, 'items'>> | undefined) => {
+ return queryData?.pages.reduce(
+ (prev: T[], curr) => [...prev, ...(curr.items)],
+ [],
+ );
+};
+
+export { flattenPages };
diff --git a/packages/pl-hooks/package.json b/packages/pl-hooks/package.json
index 86d8bb0d7..cc7cca04e 100644
--- a/packages/pl-hooks/package.json
+++ b/packages/pl-hooks/package.json
@@ -18,6 +18,7 @@
},
"license": "AGPL-3.0-or-later",
"devDependencies": {
+ "@types/lodash": "^4.17.10",
"@types/node": "^20.14.12",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.0.0",
@@ -32,6 +33,7 @@
},
"dependencies": {
"@tanstack/react-query": "^5.56.2",
+ "lodash": "^4.17.21",
"pl-api": "^0.0.37"
},
"module": "./dist/main.es.js",
diff --git a/packages/pl-hooks/tsconfig.json b/packages/pl-hooks/tsconfig.json
index eb60a062c..5ae37dd78 100644
--- a/packages/pl-hooks/tsconfig.json
+++ b/packages/pl-hooks/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "baseUrl": "./",
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
@@ -18,7 +19,11 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true
+ "noFallthroughCasesInSwitch": true,
+
+ "paths": {
+ "pl-hooks/*": ["lib/*"],
+ },
},
- "include": ["src", "lib"]
+ "include": ["lib"]
}
diff --git a/packages/pl-hooks/vite.config.ts b/packages/pl-hooks/vite.config.ts
index 5b8156db5..2d3fb004e 100644
--- a/packages/pl-hooks/vite.config.ts
+++ b/packages/pl-hooks/vite.config.ts
@@ -1,3 +1,4 @@
+import { fileURLToPath, URL } from 'node:url';
import { resolve } from 'path';
import { defineConfig } from 'vite';
@@ -16,4 +17,9 @@ export default defineConfig({
target: 'esnext',
sourcemap: true,
},
+ resolve: {
+ alias: [
+ { find: 'pl-hooks', replacement: fileURLToPath(new URL('./lib', import.meta.url)) },
+ ],
+ },
});
diff --git a/packages/pl-hooks/yarn.lock b/packages/pl-hooks/yarn.lock
index 2571337ef..0d4981bb1 100644
--- a/packages/pl-hooks/yarn.lock
+++ b/packages/pl-hooks/yarn.lock
@@ -408,6 +408,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+"@types/lodash@^4.17.10":
+ version "4.17.10"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.10.tgz#64f3edf656af2fe59e7278b73d3e62404144a6e6"
+ integrity sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==
+
"@types/node@^20.14.12":
version "20.14.12"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.12.tgz#129d7c3a822cb49fc7ff661235f19cfefd422b49"
@@ -1863,7 +1868,7 @@ lodash.pick@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==
-lodash@~4.17.15:
+lodash@^4.17.21, lodash@~4.17.15:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==