kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Fix Bundle type errors, remove bundle error components, remove group slug support
rodzic
0f10922c3d
commit
1b213452b7
|
@ -1,62 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { useGroupLookup } from 'soapbox/api/hooks';
|
|
||||||
import ColumnLoading from 'soapbox/features/ui/components/column-loading';
|
|
||||||
|
|
||||||
import { Layout } from '../ui';
|
|
||||||
|
|
||||||
interface IGroupLookup {
|
|
||||||
params: {
|
|
||||||
groupSlug: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMaybeGroupLookup {
|
|
||||||
params?: {
|
|
||||||
groupSlug?: string;
|
|
||||||
groupId?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function GroupLookupHoc(Component: React.ComponentType<{ params: { groupId: string } }>) {
|
|
||||||
const GroupLookup: React.FC<IGroupLookup> = (props) => {
|
|
||||||
const { entity: group } = useGroupLookup(props.params.groupSlug);
|
|
||||||
|
|
||||||
if (!group) return (
|
|
||||||
<>
|
|
||||||
<Layout.Main>
|
|
||||||
<ColumnLoading />
|
|
||||||
</Layout.Main>
|
|
||||||
|
|
||||||
<Layout.Aside />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const newProps = {
|
|
||||||
...props,
|
|
||||||
params: {
|
|
||||||
...props.params,
|
|
||||||
id: group.id,
|
|
||||||
groupId: group.id,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Component {...newProps} />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const MaybeGroupLookup: React.FC<IMaybeGroupLookup> = (props) => {
|
|
||||||
const { params } = props;
|
|
||||||
|
|
||||||
if (params?.groupId) {
|
|
||||||
return <Component {...props} params={{ ...params, groupId: params.groupId }} />;
|
|
||||||
} else {
|
|
||||||
return <GroupLookup {...props} params={{ ...params, groupSlug: params?.groupSlug || '' }} />;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return MaybeGroupLookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GroupLookupHoc;
|
|
|
@ -1,11 +0,0 @@
|
||||||
type HOC<P, R> = (Component: React.ComponentType<P>) => React.ComponentType<R>
|
|
||||||
type AsyncComponent<P> = () => Promise<{ default: React.ComponentType<P> }>
|
|
||||||
|
|
||||||
const withHoc = <P, R>(asyncComponent: AsyncComponent<P>, hoc: HOC<P, R>) => {
|
|
||||||
return async () => {
|
|
||||||
const { default: component } = await asyncComponent();
|
|
||||||
return { default: hoc(component) };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withHoc;
|
|
|
@ -1,39 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
|
||||||
|
|
||||||
import { Column, Stack, Text, IconButton } from 'soapbox/components/ui';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
|
|
||||||
body: { id: 'bundle_column_error.body', defaultMessage: 'Something went wrong while loading this page.' },
|
|
||||||
retry: { id: 'bundle_column_error.retry', defaultMessage: 'Try again' },
|
|
||||||
});
|
|
||||||
|
|
||||||
interface IBundleColumnError {
|
|
||||||
onRetry: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BundleColumnError: React.FC<IBundleColumnError> = ({ onRetry }) => {
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const handleRetry = () => {
|
|
||||||
onRetry();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Column label={intl.formatMessage(messages.title)}>
|
|
||||||
<Stack space={4} alignItems='center' justifyContent='center' className='min-h-[160px] rounded-lg p-10'>
|
|
||||||
<IconButton
|
|
||||||
iconClassName='h-10 w-10'
|
|
||||||
title={intl.formatMessage(messages.retry)}
|
|
||||||
src={require('@tabler/icons/refresh.svg')}
|
|
||||||
onClick={handleRetry}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Text align='center' theme='muted'>{intl.formatMessage(messages.body)}</Text>
|
|
||||||
</Stack>
|
|
||||||
</Column>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BundleColumnError;
|
|
|
@ -1,35 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
|
||||||
|
|
||||||
import { Modal } from 'soapbox/components/ui';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this modal.' },
|
|
||||||
retry: { id: 'bundle_modal_error.retry', defaultMessage: 'Try again' },
|
|
||||||
close: { id: 'bundle_modal_error.close', defaultMessage: 'Close' },
|
|
||||||
});
|
|
||||||
|
|
||||||
interface IBundleModalError {
|
|
||||||
onRetry: () => void;
|
|
||||||
onClose: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BundleModalError: React.FC<IBundleModalError> = ({ onRetry, onClose }) => {
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const handleRetry = () => {
|
|
||||||
onRetry();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={intl.formatMessage(messages.error)}
|
|
||||||
confirmationAction={onClose}
|
|
||||||
confirmationText={intl.formatMessage(messages.close)}
|
|
||||||
secondaryAction={handleRetry}
|
|
||||||
secondaryText={intl.formatMessage(messages.retry)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BundleModalError;
|
|
|
@ -40,12 +40,10 @@ import {
|
||||||
|
|
||||||
import BundleContainer from '../containers/bundle-container';
|
import BundleContainer from '../containers/bundle-container';
|
||||||
|
|
||||||
import { BundleProps } from './bundle';
|
|
||||||
import BundleModalError from './bundle-modal-error';
|
|
||||||
import ModalLoading from './modal-loading';
|
import ModalLoading from './modal-loading';
|
||||||
|
|
||||||
/* eslint sort-keys: "error" */
|
/* eslint sort-keys: "error" */
|
||||||
const MODAL_COMPONENTS = {
|
const MODAL_COMPONENTS: Record<string, React.LazyExoticComponent<any>> = {
|
||||||
'ACCOUNT_MODERATION': AccountModerationModal,
|
'ACCOUNT_MODERATION': AccountModerationModal,
|
||||||
'ACTIONS': ActionsModal,
|
'ACTIONS': ActionsModal,
|
||||||
'BIRTHDAYS': BirthdaysModal,
|
'BIRTHDAYS': BirthdaysModal,
|
||||||
|
@ -108,10 +106,6 @@ export default class ModalRoot extends React.PureComponent<IModalRoot> {
|
||||||
return !['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].includes(modalId) ? <ModalLoading /> : null;
|
return !['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].includes(modalId) ? <ModalLoading /> : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
renderError: React.ComponentType<{ onRetry: (props?: BundleProps) => void }> = (props) => {
|
|
||||||
return <BundleModalError {...props} onClose={this.onClickClose} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
onClickClose = (_?: ModalType) => {
|
onClickClose = (_?: ModalType) => {
|
||||||
const { onClose, type } = this.props;
|
const { onClose, type } = this.props;
|
||||||
onClose(type);
|
onClose(type);
|
||||||
|
@ -124,7 +118,7 @@ export default class ModalRoot extends React.PureComponent<IModalRoot> {
|
||||||
return (
|
return (
|
||||||
<Base onClose={this.onClickClose} type={type}>
|
<Base onClose={this.onClickClose} type={type}>
|
||||||
{visible && (
|
{visible && (
|
||||||
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
|
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} renderDelay={200}>
|
||||||
{(SpecificComponent) => <SpecificComponent {...props} onClose={this.onClickClose} />}
|
{(SpecificComponent) => <SpecificComponent {...props} onClose={this.onClickClose} />}
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -15,8 +15,6 @@ import { fetchSuggestionsForTimeline } from 'soapbox/actions/suggestions';
|
||||||
import { expandHomeTimeline } from 'soapbox/actions/timelines';
|
import { expandHomeTimeline } from 'soapbox/actions/timelines';
|
||||||
import { useUserStream } from 'soapbox/api/hooks';
|
import { useUserStream } from 'soapbox/api/hooks';
|
||||||
import { useSignerStream } from 'soapbox/api/hooks/nostr/useSignerStream';
|
import { useSignerStream } from 'soapbox/api/hooks/nostr/useSignerStream';
|
||||||
import GroupLookupHoc from 'soapbox/components/hoc/group-lookup-hoc';
|
|
||||||
import withHoc from 'soapbox/components/hoc/with-hoc';
|
|
||||||
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';
|
||||||
|
@ -147,16 +145,6 @@ import { WrappedRoute } from './util/react-router-helpers';
|
||||||
// Without this it ends up in ~8 very commonly used bundles.
|
// Without this it ends up in ~8 very commonly used bundles.
|
||||||
import 'soapbox/components/status';
|
import 'soapbox/components/status';
|
||||||
|
|
||||||
const GroupTagsSlug = withHoc(GroupTags as any, GroupLookupHoc);
|
|
||||||
const GroupTagTimelineSlug = withHoc(GroupTagTimeline as any, GroupLookupHoc);
|
|
||||||
const GroupTimelineSlug = withHoc(GroupTimeline as any, GroupLookupHoc);
|
|
||||||
const GroupMembersSlug = withHoc(GroupMembers as any, GroupLookupHoc);
|
|
||||||
const GroupGallerySlug = withHoc(GroupGallery as any, GroupLookupHoc);
|
|
||||||
const ManageGroupSlug = withHoc(ManageGroup as any, GroupLookupHoc);
|
|
||||||
const EditGroupSlug = withHoc(EditGroup as any, GroupLookupHoc);
|
|
||||||
const GroupBlockedMembersSlug = withHoc(GroupBlockedMembers as any, GroupLookupHoc);
|
|
||||||
const GroupMembershipRequestsSlug = withHoc(GroupMembershipRequests as any, GroupLookupHoc);
|
|
||||||
|
|
||||||
interface ISwitchingColumnsArea {
|
interface ISwitchingColumnsArea {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
@ -310,18 +298,6 @@ const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = ({ children }) =>
|
||||||
{features.groups && <WrappedRoute path='/groups/:groupId/manage/requests' exact page={ManageGroupsPage} component={GroupMembershipRequests} content={children} />}
|
{features.groups && <WrappedRoute path='/groups/:groupId/manage/requests' exact page={ManageGroupsPage} component={GroupMembershipRequests} content={children} />}
|
||||||
{features.groups && <WrappedRoute path='/groups/:groupId/posts/:statusId' exact page={StatusPage} component={Status} content={children} />}
|
{features.groups && <WrappedRoute path='/groups/:groupId/posts/:statusId' exact page={StatusPage} component={Status} content={children} />}
|
||||||
|
|
||||||
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tags' exact page={GroupPage} component={GroupTagsSlug} content={children} />}
|
|
||||||
{features.groupsTags && <WrappedRoute path='/group/:groupSlug/tag/:tagId' exact page={GroupsPendingPage} component={GroupTagTimelineSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug' publicRoute exact page={GroupPage} component={GroupTimelineSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/members' exact page={GroupPage} component={GroupMembersSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/media' publicRoute={!authenticatedProfile} component={GroupGallerySlug} page={GroupPage} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/manage' exact page={ManageGroupsPage} component={ManageGroupSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/manage/edit' exact page={ManageGroupsPage} component={EditGroupSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/manage/blocks' exact page={ManageGroupsPage} component={GroupBlockedMembersSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/manage/requests' exact page={ManageGroupsPage} component={GroupMembershipRequestsSlug} content={children} />}
|
|
||||||
{features.groups && <WrappedRoute path='/group/:groupSlug/posts/:statusId' exact page={StatusPage} component={Status} content={children} />}
|
|
||||||
{features.groups && <Redirect from='/group/:groupSlug/statuses/:statusId' to='/group/:groupSlug/posts/:statusId' />}
|
|
||||||
|
|
||||||
<WrappedRoute path='/statuses/new' page={DefaultPage} component={NewStatus} content={children} exact />
|
<WrappedRoute path='/statuses/new' page={DefaultPage} component={NewStatus} content={children} exact />
|
||||||
<WrappedRoute path='/statuses/:statusId' exact page={StatusPage} component={Status} content={children} />
|
<WrappedRoute path='/statuses/:statusId' exact page={StatusPage} component={Status} content={children} />
|
||||||
{features.scheduledStatuses && <WrappedRoute path='/scheduled_statuses' page={DefaultPage} component={ScheduledStatuses} content={children} />}
|
{features.scheduledStatuses && <WrappedRoute path='/scheduled_statuses' page={DefaultPage} component={ScheduledStatuses} content={children} />}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { Redirect, Route, useHistory, RouteProps, RouteComponentProps, match as
|
||||||
import { Layout } from 'soapbox/components/ui';
|
import { Layout } from 'soapbox/components/ui';
|
||||||
import { useOwnAccount, useSettings } from 'soapbox/hooks';
|
import { useOwnAccount, useSettings } from 'soapbox/hooks';
|
||||||
|
|
||||||
import BundleColumnError from '../components/bundle-column-error';
|
|
||||||
import ColumnForbidden from '../components/column-forbidden';
|
import ColumnForbidden from '../components/column-forbidden';
|
||||||
import ColumnLoading from '../components/column-loading';
|
import ColumnLoading from '../components/column-loading';
|
||||||
import ColumnsArea from '../components/columns-area';
|
import ColumnsArea from '../components/columns-area';
|
||||||
|
@ -48,7 +47,7 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
const renderComponent = ({ match }: RouteComponentProps) => {
|
const renderComponent = ({ match }: RouteComponentProps) => {
|
||||||
if (Page) {
|
if (Page) {
|
||||||
return (
|
return (
|
||||||
<BundleContainer fetchComponent={component} loading={renderLoading} error={renderError}>
|
<BundleContainer fetchComponent={component} loading={renderLoading}>
|
||||||
{Component =>
|
{Component =>
|
||||||
(
|
(
|
||||||
<Page params={match.params} layout={layout} {...componentParams}>
|
<Page params={match.params} layout={layout} {...componentParams}>
|
||||||
|
@ -63,7 +62,7 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BundleContainer fetchComponent={component} loading={renderLoading} error={renderError}>
|
<BundleContainer fetchComponent={component} loading={renderLoading}>
|
||||||
{Component =>
|
{Component =>
|
||||||
(
|
(
|
||||||
<ColumnsArea layout={layout}>
|
<ColumnsArea layout={layout}>
|
||||||
|
@ -89,7 +88,6 @@ const WrappedRoute: React.FC<IWrappedRoute> = ({
|
||||||
|
|
||||||
const renderLoading = () => renderWithLayout(<ColumnLoading />);
|
const renderLoading = () => renderWithLayout(<ColumnLoading />);
|
||||||
const renderForbidden = () => renderWithLayout(<ColumnForbidden />);
|
const renderForbidden = () => renderWithLayout(<ColumnForbidden />);
|
||||||
const renderError = (props: any) => renderWithLayout(<BundleColumnError {...props} />);
|
|
||||||
|
|
||||||
const loginRedirect = () => {
|
const loginRedirect = () => {
|
||||||
const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`);
|
const actualUrl = encodeURIComponent(`${history.location.pathname}${history.location.search}`);
|
||||||
|
|
|
@ -31,7 +31,7 @@ const EventPage: React.FC<IEventPage> = ({ params, children }) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const statusId = params?.statusId!;
|
const statusId = params?.statusId!;
|
||||||
|
|
||||||
const status = useAppSelector(state => getStatus(state, { id: statusId }));
|
const status = useAppSelector(state => getStatus(state, { id: statusId }) || undefined);
|
||||||
|
|
||||||
const event = status?.event;
|
const event = status?.event;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||||
import { useRouteMatch } from 'react-router-dom';
|
import { useRouteMatch } from 'react-router-dom';
|
||||||
|
|
||||||
import { useGroup, useGroupMembershipRequests } from 'soapbox/api/hooks';
|
import { useGroup, useGroupMembershipRequests } from 'soapbox/api/hooks';
|
||||||
import GroupLookupHoc from 'soapbox/components/hoc/group-lookup-hoc';
|
|
||||||
import { Column, Icon, Layout, Stack, Text, Tabs } from 'soapbox/components/ui';
|
import { Column, Icon, Layout, Stack, Text, Tabs } from 'soapbox/components/ui';
|
||||||
import GroupHeader from 'soapbox/features/group/components/group-header';
|
import GroupHeader from 'soapbox/features/group/components/group-header';
|
||||||
import LinkFooter from 'soapbox/features/ui/components/link-footer';
|
import LinkFooter from 'soapbox/features/ui/components/link-footer';
|
||||||
|
@ -191,4 +190,4 @@ const GroupPage: React.FC<IGroupPage> = ({ params, children }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GroupLookupHoc(GroupPage as any) as any;
|
export default GroupPage;
|
||||||
|
|
|
@ -13,15 +13,15 @@ import { federationRestrictionsDisclosed } from 'soapbox/utils/state';
|
||||||
import { Layout } from '../components/ui';
|
import { Layout } from '../components/ui';
|
||||||
|
|
||||||
interface IRemoteInstancePage {
|
interface IRemoteInstancePage {
|
||||||
params: {
|
params?: {
|
||||||
instance: string;
|
instance?: string;
|
||||||
};
|
};
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Page for viewing a remote instance timeline. */
|
/** Page for viewing a remote instance timeline. */
|
||||||
const RemoteInstancePage: React.FC<IRemoteInstancePage> = ({ children, params }) => {
|
const RemoteInstancePage: React.FC<IRemoteInstancePage> = ({ children, params }) => {
|
||||||
const host = params.instance;
|
const host = params!.instance!;
|
||||||
|
|
||||||
const { account } = useOwnAccount();
|
const { account } = useOwnAccount();
|
||||||
const disclosed = useAppSelector(federationRestrictionsDisclosed);
|
const disclosed = useAppSelector(federationRestrictionsDisclosed);
|
||||||
|
|
Ładowanie…
Reference in New Issue