diff --git a/packages/pl-fe/src/actions/admin.ts b/packages/pl-fe/src/actions/admin.ts
index eb0b33bc9..ee97042b0 100644
--- a/packages/pl-fe/src/actions/admin.ts
+++ b/packages/pl-fe/src/actions/admin.ts
@@ -1,6 +1,5 @@
import { fetchRelationships } from 'pl-fe/actions/accounts';
import { importEntities } from 'pl-fe/actions/importer';
-import { queryClient } from 'pl-fe/queries/client';
import { filterBadges, getTagDiff } from 'pl-fe/utils/badges';
import { getClient } from '../api';
@@ -84,7 +83,6 @@ const updateConfig = (configs: PleromaConfig['configs']) =>
dispatch
({ type: ADMIN_CONFIG_UPDATE_REQUEST, configs });
return getClient(getState).admin.config.updatePleromaConfig(configs)
.then((data) => {
- queryClient.invalidateQueries({ queryKey: ['instance', 'instanceInformation'] });
dispatch({ type: ADMIN_CONFIG_UPDATE_SUCCESS, configs: data.configs, needsReboot: data.need_reboot });
}).catch(error => {
dispatch({ type: ADMIN_CONFIG_UPDATE_FAIL, error, configs });
diff --git a/packages/pl-fe/src/actions/auth.ts b/packages/pl-fe/src/actions/auth.ts
index 5842dcf57..a0d6da0bc 100644
--- a/packages/pl-fe/src/actions/auth.ts
+++ b/packages/pl-fe/src/actions/auth.ts
@@ -93,7 +93,7 @@ const createAuthApp = () =>
const params = {
client_name: `${sourceCode.displayName} (${new URL(window.origin).host})`,
redirect_uris: 'urn:ietf:wg:oauth:2.0:oob',
- scopes: getScopes(),
+ scopes: getScopes(getState()),
website: sourceCode.homepage,
};
@@ -117,7 +117,7 @@ const createAppToken = () =>
client_secret: app.client_secret!,
redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
grant_type: 'client_credentials',
- scope: getScopes(),
+ scope: getScopes(getState()),
};
return dispatch(obtainOAuthToken(params)).then((token) =>
@@ -136,7 +136,7 @@ const createUserToken = (username: string, password: string) =>
grant_type: 'password',
username: username,
password: password,
- scope: getScopes(),
+ scope: getScopes(getState()),
};
return dispatch(obtainOAuthToken(params))
@@ -156,7 +156,7 @@ const otpVerify = (code: string, mfa_token: string) =>
code: code,
challenge_type: 'totp',
// redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
- // scope: getScopes(),
+ // scope: getScopes(getState()),
}).then((token) => dispatch(authLoggedIn(token)));
};
diff --git a/packages/pl-fe/src/actions/compose.ts b/packages/pl-fe/src/actions/compose.ts
index c4055cd89..3d8fb8fed 100644
--- a/packages/pl-fe/src/actions/compose.ts
+++ b/packages/pl-fe/src/actions/compose.ts
@@ -20,7 +20,7 @@ import { uploadFile, updateMedia } from './media';
import { createStatus } from './statuses';
import type { EditorState } from 'lexical';
-import type { Account as BaseAccount, CreateStatusParams, Group, MediaAttachment, Status as BaseStatus, Tag, Poll, ScheduledStatus, Instance } from 'pl-api';
+import type { Account as BaseAccount, CreateStatusParams, Group, MediaAttachment, Status as BaseStatus, Tag, Poll, ScheduledStatus } from 'pl-api';
import type { AutoSuggestion } from 'pl-fe/components/autosuggest-input';
import type { Emoji } from 'pl-fe/features/emoji';
import type { Account } from 'pl-fe/normalizers/account';
@@ -467,8 +467,7 @@ const submitComposeFail = (composeId: string, error: unknown) => ({
const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
- const instance = queryClient.getQueryData(['instance', 'instanceInformation', getState().auth.client.baseURL]);
- const attachmentLimit = instance!.configuration.statuses.max_media_attachments;
+ const attachmentLimit = getState().instance.configuration.statuses.max_media_attachments;
const media = getState().compose[composeId]?.media_attachments;
const progress = new Array(files.length).fill(0);
diff --git a/packages/pl-fe/src/actions/consumer-auth.ts b/packages/pl-fe/src/actions/consumer-auth.ts
index b527ac1c0..4e66b343d 100644
--- a/packages/pl-fe/src/actions/consumer-auth.ts
+++ b/packages/pl-fe/src/actions/consumer-auth.ts
@@ -1,19 +1,17 @@
-import { Instance } from 'pl-api';
import queryString from 'query-string';
import * as BuildConfig from 'pl-fe/build-config';
-import { queryClient } from 'pl-fe/queries/client';
import { isURL } from 'pl-fe/utils/auth';
import sourceCode from 'pl-fe/utils/code';
-import { getInstanceScopes } from 'pl-fe/utils/scopes';
+import { getScopes } from 'pl-fe/utils/scopes';
import { createApp } from './apps';
import type { AppDispatch, RootState } from 'pl-fe/store';
-const createProviderApp = (instance: Instance) =>
+const createProviderApp = () =>
async(dispatch: AppDispatch, getState: () => RootState) => {
- const scopes = getInstanceScopes(instance);
+ const scopes = getScopes(getState());
const params = {
client_name: `${sourceCode.displayName} (${new URL(window.origin).host})`,
@@ -29,9 +27,8 @@ const prepareRequest = (provider: string) =>
async(dispatch: AppDispatch, getState: () => RootState) => {
const baseURL = isURL(BuildConfig.BACKEND_URL) ? BuildConfig.BACKEND_URL : '';
- const instance = queryClient.getQueryData(['instance', 'instanceInformation', baseURL])!;
- const scopes = getInstanceScopes(instance);
- const app = await dispatch(createProviderApp(instance));
+ const scopes = getScopes(getState());
+ const app = await dispatch(createProviderApp());
const { client_id, redirect_uri } = app;
localStorage.setItem('plfe:external:app', JSON.stringify(app));
diff --git a/packages/pl-fe/src/actions/instance.ts b/packages/pl-fe/src/actions/instance.ts
index 5e2a0d1c0..4363b121e 100644
--- a/packages/pl-fe/src/actions/instance.ts
+++ b/packages/pl-fe/src/actions/instance.ts
@@ -1,6 +1,12 @@
import { getAuthUserUrl, getMeUrl } from 'pl-fe/utils/auth';
-import type { RootState } from 'pl-fe/store';
+import { getClient } from '../api';
+
+import type { Instance } from 'pl-api';
+import type { AppDispatch, RootState } from 'pl-fe/store';
+
+const INSTANCE_FETCH_SUCCESS = 'INSTANCE_FETCH_SUCCESS' as const;
+const INSTANCE_FETCH_FAIL = 'INSTANCE_FETCH_FAIL' as const;
/** Figure out the appropriate instance to fetch depending on the state */
const getHost = (state: RootState) => {
@@ -13,4 +19,34 @@ const getHost = (state: RootState) => {
}
};
-export { getHost };
+interface InstanceFetchSuccessAction {
+ type: typeof INSTANCE_FETCH_SUCCESS;
+ instance: Instance;
+}
+
+interface InstanceFetchFailAction {
+ type: typeof INSTANCE_FETCH_FAIL;
+ error: unknown;
+}
+
+const fetchInstance = () => async (dispatch: AppDispatch, getState: () => RootState) => {
+ try {
+ const instance = await getClient(getState).instance.getInstance();
+
+ dispatch({ type: INSTANCE_FETCH_SUCCESS, instance });
+ } catch (error) {
+ dispatch({ type: INSTANCE_FETCH_FAIL, error });
+ }
+};
+
+type InstanceAction =
+ InstanceFetchSuccessAction
+ | InstanceFetchFailAction
+
+export {
+ INSTANCE_FETCH_SUCCESS,
+ INSTANCE_FETCH_FAIL,
+ getHost,
+ fetchInstance,
+ type InstanceAction,
+};
diff --git a/packages/pl-fe/src/actions/media.ts b/packages/pl-fe/src/actions/media.ts
index 2f1b89dd5..0879dfe6f 100644
--- a/packages/pl-fe/src/actions/media.ts
+++ b/packages/pl-fe/src/actions/media.ts
@@ -1,6 +1,5 @@
import { defineMessages, type IntlShape } from 'react-intl';
-import { queryClient } from 'pl-fe/queries/client';
import toast from 'pl-fe/toast';
import { isLoggedIn } from 'pl-fe/utils/auth';
import { formatBytes, getVideoDuration } from 'pl-fe/utils/media';
@@ -8,7 +7,7 @@ import resizeImage from 'pl-fe/utils/resize-image';
import { getClient } from '../api';
-import type { Instance, MediaAttachment, UploadMediaParams } from 'pl-api';
+import type { MediaAttachment, UploadMediaParams } from 'pl-api';
import type { AppDispatch, RootState } from 'pl-fe/store';
const messages = defineMessages({
@@ -36,11 +35,9 @@ const uploadFile = (
changeTotal: (value: number) => void = () => {},
) => async (dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
- const instance = queryClient.getQueryData(['instance', 'instanceInformation', getState().auth.client.baseURL])!;
-
- const {
- image_size_limit: maxImageSize, video_size_limit: maxVideoSize, video_duration_limit: maxVideoDuration,
- } = instance.configuration.media_attachments;
+ const maxImageSize = getState().instance.configuration.media_attachments.image_size_limit;
+ const maxVideoSize = getState().instance.configuration.media_attachments.video_size_limit;
+ const maxVideoDuration = getState().instance.configuration.media_attachments.video_duration_limit;
const isImage = file.type.match(/image.*/);
const isVideo = file.type.match(/video.*/);
diff --git a/packages/pl-fe/src/actions/preload.ts b/packages/pl-fe/src/actions/preload.ts
index f2567265a..e20095cfb 100644
--- a/packages/pl-fe/src/actions/preload.ts
+++ b/packages/pl-fe/src/actions/preload.ts
@@ -67,8 +67,6 @@ interface PreloadAction {
export {
PLEROMA_PRELOAD_IMPORT,
MASTODON_PRELOAD_IMPORT,
- decodeFromMarkup,
- pleromaDecoder,
preload,
preloadMastodon,
type PreloadAction,
diff --git a/packages/pl-fe/src/actions/push-notifications/registerer.ts b/packages/pl-fe/src/actions/push-notifications/registerer.ts
index cc6ea0565..ac19530a3 100644
--- a/packages/pl-fe/src/actions/push-notifications/registerer.ts
+++ b/packages/pl-fe/src/actions/push-notifications/registerer.ts
@@ -1,5 +1,6 @@
import { createPushSubscription, updatePushSubscription } from 'pl-fe/actions/push-subscriptions';
import { pushNotificationsSetting } from 'pl-fe/settings';
+import { getVapidKey } from 'pl-fe/utils/auth';
import { decode as decodeBase64 } from 'pl-fe/utils/base64';
import { setBrowserSupport, setSubscription, clearSubscription } from './setter';
@@ -29,10 +30,10 @@ const getPushSubscription = (registration: ServiceWorkerRegistration) =>
registration.pushManager.getSubscription()
.then(subscription => ({ registration, subscription }));
-const subscribe = (registration: ServiceWorkerRegistration, vapidKey: string) =>
+const subscribe = (registration: ServiceWorkerRegistration, getState: () => RootState) =>
registration.pushManager.subscribe({
userVisibleOnly: true,
- applicationServerKey: urlBase64ToUint8Array(vapidKey),
+ applicationServerKey: urlBase64ToUint8Array(getVapidKey(getState())),
});
const unsubscribe = ({ registration, subscription }: {
@@ -60,9 +61,10 @@ const sendSubscriptionToBackend = (subscription: PushSubscription, me: Me) =>
// eslint-disable-next-line compat/compat
const supportsPushNotifications = ('serviceWorker' in navigator && 'PushManager' in window && 'getKey' in PushSubscription.prototype);
-const register = (vapidKey?: string) =>
+const register = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
const me = getState().me;
+ const vapidKey = getVapidKey(getState());
dispatch(setBrowserSupport(supportsPushNotifications));
@@ -93,13 +95,13 @@ const register = (vapidKey?: string) =>
} else {
// Something went wrong, try to subscribe again
return unsubscribe({ registration, subscription })
- .then((registration) => subscribe(registration, vapidKey))
+ .then((registration) => subscribe(registration, getState))
.then((pushSubscription) => dispatch(sendSubscriptionToBackend(pushSubscription, me)));
}
}
// No subscription, try to subscribe
- return subscribe(registration, vapidKey)
+ return subscribe(registration, getState)
.then((pushSubscription) => dispatch(sendSubscriptionToBackend(pushSubscription, me)));
})
.then((subscription) => {
diff --git a/packages/pl-fe/src/api/hooks/instance/use-instance.ts b/packages/pl-fe/src/api/hooks/instance/use-instance.ts
deleted file mode 100644
index dd75aacd1..000000000
--- a/packages/pl-fe/src/api/hooks/instance/use-instance.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useQuery } from '@tanstack/react-query';
-import { instanceSchema } from 'pl-api';
-import * as v from 'valibot';
-
-import { useClient } from 'pl-fe/hooks/use-client';
-import { initialState } from 'pl-fe/initial-state';
-
-const placeholderData = v.parse(instanceSchema, {});
-const initialData = initialState['/api/v1/instance'] ? v.parse(instanceSchema, initialState['/api/v1/instance']) : undefined;
-
-const useInstance = () => {
- const client = useClient();
-
- const query = useQuery({
- queryKey: ['instance', 'instanceInformation', client.baseURL],
- queryFn: client.instance.getInstance,
- initialData: client.baseURL === '' ? initialData : undefined,
- });
-
- return { ...query, data: query.data || placeholderData };
-};
-
-export { useInstance };
diff --git a/packages/pl-fe/src/api/hooks/instance/use-translation-languages.ts b/packages/pl-fe/src/api/hooks/instance/use-translation-languages.ts
index 2a15c09d5..0fcdc3fab 100644
--- a/packages/pl-fe/src/api/hooks/instance/use-translation-languages.ts
+++ b/packages/pl-fe/src/api/hooks/instance/use-translation-languages.ts
@@ -1,15 +1,15 @@
import { useQuery } from '@tanstack/react-query';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useClient } from 'pl-fe/hooks/use-client';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useLoggedIn } from 'pl-fe/hooks/use-logged-in';
const useTranslationLanguages = () => {
const client = useClient();
const { isLoggedIn } = useLoggedIn();
const features = useFeatures();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const getTranslationLanguages = async () => {
const metadata = instance.pleroma.metadata;
diff --git a/packages/pl-fe/src/api/hooks/streaming/use-timeline-stream.ts b/packages/pl-fe/src/api/hooks/streaming/use-timeline-stream.ts
index 6f8fbe2f0..07c2a140a 100644
--- a/packages/pl-fe/src/api/hooks/streaming/use-timeline-stream.ts
+++ b/packages/pl-fe/src/api/hooks/streaming/use-timeline-stream.ts
@@ -1,8 +1,8 @@
import { useEffect, useRef } from 'react';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useClient } from 'pl-fe/hooks/use-client';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { getAccessToken } from 'pl-fe/utils/auth';
import type { StreamingEvent } from 'pl-api';
@@ -12,7 +12,7 @@ const useTimelineStream = (stream: string, params: { list?: string; tag?: string
const client = useClient();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const socket = useRef<({
listen: (listener: any, stream?: string) => number;
unlisten: (listener: any) => void;
diff --git a/packages/pl-fe/src/components/birthday-input.tsx b/packages/pl-fe/src/components/birthday-input.tsx
index 6a8fd6f8d..58688074e 100644
--- a/packages/pl-fe/src/components/birthday-input.tsx
+++ b/packages/pl-fe/src/components/birthday-input.tsx
@@ -1,10 +1,10 @@
import React, { useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import IconButton from 'pl-fe/components/icon-button';
import { DatePicker } from 'pl-fe/features/ui/util/async-components';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
const messages = defineMessages({
birthdayPlaceholder: { id: 'edit_profile.fields.birthday_placeholder', defaultMessage: 'Your birthday' },
@@ -23,7 +23,7 @@ interface IBirthdayInput {
const BirthdayInput: React.FC = ({ value, onChange, required }) => {
const intl = useIntl();
const features = useFeatures();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const supportsBirthdays = features.birthdays;
const minAge = instance.pleroma.metadata.birthday_min_age;
diff --git a/packages/pl-fe/src/components/gdpr-banner.tsx b/packages/pl-fe/src/components/gdpr-banner.tsx
index aa16f6514..0f86c8e2d 100644
--- a/packages/pl-fe/src/components/gdpr-banner.tsx
+++ b/packages/pl-fe/src/components/gdpr-banner.tsx
@@ -2,12 +2,12 @@ import clsx from 'clsx';
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Banner from 'pl-fe/components/ui/banner';
import Button from 'pl-fe/components/ui/button';
import HStack from 'pl-fe/components/ui/hstack';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
const acceptedGdpr = !!localStorage.getItem('plfe:gdpr');
@@ -18,7 +18,7 @@ const GdprBanner: React.FC = () => {
const [shown, setShown] = useState(acceptedGdpr);
const [slideout, setSlideout] = useState(false);
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { gdprUrl } = usePlFeConfig();
const handleAccept = () => {
diff --git a/packages/pl-fe/src/components/helmet.tsx b/packages/pl-fe/src/components/helmet.tsx
index 81073f53b..dafab6605 100644
--- a/packages/pl-fe/src/components/helmet.tsx
+++ b/packages/pl-fe/src/components/helmet.tsx
@@ -1,9 +1,9 @@
import React from 'react';
import { Helmet as ReactHelmet } from 'react-helmet-async';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useStatContext } from 'pl-fe/contexts/stat-context';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useSettings } from 'pl-fe/hooks/use-settings';
import { RootState } from 'pl-fe/store';
import FaviconService from 'pl-fe/utils/favicon-service';
@@ -22,7 +22,7 @@ interface IHelmet {
}
const Helmet: React.FC = ({ children }) => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { unreadChatsCount } = useStatContext();
const unreadCount = useAppSelector((state) => getNotifTotals(state) + unreadChatsCount);
const { demetricator } = useSettings();
diff --git a/packages/pl-fe/src/components/sidebar-menu.tsx b/packages/pl-fe/src/components/sidebar-menu.tsx
index 555655b9f..928b57377 100644
--- a/packages/pl-fe/src/components/sidebar-menu.tsx
+++ b/packages/pl-fe/src/components/sidebar-menu.tsx
@@ -6,7 +6,6 @@ import { Link, NavLink } from 'react-router-dom';
import { fetchOwnAccounts, logOut, switchAccount } from 'pl-fe/actions/auth';
import { useAccount } from 'pl-fe/api/hooks/accounts/use-account';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useInteractionRequestsCount } from 'pl-fe/api/hooks/statuses/use-interaction-requests';
import Account from 'pl-fe/components/account';
import Divider from 'pl-fe/components/ui/divider';
@@ -18,6 +17,7 @@ import ProfileStats from 'pl-fe/features/ui/components/profile-stats';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useRegistrationStatus } from 'pl-fe/hooks/use-registration-status';
import { makeGetOtherAccounts } from 'pl-fe/selectors';
import { useSettingsStore } from 'pl-fe/stores/settings';
@@ -106,7 +106,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
const touchEnd = useRef(null);
const { isOpen } = useRegistrationStatus();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const restrictUnauth = instance.pleroma.metadata.restrict_unauthenticated;
const containerRef = React.useRef(null);
diff --git a/packages/pl-fe/src/components/sidebar-navigation.tsx b/packages/pl-fe/src/components/sidebar-navigation.tsx
index 02c70db74..e24dfecb1 100644
--- a/packages/pl-fe/src/components/sidebar-navigation.tsx
+++ b/packages/pl-fe/src/components/sidebar-navigation.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useInteractionRequestsCount } from 'pl-fe/api/hooks/statuses/use-interaction-requests';
import Icon from 'pl-fe/components/ui/icon';
import Stack from 'pl-fe/components/ui/stack';
@@ -10,6 +9,7 @@ import ComposeButton from 'pl-fe/features/ui/components/compose-button';
import ProfileDropdown from 'pl-fe/features/ui/components/profile-dropdown';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useLogo } from 'pl-fe/hooks/use-logo';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import { useRegistrationStatus } from 'pl-fe/hooks/use-registration-status';
@@ -40,7 +40,7 @@ const SidebarNavigation = () => {
const intl = useIntl();
const { unreadChatsCount } = useStatContext();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const features = useFeatures();
const { isDeveloper } = useSettings();
const { account } = useOwnAccount();
diff --git a/packages/pl-fe/src/components/status-action-bar.tsx b/packages/pl-fe/src/components/status-action-bar.tsx
index 65f173437..413173f89 100644
--- a/packages/pl-fe/src/components/status-action-bar.tsx
+++ b/packages/pl-fe/src/components/status-action-bar.tsx
@@ -17,7 +17,6 @@ import { useBlockGroupMember } from 'pl-fe/api/hooks/groups/use-block-group-memb
import { useDeleteGroupStatus } from 'pl-fe/api/hooks/groups/use-delete-group-status';
import { useGroup } from 'pl-fe/api/hooks/groups/use-group';
import { useGroupRelationship } from 'pl-fe/api/hooks/groups/use-group-relationship';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useTranslationLanguages } from 'pl-fe/api/hooks/instance/use-translation-languages';
import DropdownMenu from 'pl-fe/components/dropdown-menu';
import StatusActionButton from 'pl-fe/components/status-action-button';
@@ -28,6 +27,7 @@ import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useCanInteract } from 'pl-fe/hooks/use-can-interact';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import { useSettings } from 'pl-fe/hooks/use-settings';
import { useChats } from 'pl-fe/queries/chats';
@@ -595,7 +595,7 @@ const MenuButton: React.FC = ({
const { groupRelationship } = useGroupRelationship(status.group_id || undefined);
const features = useFeatures();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { autoTranslate, deleteModal, knownLanguages } = useSettings();
const { translationLanguages } = useTranslationLanguages();
diff --git a/packages/pl-fe/src/components/translate-button.tsx b/packages/pl-fe/src/components/translate-button.tsx
index 9fd1c92a0..3d8e41198 100644
--- a/packages/pl-fe/src/components/translate-button.tsx
+++ b/packages/pl-fe/src/components/translate-button.tsx
@@ -1,7 +1,6 @@
import React, { useEffect } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useTranslationLanguages } from 'pl-fe/api/hooks/instance/use-translation-languages';
import { useStatusTranslation } from 'pl-fe/api/hooks/statuses/use-status-translation';
import HStack from 'pl-fe/components/ui/hstack';
@@ -10,6 +9,7 @@ import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useSettings } from 'pl-fe/hooks/use-settings';
import { useStatusMetaStore } from 'pl-fe/stores/status-meta';
@@ -22,7 +22,7 @@ interface ITranslateButton {
const TranslateButton: React.FC = ({ status }) => {
const intl = useIntl();
const features = useFeatures();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const settings = useSettings();
const autoTranslate = settings.autoTranslate;
const knownLanguages = autoTranslate ? [...settings.knownLanguages, intl.locale] : [intl.locale];
diff --git a/packages/pl-fe/src/features/admin/components/registration-mode-picker.tsx b/packages/pl-fe/src/features/admin/components/registration-mode-picker.tsx
index eb47d3163..416aaee10 100644
--- a/packages/pl-fe/src/features/admin/components/registration-mode-picker.tsx
+++ b/packages/pl-fe/src/features/admin/components/registration-mode-picker.tsx
@@ -3,9 +3,9 @@ import React from 'react';
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
import { updateConfig } from 'pl-fe/actions/admin';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { RadioGroup, RadioItem } from 'pl-fe/components/radio';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import toast from 'pl-fe/toast';
type RegistrationMode = 'open' | 'approval' | 'closed';
@@ -37,7 +37,7 @@ const modeFromInstance = ({ registrations }: Instance): RegistrationMode => {
const RegistrationModePicker: React.FC = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const mode = modeFromInstance(instance);
diff --git a/packages/pl-fe/src/features/admin/tabs/dashboard.tsx b/packages/pl-fe/src/features/admin/tabs/dashboard.tsx
index 5ac6706c1..73b56cfcf 100644
--- a/packages/pl-fe/src/features/admin/tabs/dashboard.tsx
+++ b/packages/pl-fe/src/features/admin/tabs/dashboard.tsx
@@ -1,12 +1,12 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import List, { ListItem } from 'pl-fe/components/list';
import { CardTitle } from 'pl-fe/components/ui/card';
import Icon from 'pl-fe/components/ui/icon';
import Stack from 'pl-fe/components/ui/stack';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import sourceCode from 'pl-fe/utils/code';
@@ -14,7 +14,7 @@ import { DashCounter, DashCounters } from '../components/dashcounter';
import RegistrationModePicker from '../components/registration-mode-picker';
const Dashboard: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const features = useFeatures();
const { account } = useOwnAccount();
diff --git a/packages/pl-fe/src/features/auth-login/components/consumers-list.tsx b/packages/pl-fe/src/features/auth-login/components/consumers-list.tsx
index 8ca7d38d2..cacdf1afe 100644
--- a/packages/pl-fe/src/features/auth-login/components/consumers-list.tsx
+++ b/packages/pl-fe/src/features/auth-login/components/consumers-list.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Card from 'pl-fe/components/ui/card';
import HStack from 'pl-fe/components/ui/hstack';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import ConsumerButton from './consumer-button';
@@ -14,7 +14,7 @@ interface IConsumersList {
/** Displays OAuth consumers to log in with. */
const ConsumersList: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const providers = instance.pleroma.oauth_consumer_strategies;
if (providers.length > 0) {
diff --git a/packages/pl-fe/src/features/auth-login/components/login-page.tsx b/packages/pl-fe/src/features/auth-login/components/login-page.tsx
index 05c63bff7..f13f4cde3 100644
--- a/packages/pl-fe/src/features/auth-login/components/login-page.tsx
+++ b/packages/pl-fe/src/features/auth-login/components/login-page.tsx
@@ -3,6 +3,7 @@ import { FormattedMessage } from 'react-intl';
import { Redirect } from 'react-router-dom';
import { logIn, verifyCredentials, switchAccount } from 'pl-fe/actions/auth';
+import { fetchInstance } from 'pl-fe/actions/instance';
import { BigCard } from 'pl-fe/components/big-card';
import Button from 'pl-fe/components/ui/button';
import Stack from 'pl-fe/components/ui/stack';
@@ -42,6 +43,11 @@ const LoginPage = () => {
const { username, password } = getFormData(event.target as HTMLFormElement);
dispatch(logIn(username, password))
.then(({ access_token }) => dispatch(verifyCredentials(access_token)))
+ // Refetch the instance for authenticated fetch
+ .then(async (account) => {
+ await dispatch(fetchInstance());
+ return account;
+ })
.then((account: { id: string }) => {
closeModal();
if (typeof me === 'string') {
diff --git a/packages/pl-fe/src/features/auth-login/components/registration-form.tsx b/packages/pl-fe/src/features/auth-login/components/registration-form.tsx
index c4b5ec38d..fc65c71c1 100644
--- a/packages/pl-fe/src/features/auth-login/components/registration-form.tsx
+++ b/packages/pl-fe/src/features/auth-login/components/registration-form.tsx
@@ -5,7 +5,6 @@ import { Link, useHistory } from 'react-router-dom';
import { accountLookup } from 'pl-fe/actions/accounts';
import { register, verifyCredentials } from 'pl-fe/actions/auth';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import BirthdayInput from 'pl-fe/components/birthday-input';
import Button from 'pl-fe/components/ui/button';
import Checkbox from 'pl-fe/components/ui/checkbox';
@@ -18,6 +17,7 @@ import Textarea from 'pl-fe/components/ui/textarea';
import CaptchaField from 'pl-fe/features/auth-login/components/captcha';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useSettings } from 'pl-fe/hooks/use-settings';
import { useModalsStore } from 'pl-fe/stores/modals';
@@ -52,7 +52,7 @@ const RegistrationForm: React.FC = ({ inviteToken }) => {
const { locale } = useSettings();
const features = useFeatures();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { openModal } = useModalsStore();
const needsConfirmation = instance.pleroma.metadata.account_activation_required;
diff --git a/packages/pl-fe/src/features/auth-login/components/registration-page.tsx b/packages/pl-fe/src/features/auth-login/components/registration-page.tsx
index 84da7ef5a..cce5bf427 100644
--- a/packages/pl-fe/src/features/auth-login/components/registration-page.tsx
+++ b/packages/pl-fe/src/features/auth-login/components/registration-page.tsx
@@ -1,15 +1,15 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { BigCard } from 'pl-fe/components/big-card';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useRegistrationStatus } from 'pl-fe/hooks/use-registration-status';
import RegistrationForm from './registration-form';
const RegistrationPage: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { isOpen } = useRegistrationStatus();
if (!isOpen) {
diff --git a/packages/pl-fe/src/features/chats/components/chat-composer.tsx b/packages/pl-fe/src/features/chats/components/chat-composer.tsx
index 5c948a8f7..ed0c7b39c 100644
--- a/packages/pl-fe/src/features/chats/components/chat-composer.tsx
+++ b/packages/pl-fe/src/features/chats/components/chat-composer.tsx
@@ -3,7 +3,6 @@ import { defineMessages, IntlShape, useIntl } from 'react-intl';
import { unblockAccount } from 'pl-fe/actions/accounts';
import { useRelationship } from 'pl-fe/api/hooks/accounts/use-relationship';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Button from 'pl-fe/components/ui/button';
import Combobox, { ComboboxInput, ComboboxList, ComboboxOption, ComboboxPopover } from 'pl-fe/components/ui/combobox';
import HStack from 'pl-fe/components/ui/hstack';
@@ -14,6 +13,7 @@ import { useChatContext } from 'pl-fe/contexts/chat-context';
import UploadButton from 'pl-fe/features/compose/components/upload-button';
import emojiSearch from 'pl-fe/features/emoji/search';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useModalsStore } from 'pl-fe/stores/modals';
import { textAtCursorMatchesToken } from 'pl-fe/utils/suggestions';
@@ -85,7 +85,7 @@ const ChatComposer = React.forwardRef
const isBlocked = relationship?.blocked_by && false;
const isBlocking = relationship?.blocking && false;
- const maxCharacterCount = useInstance().data.configuration.chats.max_characters;
+ const maxCharacterCount = useInstance().configuration.chats.max_characters;
const [suggestions, setSuggestions] = useState(initialSuggestionState);
const isSuggestionsAvailable = suggestions.list.length > 0;
diff --git a/packages/pl-fe/src/features/compose-event/components/upload-button.tsx b/packages/pl-fe/src/features/compose-event/components/upload-button.tsx
index 3e17dae64..7b696e9be 100644
--- a/packages/pl-fe/src/features/compose-event/components/upload-button.tsx
+++ b/packages/pl-fe/src/features/compose-event/components/upload-button.tsx
@@ -1,10 +1,10 @@
import React, { useRef } from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Icon from 'pl-fe/components/icon';
import HStack from 'pl-fe/components/ui/hstack';
import Text from 'pl-fe/components/ui/text';
+import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
interface IUploadButton {
disabled?: boolean;
@@ -14,7 +14,7 @@ interface IUploadButton {
const UploadButton: React.FC = ({ disabled, onSelectFile }) => {
const fileElement = useRef(null);
- const attachmentTypes = useInstance().data.configuration.media_attachments.supported_mime_types
+ const attachmentTypes = useAppSelector(state => state.instance.configuration.media_attachments.supported_mime_types)
?.filter((type) => type.startsWith('image/'));
let accept = attachmentTypes?.join(',');
diff --git a/packages/pl-fe/src/features/compose/components/compose-form.tsx b/packages/pl-fe/src/features/compose/components/compose-form.tsx
index 15dc3efa0..ef8149e2a 100644
--- a/packages/pl-fe/src/features/compose/components/compose-form.tsx
+++ b/packages/pl-fe/src/features/compose/components/compose-form.tsx
@@ -12,7 +12,6 @@ import {
selectComposeSuggestion,
uploadCompose,
} from 'pl-fe/actions/compose';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Button from 'pl-fe/components/ui/button';
import HStack from 'pl-fe/components/ui/hstack';
import Stack from 'pl-fe/components/ui/stack';
@@ -22,6 +21,7 @@ import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useCompose } from 'pl-fe/hooks/use-compose';
import { useDraggedFiles } from 'pl-fe/hooks/use-dragged-files';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import QuotedStatusContainer from '../containers/quoted-status-container';
import ReplyIndicatorContainer from '../containers/reply-indicator-container';
@@ -75,7 +75,7 @@ const ComposeForm = ({ id, shouldCondense, autoFocus, clickab
const history = useHistory();
const intl = useIntl();
const dispatch = useAppDispatch();
- const { configuration } = useInstance().data;
+ const { configuration } = useInstance();
const compose = useCompose(id);
const maxTootChars = configuration.statuses.max_characters;
diff --git a/packages/pl-fe/src/features/compose/components/content-type-button.tsx b/packages/pl-fe/src/features/compose/components/content-type-button.tsx
index 6d27bf95c..9565d2b43 100644
--- a/packages/pl-fe/src/features/compose/components/content-type-button.tsx
+++ b/packages/pl-fe/src/features/compose/components/content-type-button.tsx
@@ -2,11 +2,11 @@ import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { changeComposeContentType } from 'pl-fe/actions/compose';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import DropdownMenu from 'pl-fe/components/dropdown-menu';
import Button from 'pl-fe/components/ui/button';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useCompose } from 'pl-fe/hooks/use-compose';
+import { useInstance } from 'pl-fe/hooks/use-instance';
const messages = defineMessages({
content_type_plaintext: { id: 'preferences.options.content_type_plaintext', defaultMessage: 'Plain text' },
@@ -24,7 +24,7 @@ interface IContentTypeButton {
const ContentTypeButton: React.FC = ({ composeId }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const contentType = useCompose(composeId).content_type;
diff --git a/packages/pl-fe/src/features/compose/components/polls/poll-form.tsx b/packages/pl-fe/src/features/compose/components/polls/poll-form.tsx
index 095f9e0c7..f2247bd43 100644
--- a/packages/pl-fe/src/features/compose/components/polls/poll-form.tsx
+++ b/packages/pl-fe/src/features/compose/components/polls/poll-form.tsx
@@ -2,7 +2,6 @@ import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { addPollOption, changePollOption, changePollSettings, clearComposeSuggestions, fetchComposeSuggestions, removePoll, removePollOption, selectComposeSuggestion } from 'pl-fe/actions/compose';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import AutosuggestInput from 'pl-fe/components/autosuggest-input';
import Button from 'pl-fe/components/ui/button';
import Divider from 'pl-fe/components/ui/divider';
@@ -12,6 +11,7 @@ import Text from 'pl-fe/components/ui/text';
import Toggle from 'pl-fe/components/ui/toggle';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useCompose } from 'pl-fe/hooks/use-compose';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import DurationSelector from './duration-selector';
@@ -118,7 +118,7 @@ interface IPollForm {
const PollForm: React.FC = ({ composeId }) => {
const dispatch = useAppDispatch();
const intl = useIntl();
- const { configuration } = useInstance().data;
+ const { configuration } = useInstance();
const { poll, language, modified_language: modifiedLanguage } = useCompose(composeId);
diff --git a/packages/pl-fe/src/features/compose/components/upload-button.tsx b/packages/pl-fe/src/features/compose/components/upload-button.tsx
index 174f22a28..1d6d35245 100644
--- a/packages/pl-fe/src/features/compose/components/upload-button.tsx
+++ b/packages/pl-fe/src/features/compose/components/upload-button.tsx
@@ -1,8 +1,8 @@
import React, { useRef } from 'react';
import { defineMessages, IntlShape, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import IconButton from 'pl-fe/components/ui/icon-button';
+import { useInstance } from 'pl-fe/hooks/use-instance';
const messages = defineMessages({
upload: { id: 'upload_button.label', defaultMessage: 'Add media attachment' },
@@ -32,7 +32,7 @@ const UploadButton: React.FC = ({
icon,
}) => {
const intl = useIntl();
- const { configuration } = useInstance().data;
+ const { configuration } = useInstance();
const fileElement = useRef(null);
const attachmentTypes = configuration.media_attachments.supported_mime_types;
diff --git a/packages/pl-fe/src/features/compose/components/upload.tsx b/packages/pl-fe/src/features/compose/components/upload.tsx
index 187203992..4726c4a94 100644
--- a/packages/pl-fe/src/features/compose/components/upload.tsx
+++ b/packages/pl-fe/src/features/compose/components/upload.tsx
@@ -1,10 +1,10 @@
import React, { useCallback } from 'react';
import { undoUploadCompose, changeUploadCompose } from 'pl-fe/actions/compose';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Upload from 'pl-fe/components/upload';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useCompose } from 'pl-fe/hooks/use-compose';
+import { useInstance } from 'pl-fe/hooks/use-instance';
interface IUploadCompose {
id: string;
@@ -17,7 +17,7 @@ interface IUploadCompose {
const UploadCompose: React.FC = ({ composeId, id, onSubmit, onDragStart, onDragEnter, onDragEnd }) => {
const dispatch = useAppDispatch();
- const { pleroma: { metadata: { description_limit: descriptionLimit } } } = useInstance().data;
+ const { pleroma: { metadata: { description_limit: descriptionLimit } } } = useInstance();
const media = useCompose(composeId).media_attachments.find(item => item.id === id)!;
diff --git a/packages/pl-fe/src/features/compose/editor/nodes/index.ts b/packages/pl-fe/src/features/compose/editor/nodes/index.ts
index d35644260..1daec172c 100644
--- a/packages/pl-fe/src/features/compose/editor/nodes/index.ts
+++ b/packages/pl-fe/src/features/compose/editor/nodes/index.ts
@@ -11,7 +11,7 @@ import { ListItemNode, ListNode } from '@lexical/list';
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
import { HeadingNode, QuoteNode } from '@lexical/rich-text';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { EmojiNode } from './emoji-node';
import { ImageNode } from './image-node';
@@ -20,7 +20,7 @@ import { MentionNode } from './mention-node';
import type { Klass, LexicalNode } from 'lexical';
const useNodes = (isWysiwyg?: boolean) => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const nodes: Array> = [
AutoLinkNode,
diff --git a/packages/pl-fe/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx b/packages/pl-fe/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx
index c9eb578e6..96dc90568 100644
--- a/packages/pl-fe/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx
+++ b/packages/pl-fe/src/features/compose/editor/plugins/floating-block-type-toolbar-plugin.tsx
@@ -23,8 +23,8 @@ import { createPortal } from 'react-dom';
import { defineMessages, useIntl } from 'react-intl';
import { uploadFile } from 'pl-fe/actions/compose';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { $createImageNode } from '../nodes/image-node';
import { setFloatingElemPosition } from '../utils/set-floating-elem-position';
@@ -42,7 +42,7 @@ interface IUploadButton {
const UploadButton: React.FC = ({ onSelectFile }) => {
const intl = useIntl();
- const { configuration } = useInstance().data;
+ const { configuration } = useInstance();
const dispatch = useAppDispatch();
const [disabled, setDisabled] = useState(false);
@@ -101,7 +101,7 @@ const BlockTypeFloatingToolbar = ({
}): JSX.Element => {
const intl = useIntl();
const popupCharStylesEditorRef = useRef(null);
- const { data: instance } = useInstance();
+ const instance = useInstance();
const allowInlineImages = instance.pleroma.metadata.markup.allow_inline_images;
diff --git a/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx b/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx
index f62db9602..f1f955d37 100644
--- a/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx
+++ b/packages/pl-fe/src/features/compose/editor/plugins/floating-text-format-toolbar-plugin.tsx
@@ -39,8 +39,8 @@ import * as React from 'react';
import { createPortal } from 'react-dom';
import { defineMessages, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Icon from 'pl-fe/components/ui/icon';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { getDOMRangeRect } from '../utils/get-dom-range-rect';
import { getSelectedNode } from '../utils/get-selected-node';
@@ -109,7 +109,7 @@ const BlockTypeDropdown = ({ editor, anchorElem, blockType, icon }: {
blockType: keyof typeof blockTypeToBlockName;
icon: string;
}) => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const [showDropDown, setShowDropDown] = useState(false);
diff --git a/packages/pl-fe/src/features/crypto-donate/components/crypto-donate-panel.tsx b/packages/pl-fe/src/features/crypto-donate/components/crypto-donate-panel.tsx
index ebe6b36bb..96032e34a 100644
--- a/packages/pl-fe/src/features/crypto-donate/components/crypto-donate-panel.tsx
+++ b/packages/pl-fe/src/features/crypto-donate/components/crypto-donate-panel.tsx
@@ -2,9 +2,9 @@ import React from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { useHistory } from 'react-router-dom';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Text from 'pl-fe/components/ui/text';
import Widget from 'pl-fe/components/ui/widget';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
import SiteWallet from './site-wallet';
@@ -20,7 +20,7 @@ interface ICryptoDonatePanel {
const CryptoDonatePanel: React.FC = ({ limit = 3 }): JSX.Element | null => {
const intl = useIntl();
const history = useHistory();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const addresses = usePlFeConfig().cryptoAddresses;
diff --git a/packages/pl-fe/src/features/crypto-donate/index.tsx b/packages/pl-fe/src/features/crypto-donate/index.tsx
index 9dd76d01c..1fbaffb20 100644
--- a/packages/pl-fe/src/features/crypto-donate/index.tsx
+++ b/packages/pl-fe/src/features/crypto-donate/index.tsx
@@ -1,10 +1,10 @@
import React, { useState } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Accordion from 'pl-fe/components/ui/accordion';
import Column from 'pl-fe/components/ui/column';
import Stack from 'pl-fe/components/ui/stack';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import SiteWallet from './components/site-wallet';
@@ -14,7 +14,7 @@ const messages = defineMessages({
const CryptoDonate: React.FC = (): JSX.Element => {
const intl = useIntl();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const [explanationBoxExpanded, toggleExplanationBox] = useState(true);
diff --git a/packages/pl-fe/src/features/directory/index.tsx b/packages/pl-fe/src/features/directory/index.tsx
index ce5aaf4ca..3c6e5fc2b 100644
--- a/packages/pl-fe/src/features/directory/index.tsx
+++ b/packages/pl-fe/src/features/directory/index.tsx
@@ -4,13 +4,13 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { useSearchParams } from 'react-router-dom-v5-compat';
import { useDirectory } from 'pl-fe/api/hooks/account-lists/use-directory';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import LoadMore from 'pl-fe/components/load-more';
import { RadioGroup, RadioItem } from 'pl-fe/components/radio';
import { CardTitle } from 'pl-fe/components/ui/card';
import Column from 'pl-fe/components/ui/column';
import Stack from 'pl-fe/components/ui/stack';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import AccountCard from './components/account-card';
@@ -25,7 +25,7 @@ const messages = defineMessages({
const Directory = () => {
const intl = useIntl();
const [params, setParams] = useSearchParams();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const features = useFeatures();
const order = (params.get('order') || 'active') as 'active' | 'new';
diff --git a/packages/pl-fe/src/features/edit-profile/index.tsx b/packages/pl-fe/src/features/edit-profile/index.tsx
index 22d4284a6..cc068e5df 100644
--- a/packages/pl-fe/src/features/edit-profile/index.tsx
+++ b/packages/pl-fe/src/features/edit-profile/index.tsx
@@ -5,7 +5,6 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { updateNotificationSettings } from 'pl-fe/actions/accounts';
import { patchMe } from 'pl-fe/actions/me';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import BirthdayInput from 'pl-fe/components/birthday-input';
import List, { ListItem } from 'pl-fe/components/list';
import Button from 'pl-fe/components/ui/button';
@@ -22,6 +21,7 @@ import { useImageField } from 'pl-fe/hooks/forms/use-image-field';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import toast from 'pl-fe/toast';
import { isDefaultAvatar, isDefaultHeader } from 'pl-fe/utils/accounts';
@@ -173,7 +173,7 @@ const ProfileField: StreamfieldComponent = ({ index, va
const EditProfile: React.FC = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { account } = useOwnAccount();
const features = useFeatures();
@@ -181,7 +181,8 @@ const EditProfile: React.FC = () => {
? instance.configuration.accounts.max_profile_fields
: instance.pleroma.metadata.fields_limits.max_fields;
- const attachmentTypes = useInstance().data.configuration.media_attachments.supported_mime_types
+ const attachmentTypes = useAppSelector(
+ state => state.instance.configuration.media_attachments.supported_mime_types)
?.filter(type => type.startsWith('image/'))
.join(',');
diff --git a/packages/pl-fe/src/features/federation-restrictions/components/instance-restrictions.tsx b/packages/pl-fe/src/features/federation-restrictions/components/instance-restrictions.tsx
index 7377a2ea0..b537c292e 100644
--- a/packages/pl-fe/src/features/federation-restrictions/components/instance-restrictions.tsx
+++ b/packages/pl-fe/src/features/federation-restrictions/components/instance-restrictions.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Icon from 'pl-fe/components/icon';
import HStack from 'pl-fe/components/ui/hstack';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import type { RemoteInstance } from 'pl-fe/selectors';
@@ -34,7 +34,7 @@ interface IInstanceRestrictions {
}
const InstanceRestrictions: React.FC = ({ remoteInstance }) => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const renderRestrictions = () => {
const items = [];
diff --git a/packages/pl-fe/src/features/federation-restrictions/components/restricted-instance.tsx b/packages/pl-fe/src/features/federation-restrictions/components/restricted-instance.tsx
index 0a0dd9aef..f709a9385 100644
--- a/packages/pl-fe/src/features/federation-restrictions/components/restricted-instance.tsx
+++ b/packages/pl-fe/src/features/federation-restrictions/components/restricted-instance.tsx
@@ -1,7 +1,6 @@
import clsx from 'clsx';
import React, { useState } from 'react';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Icon from 'pl-fe/components/icon';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { makeGetRemoteInstance } from 'pl-fe/selectors';
@@ -15,8 +14,7 @@ interface IRestrictedInstance {
}
const RestrictedInstance: React.FC = ({ host }) => {
- const { data: instance } = useInstance();
- const remoteInstance: any = useAppSelector((state) => getRemoteInstance(state, host, instance));
+ const remoteInstance: any = useAppSelector((state) => getRemoteInstance(state, host));
const [expanded, setExpanded] = useState(false);
diff --git a/packages/pl-fe/src/features/federation-restrictions/index.tsx b/packages/pl-fe/src/features/federation-restrictions/index.tsx
index 16b716c7d..0c07d8bcd 100644
--- a/packages/pl-fe/src/features/federation-restrictions/index.tsx
+++ b/packages/pl-fe/src/features/federation-restrictions/index.tsx
@@ -1,11 +1,11 @@
import React, { useState, useCallback } from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import ScrollableList from 'pl-fe/components/scrollable-list';
import Accordion from 'pl-fe/components/ui/accordion';
import Column from 'pl-fe/components/ui/column';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { makeGetHosts } from 'pl-fe/selectors';
import { federationRestrictionsDisclosed } from 'pl-fe/utils/state';
@@ -21,12 +21,12 @@ const messages = defineMessages({
const FederationRestrictions = () => {
const intl = useIntl();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const getHosts = useCallback(makeGetHosts(), []);
- const hosts = useAppSelector((state) => getHosts(state, instance));
- const disclosed = federationRestrictionsDisclosed(instance);
+ const hosts = useAppSelector((state) => getHosts(state));
+ const disclosed = useAppSelector((state) => federationRestrictionsDisclosed(state));
const [explanationBoxExpanded, setExplanationBoxExpanded] = useState(true);
diff --git a/packages/pl-fe/src/features/group/edit-group.tsx b/packages/pl-fe/src/features/group/edit-group.tsx
index 936d1d4ae..eb3ceefbe 100644
--- a/packages/pl-fe/src/features/group/edit-group.tsx
+++ b/packages/pl-fe/src/features/group/edit-group.tsx
@@ -3,7 +3,6 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useGroup } from 'pl-fe/api/hooks/groups/use-group';
import { useUpdateGroup } from 'pl-fe/api/hooks/groups/use-update-group';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Button from 'pl-fe/components/ui/button';
import Column from 'pl-fe/components/ui/column';
import Form from 'pl-fe/components/ui/form';
@@ -15,6 +14,8 @@ import Spinner from 'pl-fe/components/ui/spinner';
import Textarea from 'pl-fe/components/ui/textarea';
import { useImageField } from 'pl-fe/hooks/forms/use-image-field';
import { useTextField } from 'pl-fe/hooks/forms/use-text-field';
+import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import toast from 'pl-fe/toast';
import { isDefaultAvatar, isDefaultHeader } from 'pl-fe/utils/accounts';
import { unescapeHTML } from 'pl-fe/utils/html';
@@ -40,7 +41,7 @@ interface IEditGroup {
const EditGroup: React.FC = ({ params: { groupId } }) => {
const intl = useIntl();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { group, isLoading } = useGroup(groupId);
const { updateGroup } = useUpdateGroup(groupId);
@@ -56,7 +57,7 @@ const EditGroup: React.FC = ({ params: { groupId } }) => {
const maxName = Number(instance.configuration.groups.max_characters_name);
const maxNote = Number(instance.configuration.groups.max_characters_description);
- const attachmentTypes = useInstance().data.configuration.media_attachments.supported_mime_types
+ const attachmentTypes = useAppSelector(state => state.instance.configuration.media_attachments.supported_mime_types)
?.filter((type) => type.startsWith('image/'))
.join(',');
diff --git a/packages/pl-fe/src/features/home-timeline/index.tsx b/packages/pl-fe/src/features/home-timeline/index.tsx
index c8646a566..cab35870d 100644
--- a/packages/pl-fe/src/features/home-timeline/index.tsx
+++ b/packages/pl-fe/src/features/home-timeline/index.tsx
@@ -3,7 +3,6 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { fetchHomeTimeline } from 'pl-fe/actions/timelines';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import PullToRefresh from 'pl-fe/components/pull-to-refresh';
import Column from 'pl-fe/components/ui/column';
import Stack from 'pl-fe/components/ui/stack';
@@ -12,6 +11,7 @@ import Timeline from 'pl-fe/features/ui/components/timeline';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useIsMobile } from 'pl-fe/hooks/use-is-mobile';
import { useTheme } from 'pl-fe/hooks/use-theme';
@@ -23,7 +23,7 @@ const HomeTimeline: React.FC = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
const features = useFeatures();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const theme = useTheme();
const polling = useRef(null);
diff --git a/packages/pl-fe/src/features/landing-timeline/components/site-banner.tsx b/packages/pl-fe/src/features/landing-timeline/components/site-banner.tsx
index a3ab2be82..a82bcc84e 100644
--- a/packages/pl-fe/src/features/landing-timeline/components/site-banner.tsx
+++ b/packages/pl-fe/src/features/landing-timeline/components/site-banner.tsx
@@ -1,15 +1,15 @@
import React from 'react';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Markup from 'pl-fe/components/markup';
import { ParsedContent } from 'pl-fe/components/parsed-content';
import Stack from 'pl-fe/components/ui/stack';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { getTextDirection } from 'pl-fe/utils/rtl';
import { LogoText } from './logo-text';
const SiteBanner: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
return (
diff --git a/packages/pl-fe/src/features/landing-timeline/index.tsx b/packages/pl-fe/src/features/landing-timeline/index.tsx
index 3d1c3e842..25fc67af4 100644
--- a/packages/pl-fe/src/features/landing-timeline/index.tsx
+++ b/packages/pl-fe/src/features/landing-timeline/index.tsx
@@ -2,11 +2,11 @@ import React, { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { fetchPublicTimeline } from 'pl-fe/actions/timelines';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useCommunityStream } from 'pl-fe/api/hooks/streaming/use-community-stream';
import PullToRefresh from 'pl-fe/components/pull-to-refresh';
import Column from 'pl-fe/components/ui/column';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useIsMobile } from 'pl-fe/hooks/use-is-mobile';
import { useTheme } from 'pl-fe/hooks/use-theme';
@@ -17,7 +17,7 @@ import { SiteBanner } from './components/site-banner';
const LandingTimeline = () => {
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const theme = useTheme();
const isMobile = useIsMobile();
diff --git a/packages/pl-fe/src/features/migration/index.tsx b/packages/pl-fe/src/features/migration/index.tsx
index 779b4df4b..d1ca4df7f 100644
--- a/packages/pl-fe/src/features/migration/index.tsx
+++ b/packages/pl-fe/src/features/migration/index.tsx
@@ -3,7 +3,6 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { moveAccount } from 'pl-fe/actions/security';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Button from 'pl-fe/components/ui/button';
import Column from 'pl-fe/components/ui/column';
import Form from 'pl-fe/components/ui/form';
@@ -12,6 +11,7 @@ import FormGroup from 'pl-fe/components/ui/form-group';
import Input from 'pl-fe/components/ui/input';
import Text from 'pl-fe/components/ui/text';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import toast from 'pl-fe/toast';
const messages = defineMessages({
@@ -28,7 +28,7 @@ const messages = defineMessages({
const Migration = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const cooldownPeriod = instance.pleroma.metadata.migration_cooldown_period;
diff --git a/packages/pl-fe/src/features/notifications/components/notification.tsx b/packages/pl-fe/src/features/notifications/components/notification.tsx
index dc815749e..eeea9071c 100644
--- a/packages/pl-fe/src/features/notifications/components/notification.tsx
+++ b/packages/pl-fe/src/features/notifications/components/notification.tsx
@@ -4,7 +4,6 @@ import { Link, useHistory } from 'react-router-dom';
import { mentionCompose } from 'pl-fe/actions/compose';
import { reblog, favourite, unreblog, unfavourite } from 'pl-fe/actions/interactions';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import HoverAccountWrapper from 'pl-fe/components/hover-account-wrapper';
import Icon from 'pl-fe/components/icon';
import RelativeTimestamp from 'pl-fe/components/relative-timestamp';
@@ -17,6 +16,7 @@ import Emojify from 'pl-fe/features/emoji/emojify';
import { HotKeys } from 'pl-fe/features/ui/components/hotkeys';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useLoggedIn } from 'pl-fe/hooks/use-logged-in';
import { makeGetNotification } from 'pl-fe/selectors';
import { useModalsStore } from 'pl-fe/stores/modals';
@@ -212,7 +212,7 @@ const Notification: React.FC = (props) => {
const history = useHistory();
const intl = useIntl();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const type = notification.type;
const { accounts } = notification;
diff --git a/packages/pl-fe/src/features/onboarding/steps/fediverse-step.tsx b/packages/pl-fe/src/features/onboarding/steps/fediverse-step.tsx
index 2140cb79c..46b0fbe78 100644
--- a/packages/pl-fe/src/features/onboarding/steps/fediverse-step.tsx
+++ b/packages/pl-fe/src/features/onboarding/steps/fediverse-step.tsx
@@ -1,18 +1,18 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Account from 'pl-fe/components/account';
import Button from 'pl-fe/components/ui/button';
import Card, { CardBody } from 'pl-fe/components/ui/card';
import Icon from 'pl-fe/components/ui/icon';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
const FediverseStep = ({ onNext }: { onNext: () => void }) => {
const { account } = useOwnAccount();
- const { data: instance } = useInstance();
+ const instance = useInstance();
return (
diff --git a/packages/pl-fe/src/features/preferences/index.tsx b/packages/pl-fe/src/features/preferences/index.tsx
index e4c4e2609..306cbcbb1 100644
--- a/packages/pl-fe/src/features/preferences/index.tsx
+++ b/packages/pl-fe/src/features/preferences/index.tsx
@@ -2,13 +2,13 @@ import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { changeSetting } from 'pl-fe/actions/settings';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import List, { ListItem } from 'pl-fe/components/list';
import Form from 'pl-fe/components/ui/form';
import { Mutliselect, SelectDropdown } from 'pl-fe/features/forms';
import SettingToggle from 'pl-fe/features/notifications/components/setting-toggle';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useSettings } from 'pl-fe/hooks/use-settings';
import ThemeToggle from '../ui/components/theme-toggle';
@@ -98,7 +98,7 @@ const Preferences = () => {
const dispatch = useAppDispatch();
const features = useFeatures();
const settings = useSettings();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const onSelectChange = (event: React.ChangeEvent, path: string[]) => {
dispatch(changeSetting(path, event.target.value, { showAlert: true }));
diff --git a/packages/pl-fe/src/features/public-timeline/index.tsx b/packages/pl-fe/src/features/public-timeline/index.tsx
index 977d1bd8c..9f64cbebd 100644
--- a/packages/pl-fe/src/features/public-timeline/index.tsx
+++ b/packages/pl-fe/src/features/public-timeline/index.tsx
@@ -4,12 +4,12 @@ import { Link } from 'react-router-dom';
import { changeSetting } from 'pl-fe/actions/settings';
import { fetchPublicTimeline } from 'pl-fe/actions/timelines';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { usePublicStream } from 'pl-fe/api/hooks/streaming/use-public-stream';
import PullToRefresh from 'pl-fe/components/pull-to-refresh';
import Accordion from 'pl-fe/components/ui/accordion';
import Column from 'pl-fe/components/ui/column';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useIsMobile } from 'pl-fe/hooks/use-is-mobile';
import { useSettings } from 'pl-fe/hooks/use-settings';
import { useTheme } from 'pl-fe/hooks/use-theme';
@@ -27,7 +27,7 @@ const CommunityTimeline = () => {
const dispatch = useAppDispatch();
const theme = useTheme();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const settings = useSettings();
const onlyMedia = settings.timelines.public?.other.onlyMedia ?? false;
diff --git a/packages/pl-fe/src/features/register-invite/index.tsx b/packages/pl-fe/src/features/register-invite/index.tsx
index 81af6fac2..4591d3222 100644
--- a/packages/pl-fe/src/features/register-invite/index.tsx
+++ b/packages/pl-fe/src/features/register-invite/index.tsx
@@ -2,9 +2,9 @@ import React from 'react';
import { FormattedMessage } from 'react-intl';
import { useParams } from 'react-router-dom';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { BigCard } from 'pl-fe/components/big-card';
import RegistrationForm from 'pl-fe/features/auth-login/components/registration-form';
+import { useInstance } from 'pl-fe/hooks/use-instance';
interface RegisterInviteParams {
token: string;
@@ -12,7 +12,7 @@ interface RegisterInviteParams {
/** Page to register with an invitation. */
const RegisterInvite: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { token } = useParams();
const title = (
diff --git a/packages/pl-fe/src/features/server-info/index.tsx b/packages/pl-fe/src/features/server-info/index.tsx
index 7ced0eed0..3c2928ee3 100644
--- a/packages/pl-fe/src/features/server-info/index.tsx
+++ b/packages/pl-fe/src/features/server-info/index.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Column from 'pl-fe/components/ui/column';
import Divider from 'pl-fe/components/ui/divider';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import LinkFooter from '../ui/components/link-footer';
import PromoPanel from '../ui/components/panels/promo-panel';
@@ -16,7 +16,7 @@ const messages = defineMessages({
const ServerInfo = () => {
const intl = useIntl();
- const { data: instance } = useInstance();
+ const instance = useInstance();
return (
diff --git a/packages/pl-fe/src/features/status/components/thread-login-cta.tsx b/packages/pl-fe/src/features/status/components/thread-login-cta.tsx
index c145925c4..1c3167dd6 100644
--- a/packages/pl-fe/src/features/status/components/thread-login-cta.tsx
+++ b/packages/pl-fe/src/features/status/components/thread-login-cta.tsx
@@ -1,16 +1,16 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Button from 'pl-fe/components/ui/button';
import Card, { CardTitle } from 'pl-fe/components/ui/card';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
/** Prompts logged-out users to log in when viewing a thread. */
const ThreadLoginCta: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { displayCta } = usePlFeConfig();
if (!displayCta) return null;
diff --git a/packages/pl-fe/src/features/ui/components/modals/edit-federation-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/edit-federation-modal.tsx
index 5766626ed..13127c475 100644
--- a/packages/pl-fe/src/features/ui/components/modals/edit-federation-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/edit-federation-modal.tsx
@@ -2,7 +2,6 @@ import React, { useState, useEffect, useCallback } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { updateMrf } from 'pl-fe/actions/mrf';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import List, { ListItem } from 'pl-fe/components/list';
import Modal from 'pl-fe/components/ui/modal';
import Toggle from 'pl-fe/components/ui/toggle';
@@ -31,9 +30,8 @@ const EditFederationModal: React.FC =
const intl = useIntl();
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
const getRemoteInstance = useCallback(makeGetRemoteInstance(), []);
- const remoteInstance = useAppSelector(state => getRemoteInstance(state, host, instance));
+ const remoteInstance = useAppSelector(state => getRemoteInstance(state, host));
const [data, setData] = useState>({});
diff --git a/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx b/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
index 48397c5f6..e269632ab 100644
--- a/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Form from 'pl-fe/components/ui/form';
import FormGroup from 'pl-fe/components/ui/form-group';
import Input from 'pl-fe/components/ui/input';
@@ -9,6 +8,8 @@ import Textarea from 'pl-fe/components/ui/textarea';
import AvatarPicker from 'pl-fe/features/edit-profile/components/avatar-picker';
import HeaderPicker from 'pl-fe/features/edit-profile/components/header-picker';
import { usePreview } from 'pl-fe/hooks/forms/use-preview';
+import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import resizeImage from 'pl-fe/utils/resize-image';
import type { CreateGroupParams } from 'pl-api';
@@ -26,7 +27,7 @@ interface IDetailsStep {
const DetailsStep: React.FC = ({ params, onChange }) => {
const intl = useIntl();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const {
display_name: displayName = '',
@@ -36,7 +37,7 @@ const DetailsStep: React.FC = ({ params, onChange }) => {
const avatarSrc = usePreview(params.avatar);
const headerSrc = usePreview(params.header);
- const attachmentTypes = useInstance().data.configuration.media_attachments.supported_mime_types
+ const attachmentTypes = useAppSelector(state => state.instance.configuration.media_attachments.supported_mime_types)
?.filter((type) => type.startsWith('image/'))
.join(',');
diff --git a/packages/pl-fe/src/features/ui/components/modals/report-modal/index.tsx b/packages/pl-fe/src/features/ui/components/modals/report-modal/index.tsx
index c8f203e56..e949a7b9f 100644
--- a/packages/pl-fe/src/features/ui/components/modals/report-modal/index.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/report-modal/index.tsx
@@ -5,7 +5,6 @@ import { blockAccount } from 'pl-fe/actions/accounts';
import { submitReport, ReportableEntities } from 'pl-fe/actions/reports';
import { fetchAccountTimeline } from 'pl-fe/actions/timelines';
import { useAccount } from 'pl-fe/api/hooks/accounts/use-account';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import AttachmentThumbs from 'pl-fe/components/attachment-thumbs';
import StatusContent from 'pl-fe/components/status-content';
import Modal from 'pl-fe/components/ui/modal';
@@ -15,6 +14,7 @@ import Text from 'pl-fe/components/ui/text';
import AccountContainer from 'pl-fe/containers/account-container';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import ConfirmationStep from './steps/confirmation-step';
import OtherActionsStep from './steps/other-actions-step';
@@ -83,7 +83,7 @@ const ReportModal: React.FC = ({ onClose, acc
const [block, setBlock] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
- const { rules } = useInstance().data;
+ const { rules } = useInstance();
const [ruleIds, setRuleIds] = useState>([]);
const [selectedStatusIds, setSelectedStatusIds] = useState(statusIds);
const [comment, setComment] = useState('');
diff --git a/packages/pl-fe/src/features/ui/components/modals/report-modal/steps/reason-step.tsx b/packages/pl-fe/src/features/ui/components/modals/report-modal/steps/reason-step.tsx
index 3e9fa59c4..fd4b9ac86 100644
--- a/packages/pl-fe/src/features/ui/components/modals/report-modal/steps/reason-step.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/report-modal/steps/reason-step.tsx
@@ -2,11 +2,11 @@ import clsx from 'clsx';
import React, { useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import FormGroup from 'pl-fe/components/ui/form-group';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
import Textarea from 'pl-fe/components/ui/textarea';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import type { Account } from 'pl-fe/normalizers/account';
@@ -33,7 +33,7 @@ const ReasonStep: React.FC = ({ comment, setComment, ruleIds, setRu
const [isNearBottom, setNearBottom] = useState(false);
const [isNearTop, setNearTop] = useState(true);
- const { rules } = useInstance().data;
+ const { rules } = useInstance();
const shouldRequireRule = rules.length > 0;
const handleCommentChange = (event: React.ChangeEvent) => {
diff --git a/packages/pl-fe/src/features/ui/components/modals/unauthorized-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/unauthorized-modal.tsx
index 7bda58852..2fb49f939 100644
--- a/packages/pl-fe/src/features/ui/components/modals/unauthorized-modal.tsx
+++ b/packages/pl-fe/src/features/ui/components/modals/unauthorized-modal.tsx
@@ -3,7 +3,6 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { useHistory } from 'react-router-dom';
import { remoteInteraction } from 'pl-fe/actions/interactions';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Button from 'pl-fe/components/ui/button';
import Form from 'pl-fe/components/ui/form';
import Input from 'pl-fe/components/ui/input';
@@ -13,6 +12,7 @@ import Text from 'pl-fe/components/ui/text';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useRegistrationStatus } from 'pl-fe/hooks/use-registration-status';
import { selectAccount } from 'pl-fe/selectors';
import toast from 'pl-fe/toast';
@@ -40,7 +40,7 @@ const UnauthorizedModal: React.FC = ({
const intl = useIntl();
const history = useHistory();
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { isOpen } = useRegistrationStatus();
const username = useAppSelector(state => selectAccount(state, accountId!)?.display_name);
diff --git a/packages/pl-fe/src/features/ui/components/panels/instance-info-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/instance-info-panel.tsx
index b88fe2203..3273c4fe7 100644
--- a/packages/pl-fe/src/features/ui/components/panels/instance-info-panel.tsx
+++ b/packages/pl-fe/src/features/ui/components/panels/instance-info-panel.tsx
@@ -2,7 +2,6 @@ import React from 'react';
import { useIntl, defineMessages } from 'react-intl';
import { pinHost, unpinHost } from 'pl-fe/actions/remote-timeline';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import Widget from 'pl-fe/components/ui/widget';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
@@ -27,9 +26,8 @@ const InstanceInfoPanel: React.FC = ({ host }) => {
const dispatch = useAppDispatch();
const settings = useSettings();
+ const remoteInstance: any = useAppSelector(state => getRemoteInstance(state, host));
const pinned = settings.remote_timeline.pinnedHosts.includes(host);
- const { data: instance } = useInstance();
- const remoteInstance = useAppSelector(state => getRemoteInstance(state, host, instance));
const handlePinHost = () => {
if (!pinned) {
diff --git a/packages/pl-fe/src/features/ui/components/panels/instance-moderation-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/instance-moderation-panel.tsx
index f344f5d48..e0c55aa00 100644
--- a/packages/pl-fe/src/features/ui/components/panels/instance-moderation-panel.tsx
+++ b/packages/pl-fe/src/features/ui/components/panels/instance-moderation-panel.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import DropdownMenu from 'pl-fe/components/dropdown-menu';
import Widget from 'pl-fe/components/ui/widget';
import InstanceRestrictions from 'pl-fe/features/federation-restrictions/components/instance-restrictions';
@@ -26,9 +25,8 @@ const InstanceModerationPanel: React.FC = ({ host }) =
const intl = useIntl();
const { openModal } = useModalsStore();
- const { data: instance } = useInstance();
const { account } = useOwnAccount();
- const remoteInstance = useAppSelector(state => getRemoteInstance(state, host, instance));
+ const remoteInstance = useAppSelector(state => getRemoteInstance(state, host));
const handleEditFederation = () => {
openModal('EDIT_FEDERATION', { host });
diff --git a/packages/pl-fe/src/features/ui/components/panels/promo-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/promo-panel.tsx
index 165517d23..80eef9584 100644
--- a/packages/pl-fe/src/features/ui/components/panels/promo-panel.tsx
+++ b/packages/pl-fe/src/features/ui/components/panels/promo-panel.tsx
@@ -1,15 +1,15 @@
import React from 'react';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import ForkAwesomeIcon from 'pl-fe/components/fork-awesome-icon';
import List, { ListItem } from 'pl-fe/components/list';
import HStack from 'pl-fe/components/ui/hstack';
import Widget from 'pl-fe/components/ui/widget';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
import { useSettings } from 'pl-fe/hooks/use-settings';
const PromoPanel: React.FC = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { promoPanel } = usePlFeConfig();
const { locale } = useSettings();
diff --git a/packages/pl-fe/src/features/ui/components/panels/sign-up-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/sign-up-panel.tsx
index cb265daa2..201f3f4d7 100644
--- a/packages/pl-fe/src/features/ui/components/panels/sign-up-panel.tsx
+++ b/packages/pl-fe/src/features/ui/components/panels/sign-up-panel.tsx
@@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl';
import { Redirect } from 'react-router-dom';
import { logIn, switchAccount, verifyCredentials } from 'pl-fe/actions/auth';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
+import { fetchInstance } from 'pl-fe/actions/instance';
import Button from 'pl-fe/components/ui/button';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
@@ -12,6 +12,7 @@ import OtpAuthForm from 'pl-fe/features/auth-login/components/otp-auth-form';
import ExternalLoginForm from 'pl-fe/features/external-login/components/external-login-form';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useRegistrationStatus } from 'pl-fe/hooks/use-registration-status';
import { getRedirectUrl } from 'pl-fe/utils/redirect';
import { isStandalone } from 'pl-fe/utils/state';
@@ -20,7 +21,7 @@ import type { PlfeResponse } from 'pl-fe/api';
const SignUpPanel = () => {
const dispatch = useAppDispatch();
- const { data: instance } = useInstance();
+ const instance = useInstance();
const { isOpen } = useRegistrationStatus();
const me = useAppSelector((state) => state.me);
const standalone = useAppSelector(isStandalone);
@@ -41,6 +42,11 @@ const SignUpPanel = () => {
const { username, password } = getFormData(event.target as HTMLFormElement);
dispatch(logIn(username, password))
.then(({ access_token }) => dispatch(verifyCredentials(access_token as string)))
+ // Refetch the instance for authenticated fetch
+ .then(async (account) => {
+ await dispatch(fetchInstance());
+ return account;
+ })
.then((account: { id: string }) => {
if (typeof me === 'string') {
dispatch(switchAccount(account.id));
diff --git a/packages/pl-fe/src/features/ui/index.tsx b/packages/pl-fe/src/features/ui/index.tsx
index dbe28f08b..05b8bc729 100644
--- a/packages/pl-fe/src/features/ui/index.tsx
+++ b/packages/pl-fe/src/features/ui/index.tsx
@@ -12,7 +12,6 @@ import { expandNotifications } from 'pl-fe/actions/notifications';
import { register as registerPushNotifications } from 'pl-fe/actions/push-notifications/registerer';
import { fetchScheduledStatuses } from 'pl-fe/actions/scheduled-statuses';
import { fetchHomeTimeline } from 'pl-fe/actions/timelines';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import { useUserStream } from 'pl-fe/api/hooks/streaming/use-user-stream';
import SidebarNavigation from 'pl-fe/components/sidebar-navigation';
import ThumbNavigation from 'pl-fe/components/thumb-navigation';
@@ -21,6 +20,7 @@ import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useDraggedFiles } from 'pl-fe/hooks/use-dragged-files';
import { useFeatures } from 'pl-fe/hooks/use-features';
+import { useInstance } from 'pl-fe/hooks/use-instance';
import { useLoggedIn } from 'pl-fe/hooks/use-logged-in';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
@@ -41,6 +41,7 @@ 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 { useUiStore } from 'pl-fe/stores/ui';
+import { getVapidKey } from 'pl-fe/utils/auth';
import { isStandalone } from 'pl-fe/utils/state';
import BackgroundShapes from './components/background-shapes';
@@ -145,14 +146,13 @@ import { WrappedRoute } from './util/react-router-helpers';
// Dummy import, to make sure that ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles.
import 'pl-fe/components/status';
-import { useVapidKey } from 'pl-fe/hooks/use-vapid-key';
interface ISwitchingColumnsArea {
children: React.ReactNode;
}
const SwitchingColumnsArea: React.FC = ({ children }) => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const features = useFeatures();
const { search } = useLocation();
const { isLoggedIn } = useLoggedIn();
@@ -361,7 +361,7 @@ const UI: React.FC = ({ children }) => {
const me = useAppSelector(state => state.me);
const { account } = useOwnAccount();
const features = useFeatures();
- const vapidKey = useVapidKey();
+ const vapidKey = useAppSelector(state => getVapidKey(state));
const { isDropdownMenuOpen } = useUiStore();
const standalone = useAppSelector(isStandalone);
@@ -447,7 +447,7 @@ const UI: React.FC = ({ children }) => {
}, [!!account]);
useEffect(() => {
- dispatch(registerPushNotifications(vapidKey));
+ dispatch(registerPushNotifications());
}, [vapidKey]);
// Wait for login to succeed or fail
diff --git a/packages/pl-fe/src/hooks/use-features.ts b/packages/pl-fe/src/hooks/use-features.ts
index 81fb49024..0b6560f76 100644
--- a/packages/pl-fe/src/hooks/use-features.ts
+++ b/packages/pl-fe/src/hooks/use-features.ts
@@ -1,8 +1,7 @@
import { Features } from 'pl-api';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
-
import { useAppSelector } from './use-app-selector';
+import { useInstance } from './use-instance';
/** Get features for the current instance. */
const useFeatures = (): Features => {
diff --git a/packages/pl-fe/src/hooks/use-instance.ts b/packages/pl-fe/src/hooks/use-instance.ts
new file mode 100644
index 000000000..4c94a4ab2
--- /dev/null
+++ b/packages/pl-fe/src/hooks/use-instance.ts
@@ -0,0 +1,6 @@
+import { useAppSelector } from './use-app-selector';
+
+/** Get the Instance for the current backend. */
+const useInstance = () => useAppSelector((state) => state.instance);
+
+export { useInstance };
diff --git a/packages/pl-fe/src/hooks/use-registration-status.ts b/packages/pl-fe/src/hooks/use-registration-status.ts
index 8ab5d48ab..aa4700e24 100644
--- a/packages/pl-fe/src/hooks/use-registration-status.ts
+++ b/packages/pl-fe/src/hooks/use-registration-status.ts
@@ -1,9 +1,8 @@
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
-
import { useFeatures } from './use-features';
+import { useInstance } from './use-instance';
const useRegistrationStatus = () => {
- const { data: instance } = useInstance();
+ const instance = useInstance();
const features = useFeatures();
return {
diff --git a/packages/pl-fe/src/hooks/use-vapid-key.ts b/packages/pl-fe/src/hooks/use-vapid-key.ts
deleted file mode 100644
index b52879aed..000000000
--- a/packages/pl-fe/src/hooks/use-vapid-key.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
-
-import { useAppSelector } from './use-app-selector';
-
-const useVapidKey = () => {
- const { data: instance } = useInstance();
-
- return useAppSelector((state) => instance.configuration.vapid.public_key || state.auth.app?.vapid_key);
-};
-
-export { useVapidKey };
diff --git a/packages/pl-fe/src/init/pl-fe-load.tsx b/packages/pl-fe/src/init/pl-fe-load.tsx
index bbe56dbbd..cfcc6be64 100644
--- a/packages/pl-fe/src/init/pl-fe-load.tsx
+++ b/packages/pl-fe/src/init/pl-fe-load.tsx
@@ -1,9 +1,9 @@
import React, { useState, useEffect } from 'react';
import { IntlProvider } from 'react-intl';
+import { fetchInstance } from 'pl-fe/actions/instance';
import { fetchMe } from 'pl-fe/actions/me';
import { loadPlFeConfig } from 'pl-fe/actions/pl-fe';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
import LoadingScreen from 'pl-fe/components/loading-screen';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
@@ -17,6 +17,8 @@ const loadInitial = () => {
return async(dispatch, getState) => {
// Await for authenticated fetch
await dispatch(fetchMe());
+ // Await for feature detection
+ await dispatch(fetchInstance());
// Await for configuration
await dispatch(loadPlFeConfig());
};
@@ -29,7 +31,6 @@ interface IPlFeLoad {
/** Initial data loader. */
const PlFeLoad: React.FC = ({ children }) => {
const dispatch = useAppDispatch();
- const { isLoading: isLoadingInstance } = useInstance();
const me = useAppSelector(state => state.me);
const { account } = useOwnAccount();
@@ -45,7 +46,6 @@ const PlFeLoad: React.FC = ({ children }) => {
me && !account,
!isLoaded,
localeLoading,
- isLoadingInstance,
].some(Boolean);
// Load the user's locale
diff --git a/packages/pl-fe/src/initial-state.ts b/packages/pl-fe/src/initial-state.ts
deleted file mode 100644
index 9dcdce221..000000000
--- a/packages/pl-fe/src/initial-state.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { decodeFromMarkup, pleromaDecoder } from './actions/preload';
-
-let initialState: Record = {};
-
-try {
- initialState = decodeFromMarkup('initial-results', pleromaDecoder);
-} catch (e) {
- //
-}
-
-export { initialState };
diff --git a/packages/pl-fe/src/layouts/remote-instance-layout.tsx b/packages/pl-fe/src/layouts/remote-instance-layout.tsx
index 4ecc060a6..424f903aa 100644
--- a/packages/pl-fe/src/layouts/remote-instance-layout.tsx
+++ b/packages/pl-fe/src/layouts/remote-instance-layout.tsx
@@ -10,7 +10,6 @@ import {
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useOwnAccount } from 'pl-fe/hooks/use-own-account';
import { federationRestrictionsDisclosed } from 'pl-fe/utils/state';
-import { useInstance } from 'pl-fe/api/hooks/instance/use-instance';
interface IRemoteInstanceLayout {
params?: {
@@ -24,8 +23,7 @@ const RemoteInstanceLayout: React.FC = ({ children, param
const host = params!.instance!;
const { account } = useOwnAccount();
- const { data: instance } = useInstance();
- const disclosed = federationRestrictionsDisclosed(instance);
+ const disclosed = useAppSelector(federationRestrictionsDisclosed);
return (
<>
diff --git a/packages/pl-fe/src/reducers/compose.ts b/packages/pl-fe/src/reducers/compose.ts
index 853904fd2..d68a931bb 100644
--- a/packages/pl-fe/src/reducers/compose.ts
+++ b/packages/pl-fe/src/reducers/compose.ts
@@ -1,5 +1,7 @@
import { create } from 'mutative';
+import { type CredentialAccount, type Instance, type MediaAttachment, type Tag } from 'pl-api';
+import { INSTANCE_FETCH_SUCCESS, type InstanceAction } from 'pl-fe/actions/instance';
import { isNativeEmoji, type Emoji } from 'pl-fe/features/emoji';
import { tagHistory } from 'pl-fe/settings';
@@ -65,7 +67,6 @@ import { FE_NAME } from '../actions/settings';
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
import { unescapeHTML } from '../utils/html';
-import type { CredentialAccount, MediaAttachment, Tag } from 'pl-api';
import type { Language } from 'pl-fe/features/preferences';
import type { Account } from 'pl-fe/normalizers/account';
import type { Status } from 'pl-fe/normalizers/status';
@@ -309,11 +310,11 @@ const importAccount = (compose: Compose, account: CredentialAccount) => {
// }
// };
-// const updateDefaultContentType = (compose: Compose, instance: Instance) => {
-// const postFormats = instance.pleroma.metadata.post_formats;
+const updateDefaultContentType = (compose: Compose, instance: Instance) => {
+ const postFormats = instance.pleroma.metadata.post_formats;
-// compose.content_type = postFormats.includes(compose.content_type) ? compose.content_type : postFormats.includes('text/markdown') ? 'text/markdown' : postFormats[0];
-// };
+ compose.content_type = postFormats.includes(compose.content_type) ? compose.content_type : postFormats.includes('text/markdown') ? 'text/markdown' : postFormats[0];
+};
const updateCompose = (state: State, key: string, updater: (compose: Compose) => void) =>
create(state, draft => {
@@ -326,7 +327,7 @@ const initialState: State = {
default: newCompose({ idempotencyKey: crypto.randomUUID(), resetFileKey: getResetFileKey() }),
};
-const compose = (state = initialState, action: ComposeAction | EventsAction | MeAction | TimelineAction): State => {
+const compose = (state = initialState, action: ComposeAction | EventsAction | InstanceAction | MeAction | TimelineAction): State => {
switch (action.type) {
case COMPOSE_TYPE_CHANGE:
return updateCompose(state, action.composeId, compose => {
@@ -687,6 +688,8 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | Me
return updateCompose(state, action.composeId, compose => {
compose.federated = !compose.federated;
});
+ case INSTANCE_FETCH_SUCCESS:
+ return updateCompose(state, 'default', (compose) => updateDefaultContentType(compose, action.instance));
default:
return state;
}
diff --git a/packages/pl-fe/src/reducers/index.ts b/packages/pl-fe/src/reducers/index.ts
index c26ad4915..945556710 100644
--- a/packages/pl-fe/src/reducers/index.ts
+++ b/packages/pl-fe/src/reducers/index.ts
@@ -18,6 +18,7 @@ import domain_lists from './domain-lists';
import draft_statuses from './draft-statuses';
import filters from './filters';
import followed_tags from './followed-tags';
+import instance from './instance';
import listAdder from './list-adder';
import listEditor from './list-editor';
import lists from './lists';
@@ -53,6 +54,7 @@ const reducers = {
entities,
filters,
followed_tags,
+ instance,
listAdder,
listEditor,
lists,
@@ -85,8 +87,8 @@ const logOut = (state: AppState): ReturnType => {
const newState = rootReducer(undefined, { type: '' });
- const { plfe, custom_emojis, auth } = state;
- return { ...newState, plfe, custom_emojis, auth };
+ const { instance, plfe, custom_emojis, auth } = state;
+ return { ...newState, instance, plfe, custom_emojis, auth };
};
const rootReducer: typeof appReducer = (state, action) => {
diff --git a/packages/pl-fe/src/reducers/instance.ts b/packages/pl-fe/src/reducers/instance.ts
index 96312b8c3..9d4475dc5 100644
--- a/packages/pl-fe/src/reducers/instance.ts
+++ b/packages/pl-fe/src/reducers/instance.ts
@@ -1,8 +1,102 @@
-import { instanceSchema } from 'pl-api';
+import { create } from 'mutative';
+import { type Instance, instanceSchema, PleromaConfig } from 'pl-api';
import * as v from 'valibot';
-const initialState = v.parse(instanceSchema, {});
+import { ADMIN_CONFIG_UPDATE_REQUEST, ADMIN_CONFIG_UPDATE_SUCCESS, type AdminActions } from 'pl-fe/actions/admin';
+import { INSTANCE_FETCH_FAIL, INSTANCE_FETCH_SUCCESS, type InstanceAction } from 'pl-fe/actions/instance';
+import { PLEROMA_PRELOAD_IMPORT, type PreloadAction } from 'pl-fe/actions/preload';
+import KVStore from 'pl-fe/storage/kv-store';
+import ConfigDB from 'pl-fe/utils/config-db';
-const instance = () => initialState;
+const initialState: State = v.parse(instanceSchema, {});
+type State = Instance;
+
+const preloadImport = (state: State, action: Record, path: string) => {
+ const instance = action.data[path];
+ return instance ? v.parse(instanceSchema, instance) : state;
+};
+
+const getConfigValue = (instanceConfig: Array, key: string) => {
+ const v = instanceConfig
+ .find(value => value?.tuple?.[0] === key);
+
+ return v ? v?.tuple?.[1] : undefined;
+};
+
+const importConfigs = (state: State, configs: PleromaConfig['configs']) => {
+ // FIXME: This is pretty hacked together. Need to make a cleaner map.
+ const config = ConfigDB.find(configs, ':pleroma', ':instance');
+ const simplePolicy = ConfigDB.toSimplePolicy(configs);
+
+ if (!config && !simplePolicy) return state;
+
+ if (config) {
+ const value = config.value || [];
+ const registrationsOpen = getConfigValue(value, ':registrations_open') as boolean | undefined;
+ const approvalRequired = getConfigValue(value, ':account_approval_required') as boolean | undefined;
+
+ state.registrations = {
+ enabled: registrationsOpen ?? state.registrations.enabled,
+ approval_required: approvalRequired ?? state.registrations.approval_required,
+ };
+ }
+
+ if (simplePolicy) {
+ state.pleroma.metadata.federation.mrf_simple = simplePolicy;
+ }
+};
+
+const handleAuthFetch = (state: State) => {
+ // Authenticated fetch is enabled, so make the instance appear censored
+ return {
+ ...state,
+ title: state.title || '██████',
+ description: state.description || '████████████',
+ };
+};
+
+const getHost = (instance: { domain: string }) => {
+ const domain = instance.domain;
+ try {
+ return new URL(domain).host;
+ } catch {
+ try {
+ return new URL(`https://${domain}`).host;
+ } catch {
+ return null;
+ }
+ }
+};
+
+const persistInstance = (instance: { domain: string }, host: string | null = getHost(instance)) => {
+ if (host) {
+ KVStore.setItem(`instance:${host}`, instance).catch(console.error);
+ }
+};
+
+const handleInstanceFetchFail = (state: State, error: any) => {
+ if (error.response?.status === 401) {
+ return handleAuthFetch(state);
+ } else {
+ return state;
+ }
+};
+
+const instance = (state = initialState, action: AdminActions | InstanceAction | PreloadAction): State => {
+ switch (action.type) {
+ case PLEROMA_PRELOAD_IMPORT:
+ return create(state, (draft) => preloadImport(draft, action, '/api/v1/instance'));
+ case INSTANCE_FETCH_SUCCESS:
+ persistInstance(action.instance);
+ return action.instance;
+ case INSTANCE_FETCH_FAIL:
+ return handleInstanceFetchFail(state, action.error);
+ case ADMIN_CONFIG_UPDATE_REQUEST:
+ case ADMIN_CONFIG_UPDATE_SUCCESS:
+ return create(state, (draft) => importConfigs(draft, action.configs));
+ default:
+ return state;
+ }
+};
export { instance as default };
diff --git a/packages/pl-fe/src/reducers/meta.ts b/packages/pl-fe/src/reducers/meta.ts
index 4ab9d37e1..78e5e9f3b 100644
--- a/packages/pl-fe/src/reducers/meta.ts
+++ b/packages/pl-fe/src/reducers/meta.ts
@@ -1,10 +1,20 @@
-import type { AnyAction } from 'redux';
+import { INSTANCE_FETCH_FAIL, type InstanceAction } from 'pl-fe/actions/instance';
const initialState = {
/** Whether /api/v1/instance 404'd (and we should display the external auth form). */
instance_fetch_failed: false,
};
-const meta = (state = initialState, action: AnyAction): typeof initialState => state;
+const meta = (state = initialState, action: InstanceAction): typeof initialState => {
+ switch (action.type) {
+ case INSTANCE_FETCH_FAIL:
+ if ((action.error as any)?.response?.status === 404) {
+ return { instance_fetch_failed: true };
+ }
+ return state;
+ default:
+ return state;
+ }
+};
export { meta as default };
diff --git a/packages/pl-fe/src/selectors/index.ts b/packages/pl-fe/src/selectors/index.ts
index dd538d5ce..1eddc1584 100644
--- a/packages/pl-fe/src/selectors/index.ts
+++ b/packages/pl-fe/src/selectors/index.ts
@@ -8,7 +8,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, Instance, MediaAttachment, NotificationGroup, Relationship } from 'pl-api';
+import type { Account as BaseAccount, Filter, MediaAttachment, NotificationGroup, Relationship } from 'pl-api';
import type { EntityStore } from 'pl-fe/entity-store/types';
import type { Account } from 'pl-fe/normalizers/account';
import type { Group } from 'pl-fe/normalizers/group';
@@ -275,7 +275,7 @@ const makeGetOtherAccounts = () => createSelector([
const getSimplePolicy = createSelector([
(state: RootState) => state.admin.configs,
- (_state: RootState, instance: Instance) => instance.pleroma.metadata.federation.mrf_simple,
+ (state: RootState) => state.instance.pleroma.metadata.federation.mrf_simple,
], (configs, instancePolicy) => ({
...instancePolicy,
...ConfigDB.toSimplePolicy(configs),
@@ -291,8 +291,8 @@ type HostFederation = {
[key in keyof MRFSimple]: boolean;
};
-const getRemoteInstanceFederation = (state: RootState, host: string, instance: Instance): HostFederation => {
- const simplePolicy = getSimplePolicy(state, instance);
+const getRemoteInstanceFederation = (state: RootState, host: string): HostFederation => {
+ const simplePolicy = getSimplePolicy(state);
return Object.fromEntries(
Object.entries(simplePolicy).map(([key, hosts]) => [key, hosts.includes(host)]),
diff --git a/packages/pl-fe/src/utils/auth.ts b/packages/pl-fe/src/utils/auth.ts
index 8bd27659e..59cd8e545 100644
--- a/packages/pl-fe/src/utils/auth.ts
+++ b/packages/pl-fe/src/utils/auth.ts
@@ -56,6 +56,10 @@ const getAuthUserUrl = (state: RootState) => {
].filter(url => url).find(isURL);
};
+/** Get the VAPID public key. */
+const getVapidKey = (state: RootState) =>
+ state.auth.app?.vapid_key || state.instance.configuration.vapid.public_key;
+
const getMeUrl = (state: RootState) => selectOwnAccount(state)?.url;
export {
@@ -67,5 +71,6 @@ export {
getAccessToken,
getAuthUserId,
getAuthUserUrl,
+ getVapidKey,
getMeUrl,
};
diff --git a/packages/pl-fe/src/utils/scopes.ts b/packages/pl-fe/src/utils/scopes.ts
index 966b146ff..bfaf61d22 100644
--- a/packages/pl-fe/src/utils/scopes.ts
+++ b/packages/pl-fe/src/utils/scopes.ts
@@ -1,16 +1,15 @@
import { getFeatures, PLEROMA, TOKI, type Instance } from 'pl-api';
-import * as BuildConfig from 'pl-fe/build-config';
-import { queryClient } from 'pl-fe/queries/client';
+import type { RootState } from 'pl-fe/store';
/**
* Get the OAuth scopes to use for login & signup.
* Mastodon will refuse scopes it doesn't know, so care is needed.
*/
-const getInstanceScopes = (instance?: Instance) => {
- const software = instance ? getFeatures(instance).version.software : null;
+const getInstanceScopes = (instance: Instance) => {
+ const v = getFeatures(instance).version;
- switch (software) {
+ switch (v.software) {
case TOKI:
return 'read write follow push write:bites';
case PLEROMA:
@@ -21,11 +20,7 @@ const getInstanceScopes = (instance?: Instance) => {
};
/** Convenience function to get scopes from instance in store. */
-const getScopes = (baseURL = BuildConfig.BACKEND_URL || '') => {
- const instance = queryClient.getQueryData(['instance', 'instanceInformation', baseURL]);
-
- return getInstanceScopes(instance);
-};
+const getScopes = (state: RootState) => getInstanceScopes(state.instance);
export {
getInstanceScopes,
diff --git a/packages/pl-fe/src/utils/state.ts b/packages/pl-fe/src/utils/state.ts
index 5ec11d05a..f461bff42 100644
--- a/packages/pl-fe/src/utils/state.ts
+++ b/packages/pl-fe/src/utils/state.ts
@@ -9,15 +9,14 @@ import { isPrerendered } from 'pl-fe/precheck';
import { selectOwnAccount } from 'pl-fe/selectors';
import { isURL } from 'pl-fe/utils/auth';
-import type { Instance } from 'pl-api';
import type { RootState } from 'pl-fe/store';
/** Whether to display the fqn instead of the acct. */
const displayFqn = (state: RootState): boolean => getPlFeConfig(state).displayFqn;
/** Whether the instance exposes instance blocks through the API. */
-const federationRestrictionsDisclosed = (instance: Instance): boolean =>
- !!instance.pleroma.metadata.federation.mrf_policies;
+const federationRestrictionsDisclosed = (state: RootState): boolean =>
+ !!state.instance.pleroma.metadata.federation.mrf_policies;
/**
* Determine whether pl-fe is running in standalone mode.