Merge branch 'use-instance' into 'develop'
Add useInstance() hook See merge request soapbox-pub/soapbox!1946
This commit is contained in:
commit
3a489f98d2
|
@ -4,7 +4,7 @@ import { defineMessages, useIntl } from 'react-intl';
|
||||||
import IconButton from 'soapbox/components/icon-button';
|
import IconButton from 'soapbox/components/icon-button';
|
||||||
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
|
import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
|
||||||
import { DatePicker } from 'soapbox/features/ui/util/async-components';
|
import { DatePicker } from 'soapbox/features/ui/util/async-components';
|
||||||
import { useAppSelector, useFeatures } from 'soapbox/hooks';
|
import { useInstance, useFeatures } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
birthdayPlaceholder: { id: 'edit_profile.fields.birthday_placeholder', defaultMessage: 'Your birthday' },
|
birthdayPlaceholder: { id: 'edit_profile.fields.birthday_placeholder', defaultMessage: 'Your birthday' },
|
||||||
|
@ -23,9 +23,10 @@ interface IBirthdayInput {
|
||||||
const BirthdayInput: React.FC<IBirthdayInput> = ({ value, onChange, required }) => {
|
const BirthdayInput: React.FC<IBirthdayInput> = ({ value, onChange, required }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const supportsBirthdays = features.birthdays;
|
const supportsBirthdays = features.birthdays;
|
||||||
const minAge = useAppSelector((state) => state.instance.pleroma.getIn(['metadata', 'birthday_min_age'])) as number;
|
const minAge = instance.pleroma.getIn(['metadata', 'birthday_min_age']) as number;
|
||||||
|
|
||||||
const maxDate = useMemo(() => {
|
const maxDate = useMemo(() => {
|
||||||
if (!supportsBirthdays) return null;
|
if (!supportsBirthdays) return null;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Banner, Button, HStack, Stack, Text } from 'soapbox/components/ui';
|
import { Banner, Button, HStack, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppSelector, useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
const acceptedGdpr = !!localStorage.getItem('soapbox:gdpr');
|
const acceptedGdpr = !!localStorage.getItem('soapbox:gdpr');
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ const GdprBanner: React.FC = () => {
|
||||||
const [shown, setShown] = useState<boolean>(acceptedGdpr);
|
const [shown, setShown] = useState<boolean>(acceptedGdpr);
|
||||||
const [slideout, setSlideout] = useState(false);
|
const [slideout, setSlideout] = useState(false);
|
||||||
|
|
||||||
|
const instance = useInstance();
|
||||||
const soapbox = useSoapboxConfig();
|
const soapbox = useSoapboxConfig();
|
||||||
const isLoggedIn = useAppSelector(state => !!state.me);
|
const isLoggedIn = useAppSelector(state => !!state.me);
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
|
||||||
|
|
||||||
const handleAccept = () => {
|
const handleAccept = () => {
|
||||||
localStorage.setItem('soapbox:gdpr', 'true');
|
localStorage.setItem('soapbox:gdpr', 'true');
|
||||||
|
@ -34,14 +34,14 @@ const GdprBanner: React.FC = () => {
|
||||||
<div className='flex flex-col space-y-4 lg:space-y-0 lg:space-x-4 rtl:space-x-reverse lg:flex-row lg:items-center lg:justify-between'>
|
<div className='flex flex-col space-y-4 lg:space-y-0 lg:space-x-4 rtl:space-x-reverse lg:flex-row lg:items-center lg:justify-between'>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Text size='xl' weight='bold'>
|
<Text size='xl' weight='bold'>
|
||||||
<FormattedMessage id='gdpr.title' defaultMessage='{siteTitle} uses cookies' values={{ siteTitle }} />
|
<FormattedMessage id='gdpr.title' defaultMessage='{siteTitle} uses cookies' values={{ siteTitle: instance.title }} />
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text weight='medium' className='opacity-60'>
|
<Text weight='medium' className='opacity-60'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='gdpr.message'
|
id='gdpr.message'
|
||||||
defaultMessage="{siteTitle} uses session cookies, which are essential to the website's functioning."
|
defaultMessage="{siteTitle} uses session cookies, which are essential to the website's functioning."
|
||||||
values={{ siteTitle }}
|
values={{ siteTitle: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Helmet as ReactHelmet } from 'react-helmet';
|
import { Helmet as ReactHelmet } from 'react-helmet';
|
||||||
|
|
||||||
import { useAppSelector, useSettings } from 'soapbox/hooks';
|
import { useAppSelector, useInstance, useSettings } from 'soapbox/hooks';
|
||||||
import { RootState } from 'soapbox/store';
|
import { RootState } from 'soapbox/store';
|
||||||
import FaviconService from 'soapbox/utils/favicon-service';
|
import FaviconService from 'soapbox/utils/favicon-service';
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ const getNotifTotals = (state: RootState): number => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Helmet: React.FC = ({ children }) => {
|
const Helmet: React.FC = ({ children }) => {
|
||||||
const title = useAppSelector((state) => state.instance.title);
|
const instance = useInstance();
|
||||||
const unreadCount = useAppSelector((state) => getNotifTotals(state));
|
const unreadCount = useAppSelector((state) => getNotifTotals(state));
|
||||||
const demetricator = useSettings().get('demetricator');
|
const demetricator = useSettings().get('demetricator');
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ const Helmet: React.FC = ({ children }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactHelmet
|
<ReactHelmet
|
||||||
titleTemplate={addCounter(`%s | ${title}`)}
|
titleTemplate={addCounter(`%s | ${instance.title}`)}
|
||||||
defaultTitle={addCounter(title)}
|
defaultTitle={addCounter(instance.title)}
|
||||||
defer={false}
|
defer={false}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { getSettings } from 'soapbox/actions/settings';
|
|
||||||
import DropdownMenu from 'soapbox/containers/dropdown-menu-container';
|
import DropdownMenu from 'soapbox/containers/dropdown-menu-container';
|
||||||
import ComposeButton from 'soapbox/features/ui/components/compose-button';
|
import ComposeButton from 'soapbox/features/ui/components/compose-button';
|
||||||
import { useAppSelector, useOwnAccount } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useOwnAccount, useSettings } from 'soapbox/hooks';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import SidebarNavigationLink from './sidebar-navigation-link';
|
import SidebarNavigationLink from './sidebar-navigation-link';
|
||||||
|
|
||||||
|
@ -22,16 +20,14 @@ const messages = defineMessages({
|
||||||
const SidebarNavigation = () => {
|
const SidebarNavigation = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const features = useFeatures();
|
||||||
const settings = useAppSelector((state) => getSettings(state));
|
const settings = useSettings();
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
||||||
const chatsCount = useAppSelector((state) => state.chats.items.reduce((acc, curr) => acc + Math.min(curr.unread || 0, 1), 0));
|
const chatsCount = useAppSelector((state) => state.chats.items.reduce((acc, curr) => acc + Math.min(curr.unread || 0, 1), 0));
|
||||||
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
|
||||||
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
||||||
|
|
||||||
const features = getFeatures(instance);
|
|
||||||
|
|
||||||
const makeMenu = (): Menu => {
|
const makeMenu = (): Menu => {
|
||||||
const menu: Menu = [];
|
const menu: Menu = [];
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,14 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import ThumbNavigationLink from 'soapbox/components/thumb-navigation-link';
|
import ThumbNavigationLink from 'soapbox/components/thumb-navigation-link';
|
||||||
import { useAppSelector, useOwnAccount } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
const ThumbNavigation: React.FC = (): JSX.Element => {
|
const ThumbNavigation: React.FC = (): JSX.Element => {
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
const notificationCount = useAppSelector((state) => state.notifications.unread);
|
||||||
const chatsCount = useAppSelector((state) => state.chats.items.reduce((acc, curr) => acc + Math.min(curr.unread || 0, 1), 0));
|
const chatsCount = useAppSelector((state) => state.chats.items.reduce((acc, curr) => acc + Math.min(curr.unread || 0, 1), 0));
|
||||||
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
const dashboardCount = useAppSelector((state) => state.admin.openReports.count() + state.admin.awaitingApproval.count());
|
||||||
const features = getFeatures(useAppSelector((state) => state.instance));
|
const features = useFeatures();
|
||||||
|
|
||||||
/** Conditionally render the supported messages link */
|
/** Conditionally render the supported messages link */
|
||||||
const renderMessagesLink = (): React.ReactNode => {
|
const renderMessagesLink = (): React.ReactNode => {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import {
|
||||||
useSettings,
|
useSettings,
|
||||||
useTheme,
|
useTheme,
|
||||||
useLocale,
|
useLocale,
|
||||||
|
useInstance,
|
||||||
} from 'soapbox/hooks';
|
} from 'soapbox/hooks';
|
||||||
import MESSAGES from 'soapbox/locales/messages';
|
import MESSAGES from 'soapbox/locales/messages';
|
||||||
import { queryClient } from 'soapbox/queries/client';
|
import { queryClient } from 'soapbox/queries/client';
|
||||||
|
@ -85,7 +86,7 @@ const loadInitial = () => {
|
||||||
const SoapboxMount = () => {
|
const SoapboxMount = () => {
|
||||||
useCachedLocationHandler();
|
useCachedLocationHandler();
|
||||||
const me = useAppSelector(state => state.me);
|
const me = useAppSelector(state => state.me);
|
||||||
const instance = useAppSelector(state => state.instance);
|
const instance = useInstance();
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
const soapboxConfig = useSoapboxConfig();
|
const soapboxConfig = useSoapboxConfig();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
|
|
@ -11,9 +11,8 @@ import { expandAccountMediaTimeline } from 'soapbox/actions/timelines';
|
||||||
import LoadMore from 'soapbox/components/load-more';
|
import LoadMore from 'soapbox/components/load-more';
|
||||||
import MissingIndicator from 'soapbox/components/missing-indicator';
|
import MissingIndicator from 'soapbox/components/missing-indicator';
|
||||||
import { Column, Spinner } from 'soapbox/components/ui';
|
import { Column, Spinner } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||||
import { getAccountGallery, findAccountByUsername } from 'soapbox/selectors';
|
import { getAccountGallery, findAccountByUsername } from 'soapbox/selectors';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import MediaItem from './components/media-item';
|
import MediaItem from './components/media-item';
|
||||||
|
|
||||||
|
@ -38,11 +37,11 @@ const LoadMoreMedia: React.FC<ILoadMoreMedia> = ({ maxId, onLoadMore }) => {
|
||||||
const AccountGallery = () => {
|
const AccountGallery = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { username } = useParams<{ username: string }>();
|
const { username } = useParams<{ username: string }>();
|
||||||
|
const features = useFeatures();
|
||||||
|
|
||||||
const { accountId, unavailable, accountUsername } = useAppSelector((state) => {
|
const { accountId, unavailable, accountUsername } = useAppSelector((state) => {
|
||||||
const me = state.me;
|
const me = state.me;
|
||||||
const accountFetchError = (state.accounts.get(-1)?.username || '').toLowerCase() === username.toLowerCase();
|
const accountFetchError = (state.accounts.get(-1)?.username || '').toLowerCase() === username.toLowerCase();
|
||||||
const features = getFeatures(state.instance);
|
|
||||||
|
|
||||||
let accountId: string | -1 | null = -1;
|
let accountId: string | -1 | null = -1;
|
||||||
let accountUsername = username;
|
let accountUsername = username;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
RadioItem,
|
RadioItem,
|
||||||
} from 'soapbox/features/forms';
|
} from 'soapbox/features/forms';
|
||||||
import { useAppSelector, useAppDispatch } from 'soapbox/hooks';
|
import { useAppDispatch, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { Instance } from 'soapbox/types/entities';
|
import type { Instance } from 'soapbox/types/entities';
|
||||||
|
|
||||||
|
@ -42,8 +42,9 @@ const modeFromInstance = (instance: Instance): RegistrationMode => {
|
||||||
const RegistrationModePicker: React.FC = () => {
|
const RegistrationModePicker: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const mode = useAppSelector(state => modeFromInstance(state.instance));
|
const mode = modeFromInstance(instance);
|
||||||
|
|
||||||
const onChange: React.ChangeEventHandler<HTMLInputElement> = e => {
|
const onChange: React.ChangeEventHandler<HTMLInputElement> = e => {
|
||||||
const config = generateConfig(e.target.value as RegistrationMode);
|
const config = generateConfig(e.target.value as RegistrationMode);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { getSubscribersCsv, getUnsubscribersCsv, getCombinedCsv } from 'soapbox/actions/email-list';
|
import { getSubscribersCsv, getUnsubscribersCsv, getCombinedCsv } from 'soapbox/actions/email-list';
|
||||||
import { Text } from 'soapbox/components/ui';
|
import { Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures } from 'soapbox/hooks';
|
import { useAppDispatch, useOwnAccount, useFeatures, useInstance } from 'soapbox/hooks';
|
||||||
import sourceCode from 'soapbox/utils/code';
|
import sourceCode from 'soapbox/utils/code';
|
||||||
import { parseVersion } from 'soapbox/utils/features';
|
import { parseVersion } from 'soapbox/utils/features';
|
||||||
import { isNumber } from 'soapbox/utils/numbers';
|
import { isNumber } from 'soapbox/utils/numbers';
|
||||||
|
@ -27,7 +27,7 @@ const download = (response: AxiosResponse, filename: string) => {
|
||||||
|
|
||||||
const Dashboard: React.FC = () => {
|
const Dashboard: React.FC = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const instance = useAppSelector(state => state.instance);
|
const instance = useInstance();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Avatar, Card, HStack, Icon, IconButton, Stack, Text } from 'soapbox/components/ui';
|
import { Avatar, Card, HStack, Icon, IconButton, Stack, Text } from 'soapbox/components/ui';
|
||||||
import StatusCard from 'soapbox/features/status/components/card';
|
import StatusCard from 'soapbox/features/status/components/card';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { Ad as AdEntity } from 'soapbox/types/soapbox';
|
import type { Ad as AdEntity } from 'soapbox/types/soapbox';
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ interface IAd {
|
||||||
/** Displays an ad in sponsored post format. */
|
/** Displays an ad in sponsored post format. */
|
||||||
const Ad: React.FC<IAd> = ({ ad }) => {
|
const Ad: React.FC<IAd> = ({ ad }) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const instance = useAppSelector(state => state.instance);
|
const instance = useInstance();
|
||||||
|
|
||||||
const timer = useRef<NodeJS.Timeout | undefined>(undefined);
|
const timer = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||||
const infobox = useRef<HTMLDivElement>(null);
|
const infobox = useRef<HTMLDivElement>(null);
|
||||||
|
|
|
@ -5,9 +5,8 @@ import { addToAliases } from 'soapbox/actions/aliases';
|
||||||
import AccountComponent from 'soapbox/components/account';
|
import AccountComponent from 'soapbox/components/account';
|
||||||
import IconButton from 'soapbox/components/icon-button';
|
import IconButton from 'soapbox/components/icon-button';
|
||||||
import { HStack } from 'soapbox/components/ui';
|
import { HStack } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||||
import { makeGetAccount } from 'soapbox/selectors';
|
import { makeGetAccount } from 'soapbox/selectors';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import type { List as ImmutableList } from 'immutable';
|
import type { List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
|
@ -23,21 +22,19 @@ interface IAccount {
|
||||||
const Account: React.FC<IAccount> = ({ accountId, aliases }) => {
|
const Account: React.FC<IAccount> = ({ accountId, aliases }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const features = useFeatures();
|
||||||
|
|
||||||
const getAccount = useCallback(makeGetAccount(), []);
|
const getAccount = useCallback(makeGetAccount(), []);
|
||||||
|
|
||||||
const account = useAppSelector((state) => getAccount(state, accountId));
|
const account = useAppSelector((state) => getAccount(state, accountId));
|
||||||
const added = useAppSelector((state) => {
|
const me = useAppSelector((state) => state.me);
|
||||||
const instance = state.instance;
|
|
||||||
const features = getFeatures(instance);
|
|
||||||
|
|
||||||
|
const added = useAppSelector((state) => {
|
||||||
const account = getAccount(state, accountId);
|
const account = getAccount(state, accountId);
|
||||||
const apId = account?.pleroma.get('ap_id');
|
const apId = account?.pleroma.get('ap_id');
|
||||||
const name = features.accountMoving ? account?.acct : apId;
|
const name = features.accountMoving ? account?.acct : apId;
|
||||||
|
|
||||||
return aliases.includes(name);
|
return aliases.includes(name);
|
||||||
});
|
});
|
||||||
const me = useAppSelector((state) => state.me);
|
|
||||||
|
|
||||||
const handleOnAdd = () => dispatch(addToAliases(account!));
|
const handleOnAdd = () => dispatch(addToAliases(account!));
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@ import { fetchAliases, removeFromAliases } from 'soapbox/actions/aliases';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||||
import { CardHeader, CardTitle, Column, HStack, Text } from 'soapbox/components/ui';
|
import { CardHeader, CardTitle, Column, HStack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||||
import { makeGetAccount } from 'soapbox/selectors';
|
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import Account from './components/account';
|
import Account from './components/account';
|
||||||
import Search from './components/search';
|
import Search from './components/search';
|
||||||
|
@ -22,22 +20,21 @@ const messages = defineMessages({
|
||||||
delete: { id: 'column.aliases.delete', defaultMessage: 'Delete' },
|
delete: { id: 'column.aliases.delete', defaultMessage: 'Delete' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const getAccount = makeGetAccount();
|
|
||||||
|
|
||||||
const Aliases = () => {
|
const Aliases = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const features = useFeatures();
|
||||||
|
const account = useOwnAccount();
|
||||||
|
|
||||||
const aliases = useAppSelector((state) => {
|
const aliases = useAppSelector((state) => {
|
||||||
const me = state.me as string;
|
if (features.accountMoving) {
|
||||||
const account = getAccount(state, me);
|
return state.aliases.aliases.items;
|
||||||
|
} else {
|
||||||
const instance = state.instance;
|
|
||||||
const features = getFeatures(instance);
|
|
||||||
|
|
||||||
if (features.accountMoving) return state.aliases.aliases.items;
|
|
||||||
return account!.pleroma.get('also_known_as');
|
return account!.pleroma.get('also_known_as');
|
||||||
|
}
|
||||||
}) as ImmutableList<string>;
|
}) as ImmutableList<string>;
|
||||||
|
|
||||||
const searchAccountIds = useAppSelector((state) => state.aliases.suggestions.items);
|
const searchAccountIds = useAppSelector((state) => state.aliases.suggestions.items);
|
||||||
const loaded = useAppSelector((state) => state.aliases.suggestions.loaded);
|
const loaded = useAppSelector((state) => state.aliases.suggestions.loaded);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Link, Redirect, Route, Switch, useHistory, useLocation } from 'react-ro
|
||||||
|
|
||||||
import LandingGradient from 'soapbox/components/landing-gradient';
|
import LandingGradient from 'soapbox/components/landing-gradient';
|
||||||
import SiteLogo from 'soapbox/components/site-logo';
|
import SiteLogo from 'soapbox/components/site-logo';
|
||||||
import { useAppSelector, useFeatures, useSoapboxConfig, useOwnAccount } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useSoapboxConfig, useOwnAccount, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import { Button, Card, CardBody } from '../../components/ui';
|
import { Button, Card, CardBody } from '../../components/ui';
|
||||||
import LoginPage from '../auth-login/components/login-page';
|
import LoginPage from '../auth-login/components/login-page';
|
||||||
|
@ -27,12 +27,11 @@ const AuthLayout = () => {
|
||||||
const { search } = useLocation();
|
const { search } = useLocation();
|
||||||
|
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
const instance = useInstance();
|
||||||
const soapboxConfig = useSoapboxConfig();
|
|
||||||
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
|
|
||||||
|
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const soapboxConfig = useSoapboxConfig();
|
||||||
|
|
||||||
|
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
|
||||||
const isOpen = features.accountCreation && instance.registrations;
|
const isOpen = features.accountCreation && instance.registrations;
|
||||||
const pepeOpen = useAppSelector(state => state.verification.instance.get('registrations') === true);
|
const pepeOpen = useAppSelector(state => state.verification.instance.get('registrations') === true);
|
||||||
const isLoginPage = history.location.pathname === '/login';
|
const isLoginPage = history.location.pathname === '/login';
|
||||||
|
@ -47,7 +46,7 @@ const AuthLayout = () => {
|
||||||
<header className='flex justify-between relative py-12 px-2 mb-auto'>
|
<header className='flex justify-between relative py-12 px-2 mb-auto'>
|
||||||
<div className='relative z-0 flex-1 px-2 lg:flex lg:items-center lg:justify-center lg:absolute lg:inset-0'>
|
<div className='relative z-0 flex-1 px-2 lg:flex lg:items-center lg:justify-center lg:absolute lg:inset-0'>
|
||||||
<Link to='/' className='cursor-pointer'>
|
<Link to='/' className='cursor-pointer'>
|
||||||
<SiteLogo alt={siteTitle} className='h-7' />
|
<SiteLogo alt={instance.title} className='h-7' />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Card, HStack, Text } from 'soapbox/components/ui';
|
import { Card, HStack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import ConsumerButton from './consumer-button';
|
import ConsumerButton from './consumer-button';
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ interface IConsumersList {
|
||||||
|
|
||||||
/** Displays OAuth consumers to log in with. */
|
/** Displays OAuth consumers to log in with. */
|
||||||
const ConsumersList: React.FC<IConsumersList> = () => {
|
const ConsumersList: React.FC<IConsumersList> = () => {
|
||||||
const providers = useAppSelector(state => ImmutableList<string>(state.instance.pleroma.get('oauth_consumer_strategies')));
|
const instance = useInstance();
|
||||||
|
const providers = ImmutableList<string>(instance.pleroma.get('oauth_consumer_strategies'));
|
||||||
|
|
||||||
if (providers.size > 0) {
|
if (providers.size > 0) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { openModal } from 'soapbox/actions/modals';
|
||||||
import BirthdayInput from 'soapbox/components/birthday-input';
|
import BirthdayInput from 'soapbox/components/birthday-input';
|
||||||
import { Checkbox, Form, FormGroup, FormActions, Button, Input, Textarea } from 'soapbox/components/ui';
|
import { Checkbox, Form, FormGroup, FormActions, Button, Input, Textarea } from 'soapbox/components/ui';
|
||||||
import CaptchaField from 'soapbox/features/auth-login/components/captcha';
|
import CaptchaField from 'soapbox/features/auth-login/components/captcha';
|
||||||
import { useAppSelector, useAppDispatch, useSettings, useFeatures } from 'soapbox/hooks';
|
import { useAppDispatch, useSettings, useFeatures, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
username: { id: 'registration.fields.username_placeholder', defaultMessage: 'Username' },
|
username: { id: 'registration.fields.username_placeholder', defaultMessage: 'Username' },
|
||||||
|
@ -42,7 +42,7 @@ const RegistrationForm: React.FC<IRegistrationForm> = ({ inviteToken }) => {
|
||||||
|
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const instance = useAppSelector(state => state.instance);
|
const instance = useInstance();
|
||||||
|
|
||||||
const locale = settings.get('locale');
|
const locale = settings.get('locale');
|
||||||
const needsConfirmation = !!instance.pleroma.getIn(['metadata', 'account_activation_required']);
|
const needsConfirmation = !!instance.pleroma.getIn(['metadata', 'account_activation_required']);
|
||||||
|
|
|
@ -17,7 +17,7 @@ import AutosuggestInput, { AutoSuggestion } from 'soapbox/components/autosuggest
|
||||||
import AutosuggestTextarea from 'soapbox/components/autosuggest-textarea';
|
import AutosuggestTextarea from 'soapbox/components/autosuggest-textarea';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import { Button, HStack, Stack } from 'soapbox/components/ui';
|
import { Button, HStack, Stack } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector, useCompose, useFeatures, usePrevious } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useCompose, useFeatures, useInstance, usePrevious } from 'soapbox/hooks';
|
||||||
import { isMobile } from 'soapbox/is-mobile';
|
import { isMobile } from 'soapbox/is-mobile';
|
||||||
|
|
||||||
import QuotedStatusContainer from '../containers/quoted-status-container';
|
import QuotedStatusContainer from '../containers/quoted-status-container';
|
||||||
|
@ -67,11 +67,12 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const { configuration } = useInstance();
|
||||||
|
|
||||||
const compose = useCompose(id);
|
const compose = useCompose(id);
|
||||||
const showSearch = useAppSelector((state) => state.search.submitted && !state.search.hidden);
|
const showSearch = useAppSelector((state) => state.search.submitted && !state.search.hidden);
|
||||||
const isModalOpen = useAppSelector((state) => !!(state.modals.size && state.modals.last()!.modalType === 'COMPOSE'));
|
const isModalOpen = useAppSelector((state) => !!(state.modals.size && state.modals.last()!.modalType === 'COMPOSE'));
|
||||||
const maxTootChars = useAppSelector((state) => state.instance.getIn(['configuration', 'statuses', 'max_characters'])) as number;
|
const maxTootChars = configuration.getIn(['statuses', 'max_characters']) as number;
|
||||||
const scheduledStatusCount = useAppSelector((state) => state.get('scheduled_statuses').size);
|
const scheduledStatusCount = useAppSelector((state) => state.get('scheduled_statuses').size);
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { addPollOption, changePollOption, changePollSettings, clearComposeSuggestions, fetchComposeSuggestions, removePoll, removePollOption, selectComposeSuggestion } from 'soapbox/actions/compose';
|
import { addPollOption, changePollOption, changePollSettings, clearComposeSuggestions, fetchComposeSuggestions, removePoll, removePollOption, selectComposeSuggestion } from 'soapbox/actions/compose';
|
||||||
import AutosuggestInput from 'soapbox/components/autosuggest-input';
|
import AutosuggestInput from 'soapbox/components/autosuggest-input';
|
||||||
import { Button, Divider, HStack, Stack, Text, Toggle } from 'soapbox/components/ui';
|
import { Button, Divider, HStack, Stack, Text, Toggle } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector, useCompose } from 'soapbox/hooks';
|
import { useAppDispatch, useCompose, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import DurationSelector from './duration-selector';
|
import DurationSelector from './duration-selector';
|
||||||
|
|
||||||
|
import type { Map as ImmutableMap } from 'immutable';
|
||||||
import type { AutoSuggestion } from 'soapbox/components/autosuggest-input';
|
import type { AutoSuggestion } from 'soapbox/components/autosuggest-input';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -110,16 +111,17 @@ interface IPollForm {
|
||||||
const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
const PollForm: React.FC<IPollForm> = ({ composeId }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const { configuration } = useInstance();
|
||||||
|
|
||||||
const compose = useCompose(composeId);
|
const compose = useCompose(composeId);
|
||||||
|
|
||||||
const pollLimits = useAppSelector((state) => state.instance.getIn(['configuration', 'polls']) as any);
|
const pollLimits = configuration.get('polls') as ImmutableMap<string, number>;
|
||||||
const options = compose.poll?.options;
|
const options = compose.poll?.options;
|
||||||
const expiresIn = compose.poll?.expires_in;
|
const expiresIn = compose.poll?.expires_in;
|
||||||
const isMultiple = compose.poll?.multiple;
|
const isMultiple = compose.poll?.multiple;
|
||||||
|
|
||||||
const maxOptions = pollLimits.get('max_options');
|
const maxOptions = pollLimits.get('max_options') as number;
|
||||||
const maxOptionChars = pollLimits.get('max_characters_per_option');
|
const maxOptionChars = pollLimits.get('max_characters_per_option') as number;
|
||||||
|
|
||||||
const onRemoveOption = (index: number) => dispatch(removePollOption(composeId, index));
|
const onRemoveOption = (index: number) => dispatch(removePollOption(composeId, index));
|
||||||
const onChangeOption = (index: number, title: string) => dispatch(changePollOption(composeId, index, title));
|
const onChangeOption = (index: number, title: string) => dispatch(changePollOption(composeId, index, title));
|
||||||
|
|
|
@ -3,10 +3,9 @@ import { FormattedList, FormattedMessage } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
import { useAppSelector, useCompose } from 'soapbox/hooks';
|
import { useAppSelector, useCompose, useFeatures } from 'soapbox/hooks';
|
||||||
import { statusToMentionsAccountIdsArray } from 'soapbox/reducers/compose';
|
import { statusToMentionsAccountIdsArray } from 'soapbox/reducers/compose';
|
||||||
import { makeGetStatus } from 'soapbox/selectors';
|
import { makeGetStatus } from 'soapbox/selectors';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import type { Status as StatusEntity } from 'soapbox/types/entities';
|
import type { Status as StatusEntity } from 'soapbox/types/entities';
|
||||||
|
|
||||||
|
@ -16,18 +15,15 @@ interface IReplyMentions {
|
||||||
|
|
||||||
const ReplyMentions: React.FC<IReplyMentions> = ({ composeId }) => {
|
const ReplyMentions: React.FC<IReplyMentions> = ({ composeId }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const getStatus = useCallback(makeGetStatus(), []);
|
const features = useFeatures();
|
||||||
|
|
||||||
const compose = useCompose(composeId);
|
const compose = useCompose(composeId);
|
||||||
|
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const getStatus = useCallback(makeGetStatus(), []);
|
||||||
const status = useAppSelector<StatusEntity | null>(state => getStatus(state, { id: compose.in_reply_to! }));
|
const status = useAppSelector<StatusEntity | null>(state => getStatus(state, { id: compose.in_reply_to! }));
|
||||||
const to = compose.to;
|
const to = compose.to;
|
||||||
const account = useAppSelector((state) => state.accounts.get(state.me));
|
const account = useAppSelector((state) => state.accounts.get(state.me));
|
||||||
|
|
||||||
const { explicitAddressing } = getFeatures(instance);
|
if (!features.explicitAddressing || !status || !to) {
|
||||||
|
|
||||||
if (!explicitAddressing || !status || !to) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useRef } from 'react';
|
||||||
import { defineMessages, IntlShape, useIntl } from 'react-intl';
|
import { defineMessages, IntlShape, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { IconButton } from 'soapbox/components/ui';
|
import { IconButton } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { List as ImmutableList } from 'immutable';
|
import type { List as ImmutableList } from 'immutable';
|
||||||
|
|
||||||
|
@ -29,9 +29,10 @@ const UploadButton: React.FC<IUploadButton> = ({
|
||||||
resetFileKey,
|
resetFileKey,
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const { configuration } = useInstance();
|
||||||
|
|
||||||
const fileElement = useRef<HTMLInputElement>(null);
|
const fileElement = useRef<HTMLInputElement>(null);
|
||||||
const attachmentTypes = useAppSelector(state => state.instance.configuration.getIn(['media_attachments', 'supported_mime_types']) as ImmutableList<string>);
|
const attachmentTypes = configuration.getIn(['media_attachments', 'supported_mime_types']) as ImmutableList<string>;
|
||||||
|
|
||||||
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
if (e.target.files?.length) {
|
if (e.target.files?.length) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { openModal } from 'soapbox/actions/modals';
|
||||||
import Blurhash from 'soapbox/components/blurhash';
|
import Blurhash from 'soapbox/components/blurhash';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import IconButton from 'soapbox/components/icon-button';
|
import IconButton from 'soapbox/components/icon-button';
|
||||||
import { useAppDispatch, useAppSelector, useCompose } from 'soapbox/hooks';
|
import { useAppDispatch, useCompose, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import Motion from '../../ui/util/optional-motion';
|
import Motion from '../../ui/util/optional-motion';
|
||||||
|
|
||||||
|
@ -70,9 +70,9 @@ const Upload: React.FC<IUpload> = ({ composeId, id }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const { description_limit: descriptionLimit } = useInstance();
|
||||||
|
|
||||||
const media = useCompose(composeId).media_attachments.find(item => item.get('id') === id)!;
|
const media = useCompose(composeId).media_attachments.find(item => item.id === id)!;
|
||||||
const descriptionLimit = useAppSelector((state) => state.instance.get('description_limit'));
|
|
||||||
|
|
||||||
const [hovered, setHovered] = useState(false);
|
const [hovered, setHovered] = useState(false);
|
||||||
const [focused, setFocused] = useState(false);
|
const [focused, setFocused] = useState(false);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { Text, Widget } from 'soapbox/components/ui';
|
import { Text, Widget } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
|
import { useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
import SiteWallet from './site-wallet';
|
import SiteWallet from './site-wallet';
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ interface ICryptoDonatePanel {
|
||||||
const CryptoDonatePanel: React.FC<ICryptoDonatePanel> = ({ limit = 3 }): JSX.Element | null => {
|
const CryptoDonatePanel: React.FC<ICryptoDonatePanel> = ({ limit = 3 }): JSX.Element | null => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const addresses = useSoapboxConfig().get('cryptoAddresses');
|
const addresses = useSoapboxConfig().get('cryptoAddresses');
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
|
|
||||||
if (limit === 0 || addresses.size === 0) {
|
if (limit === 0 || addresses.size === 0) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -40,7 +40,7 @@ const CryptoDonatePanel: React.FC<ICryptoDonatePanel> = ({ limit = 3 }): JSX.Ele
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='crypto_donate_panel.intro.message'
|
id='crypto_donate_panel.intro.message'
|
||||||
defaultMessage='{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!'
|
defaultMessage='{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!'
|
||||||
values={{ siteTitle }}
|
values={{ siteTitle: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Accordion, Column, Stack } from 'soapbox/components/ui';
|
import { Accordion, Column, Stack } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import SiteWallet from './components/site-wallet';
|
import SiteWallet from './components/site-wallet';
|
||||||
|
|
||||||
|
@ -11,9 +11,10 @@ const messages = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
const CryptoDonate: React.FC = (): JSX.Element => {
|
const CryptoDonate: React.FC = (): JSX.Element => {
|
||||||
const [explanationBoxExpanded, toggleExplanationBox] = useState(true);
|
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
|
const [explanationBoxExpanded, toggleExplanationBox] = useState(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column label={intl.formatMessage(messages.heading)} withHeader>
|
<Column label={intl.formatMessage(messages.heading)} withHeader>
|
||||||
|
@ -26,7 +27,7 @@ const CryptoDonate: React.FC = (): JSX.Element => {
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='crypto_donate.explanation_box.message'
|
id='crypto_donate.explanation_box.message'
|
||||||
defaultMessage='{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!'
|
defaultMessage='{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!'
|
||||||
values={{ siteTitle }}
|
values={{ siteTitle: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@ import { useLocation } from 'react-router-dom';
|
||||||
import { fetchDirectory, expandDirectory } from 'soapbox/actions/directory';
|
import { fetchDirectory, expandDirectory } from 'soapbox/actions/directory';
|
||||||
import LoadMore from 'soapbox/components/load-more';
|
import LoadMore from 'soapbox/components/load-more';
|
||||||
import { Column, RadioButton, Stack, Text } from 'soapbox/components/ui';
|
import { Column, RadioButton, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useInstance } from 'soapbox/hooks';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import AccountCard from './components/account-card';
|
import AccountCard from './components/account-card';
|
||||||
|
|
||||||
|
@ -25,11 +24,11 @@ const Directory = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { search } = useLocation();
|
const { search } = useLocation();
|
||||||
const params = new URLSearchParams(search);
|
const params = new URLSearchParams(search);
|
||||||
|
const instance = useInstance();
|
||||||
|
const features = useFeatures();
|
||||||
|
|
||||||
const accountIds = useAppSelector((state) => state.user_lists.directory.items);
|
const accountIds = useAppSelector((state) => state.user_lists.directory.items);
|
||||||
const isLoading = useAppSelector((state) => state.user_lists.directory.isLoading);
|
const isLoading = useAppSelector((state) => state.user_lists.directory.isLoading);
|
||||||
const title = useAppSelector((state) => state.instance.get('title'));
|
|
||||||
const features = useAppSelector((state) => getFeatures(state.instance));
|
|
||||||
|
|
||||||
const [order, setOrder] = useState(params.get('order') || 'active');
|
const [order, setOrder] = useState(params.get('order') || 'active');
|
||||||
const [local, setLocal] = useState(!!params.get('local'));
|
const [local, setLocal] = useState(!!params.get('local'));
|
||||||
|
@ -71,7 +70,7 @@ const Directory = () => {
|
||||||
<fieldset className='mt-3'>
|
<fieldset className='mt-3'>
|
||||||
<legend className='sr-only'>Fediverse filter</legend>
|
<legend className='sr-only'>Fediverse filter</legend>
|
||||||
<div className='space-y-2'>
|
<div className='space-y-2'>
|
||||||
<RadioButton name='local' value='1' label={intl.formatMessage(messages.local, { domain: title })} checked={local} onChange={handleChangeLocal} />
|
<RadioButton name='local' value='1' label={intl.formatMessage(messages.local, { domain: instance.title })} checked={local} onChange={handleChangeLocal} />
|
||||||
<RadioButton name='local' value='0' label={intl.formatMessage(messages.federated)} checked={!local} onChange={handleChangeLocal} />
|
<RadioButton name='local' value='0' label={intl.formatMessage(messages.federated)} checked={!local} onChange={handleChangeLocal} />
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
Textarea,
|
Textarea,
|
||||||
Toggle,
|
Toggle,
|
||||||
} from 'soapbox/components/ui';
|
} from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures } from 'soapbox/hooks';
|
import { useAppDispatch, useOwnAccount, useFeatures, useInstance } from 'soapbox/hooks';
|
||||||
import { normalizeAccount } from 'soapbox/normalizers';
|
import { normalizeAccount } from 'soapbox/normalizers';
|
||||||
import resizeImage from 'soapbox/utils/resize-image';
|
import resizeImage from 'soapbox/utils/resize-image';
|
||||||
|
|
||||||
|
@ -171,10 +171,11 @@ const ProfileField: StreamfieldComponent<AccountCredentialsField> = ({ value, on
|
||||||
const EditProfile: React.FC = () => {
|
const EditProfile: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const maxFields = useAppSelector(state => state.instance.pleroma.getIn(['metadata', 'fields_limits', 'max_fields'], 4) as number);
|
const maxFields = instance.pleroma.getIn(['metadata', 'fields_limits', 'max_fields'], 4) as number;
|
||||||
|
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
const [data, setData] = useState<AccountCredentials>({});
|
const [data, setData] = useState<AccountCredentials>({});
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import { HStack, Stack, Text } from 'soapbox/components/ui';
|
import { HStack, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { Map as ImmutableMap } from 'immutable';
|
import type { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ interface IInstanceRestrictions {
|
||||||
}
|
}
|
||||||
|
|
||||||
const InstanceRestrictions: React.FC<IInstanceRestrictions> = ({ remoteInstance }) => {
|
const InstanceRestrictions: React.FC<IInstanceRestrictions> = ({ remoteInstance }) => {
|
||||||
const instance = useAppSelector(state => state.instance);
|
const instance = useInstance();
|
||||||
|
|
||||||
const renderRestrictions = () => {
|
const renderRestrictions = () => {
|
||||||
const items = [];
|
const items = [];
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import ScrollableList from 'soapbox/components/scrollable-list';
|
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||||
import { Accordion } from 'soapbox/components/ui';
|
import { Accordion } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useAppSelector, useInstance } from 'soapbox/hooks';
|
||||||
import { makeGetHosts } from 'soapbox/selectors';
|
import { makeGetHosts } from 'soapbox/selectors';
|
||||||
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
||||||
|
|
||||||
|
@ -21,12 +21,12 @@ const messages = defineMessages({
|
||||||
notDisclosed: { id: 'federation_restrictions.not_disclosed_message', defaultMessage: '{siteTitle} does not disclose federation restrictions through the API.' },
|
notDisclosed: { id: 'federation_restrictions.not_disclosed_message', defaultMessage: '{siteTitle} does not disclose federation restrictions through the API.' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const getHosts = makeGetHosts();
|
|
||||||
|
|
||||||
const FederationRestrictions = () => {
|
const FederationRestrictions = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
|
const getHosts = useCallback(makeGetHosts(), []);
|
||||||
|
|
||||||
const siteTitle = useAppSelector((state) => state.instance.get('title'));
|
|
||||||
const hosts = useAppSelector((state) => getHosts(state)) as ImmutableOrderedSet<string>;
|
const hosts = useAppSelector((state) => getHosts(state)) as ImmutableOrderedSet<string>;
|
||||||
const disclosed = useAppSelector((state) => federationRestrictionsDisclosed(state));
|
const disclosed = useAppSelector((state) => federationRestrictionsDisclosed(state));
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ const FederationRestrictions = () => {
|
||||||
expanded={explanationBoxExpanded}
|
expanded={explanationBoxExpanded}
|
||||||
onToggle={toggleExplanationBox}
|
onToggle={toggleExplanationBox}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.boxMessage, { siteTitle })}
|
{intl.formatMessage(messages.boxMessage, { siteTitle: instance.title })}
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
||||||
<div className='pt-4'>
|
<div className='pt-4'>
|
||||||
<ScrollableList emptyMessage={intl.formatMessage(emptyMessage, { siteTitle })}>
|
<ScrollableList emptyMessage={intl.formatMessage(emptyMessage, { siteTitle: instance.title })}>
|
||||||
{hosts.map((host) => <RestrictedInstance key={host} host={host} />)}
|
{hosts.map((host) => <RestrictedInstance key={host} host={host} />)}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { expandHomeTimeline } from 'soapbox/actions/timelines';
|
||||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||||
import { Column, Stack, Text } from 'soapbox/components/ui';
|
import { Column, Stack, Text } from 'soapbox/components/ui';
|
||||||
import Timeline from 'soapbox/features/ui/components/timeline';
|
import Timeline from 'soapbox/features/ui/components/timeline';
|
||||||
import { useAppSelector, useAppDispatch, useFeatures } from 'soapbox/hooks';
|
import { useAppSelector, useAppDispatch, useFeatures, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import { clearFeedAccountId } from '../../actions/timelines';
|
import { clearFeedAccountId } from '../../actions/timelines';
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ const HomeTimeline: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const polling = useRef<NodeJS.Timer | null>(null);
|
const polling = useRef<NodeJS.Timer | null>(null);
|
||||||
|
|
||||||
const isPartial = useAppSelector(state => state.timelines.get('home')?.isPartial === true);
|
const isPartial = useAppSelector(state => state.timelines.get('home')?.isPartial === true);
|
||||||
const currentAccountId = useAppSelector(state => state.timelines.get('home')?.feedAccountId as string | undefined);
|
const currentAccountId = useAppSelector(state => state.timelines.get('home')?.feedAccountId as string | undefined);
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
|
||||||
const currentAccountRelationship = useAppSelector(state => currentAccountId ? state.relationships.get(currentAccountId) : null);
|
const currentAccountRelationship = useAppSelector(state => currentAccountId ? state.relationships.get(currentAccountId) : null);
|
||||||
|
|
||||||
const handleLoadMore = (maxId: string) => {
|
const handleLoadMore = (maxId: string) => {
|
||||||
|
@ -104,7 +104,7 @@ const HomeTimeline: React.FC = () => {
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='empty_column.home.subtitle'
|
id='empty_column.home.subtitle'
|
||||||
defaultMessage='{siteTitle} gets more interesting once you follow other users.'
|
defaultMessage='{siteTitle} gets more interesting once you follow other users.'
|
||||||
values={{ siteTitle }}
|
values={{ siteTitle: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ const HomeTimeline: React.FC = () => {
|
||||||
values={{
|
values={{
|
||||||
public: (
|
public: (
|
||||||
<Link to='/timeline/local' className='text-primary-600 dark:text-primary-400 hover:underline'>
|
<Link to='/timeline/local' className='text-primary-600 dark:text-primary-400 hover:underline'>
|
||||||
<FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{ site_title: siteTitle }} />
|
<FormattedMessage id='empty_column.home.local_tab' defaultMessage='the {site_title} tab' values={{ site_title: instance.title }} />
|
||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import Markup from 'soapbox/components/markup';
|
||||||
import { Button, Card, CardBody, Stack, Text } from 'soapbox/components/ui';
|
import { Button, Card, CardBody, Stack, Text } from 'soapbox/components/ui';
|
||||||
import VerificationBadge from 'soapbox/components/verification-badge';
|
import VerificationBadge from 'soapbox/components/verification-badge';
|
||||||
import RegistrationForm from 'soapbox/features/auth-login/components/registration-form';
|
import RegistrationForm from 'soapbox/features/auth-login/components/registration-form';
|
||||||
import { useAppDispatch, useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useFeatures, useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
import { capitalize } from 'soapbox/utils/strings';
|
import { capitalize } from 'soapbox/utils/strings';
|
||||||
|
|
||||||
const LandingPage = () => {
|
const LandingPage = () => {
|
||||||
|
@ -15,7 +15,7 @@ const LandingPage = () => {
|
||||||
const soapboxConfig = useSoapboxConfig();
|
const soapboxConfig = useSoapboxConfig();
|
||||||
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
|
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
|
||||||
|
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const instance = useInstance();
|
||||||
const pepeOpen = useAppSelector(state => state.verification.instance.get('registrations') === true);
|
const pepeOpen = useAppSelector(state => state.verification.instance.get('registrations') === true);
|
||||||
|
|
||||||
/** Registrations are closed */
|
/** Registrations are closed */
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Link } from 'react-router-dom';
|
||||||
import { moveAccount } from 'soapbox/actions/security';
|
import { moveAccount } from 'soapbox/actions/security';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { Button, Column, Form, FormActions, FormGroup, Input, Text } from 'soapbox/components/ui';
|
import { Button, Column, Form, FormActions, FormGroup, Input, Text } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.migration', defaultMessage: 'Account migration' },
|
heading: { id: 'column.migration', defaultMessage: 'Account migration' },
|
||||||
|
@ -21,8 +21,9 @@ const messages = defineMessages({
|
||||||
const Migration = () => {
|
const Migration = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const cooldownPeriod = useAppSelector((state) => state.instance.pleroma.getIn(['metadata', 'migration_cooldown_period'])) as number | undefined;
|
const cooldownPeriod = instance.pleroma.getIn(['metadata', 'migration_cooldown_period']) as number | undefined;
|
||||||
|
|
||||||
const [targetAccount, setTargetAccount] = useState('');
|
const [targetAccount, setTargetAccount] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
|
|
|
@ -12,7 +12,7 @@ import Icon from 'soapbox/components/icon';
|
||||||
import { HStack, Text, Emoji } from 'soapbox/components/ui';
|
import { HStack, Text, Emoji } from 'soapbox/components/ui';
|
||||||
import AccountContainer from 'soapbox/containers/account-container';
|
import AccountContainer from 'soapbox/containers/account-container';
|
||||||
import StatusContainer from 'soapbox/containers/status-container';
|
import StatusContainer from 'soapbox/containers/status-container';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks';
|
||||||
import { makeGetNotification } from 'soapbox/selectors';
|
import { makeGetNotification } from 'soapbox/selectors';
|
||||||
import { NotificationType, validType } from 'soapbox/utils/notification';
|
import { NotificationType, validType } from 'soapbox/utils/notification';
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ const Notification: React.FC<INotificaton> = (props) => {
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const instance = useInstance();
|
||||||
|
|
||||||
const type = notification.type;
|
const type = notification.type;
|
||||||
const { account, status } = notification;
|
const { account, status } = notification;
|
||||||
|
|
|
@ -3,13 +3,13 @@ import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import Account from 'soapbox/components/account';
|
import Account from 'soapbox/components/account';
|
||||||
import { Button, Card, CardBody, Icon, Stack, Text } from 'soapbox/components/ui';
|
import { Button, Card, CardBody, Icon, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useOwnAccount } from 'soapbox/hooks';
|
import { useInstance, useOwnAccount } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||||
|
|
||||||
const FediverseStep = ({ onNext }: { onNext: () => void }) => {
|
const FediverseStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
const account = useOwnAccount() as AccountEntity;
|
const account = useOwnAccount() as AccountEntity;
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card variant='rounded' size='xl'>
|
<Card variant='rounded' size='xl'>
|
||||||
|
@ -22,7 +22,7 @@ const FediverseStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
id='onboarding.fediverse.title'
|
id='onboarding.fediverse.title'
|
||||||
defaultMessage='{siteTitle} is just one part of the Fediverse'
|
defaultMessage='{siteTitle} is just one part of the Fediverse'
|
||||||
values={{
|
values={{
|
||||||
siteTitle,
|
siteTitle: instance.title,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -35,7 +35,7 @@ const FediverseStep = ({ onNext }: { onNext: () => void }) => {
|
||||||
id='onboarding.fediverse.message'
|
id='onboarding.fediverse.message'
|
||||||
defaultMessage='The Fediverse is a social network made up of thousands of diverse and independently-run social media sites (aka "servers"). You can follow users — and like, repost, and reply to posts — from most other Fediverse servers, because they can communicate with {siteTitle}.'
|
defaultMessage='The Fediverse is a social network made up of thousands of diverse and independently-run social media sites (aka "servers"). You can follow users — and like, repost, and reply to posts — from most other Fediverse servers, because they can communicate with {siteTitle}.'
|
||||||
values={{
|
values={{
|
||||||
siteTitle,
|
siteTitle: instance.title,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { fetchInstance } from 'soapbox/actions/instance';
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
import SiteLogo from 'soapbox/components/site-logo';
|
import SiteLogo from 'soapbox/components/site-logo';
|
||||||
import { Button, Form, HStack, IconButton, Input, Tooltip } from 'soapbox/components/ui';
|
import { Button, Form, HStack, IconButton, Input, Tooltip } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useFeatures, useSoapboxConfig, useOwnAccount } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useSoapboxConfig, useOwnAccount, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import Sonar from './sonar';
|
import Sonar from './sonar';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ const Header = () => {
|
||||||
const { links } = soapboxConfig;
|
const { links } = soapboxConfig;
|
||||||
|
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const instance = useInstance();
|
||||||
const isOpen = features.accountCreation && instance.registrations;
|
const isOpen = features.accountCreation && instance.registrations;
|
||||||
const pepeOpen = useAppSelector(state => state.verification.instance.get('registrations') === true);
|
const pepeOpen = useAppSelector(state => state.verification.instance.get('registrations') === true);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { expandPublicTimeline } from 'soapbox/actions/timelines';
|
||||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||||
import SubNavigation from 'soapbox/components/sub-navigation';
|
import SubNavigation from 'soapbox/components/sub-navigation';
|
||||||
import { Accordion, Column } from 'soapbox/components/ui';
|
import { Accordion, Column } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector, useSettings } from 'soapbox/hooks';
|
import { useAppDispatch, useInstance, useSettings } from 'soapbox/hooks';
|
||||||
|
|
||||||
import PinnedHostsPicker from '../remote-timeline/components/pinned-hosts-picker';
|
import PinnedHostsPicker from '../remote-timeline/components/pinned-hosts-picker';
|
||||||
import Timeline from '../ui/components/timeline';
|
import Timeline from '../ui/components/timeline';
|
||||||
|
@ -22,12 +22,12 @@ const CommunityTimeline = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const instance = useInstance();
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const onlyMedia = settings.getIn(['public', 'other', 'onlyMedia']);
|
const onlyMedia = settings.getIn(['public', 'other', 'onlyMedia']);
|
||||||
|
|
||||||
const timelineId = 'public';
|
const timelineId = 'public';
|
||||||
|
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
const explanationBoxExpanded = settings.get('explanationBox');
|
const explanationBoxExpanded = settings.get('explanationBox');
|
||||||
const showExplanationBox = settings.get('showExplanationBox');
|
const showExplanationBox = settings.get('showExplanationBox');
|
||||||
|
|
||||||
|
@ -79,13 +79,13 @@ const CommunityTimeline = () => {
|
||||||
id='fediverse_tab.explanation_box.explanation'
|
id='fediverse_tab.explanation_box.explanation'
|
||||||
defaultMessage='{site_title} is part of the Fediverse, a social network made up of thousands of independent social media sites (aka "servers"). The posts you see here are from 3rd-party servers. You have the freedom to engage with them, or to block any server you don't like. Pay attention to the full username after the second @ symbol to know which server a post is from. To see only {site_title} posts, visit {local}.'
|
defaultMessage='{site_title} is part of the Fediverse, a social network made up of thousands of independent social media sites (aka "servers"). The posts you see here are from 3rd-party servers. You have the freedom to engage with them, or to block any server you don't like. Pay attention to the full username after the second @ symbol to know which server a post is from. To see only {site_title} posts, visit {local}.'
|
||||||
values={{
|
values={{
|
||||||
site_title: siteTitle,
|
site_title: instance.title,
|
||||||
local: (
|
local: (
|
||||||
<Link to='/timeline/local'>
|
<Link to='/timeline/local'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='empty_column.home.local_tab'
|
id='empty_column.home.local_tab'
|
||||||
defaultMessage='the {site_title} tab'
|
defaultMessage='the {site_title} tab'
|
||||||
values={{ site_title: siteTitle }}
|
values={{ site_title: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { Stack, CardTitle, Text } from 'soapbox/components/ui';
|
import { Stack, CardTitle, Text } from 'soapbox/components/ui';
|
||||||
import RegistrationForm from 'soapbox/features/auth-login/components/registration-form';
|
import RegistrationForm from 'soapbox/features/auth-login/components/registration-form';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
interface RegisterInviteParams {
|
interface RegisterInviteParams {
|
||||||
token: string,
|
token: string,
|
||||||
|
@ -12,14 +12,14 @@ interface RegisterInviteParams {
|
||||||
|
|
||||||
/** Page to register with an invitation. */
|
/** Page to register with an invitation. */
|
||||||
const RegisterInvite: React.FC = () => {
|
const RegisterInvite: React.FC = () => {
|
||||||
|
const instance = useInstance();
|
||||||
const { token } = useParams<RegisterInviteParams>();
|
const { token } = useParams<RegisterInviteParams>();
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
|
||||||
|
|
||||||
const title = (
|
const title = (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='register_invite.title'
|
id='register_invite.title'
|
||||||
defaultMessage="You've been invited to join {siteTitle}!"
|
defaultMessage="You've been invited to join {siteTitle}!"
|
||||||
values={{ siteTitle }}
|
values={{ siteTitle: instance.title }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { Column, Divider, Stack, Text } from 'soapbox/components/ui';
|
import { Column, Divider, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
import LinkFooter from '../ui/components/link-footer';
|
import LinkFooter from '../ui/components/link-footer';
|
||||||
import PromoPanel from '../ui/components/promo-panel';
|
import PromoPanel from '../ui/components/promo-panel';
|
||||||
|
@ -13,7 +13,7 @@ const messages = defineMessages({
|
||||||
|
|
||||||
const ServerInfo = () => {
|
const ServerInfo = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const instance = useInstance();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column label={intl.formatMessage(messages.heading)}>
|
<Column label={intl.formatMessage(messages.heading)}>
|
||||||
|
|
|
@ -6,8 +6,7 @@ import { useHistory } from 'react-router-dom';
|
||||||
import { fetchMfa } from 'soapbox/actions/mfa';
|
import { fetchMfa } from 'soapbox/actions/mfa';
|
||||||
import List, { ListItem } from 'soapbox/components/list';
|
import List, { ListItem } from 'soapbox/components/list';
|
||||||
import { Card, CardBody, CardHeader, CardTitle, Column } from 'soapbox/components/ui';
|
import { Card, CardBody, CardHeader, CardTitle, Column } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useOwnAccount } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import Preferences from '../preferences';
|
import Preferences from '../preferences';
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ const Settings = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const mfa = useAppSelector((state) => state.security.get('mfa'));
|
const mfa = useAppSelector((state) => state.security.get('mfa'));
|
||||||
const features = useAppSelector((state) => getFeatures(state.instance));
|
const features = useFeatures();
|
||||||
const account = useOwnAccount();
|
const account = useOwnAccount();
|
||||||
|
|
||||||
const navigateToChangeEmail = () => history.push('/settings/email');
|
const navigateToChangeEmail = () => history.push('/settings/email');
|
||||||
|
|
|
@ -2,12 +2,12 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Card, CardTitle, Text, Stack, Button } from 'soapbox/components/ui';
|
import { Card, CardTitle, Text, Stack, Button } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
|
import { useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
/** Prompts logged-out users to log in when viewing a thread. */
|
/** Prompts logged-out users to log in when viewing a thread. */
|
||||||
const ThreadLoginCta: React.FC = () => {
|
const ThreadLoginCta: React.FC = () => {
|
||||||
|
const instance = useInstance();
|
||||||
const { displayCta } = useSoapboxConfig();
|
const { displayCta } = useSoapboxConfig();
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
|
||||||
|
|
||||||
if (!displayCta) return null;
|
if (!displayCta) return null;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ const ThreadLoginCta: React.FC = () => {
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='thread_login.message'
|
id='thread_login.message'
|
||||||
defaultMessage='Join {siteTitle} to get the full story and details.'
|
defaultMessage='Join {siteTitle} to get the full story and details.'
|
||||||
values={{ siteTitle }}
|
values={{ siteTitle: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -2,11 +2,11 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Banner, Button, HStack, Stack, Text } from 'soapbox/components/ui';
|
import { Banner, Button, HStack, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppSelector, useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
const CtaBanner = () => {
|
const CtaBanner = () => {
|
||||||
|
const instance = useInstance();
|
||||||
const { displayCta, singleUserMode } = useSoapboxConfig();
|
const { displayCta, singleUserMode } = useSoapboxConfig();
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
const me = useAppSelector((state) => state.me);
|
const me = useAppSelector((state) => state.me);
|
||||||
|
|
||||||
if (me || !displayCta || singleUserMode) return null;
|
if (me || !displayCta || singleUserMode) return null;
|
||||||
|
@ -17,7 +17,7 @@ const CtaBanner = () => {
|
||||||
<HStack alignItems='center' justifyContent='between'>
|
<HStack alignItems='center' justifyContent='between'>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text theme='white' size='xl' weight='bold'>
|
<Text theme='white' size='xl' weight='bold'>
|
||||||
<FormattedMessage id='signup_panel.title' defaultMessage='New to {site_title}?' values={{ site_title: siteTitle }} />
|
<FormattedMessage id='signup_panel.title' defaultMessage='New to {site_title}?' values={{ site_title: instance.title }} />
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text theme='white' weight='medium' className='opacity-90'>
|
<Text theme='white' weight='medium' className='opacity-90'>
|
||||||
|
|
|
@ -2,8 +2,7 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Modal } from 'soapbox/components/ui';
|
import { Modal } from 'soapbox/components/ui';
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useFeatures } from 'soapbox/hooks';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
interface IHotkeysModal {
|
interface IHotkeysModal {
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
|
@ -22,7 +21,7 @@ const TableCell: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
const HotkeysModal: React.FC<IHotkeysModal> = ({ onClose }) => {
|
const HotkeysModal: React.FC<IHotkeysModal> = ({ onClose }) => {
|
||||||
const features = useAppSelector((state) => getFeatures(state.instance));
|
const features = useFeatures();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import SiteLogo from 'soapbox/components/site-logo';
|
import SiteLogo from 'soapbox/components/site-logo';
|
||||||
import { Text, Button, Icon, Modal } from 'soapbox/components/ui';
|
import { Text, Button, Icon, Modal } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppSelector, useFeatures, useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
download: { id: 'landing_page_modal.download', defaultMessage: 'Download' },
|
download: { id: 'landing_page_modal.download', defaultMessage: 'Download' },
|
||||||
|
@ -25,7 +25,7 @@ const LandingPageModal: React.FC<ILandingPageModal> = ({ onClose }) => {
|
||||||
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
|
const pepeEnabled = soapboxConfig.getIn(['extensions', 'pepe', 'enabled']) === true;
|
||||||
const { links } = soapboxConfig;
|
const { links } = soapboxConfig;
|
||||||
|
|
||||||
const instance = useAppSelector((state) => state.instance);
|
const instance = useInstance();
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
|
||||||
const isOpen = features.accountCreation && instance.registrations;
|
const isOpen = features.accountCreation && instance.registrations;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useHistory } from 'react-router-dom';
|
||||||
import { remoteInteraction } from 'soapbox/actions/interactions';
|
import { remoteInteraction } from 'soapbox/actions/interactions';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { Button, Modal, Stack, Text } from 'soapbox/components/ui';
|
import { Button, Modal, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useAppDispatch, useFeatures, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppSelector, useAppDispatch, useFeatures, useSoapboxConfig, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
|
@ -29,9 +29,9 @@ const UnauthorizedModal: React.FC<IUnauthorizedModal> = ({ action, onClose, acco
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const { singleUserMode } = useSoapboxConfig();
|
const { singleUserMode } = useSoapboxConfig();
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
|
||||||
const username = useAppSelector(state => state.accounts.get(accountId)?.display_name);
|
const username = useAppSelector(state => state.accounts.get(accountId)?.display_name);
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ const UnauthorizedModal: React.FC<IUnauthorizedModal> = ({ action, onClose, acco
|
||||||
</div>
|
</div>
|
||||||
{!singleUserMode && (
|
{!singleUserMode && (
|
||||||
<Text size='lg' weight='medium'>
|
<Text size='lg' weight='medium'>
|
||||||
<FormattedMessage id='unauthorized_modal.title' defaultMessage='Sign up for {site_title}' values={{ site_title: siteTitle }} />
|
<FormattedMessage id='unauthorized_modal.title' defaultMessage='Sign up for {site_title}' values={{ site_title: instance.title }} />
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -135,7 +135,7 @@ const UnauthorizedModal: React.FC<IUnauthorizedModal> = ({ action, onClose, acco
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={<FormattedMessage id='unauthorized_modal.title' defaultMessage='Sign up for {site_title}' values={{ site_title: siteTitle }} />}
|
title={<FormattedMessage id='unauthorized_modal.title' defaultMessage='Sign up for {site_title}' values={{ site_title: instance.title }} />}
|
||||||
onClose={onClickClose}
|
onClose={onClickClose}
|
||||||
confirmationAction={onLogin}
|
confirmationAction={onLogin}
|
||||||
confirmationText={<FormattedMessage id='account.login' defaultMessage='Log in' />}
|
confirmationText={<FormattedMessage id='account.login' defaultMessage='Log in' />}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { closeModal } from 'soapbox/actions/modals';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { reConfirmPhoneVerification, reRequestPhoneVerification } from 'soapbox/actions/verification';
|
import { reConfirmPhoneVerification, reRequestPhoneVerification } from 'soapbox/actions/verification';
|
||||||
import { FormGroup, PhoneInput, Modal, Stack, Text } from 'soapbox/components/ui';
|
import { FormGroup, PhoneInput, Modal, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks';
|
||||||
import { getAccessToken } from 'soapbox/utils/auth';
|
import { getAccessToken } from 'soapbox/utils/auth';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -56,8 +56,8 @@ enum Statuses {
|
||||||
const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const instance = useInstance();
|
||||||
const accessToken = useAppSelector((state) => getAccessToken(state));
|
const accessToken = useAppSelector((state) => getAccessToken(state));
|
||||||
const title = useAppSelector((state) => state.instance.title);
|
|
||||||
const isLoading = useAppSelector((state) => state.verification.isLoading);
|
const isLoading = useAppSelector((state) => state.verification.isLoading);
|
||||||
|
|
||||||
const [status, setStatus] = useState<Statuses>(Statuses.IDLE);
|
const [status, setStatus] = useState<Statuses>(Statuses.IDLE);
|
||||||
|
@ -143,7 +143,7 @@ const VerifySmsModal: React.FC<IVerifySmsModal> = ({ onClose }) => {
|
||||||
id='sms_verification.modal.verify_help_text'
|
id='sms_verification.modal.verify_help_text'
|
||||||
defaultMessage='Verify your phone number to start using {instance}.'
|
defaultMessage='Verify your phone number to start using {instance}.'
|
||||||
values={{
|
values={{
|
||||||
instance: title,
|
instance: instance.title,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -2,11 +2,11 @@ import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Button, Stack, Text } from 'soapbox/components/ui';
|
import { Button, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppSelector, useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
const SignUpPanel = () => {
|
const SignUpPanel = () => {
|
||||||
|
const instance = useInstance();
|
||||||
const { singleUserMode } = useSoapboxConfig();
|
const { singleUserMode } = useSoapboxConfig();
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
const me = useAppSelector((state) => state.me);
|
const me = useAppSelector((state) => state.me);
|
||||||
|
|
||||||
if (me || singleUserMode) return null;
|
if (me || singleUserMode) return null;
|
||||||
|
@ -15,7 +15,7 @@ const SignUpPanel = () => {
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text size='lg' weight='bold'>
|
<Text size='lg' weight='bold'>
|
||||||
<FormattedMessage id='signup_panel.title' defaultMessage='New to {site_title}?' values={{ site_title: siteTitle }} />
|
<FormattedMessage id='signup_panel.title' defaultMessage='New to {site_title}?' values={{ site_title: instance.title }} />
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text theme='muted' size='sm'>
|
<Text theme='muted' size='sm'>
|
||||||
|
|
|
@ -2,20 +2,20 @@ import React from 'react';
|
||||||
|
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import { Widget, Stack, Text } from 'soapbox/components/ui';
|
import { Widget, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useSettings, useSoapboxConfig } from 'soapbox/hooks';
|
import { useInstance, useSettings, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
const PromoPanel: React.FC = () => {
|
const PromoPanel: React.FC = () => {
|
||||||
|
const instance = useInstance();
|
||||||
const { promoPanel } = useSoapboxConfig();
|
const { promoPanel } = useSoapboxConfig();
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
|
|
||||||
const siteTitle = useAppSelector(state => state.instance.title);
|
|
||||||
const promoItems = promoPanel.get('items');
|
const promoItems = promoPanel.get('items');
|
||||||
const locale = settings.get('locale');
|
const locale = settings.get('locale');
|
||||||
|
|
||||||
if (!promoItems || promoItems.isEmpty()) return null;
|
if (!promoItems || promoItems.isEmpty()) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Widget title={siteTitle}>
|
<Widget title={instance.title}>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
{promoItems.map((item, i) => (
|
{promoItems.map((item, i) => (
|
||||||
<Text key={i}>
|
<Text key={i}>
|
||||||
|
|
|
@ -25,18 +25,15 @@ import Icon from 'soapbox/components/icon';
|
||||||
import SidebarNavigation from 'soapbox/components/sidebar-navigation';
|
import SidebarNavigation from 'soapbox/components/sidebar-navigation';
|
||||||
import ThumbNavigation from 'soapbox/components/thumb-navigation';
|
import ThumbNavigation from 'soapbox/components/thumb-navigation';
|
||||||
import { Layout } from 'soapbox/components/ui';
|
import { Layout } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig, useFeatures } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useOwnAccount, useSoapboxConfig, useFeatures, useInstance } from 'soapbox/hooks';
|
||||||
import AdminPage from 'soapbox/pages/admin-page';
|
import AdminPage from 'soapbox/pages/admin-page';
|
||||||
import DefaultPage from 'soapbox/pages/default-page';
|
import DefaultPage from 'soapbox/pages/default-page';
|
||||||
// import GroupsPage from 'soapbox/pages/groups_page';
|
|
||||||
// import GroupPage from 'soapbox/pages/group_page';
|
|
||||||
import HomePage from 'soapbox/pages/home-page';
|
import HomePage from 'soapbox/pages/home-page';
|
||||||
import ProfilePage from 'soapbox/pages/profile-page';
|
import ProfilePage from 'soapbox/pages/profile-page';
|
||||||
import RemoteInstancePage from 'soapbox/pages/remote-instance-page';
|
import RemoteInstancePage from 'soapbox/pages/remote-instance-page';
|
||||||
import StatusPage from 'soapbox/pages/status-page';
|
import StatusPage from 'soapbox/pages/status-page';
|
||||||
import { getAccessToken, getVapidKey } from 'soapbox/utils/auth';
|
import { getAccessToken, getVapidKey } from 'soapbox/utils/auth';
|
||||||
import { isStandalone } from 'soapbox/utils/state';
|
import { isStandalone } from 'soapbox/utils/state';
|
||||||
// import GroupSidebarPanel from '../groups/sidebar_panel';
|
|
||||||
|
|
||||||
import BackgroundShapes from './components/background-shapes';
|
import BackgroundShapes from './components/background-shapes';
|
||||||
import Navbar from './components/navbar';
|
import Navbar from './components/navbar';
|
||||||
|
@ -190,18 +187,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
|
||||||
<WrappedRoute path='/messages' page={DefaultPage} component={Conversations} content={children} />
|
<WrappedRoute path='/messages' page={DefaultPage} component={Conversations} content={children} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Gab groups */}
|
|
||||||
{/*
|
|
||||||
<WrappedRoute path='/groups' exact page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'featured' }} />
|
|
||||||
<WrappedRoute path='/groups/create' page={GroupsPage} component={Groups} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} />
|
|
||||||
<WrappedRoute path='/groups/browse/member' page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'member' }} />
|
|
||||||
<WrappedRoute path='/groups/browse/admin' page={GroupsPage} component={Groups} content={children} componentParams={{ activeTab: 'admin' }} />
|
|
||||||
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
|
||||||
<WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
|
|
||||||
<WrappedRoute path='/groups/:id/edit' page={GroupPage} component={GroupEdit} content={children} />
|
|
||||||
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
|
|
||||||
*/}
|
|
||||||
|
|
||||||
{/* Mastodon web routes */}
|
{/* Mastodon web routes */}
|
||||||
<Redirect from='/web/:path1/:path2/:path3' to='/:path1/:path2/:path3' />
|
<Redirect from='/web/:path1/:path2/:path3' to='/:path1/:path2/:path3' />
|
||||||
<Redirect from='/web/:path1/:path2' to='/:path1/:path2' />
|
<Redirect from='/web/:path1/:path2' to='/:path1/:path2' />
|
||||||
|
@ -331,6 +316,7 @@ const UI: React.FC = ({ children }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const [draggingOver, setDraggingOver] = useState<boolean>(false);
|
const [draggingOver, setDraggingOver] = useState<boolean>(false);
|
||||||
const [mobile, setMobile] = useState<boolean>(isMobile(window.innerWidth));
|
const [mobile, setMobile] = useState<boolean>(isMobile(window.innerWidth));
|
||||||
|
@ -347,7 +333,7 @@ const UI: React.FC = ({ children }) => {
|
||||||
|
|
||||||
const dropdownMenuIsOpen = useAppSelector(state => state.dropdown_menu.openId !== null);
|
const dropdownMenuIsOpen = useAppSelector(state => state.dropdown_menu.openId !== null);
|
||||||
const accessToken = useAppSelector(state => getAccessToken(state));
|
const accessToken = useAppSelector(state => getAccessToken(state));
|
||||||
const streamingUrl = useAppSelector(state => state.instance.urls.get('streaming_api'));
|
const streamingUrl = instance.urls.get('streaming_api');
|
||||||
const standalone = useAppSelector(isStandalone);
|
const standalone = useAppSelector(isStandalone);
|
||||||
|
|
||||||
const handleDragEnter = (e: DragEvent) => {
|
const handleDragEnter = (e: DragEvent) => {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { startOnboarding } from 'soapbox/actions/onboarding';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { createAccount, removeStoredVerification } from 'soapbox/actions/verification';
|
import { createAccount, removeStoredVerification } from 'soapbox/actions/verification';
|
||||||
import { Button, Form, FormGroup, Input, Text } from 'soapbox/components/ui';
|
import { Button, Form, FormGroup, Input, Text } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector, useSoapboxConfig } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useInstance, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
import { getRedirectUrl } from 'soapbox/utils/redirect';
|
import { getRedirectUrl } from 'soapbox/utils/redirect';
|
||||||
|
|
||||||
import PasswordIndicator from './components/password-indicator';
|
import PasswordIndicator from './components/password-indicator';
|
||||||
|
@ -32,11 +32,11 @@ const initialState = {
|
||||||
const Registration = () => {
|
const Registration = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const instance = useInstance();
|
||||||
const soapboxConfig = useSoapboxConfig();
|
const soapboxConfig = useSoapboxConfig();
|
||||||
const { links } = soapboxConfig;
|
const { links } = soapboxConfig;
|
||||||
|
|
||||||
const isLoading = useAppSelector((state) => state.verification.isLoading as boolean);
|
const isLoading = useAppSelector((state) => state.verification.isLoading as boolean);
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
|
|
||||||
const [state, setState] = React.useState(initialState);
|
const [state, setState] = React.useState(initialState);
|
||||||
const [shouldRedirect, setShouldRedirect] = React.useState<boolean>(false);
|
const [shouldRedirect, setShouldRedirect] = React.useState<boolean>(false);
|
||||||
|
@ -56,7 +56,7 @@ const Registration = () => {
|
||||||
dispatch(startOnboarding());
|
dispatch(startOnboarding());
|
||||||
dispatch(
|
dispatch(
|
||||||
snackbar.success(
|
snackbar.success(
|
||||||
intl.formatMessage(messages.success, { siteTitle }),
|
intl.formatMessage(messages.success, { siteTitle: instance.title }),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
import { verifyAge } from 'soapbox/actions/verification';
|
import { verifyAge } from 'soapbox/actions/verification';
|
||||||
import { Button, Datepicker, Form, Text } from 'soapbox/components/ui';
|
import { Button, Datepicker, Form, Text } from 'soapbox/components/ui';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
fail: {
|
fail: {
|
||||||
|
@ -24,10 +24,10 @@ function meetsAgeMinimum(birthday: Date, ageMinimum: number) {
|
||||||
const AgeVerification = () => {
|
const AgeVerification = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const instance = useInstance();
|
||||||
|
|
||||||
const isLoading = useAppSelector((state) => state.verification.isLoading) as boolean;
|
const isLoading = useAppSelector((state) => state.verification.isLoading) as boolean;
|
||||||
const ageMinimum = useAppSelector((state) => state.verification.ageMinimum) as any;
|
const ageMinimum = useAppSelector((state) => state.verification.ageMinimum) as any;
|
||||||
const siteTitle = useAppSelector((state) => state.instance.title);
|
|
||||||
|
|
||||||
const [date, setDate] = React.useState('');
|
const [date, setDate] = React.useState('');
|
||||||
const isValid = typeof date === 'object';
|
const isValid = typeof date === 'object';
|
||||||
|
@ -65,7 +65,7 @@ const AgeVerification = () => {
|
||||||
id='age_verification.body'
|
id='age_verification.body'
|
||||||
defaultMessage='{siteTitle} requires users to be at least {ageMinimum} years old to access its platform. Anyone under the age of {ageMinimum} years old cannot access this platform.'
|
defaultMessage='{siteTitle} requires users to be at least {ageMinimum} years old to access its platform. Anyone under the age of {ageMinimum} years old cannot access this platform.'
|
||||||
values={{
|
values={{
|
||||||
siteTitle,
|
siteTitle: instance.title,
|
||||||
ageMinimum,
|
ageMinimum,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -8,11 +8,11 @@ import { openModal } from 'soapbox/actions/modals';
|
||||||
import LandingGradient from 'soapbox/components/landing-gradient';
|
import LandingGradient from 'soapbox/components/landing-gradient';
|
||||||
import SiteLogo from 'soapbox/components/site-logo';
|
import SiteLogo from 'soapbox/components/site-logo';
|
||||||
import { Button, Stack, Text } from 'soapbox/components/ui';
|
import { Button, Stack, Text } from 'soapbox/components/ui';
|
||||||
import { useAppSelector, useOwnAccount } from 'soapbox/hooks';
|
import { useInstance, useOwnAccount } from 'soapbox/hooks';
|
||||||
|
|
||||||
const WaitlistPage = (/* { account } */) => {
|
const WaitlistPage = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const title = useAppSelector((state) => state.instance.title);
|
const instance = useInstance();
|
||||||
|
|
||||||
const me = useOwnAccount();
|
const me = useOwnAccount();
|
||||||
const isSmsVerified = me?.source.get('sms_verified');
|
const isSmsVerified = me?.source.get('sms_verified');
|
||||||
|
@ -59,7 +59,7 @@ const WaitlistPage = (/* { account } */) => {
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='waitlist.body'
|
id='waitlist.body'
|
||||||
defaultMessage='Welcome back to {title}! You were previously placed on our waitlist. Please verify your phone number to receive immediate access to your account!'
|
defaultMessage='Welcome back to {title}! You were previously placed on our waitlist. Please verify your phone number to receive immediate access to your account!'
|
||||||
values={{ title }}
|
values={{ title: instance.title }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ export { useAppSelector } from './useAppSelector';
|
||||||
export { useCompose } from './useCompose';
|
export { useCompose } from './useCompose';
|
||||||
export { useDimensions } from './useDimensions';
|
export { useDimensions } from './useDimensions';
|
||||||
export { useFeatures } from './useFeatures';
|
export { useFeatures } from './useFeatures';
|
||||||
|
export { useInstance } from './useInstance';
|
||||||
export { useLocale } from './useLocale';
|
export { useLocale } from './useLocale';
|
||||||
export { useOnScreen } from './useOnScreen';
|
export { useOnScreen } from './useOnScreen';
|
||||||
export { useOwnAccount } from './useOwnAccount';
|
export { useOwnAccount } from './useOwnAccount';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { getFeatures, Features } from 'soapbox/utils/features';
|
||||||
import { getFeatures } from 'soapbox/utils/features';
|
|
||||||
|
|
||||||
import type { Features } from 'soapbox/utils/features';
|
import { useInstance } from './useInstance';
|
||||||
|
|
||||||
/** Get features for the current instance */
|
/** Get features for the current instance. */
|
||||||
export const useFeatures = (): Features => {
|
export const useFeatures = (): Features => {
|
||||||
return useAppSelector((state) => getFeatures(state.instance));
|
const instance = useInstance();
|
||||||
|
return getFeatures(instance);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
/** Get the Instance for the current backend. */
|
||||||
|
export const useInstance = () => {
|
||||||
|
return useAppSelector((state) => state.instance);
|
||||||
|
};
|
|
@ -1,13 +1,21 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { useAppSelector } from 'soapbox/hooks';
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
import { makeGetAccount } from 'soapbox/selectors';
|
import { makeGetAccount } from 'soapbox/selectors';
|
||||||
|
|
||||||
import type { Account } from 'soapbox/types/entities';
|
import type { Account } from 'soapbox/types/entities';
|
||||||
|
|
||||||
// FIXME: There is no reason this selector shouldn't be global accross the whole app
|
/** Get the logged-in account from the store, if any. */
|
||||||
// FIXME: getAccount() has the wrong type??
|
|
||||||
const getAccount: (state: any, accountId: any) => any = makeGetAccount();
|
|
||||||
|
|
||||||
/** Get the logged-in account from the store, if any */
|
|
||||||
export const useOwnAccount = (): Account | null => {
|
export const useOwnAccount = (): Account | null => {
|
||||||
return useAppSelector((state) => getAccount(state, state.me));
|
const getAccount = useCallback(makeGetAccount(), []);
|
||||||
|
|
||||||
|
return useAppSelector((state) => {
|
||||||
|
const { me } = state;
|
||||||
|
|
||||||
|
if (typeof me === 'string') {
|
||||||
|
return getAccount(state, me);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue