Merge commit 'd0502ac3c1630e281fda5492cbc28390262b0aeb' into glitch-soc/merge-upstream
This commit is contained in:
commit
d62a7775b5
69 files changed
+1090
-284
No files matched your search
@@ -162,11 +162,13 @@ export const AccountHeader: React.FC<{
|
||||
{!suspendedOrHidden && (
|
||||
<div className='account__header__extra'>
|
||||
<div className='account__header__bio'>
|
||||
{me && account.id !== me && isRedesignEnabled() ? (
|
||||
<AccountNoteRedesign accountId={accountId} />
|
||||
) : (
|
||||
<AccountNote accountId={accountId} />
|
||||
)}
|
||||
{me &&
|
||||
account.id !== me &&
|
||||
(isRedesignEnabled() ? (
|
||||
<AccountNoteRedesign accountId={accountId} />
|
||||
) : (
|
||||
<AccountNote accountId={accountId} />
|
||||
))}
|
||||
|
||||
<AccountBio
|
||||
accountId={accountId}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { FC } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import type { NavLinkProps } from 'react-router-dom';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { isRedesignEnabled } from '../common';
|
||||
@@ -12,7 +13,7 @@ export const AccountTabs: FC<{ acct: string }> = ({ acct }) => {
|
||||
if (isRedesignEnabled()) {
|
||||
return (
|
||||
<div className={classes.tabs}>
|
||||
<NavLink exact to={`/@${acct}`}>
|
||||
<NavLink isActive={isActive} to={`/@${acct}`}>
|
||||
<FormattedMessage id='account.activity' defaultMessage='Activity' />
|
||||
</NavLink>
|
||||
<NavLink exact to={`/@${acct}/media`}>
|
||||
@@ -44,3 +45,7 @@ export const AccountTabs: FC<{ acct: string }> = ({ acct }) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const isActive: Required<NavLinkProps>['isActive'] = (match, location) =>
|
||||
match?.url === location.pathname ||
|
||||
(!!match?.url && location.pathname.startsWith(`${match.url}/tagged/`));
|
||||
@@ -0,0 +1,124 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import type { FC, MouseEventHandler } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { useParams } from 'react-router';
|
||||
|
||||
import { fetchFeaturedTags } from '@/mastodon/actions/featured_tags';
|
||||
import { useAppHistory } from '@/mastodon/components/router';
|
||||
import { Tag } from '@/mastodon/components/tags/tag';
|
||||
import { useOverflow } from '@/mastodon/hooks/useOverflow';
|
||||
import { selectAccountFeaturedTags } from '@/mastodon/selectors/accounts';
|
||||
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
|
||||
|
||||
import { useFilters } from '../hooks/useFilters';
|
||||
|
||||
import classes from './styles.module.scss';
|
||||
|
||||
export const FeaturedTags: FC<{ accountId: string }> = ({ accountId }) => {
|
||||
// Fetch tags.
|
||||
const featuredTags = useAppSelector((state) =>
|
||||
selectAccountFeaturedTags(state, accountId),
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
useEffect(() => {
|
||||
void dispatch(fetchFeaturedTags({ accountId }));
|
||||
}, [accountId, dispatch]);
|
||||
|
||||
// Get list of tags with overflow handling.
|
||||
const [showOverflow, setShowOverflow] = useState(false);
|
||||
const { hiddenCount, wrapperRef, listRef, hiddenIndex, maxWidth } =
|
||||
useOverflow();
|
||||
|
||||
// Handle whether to show all tags.
|
||||
const handleOverflowClick: MouseEventHandler = useCallback(() => {
|
||||
setShowOverflow(true);
|
||||
}, []);
|
||||
|
||||
const { onClick, currentTag } = useTagNavigate();
|
||||
|
||||
if (featuredTags.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.tagsWrapper} ref={wrapperRef}>
|
||||
<div
|
||||
className={classNames(
|
||||
classes.tagsList,
|
||||
showOverflow && classes.tagsListShowAll,
|
||||
)}
|
||||
style={{ maxWidth }}
|
||||
ref={listRef}
|
||||
>
|
||||
{featuredTags.map(({ id, name }, index) => (
|
||||
<Tag
|
||||
name={name}
|
||||
key={id}
|
||||
inert={hiddenIndex > 0 && index >= hiddenIndex ? '' : undefined}
|
||||
onClick={onClick}
|
||||
active={currentTag === name}
|
||||
data-name={name}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{!showOverflow && hiddenCount > 0 && (
|
||||
<Tag
|
||||
onClick={handleOverflowClick}
|
||||
name={
|
||||
<FormattedMessage
|
||||
id='featured_tags.more_items'
|
||||
defaultMessage='+{count}'
|
||||
values={{ count: hiddenCount }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function useTagNavigate() {
|
||||
// Get current account, tag, and filters.
|
||||
const { acct, tagged } = useParams<{ acct: string; tagged?: string }>();
|
||||
const { boosts, replies } = useFilters();
|
||||
|
||||
const history = useAppHistory();
|
||||
|
||||
const handleTagClick: MouseEventHandler<HTMLButtonElement> = useCallback(
|
||||
(event) => {
|
||||
const name = event.currentTarget.getAttribute('data-name');
|
||||
if (!name || !acct) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine whether to navigate to or from the tag.
|
||||
let url = `/@${acct}/tagged/${encodeURIComponent(name)}`;
|
||||
if (name === tagged) {
|
||||
url = `/@${acct}`;
|
||||
}
|
||||
|
||||
// Append filters.
|
||||
const params = new URLSearchParams();
|
||||
if (boosts) {
|
||||
params.append('boosts', '1');
|
||||
}
|
||||
if (replies) {
|
||||
params.append('replies', '1');
|
||||
}
|
||||
|
||||
history.push({
|
||||
pathname: url,
|
||||
search: params.toString(),
|
||||
});
|
||||
},
|
||||
[acct, tagged, boosts, replies, history],
|
||||
);
|
||||
|
||||
return {
|
||||
onClick: handleTagClick,
|
||||
currentTag: tagged,
|
||||
};
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import { AccountHeader } from '../components/account_header';
|
||||
import { LimitedAccountHint } from '../components/limited_account_hint';
|
||||
import { useFilters } from '../hooks/useFilters';
|
||||
|
||||
import { FeaturedTags } from './featured_tags';
|
||||
import { AccountFilters } from './filters';
|
||||
|
||||
const emptyList = ImmutableList<string>();
|
||||
@@ -135,6 +136,7 @@ const Prepend: FC<{
|
||||
<>
|
||||
<AccountHeader accountId={accountId} hideTabs />
|
||||
<AccountFilters />
|
||||
<FeaturedTags accountId={accountId} />
|
||||
<FeaturedCarousel accountId={accountId} tagged={tagged} />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -35,3 +35,25 @@
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.tagsWrapper {
|
||||
margin: 0 24px 8px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tagsList {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tagsListShowAll {
|
||||
flex-wrap: wrap;
|
||||
overflow: visible;
|
||||
max-width: none !important;
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
import { useCallback, useState, useEffect } from 'react';
|
||||
|
||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
|
||||
import { isFulfilled } from '@reduxjs/toolkit';
|
||||
|
||||
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
||||
import type {
|
||||
ApiCollectionJSON,
|
||||
ApiCreateCollectionPayload,
|
||||
ApiUpdateCollectionPayload,
|
||||
} from 'mastodon/api_types/collections';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { Column } from 'mastodon/components/column';
|
||||
import { ColumnHeader } from 'mastodon/components/column_header';
|
||||
import { TextAreaField, ToggleField } from 'mastodon/components/form_fields';
|
||||
import { TextInputField } from 'mastodon/components/form_fields/text_input_field';
|
||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import {
|
||||
createCollection,
|
||||
fetchCollection,
|
||||
updateCollection,
|
||||
} from 'mastodon/reducers/slices/collections';
|
||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
||||
const messages = defineMessages({
|
||||
edit: { id: 'column.edit_collection', defaultMessage: 'Edit collection' },
|
||||
create: {
|
||||
id: 'column.create_collection',
|
||||
defaultMessage: 'Create collection',
|
||||
},
|
||||
});
|
||||
|
||||
const CollectionSettings: React.FC<{
|
||||
collection?: ApiCollectionJSON | null;
|
||||
}> = ({ collection }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const history = useHistory();
|
||||
|
||||
const {
|
||||
id,
|
||||
name: initialName = '',
|
||||
description: initialDescription = '',
|
||||
tag,
|
||||
discoverable: initialDiscoverable = true,
|
||||
sensitive: initialSensitive = false,
|
||||
} = collection ?? {};
|
||||
|
||||
const [name, setName] = useState(initialName);
|
||||
const [description, setDescription] = useState(initialDescription);
|
||||
const [topic, setTopic] = useState(tag?.name ?? '');
|
||||
const [discoverable] = useState(initialDiscoverable);
|
||||
const [sensitive, setSensitive] = useState(initialSensitive);
|
||||
|
||||
const handleNameChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setName(event.target.value);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleDescriptionChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setDescription(event.target.value);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleTopicChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTopic(event.target.value);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleSensitiveChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSensitive(event.target.checked);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleSubmit = useCallback(
|
||||
(e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (id) {
|
||||
const payload: ApiUpdateCollectionPayload = {
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
tag_name: topic,
|
||||
discoverable,
|
||||
sensitive,
|
||||
};
|
||||
|
||||
void dispatch(updateCollection({ payload })).then(() => {
|
||||
history.push(`/collections`);
|
||||
});
|
||||
} else {
|
||||
const payload: ApiCreateCollectionPayload = {
|
||||
name,
|
||||
description,
|
||||
discoverable,
|
||||
sensitive,
|
||||
};
|
||||
if (topic) {
|
||||
payload.tag_name = topic;
|
||||
}
|
||||
|
||||
void dispatch(
|
||||
createCollection({
|
||||
payload,
|
||||
}),
|
||||
).then((result) => {
|
||||
if (isFulfilled(result)) {
|
||||
history.replace(
|
||||
`/collections/${result.payload.collection.id}/edit`,
|
||||
);
|
||||
history.push(`/collections`);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
[id, dispatch, name, description, topic, discoverable, sensitive, history],
|
||||
);
|
||||
|
||||
return (
|
||||
<form className='simple_form app-form' onSubmit={handleSubmit}>
|
||||
<div className='fields-group'>
|
||||
<TextInputField
|
||||
required
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='collections.collection_name'
|
||||
defaultMessage='Name'
|
||||
/>
|
||||
}
|
||||
hint={
|
||||
<FormattedMessage
|
||||
id='collections.name_length_hint'
|
||||
defaultMessage='40 characters limit'
|
||||
/>
|
||||
}
|
||||
value={name}
|
||||
onChange={handleNameChange}
|
||||
maxLength={40}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='fields-group'>
|
||||
<TextAreaField
|
||||
required
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='collections.collection_description'
|
||||
defaultMessage='Description'
|
||||
/>
|
||||
}
|
||||
hint={
|
||||
<FormattedMessage
|
||||
id='collections.description_length_hint'
|
||||
defaultMessage='100 characters limit'
|
||||
/>
|
||||
}
|
||||
value={description}
|
||||
onChange={handleDescriptionChange}
|
||||
maxLength={100}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='fields-group'>
|
||||
<TextInputField
|
||||
required={false}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='collections.collection_topic'
|
||||
defaultMessage='Topic'
|
||||
/>
|
||||
}
|
||||
hint={
|
||||
<FormattedMessage
|
||||
id='collections.topic_hint'
|
||||
defaultMessage='Add a hashtag that helps others understand the main topic of this collection.'
|
||||
/>
|
||||
}
|
||||
value={topic}
|
||||
onChange={handleTopicChange}
|
||||
maxLength={40}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='fields-group'>
|
||||
<ToggleField
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='collections.mark_as_sensitive'
|
||||
defaultMessage='Mark as sensitive'
|
||||
/>
|
||||
}
|
||||
hint={
|
||||
<FormattedMessage
|
||||
id='collections.mark_as_sensitive_hint'
|
||||
defaultMessage="Hides the collection's description and accounts behind a content warning. The collection name will still be visible."
|
||||
/>
|
||||
}
|
||||
checked={sensitive}
|
||||
onChange={handleSensitiveChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='actions'>
|
||||
<Button type='submit'>
|
||||
{id ? (
|
||||
<FormattedMessage id='lists.save' defaultMessage='Save' />
|
||||
) : (
|
||||
<FormattedMessage id='lists.create' defaultMessage='Create' />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export const CollectionEditorPage: React.FC<{
|
||||
multiColumn?: boolean;
|
||||
}> = ({ multiColumn }) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const { id } = useParams<{ id?: string }>();
|
||||
const collection = useAppSelector((state) =>
|
||||
id ? state.collections.collections[id] : undefined,
|
||||
);
|
||||
const isEditMode = !!id;
|
||||
const isLoading = isEditMode && !collection;
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
void dispatch(fetchCollection({ collectionId: id }));
|
||||
}
|
||||
}, [dispatch, id]);
|
||||
|
||||
const pageTitle = intl.formatMessage(id ? messages.edit : messages.create);
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn} label={pageTitle}>
|
||||
<ColumnHeader
|
||||
title={pageTitle}
|
||||
icon='list-ul'
|
||||
iconComponent={ListAltIcon}
|
||||
multiColumn={multiColumn}
|
||||
showBackButton
|
||||
/>
|
||||
|
||||
<div className='scrollable'>
|
||||
{isLoading ? (
|
||||
<LoadingIndicator />
|
||||
) : (
|
||||
<CollectionSettings collection={collection} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Helmet>
|
||||
<title>{pageTitle}</title>
|
||||
<meta name='robots' content='noindex' />
|
||||
</Helmet>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
@@ -16,7 +16,6 @@ import { Dropdown } from 'mastodon/components/dropdown_menu';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import {
|
||||
createCollection,
|
||||
fetchAccountCollections,
|
||||
selectMyCollections,
|
||||
} from 'mastodon/reducers/slices/collections';
|
||||
@@ -49,13 +48,14 @@ const ListItem: React.FC<{
|
||||
const handleDeleteClick = useCallback(() => {
|
||||
dispatch(
|
||||
openModal({
|
||||
modalType: 'CONFIRM_DELETE_LIST',
|
||||
modalType: 'CONFIRM_DELETE_COLLECTION',
|
||||
modalProps: {
|
||||
listId: id,
|
||||
name,
|
||||
id,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}, [dispatch, id]);
|
||||
}, [dispatch, id, name]);
|
||||
|
||||
const menu = useMemo(
|
||||
() => [
|
||||
@@ -67,7 +67,7 @@ const ListItem: React.FC<{
|
||||
|
||||
return (
|
||||
<div className='lists__item'>
|
||||
<Link to={`/collections/${id}`} className='lists__item__title'>
|
||||
<Link to={`/collections/${id}/edit`} className='lists__item__title'>
|
||||
<span>{name}</span>
|
||||
</Link>
|
||||
|
||||
@@ -94,24 +94,6 @@ export const Collections: React.FC<{
|
||||
void dispatch(fetchAccountCollections({ accountId: me }));
|
||||
}, [dispatch, me]);
|
||||
|
||||
const addDummyCollection = useCallback(
|
||||
(event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
|
||||
void dispatch(
|
||||
createCollection({
|
||||
payload: {
|
||||
name: 'Test Collection',
|
||||
description: 'A useful test collection',
|
||||
discoverable: true,
|
||||
sensitive: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
},
|
||||
[dispatch],
|
||||
);
|
||||
|
||||
const emptyMessage =
|
||||
status === 'error' ? (
|
||||
<FormattedMessage
|
||||
@@ -152,7 +134,6 @@ export const Collections: React.FC<{
|
||||
className='column-header__button'
|
||||
title={intl.formatMessage(messages.create)}
|
||||
aria-label={intl.formatMessage(messages.create)}
|
||||
onClick={addDummyCollection}
|
||||
>
|
||||
<Icon id='plus' icon={AddIcon} />
|
||||
</Link>
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
|
||||
import { useHistory } from 'react-router';
|
||||
|
||||
import { deleteCollection } from 'mastodon/reducers/slices/collections';
|
||||
import { useAppDispatch } from 'mastodon/store';
|
||||
|
||||
import type { BaseConfirmationModalProps } from './confirmation_modal';
|
||||
import { ConfirmationModal } from './confirmation_modal';
|
||||
|
||||
const messages = defineMessages({
|
||||
deleteListTitle: {
|
||||
id: 'confirmations.delete_collection.title',
|
||||
defaultMessage: 'Delete "{name}"?',
|
||||
},
|
||||
deleteListMessage: {
|
||||
id: 'confirmations.delete_collection.message',
|
||||
defaultMessage: 'This action cannot be undone.',
|
||||
},
|
||||
deleteListConfirm: {
|
||||
id: 'confirmations.delete_collection.confirm',
|
||||
defaultMessage: 'Delete',
|
||||
},
|
||||
});
|
||||
|
||||
export const ConfirmDeleteCollectionModal: React.FC<
|
||||
{
|
||||
id: string;
|
||||
name: string;
|
||||
} & BaseConfirmationModalProps
|
||||
> = ({ id, name, onClose }) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const history = useHistory();
|
||||
|
||||
const onConfirm = useCallback(() => {
|
||||
void dispatch(deleteCollection({ collectionId: id }));
|
||||
history.push('/collections');
|
||||
}, [dispatch, history, id]);
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={intl.formatMessage(messages.deleteListTitle, {
|
||||
name,
|
||||
})}
|
||||
message={intl.formatMessage(messages.deleteListMessage)}
|
||||
confirm={intl.formatMessage(messages.deleteListConfirm)}
|
||||
onConfirm={onConfirm}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
export { ConfirmationModal } from './confirmation_modal';
|
||||
export { ConfirmDeleteStatusModal } from './delete_status';
|
||||
export { ConfirmDeleteListModal } from './delete_list';
|
||||
export { ConfirmDeleteCollectionModal } from './delete_collection';
|
||||
export {
|
||||
ConfirmReplyModal,
|
||||
ConfirmEditStatusModal,
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
ConfirmationModal,
|
||||
ConfirmDeleteStatusModal,
|
||||
ConfirmDeleteListModal,
|
||||
ConfirmDeleteCollectionModal,
|
||||
ConfirmReplyModal,
|
||||
ConfirmEditStatusModal,
|
||||
ConfirmUnblockModal,
|
||||
@@ -57,6 +58,7 @@ export const MODAL_COMPONENTS = {
|
||||
'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
|
||||
'CONFIRM_DELETE_STATUS': () => Promise.resolve({ default: ConfirmDeleteStatusModal }),
|
||||
'CONFIRM_DELETE_LIST': () => Promise.resolve({ default: ConfirmDeleteListModal }),
|
||||
'CONFIRM_DELETE_COLLECTION': () => Promise.resolve({ default: ConfirmDeleteCollectionModal }),
|
||||
'CONFIRM_REPLY': () => Promise.resolve({ default: ConfirmReplyModal }),
|
||||
'CONFIRM_EDIT_STATUS': () => Promise.resolve({ default: ConfirmEditStatusModal }),
|
||||
'CONFIRM_UNBLOCK': () => Promise.resolve({ default: ConfirmUnblockModal }),
|
||||
|
||||
@@ -64,6 +64,7 @@ import {
|
||||
ListEdit,
|
||||
ListMembers,
|
||||
Collections,
|
||||
CollectionsEditor,
|
||||
Blocks,
|
||||
DomainBlocks,
|
||||
Mutes,
|
||||
@@ -229,6 +230,12 @@ class SwitchingColumnsArea extends PureComponent {
|
||||
<WrappedRoute path='/followed_tags' component={FollowedTags} content={children} />
|
||||
<WrappedRoute path='/mutes' component={Mutes} content={children} />
|
||||
<WrappedRoute path='/lists' component={Lists} content={children} />
|
||||
{areCollectionsEnabled() &&
|
||||
<WrappedRoute path='/collections/new' component={CollectionsEditor} content={children} />
|
||||
}
|
||||
{areCollectionsEnabled() &&
|
||||
<WrappedRoute path='/collections/:id/edit' component={CollectionsEditor} content={children} />
|
||||
}
|
||||
{areCollectionsEnabled() &&
|
||||
<WrappedRoute path='/collections' component={Collections} content={children} />
|
||||
}
|
||||
|
||||
@@ -50,6 +50,12 @@ export function Collections () {
|
||||
);
|
||||
}
|
||||
|
||||
export function CollectionsEditor () {
|
||||
return import('../../collections/editor').then(
|
||||
module => ({default: module.CollectionEditorPage})
|
||||
);
|
||||
}
|
||||
|
||||
export function Status () {
|
||||
return import('../../status');
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user