mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-07 18:31:07 +00:00
refactor: Use new main menu as "Getting started" column in Advanced Web UI (#35117)
This commit is contained in:
parent
6166e61638
commit
d28a4428b5
|
@ -15,39 +15,34 @@ import LogoutIcon from '@/material-icons/400-24px/logout.svg?react';
|
||||||
import MenuIcon from '@/material-icons/400-24px/menu.svg?react';
|
import MenuIcon from '@/material-icons/400-24px/menu.svg?react';
|
||||||
import NotificationsIcon from '@/material-icons/400-24px/notifications-fill.svg?react';
|
import NotificationsIcon from '@/material-icons/400-24px/notifications-fill.svg?react';
|
||||||
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
|
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
|
||||||
import SettingsIcon from '@/material-icons/400-24px/settings-fill.svg?react';
|
import SettingsIcon from '@/material-icons/400-24px/settings.svg?react';
|
||||||
import { mountCompose, unmountCompose } from 'mastodon/actions/compose';
|
import { mountCompose, unmountCompose } from 'mastodon/actions/compose';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
import { Column } from 'mastodon/components/column';
|
import { Column } from 'mastodon/components/column';
|
||||||
import { ColumnHeader } from 'mastodon/components/column_header';
|
import { ColumnHeader } from 'mastodon/components/column_header';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { mascot } from 'mastodon/initial_state';
|
import { mascot, reduceMotion } from 'mastodon/initial_state';
|
||||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||||
|
|
||||||
|
import { messages as navbarMessages } from '../ui/components/navigation_bar';
|
||||||
|
|
||||||
import { Search } from './components/search';
|
import { Search } from './components/search';
|
||||||
import ComposeFormContainer from './containers/compose_form_container';
|
import ComposeFormContainer from './containers/compose_form_container';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
start: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
|
live_feed_public: {
|
||||||
home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
|
id: 'navigation_bar.live_feed_public',
|
||||||
notifications: {
|
defaultMessage: 'Live feed (public)',
|
||||||
id: 'tabs_bar.notifications',
|
|
||||||
defaultMessage: 'Notifications',
|
|
||||||
},
|
},
|
||||||
public: {
|
live_feed_local: {
|
||||||
id: 'navigation_bar.public_timeline',
|
id: 'navigation_bar.live_feed_local',
|
||||||
defaultMessage: 'Federated timeline',
|
defaultMessage: 'Live feed (local)',
|
||||||
},
|
|
||||||
community: {
|
|
||||||
id: 'navigation_bar.community_timeline',
|
|
||||||
defaultMessage: 'Local timeline',
|
|
||||||
},
|
},
|
||||||
preferences: {
|
preferences: {
|
||||||
id: 'navigation_bar.preferences',
|
id: 'navigation_bar.preferences',
|
||||||
defaultMessage: 'Preferences',
|
defaultMessage: 'Preferences',
|
||||||
},
|
},
|
||||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||||
compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new post' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
type ColumnMap = ImmutableMap<'id' | 'uuid' | 'params', string>;
|
type ColumnMap = ImmutableMap<'id' | 'uuid' | 'params', string>;
|
||||||
|
@ -82,19 +77,27 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||||
[dispatch],
|
[dispatch],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const scrollNavbarIntoView = useCallback(() => {
|
||||||
|
const navbar = document.querySelector('.navigation-panel');
|
||||||
|
navbar?.scrollIntoView({
|
||||||
|
behavior: reduceMotion ? 'auto' : 'smooth',
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (multiColumn) {
|
if (multiColumn) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className='drawer'
|
className='drawer'
|
||||||
role='region'
|
role='region'
|
||||||
aria-label={intl.formatMessage(messages.compose)}
|
aria-label={intl.formatMessage(navbarMessages.publish)}
|
||||||
>
|
>
|
||||||
<nav className='drawer__header'>
|
<nav className='drawer__header'>
|
||||||
<Link
|
<Link
|
||||||
to='/getting-started'
|
to='/getting-started'
|
||||||
className='drawer__tab'
|
className='drawer__tab'
|
||||||
title={intl.formatMessage(messages.start)}
|
title={intl.formatMessage(navbarMessages.menu)}
|
||||||
aria-label={intl.formatMessage(messages.start)}
|
aria-label={intl.formatMessage(navbarMessages.menu)}
|
||||||
|
onClick={scrollNavbarIntoView}
|
||||||
>
|
>
|
||||||
<Icon id='bars' icon={MenuIcon} />
|
<Icon id='bars' icon={MenuIcon} />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -102,8 +105,8 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||||
<Link
|
<Link
|
||||||
to='/home'
|
to='/home'
|
||||||
className='drawer__tab'
|
className='drawer__tab'
|
||||||
title={intl.formatMessage(messages.home_timeline)}
|
title={intl.formatMessage(navbarMessages.home)}
|
||||||
aria-label={intl.formatMessage(messages.home_timeline)}
|
aria-label={intl.formatMessage(navbarMessages.home)}
|
||||||
>
|
>
|
||||||
<Icon id='home' icon={HomeIcon} />
|
<Icon id='home' icon={HomeIcon} />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -112,8 +115,8 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||||
<Link
|
<Link
|
||||||
to='/notifications'
|
to='/notifications'
|
||||||
className='drawer__tab'
|
className='drawer__tab'
|
||||||
title={intl.formatMessage(messages.notifications)}
|
title={intl.formatMessage(navbarMessages.notifications)}
|
||||||
aria-label={intl.formatMessage(messages.notifications)}
|
aria-label={intl.formatMessage(navbarMessages.notifications)}
|
||||||
>
|
>
|
||||||
<Icon id='bell' icon={NotificationsIcon} />
|
<Icon id='bell' icon={NotificationsIcon} />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -122,8 +125,8 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||||
<Link
|
<Link
|
||||||
to='/public/local'
|
to='/public/local'
|
||||||
className='drawer__tab'
|
className='drawer__tab'
|
||||||
title={intl.formatMessage(messages.community)}
|
title={intl.formatMessage(messages.live_feed_local)}
|
||||||
aria-label={intl.formatMessage(messages.community)}
|
aria-label={intl.formatMessage(messages.live_feed_local)}
|
||||||
>
|
>
|
||||||
<Icon id='users' icon={PeopleIcon} />
|
<Icon id='users' icon={PeopleIcon} />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -132,8 +135,8 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||||
<Link
|
<Link
|
||||||
to='/public'
|
to='/public'
|
||||||
className='drawer__tab'
|
className='drawer__tab'
|
||||||
title={intl.formatMessage(messages.public)}
|
title={intl.formatMessage(messages.live_feed_public)}
|
||||||
aria-label={intl.formatMessage(messages.public)}
|
aria-label={intl.formatMessage(messages.live_feed_public)}
|
||||||
>
|
>
|
||||||
<Icon id='globe' icon={PublicIcon} />
|
<Icon id='globe' icon={PublicIcon} />
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -175,12 +178,12 @@ const Compose: React.FC<{ multiColumn: boolean }> = ({ multiColumn }) => {
|
||||||
return (
|
return (
|
||||||
<Column
|
<Column
|
||||||
bindToDocument={!multiColumn}
|
bindToDocument={!multiColumn}
|
||||||
label={intl.formatMessage(messages.compose)}
|
label={intl.formatMessage(navbarMessages.publish)}
|
||||||
>
|
>
|
||||||
<ColumnHeader
|
<ColumnHeader
|
||||||
icon='pencil'
|
icon='pencil'
|
||||||
iconComponent={EditIcon}
|
iconComponent={EditIcon}
|
||||||
title={intl.formatMessage(messages.compose)}
|
title={intl.formatMessage(navbarMessages.publish)}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
showBackButton
|
showBackButton
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
|
||||||
|
|
||||||
import { List as ImmutableList } from 'immutable';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
|
|
||||||
import BookmarksIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react';
|
|
||||||
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
|
|
||||||
import ModerationIcon from '@/material-icons/400-24px/gavel.svg?react';
|
|
||||||
import PeopleIcon from '@/material-icons/400-24px/group.svg?react';
|
|
||||||
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
|
|
||||||
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
|
|
||||||
import AdministrationIcon from '@/material-icons/400-24px/manufacturing.svg?react';
|
|
||||||
import MenuIcon from '@/material-icons/400-24px/menu.svg?react';
|
|
||||||
import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react';
|
|
||||||
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
|
|
||||||
import SettingsIcon from '@/material-icons/400-24px/settings-fill.svg?react';
|
|
||||||
import StarIcon from '@/material-icons/400-24px/star.svg?react';
|
|
||||||
import { fetchFollowRequests } from 'mastodon/actions/accounts';
|
|
||||||
import Column from 'mastodon/components/column';
|
|
||||||
import ColumnHeader from 'mastodon/components/column_header';
|
|
||||||
import { LinkFooter } from 'mastodon/features/ui/components/link_footer';
|
|
||||||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
|
||||||
import { canManageReports, canViewAdminDashboard } from 'mastodon/permissions';
|
|
||||||
|
|
||||||
import { me, showTrends } from '../../initial_state';
|
|
||||||
import { NavigationBar } from '../compose/components/navigation_bar';
|
|
||||||
import { ColumnLink } from '../ui/components/column_link';
|
|
||||||
import ColumnSubheading from '../ui/components/column_subheading';
|
|
||||||
|
|
||||||
import { Trends } from 'mastodon/features/navigation_panel/components/trends';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
|
|
||||||
notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' },
|
|
||||||
public_timeline: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' },
|
|
||||||
settings_subheading: { id: 'column_subheading.settings', defaultMessage: 'Settings' },
|
|
||||||
community_timeline: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
|
|
||||||
explore: { id: 'navigation_bar.explore', defaultMessage: 'Explore' },
|
|
||||||
direct: { id: 'navigation_bar.direct', defaultMessage: 'Private mentions' },
|
|
||||||
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
|
|
||||||
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
|
||||||
administration: { id: 'navigation_bar.administration', defaultMessage: 'Administration' },
|
|
||||||
moderation: { id: 'navigation_bar.moderation', defaultMessage: 'Moderation' },
|
|
||||||
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
|
|
||||||
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' },
|
|
||||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
|
||||||
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Blocked domains' },
|
|
||||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
|
||||||
pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned posts' },
|
|
||||||
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
|
|
||||||
discover: { id: 'navigation_bar.discover', defaultMessage: 'Discover' },
|
|
||||||
personal: { id: 'navigation_bar.personal', defaultMessage: 'Personal' },
|
|
||||||
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
|
||||||
menu: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
|
||||||
myAccount: state.getIn(['accounts', me]),
|
|
||||||
unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
|
||||||
fetchFollowRequests: () => dispatch(fetchFollowRequests()),
|
|
||||||
});
|
|
||||||
|
|
||||||
const badgeDisplay = (number, limit) => {
|
|
||||||
if (number === 0) {
|
|
||||||
return undefined;
|
|
||||||
} else if (limit && number >= limit) {
|
|
||||||
return `${limit}+`;
|
|
||||||
} else {
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GettingStarted extends ImmutablePureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
identity: identityContextPropShape,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
myAccount: ImmutablePropTypes.record,
|
|
||||||
multiColumn: PropTypes.bool,
|
|
||||||
fetchFollowRequests: PropTypes.func.isRequired,
|
|
||||||
unreadFollowRequests: PropTypes.number,
|
|
||||||
unreadNotifications: PropTypes.number,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
const { fetchFollowRequests } = this.props;
|
|
||||||
const { signedIn } = this.props.identity;
|
|
||||||
|
|
||||||
if (!signedIn) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchFollowRequests();
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { intl, myAccount, multiColumn, unreadFollowRequests } = this.props;
|
|
||||||
const { signedIn, permissions } = this.props.identity;
|
|
||||||
|
|
||||||
const navItems = [];
|
|
||||||
|
|
||||||
navItems.push(
|
|
||||||
<ColumnSubheading key='header-discover' text={intl.formatMessage(messages.discover)} />,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (showTrends) {
|
|
||||||
navItems.push(
|
|
||||||
<ColumnLink key='explore' icon='explore' iconComponent={ExploreIcon} text={intl.formatMessage(messages.explore)} to='/explore' />,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
navItems.push(
|
|
||||||
<ColumnLink key='community_timeline' icon='users' iconComponent={PeopleIcon} text={intl.formatMessage(messages.community_timeline)} to='/public/local' />,
|
|
||||||
<ColumnLink key='public_timeline' icon='globe' iconComponent={PublicIcon} text={intl.formatMessage(messages.public_timeline)} to='/public' />,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (signedIn) {
|
|
||||||
navItems.push(
|
|
||||||
<ColumnSubheading key='header-personal' text={intl.formatMessage(messages.personal)} />,
|
|
||||||
<ColumnLink key='home' icon='home' iconComponent={HomeIcon} text={intl.formatMessage(messages.home_timeline)} to='/home' />,
|
|
||||||
<ColumnLink key='direct' icon='at' iconComponent={AlternateEmailIcon} text={intl.formatMessage(messages.direct)} to='/conversations' />,
|
|
||||||
<ColumnLink key='bookmark' icon='bookmarks' iconComponent={BookmarksIcon} text={intl.formatMessage(messages.bookmarks)} to='/bookmarks' />,
|
|
||||||
<ColumnLink key='favourites' icon='star' iconComponent={StarIcon} text={intl.formatMessage(messages.favourites)} to='/favourites' />,
|
|
||||||
<ColumnLink key='lists' icon='list-ul' iconComponent={ListAltIcon} text={intl.formatMessage(messages.lists)} to='/lists' />,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (myAccount.get('locked') || unreadFollowRequests > 0) {
|
|
||||||
navItems.push(<ColumnLink key='follow_requests' icon='user-plus' iconComponent={PersonAddIcon} text={intl.formatMessage(messages.follow_requests)} badge={badgeDisplay(unreadFollowRequests, 40)} to='/follow_requests' />);
|
|
||||||
}
|
|
||||||
|
|
||||||
navItems.push(
|
|
||||||
<ColumnSubheading key='header-settings' text={intl.formatMessage(messages.settings_subheading)} />,
|
|
||||||
<ColumnLink key='preferences' icon='cog' iconComponent={SettingsIcon} text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (canManageReports(permissions)) {
|
|
||||||
navItems.push(<ColumnLink key='moderation' href='/admin/reports' icon='flag' iconComponent={ModerationIcon} text={intl.formatMessage(messages.moderation)} />);
|
|
||||||
}
|
|
||||||
if (canViewAdminDashboard(permissions)) {
|
|
||||||
navItems.push(<ColumnLink key='administration' href='/admin/dashboard' icon='tachometer' iconComponent={AdministrationIcon} text={intl.formatMessage(messages.administration)} />);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Column>
|
|
||||||
{(signedIn && !multiColumn) ? <NavigationBar /> : <ColumnHeader title={intl.formatMessage(messages.menu)} icon='bars' iconComponent={MenuIcon} multiColumn={multiColumn} />}
|
|
||||||
|
|
||||||
<div className='getting-started scrollable scrollable--flex'>
|
|
||||||
<div className='getting-started__wrapper'>
|
|
||||||
{navItems}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!multiColumn && <div className='flex-spacer' />}
|
|
||||||
|
|
||||||
<LinkFooter multiColumn />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{(multiColumn && showTrends) && <Trends />}
|
|
||||||
|
|
||||||
<Helmet>
|
|
||||||
<title>{intl.formatMessage(messages.menu)}</title>
|
|
||||||
<meta name='robots' content='noindex' />
|
|
||||||
</Helmet>
|
|
||||||
</Column>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withIdentity(connect(mapStateToProps, mapDispatchToProps)(injectIntl(GettingStarted)));
|
|
32
app/javascript/mastodon/features/getting_started/index.tsx
Normal file
32
app/javascript/mastodon/features/getting_started/index.tsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { Column } from 'mastodon/components/column';
|
||||||
|
|
||||||
|
import { NavigationPanel } from '../navigation_panel';
|
||||||
|
import { LinkFooter } from '../ui/components/link_footer';
|
||||||
|
|
||||||
|
const GettingStarted: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
return (
|
||||||
|
<Column>
|
||||||
|
<NavigationPanel multiColumn />
|
||||||
|
|
||||||
|
<LinkFooter multiColumn />
|
||||||
|
|
||||||
|
<Helmet>
|
||||||
|
<title>
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'getting_started.heading',
|
||||||
|
defaultMessage: 'Getting started',
|
||||||
|
})}
|
||||||
|
</title>
|
||||||
|
<meta name='robots' content='noindex' />
|
||||||
|
</Helmet>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default GettingStarted;
|
|
@ -185,13 +185,169 @@ const isFirehoseActive = (
|
||||||
|
|
||||||
const MENU_WIDTH = 284;
|
const MENU_WIDTH = 284;
|
||||||
|
|
||||||
export const NavigationPanel: React.FC = () => {
|
export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
|
||||||
|
multiColumn = false,
|
||||||
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { signedIn, disabledAccountId } = useIdentity();
|
const { signedIn, disabledAccountId } = useIdentity();
|
||||||
|
const location = useLocation();
|
||||||
|
const showSearch = useBreakpoint('full') && !multiColumn;
|
||||||
|
|
||||||
|
let banner: React.ReactNode;
|
||||||
|
|
||||||
|
if (transientSingleColumn) {
|
||||||
|
banner = (
|
||||||
|
<div className='switch-to-advanced'>
|
||||||
|
{intl.formatMessage(messages.openedInClassicInterface)}{' '}
|
||||||
|
<a
|
||||||
|
href={`/deck${location.pathname}`}
|
||||||
|
className='switch-to-advanced__toggle'
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.advancedInterface)}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='navigation-panel'>
|
||||||
|
<div className='navigation-panel__logo'>
|
||||||
|
<Link to='/' className='column-link column-link--logo'>
|
||||||
|
<WordmarkLogo />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showSearch && <Search singleColumn />}
|
||||||
|
|
||||||
|
{!multiColumn && <ProfileCard />}
|
||||||
|
|
||||||
|
{banner && <div className='navigation-panel__banner'>{banner}</div>}
|
||||||
|
|
||||||
|
<div className='navigation-panel__menu'>
|
||||||
|
{signedIn && (
|
||||||
|
<>
|
||||||
|
{!multiColumn && (
|
||||||
|
<ColumnLink
|
||||||
|
to='/publish'
|
||||||
|
icon='plus'
|
||||||
|
iconComponent={AddIcon}
|
||||||
|
activeIconComponent={AddIcon}
|
||||||
|
text={intl.formatMessage(messages.compose)}
|
||||||
|
className='button navigation-panel__compose-button'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/home'
|
||||||
|
icon='home'
|
||||||
|
iconComponent={HomeIcon}
|
||||||
|
activeIconComponent={HomeActiveIcon}
|
||||||
|
text={intl.formatMessage(messages.home)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{trendsEnabled && (
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/explore'
|
||||||
|
icon='explore'
|
||||||
|
iconComponent={TrendingUpIcon}
|
||||||
|
text={intl.formatMessage(messages.explore)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{(signedIn || timelinePreview) && (
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/public/local'
|
||||||
|
icon='globe'
|
||||||
|
iconComponent={PublicIcon}
|
||||||
|
isActive={isFirehoseActive}
|
||||||
|
text={intl.formatMessage(messages.firehose)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{signedIn && (
|
||||||
|
<>
|
||||||
|
<NotificationsLink />
|
||||||
|
|
||||||
|
<FollowRequestsLink />
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<ListPanel />
|
||||||
|
|
||||||
|
<FollowedTagsPanel />
|
||||||
|
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/favourites'
|
||||||
|
icon='star'
|
||||||
|
iconComponent={StarIcon}
|
||||||
|
activeIconComponent={StarActiveIcon}
|
||||||
|
text={intl.formatMessage(messages.favourites)}
|
||||||
|
/>
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/bookmarks'
|
||||||
|
icon='bookmarks'
|
||||||
|
iconComponent={BookmarksIcon}
|
||||||
|
activeIconComponent={BookmarksActiveIcon}
|
||||||
|
text={intl.formatMessage(messages.bookmarks)}
|
||||||
|
/>
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/conversations'
|
||||||
|
icon='at'
|
||||||
|
iconComponent={AlternateEmailIcon}
|
||||||
|
text={intl.formatMessage(messages.direct)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
href='/settings/preferences'
|
||||||
|
icon='cog'
|
||||||
|
iconComponent={SettingsIcon}
|
||||||
|
text={intl.formatMessage(messages.preferences)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MoreLink />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className='navigation-panel__legal'>
|
||||||
|
<ColumnLink
|
||||||
|
transparent
|
||||||
|
to='/about'
|
||||||
|
icon='ellipsis-h'
|
||||||
|
iconComponent={InfoIcon}
|
||||||
|
text={intl.formatMessage(messages.about)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!signedIn && (
|
||||||
|
<div className='navigation-panel__sign-in-banner'>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
{disabledAccountId ? <DisabledAccountBanner /> : <SignInBanner />}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex-spacer' />
|
||||||
|
|
||||||
|
<Trends />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CollapsibleNavigationPanel: React.FC = () => {
|
||||||
const open = useAppSelector((state) => state.navigation.open);
|
const open = useAppSelector((state) => state.navigation.open);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const openable = useBreakpoint('openable');
|
const openable = useBreakpoint('openable');
|
||||||
const showSearch = useBreakpoint('full');
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const overlayRef = useRef<HTMLDivElement | null>(null);
|
const overlayRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
@ -293,22 +449,6 @@ export const NavigationPanel: React.FC = () => {
|
||||||
}
|
}
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
let banner: React.ReactNode;
|
|
||||||
|
|
||||||
if (transientSingleColumn) {
|
|
||||||
banner = (
|
|
||||||
<div className='switch-to-advanced'>
|
|
||||||
{intl.formatMessage(messages.openedInClassicInterface)}{' '}
|
|
||||||
<a
|
|
||||||
href={`/deck${location.pathname}`}
|
|
||||||
className='switch-to-advanced__toggle'
|
|
||||||
>
|
|
||||||
{intl.formatMessage(messages.advancedInterface)}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const showOverlay = openable && open;
|
const showOverlay = openable && open;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -324,139 +464,7 @@ export const NavigationPanel: React.FC = () => {
|
||||||
{...bind()}
|
{...bind()}
|
||||||
style={openable ? { x } : undefined}
|
style={openable ? { x } : undefined}
|
||||||
>
|
>
|
||||||
<div className='navigation-panel'>
|
<NavigationPanel />
|
||||||
<div className='navigation-panel__logo'>
|
|
||||||
<Link to='/' className='column-link column-link--logo'>
|
|
||||||
<WordmarkLogo />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{showSearch && <Search singleColumn />}
|
|
||||||
|
|
||||||
<ProfileCard />
|
|
||||||
|
|
||||||
{banner && <div className='navigation-panel__banner'>{banner}</div>}
|
|
||||||
|
|
||||||
<div className='navigation-panel__menu'>
|
|
||||||
{signedIn && (
|
|
||||||
<>
|
|
||||||
<ColumnLink
|
|
||||||
to='/publish'
|
|
||||||
icon='plus'
|
|
||||||
iconComponent={AddIcon}
|
|
||||||
activeIconComponent={AddIcon}
|
|
||||||
text={intl.formatMessage(messages.compose)}
|
|
||||||
className='button navigation-panel__compose-button'
|
|
||||||
/>
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/home'
|
|
||||||
icon='home'
|
|
||||||
iconComponent={HomeIcon}
|
|
||||||
activeIconComponent={HomeActiveIcon}
|
|
||||||
text={intl.formatMessage(messages.home)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{trendsEnabled && (
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/explore'
|
|
||||||
icon='explore'
|
|
||||||
iconComponent={TrendingUpIcon}
|
|
||||||
text={intl.formatMessage(messages.explore)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(signedIn || timelinePreview) && (
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/public/local'
|
|
||||||
icon='globe'
|
|
||||||
iconComponent={PublicIcon}
|
|
||||||
isActive={isFirehoseActive}
|
|
||||||
text={intl.formatMessage(messages.firehose)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{signedIn && (
|
|
||||||
<>
|
|
||||||
<NotificationsLink />
|
|
||||||
|
|
||||||
<FollowRequestsLink />
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<ListPanel />
|
|
||||||
|
|
||||||
<FollowedTagsPanel />
|
|
||||||
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/favourites'
|
|
||||||
icon='star'
|
|
||||||
iconComponent={StarIcon}
|
|
||||||
activeIconComponent={StarActiveIcon}
|
|
||||||
text={intl.formatMessage(messages.favourites)}
|
|
||||||
/>
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/bookmarks'
|
|
||||||
icon='bookmarks'
|
|
||||||
iconComponent={BookmarksIcon}
|
|
||||||
activeIconComponent={BookmarksActiveIcon}
|
|
||||||
text={intl.formatMessage(messages.bookmarks)}
|
|
||||||
/>
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/conversations'
|
|
||||||
icon='at'
|
|
||||||
iconComponent={AlternateEmailIcon}
|
|
||||||
text={intl.formatMessage(messages.direct)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
href='/settings/preferences'
|
|
||||||
icon='cog'
|
|
||||||
iconComponent={SettingsIcon}
|
|
||||||
text={intl.formatMessage(messages.preferences)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<MoreLink />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className='navigation-panel__legal'>
|
|
||||||
<ColumnLink
|
|
||||||
transparent
|
|
||||||
to='/about'
|
|
||||||
icon='ellipsis-h'
|
|
||||||
iconComponent={InfoIcon}
|
|
||||||
text={intl.formatMessage(messages.about)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!signedIn && (
|
|
||||||
<div className='navigation-panel__sign-in-banner'>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
{disabledAccountId ? (
|
|
||||||
<DisabledAccountBanner />
|
|
||||||
) : (
|
|
||||||
<SignInBanner />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex-spacer' />
|
|
||||||
|
|
||||||
<Trends />
|
|
||||||
</div>
|
|
||||||
</animated.div>
|
</animated.div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import BundleColumnError from './bundle_column_error';
|
||||||
import { ColumnLoading } from './column_loading';
|
import { ColumnLoading } from './column_loading';
|
||||||
import { ComposePanel, RedirectToMobileComposeIfNeeded } from './compose_panel';
|
import { ComposePanel, RedirectToMobileComposeIfNeeded } from './compose_panel';
|
||||||
import DrawerLoading from './drawer_loading';
|
import DrawerLoading from './drawer_loading';
|
||||||
import { NavigationPanel } from 'mastodon/features/navigation_panel';
|
import { CollapsibleNavigationPanel } from 'mastodon/features/navigation_panel';
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
'COMPOSE': Compose,
|
'COMPOSE': Compose,
|
||||||
|
@ -133,7 +133,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||||
<div className='columns-area columns-area--mobile'>{children}</div>
|
<div className='columns-area columns-area--mobile'>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<NavigationPanel />
|
<CollapsibleNavigationPanel />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { registrationsOpen, sso_redirect } from 'mastodon/initial_state';
|
||||||
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications';
|
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications';
|
||||||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||||
|
|
||||||
const messages = defineMessages({
|
export const messages = defineMessages({
|
||||||
home: { id: 'tabs_bar.home', defaultMessage: 'Home' },
|
home: { id: 'tabs_bar.home', defaultMessage: 'Home' },
|
||||||
search: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
search: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
||||||
publish: { id: 'tabs_bar.publish', defaultMessage: 'New Post' },
|
publish: { id: 'tabs_bar.publish', defaultMessage: 'New Post' },
|
||||||
|
|
|
@ -142,13 +142,8 @@ class SwitchingColumnsArea extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
UNSAFE_componentWillMount () {
|
UNSAFE_componentWillMount () {
|
||||||
if (this.props.singleColumn) {
|
document.body.classList.toggle('layout-single-column', this.props.singleColumn);
|
||||||
document.body.classList.toggle('layout-single-column', true);
|
document.body.classList.toggle('layout-multiple-columns', !this.props.singleColumn);
|
||||||
document.body.classList.toggle('layout-multiple-columns', false);
|
|
||||||
} else {
|
|
||||||
document.body.classList.toggle('layout-single-column', false);
|
|
||||||
document.body.classList.toggle('layout-multiple-columns', true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
|
@ -200,8 +195,8 @@ class SwitchingColumnsArea extends PureComponent {
|
||||||
{singleColumn ? <Redirect from='/deck' to='/home' exact /> : null}
|
{singleColumn ? <Redirect from='/deck' to='/home' exact /> : null}
|
||||||
{singleColumn && pathName.startsWith('/deck/') ? <Redirect from={pathName} to={{...this.props.location, pathname: pathName.slice(5)}} /> : null}
|
{singleColumn && pathName.startsWith('/deck/') ? <Redirect from={pathName} to={{...this.props.location, pathname: pathName.slice(5)}} /> : null}
|
||||||
{/* Redirect old bookmarks (without /deck) with home-like routes to the advanced interface */}
|
{/* Redirect old bookmarks (without /deck) with home-like routes to the advanced interface */}
|
||||||
{!singleColumn && pathName === '/getting-started' ? <Redirect from='/getting-started' to='/deck/getting-started' exact /> : null}
|
|
||||||
{!singleColumn && pathName === '/home' ? <Redirect from='/home' to='/deck/getting-started' exact /> : null}
|
{!singleColumn && pathName === '/home' ? <Redirect from='/home' to='/deck/getting-started' exact /> : null}
|
||||||
|
{pathName === '/getting-started' ? <Redirect from='/getting-started' to={singleColumn ? '/home' : '/deck/getting-started'} exact /> : null}
|
||||||
|
|
||||||
<WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
|
<WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
|
||||||
<WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
|
<WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
|
||||||
|
|
|
@ -184,7 +184,6 @@
|
||||||
"column_header.show_settings": "Show settings",
|
"column_header.show_settings": "Show settings",
|
||||||
"column_header.unpin": "Unpin",
|
"column_header.unpin": "Unpin",
|
||||||
"column_search.cancel": "Cancel",
|
"column_search.cancel": "Cancel",
|
||||||
"column_subheading.settings": "Settings",
|
|
||||||
"community.column_settings.local_only": "Local only",
|
"community.column_settings.local_only": "Local only",
|
||||||
"community.column_settings.media_only": "Media Only",
|
"community.column_settings.media_only": "Media Only",
|
||||||
"community.column_settings.remote_only": "Remote only",
|
"community.column_settings.remote_only": "Remote only",
|
||||||
|
@ -555,12 +554,8 @@
|
||||||
"navigation_bar.automated_deletion": "Automated post deletion",
|
"navigation_bar.automated_deletion": "Automated post deletion",
|
||||||
"navigation_bar.blocks": "Blocked users",
|
"navigation_bar.blocks": "Blocked users",
|
||||||
"navigation_bar.bookmarks": "Bookmarks",
|
"navigation_bar.bookmarks": "Bookmarks",
|
||||||
"navigation_bar.community_timeline": "Local timeline",
|
|
||||||
"navigation_bar.compose": "Compose new post",
|
|
||||||
"navigation_bar.direct": "Private mentions",
|
"navigation_bar.direct": "Private mentions",
|
||||||
"navigation_bar.discover": "Discover",
|
|
||||||
"navigation_bar.domain_blocks": "Blocked domains",
|
"navigation_bar.domain_blocks": "Blocked domains",
|
||||||
"navigation_bar.explore": "Explore",
|
|
||||||
"navigation_bar.favourites": "Favorites",
|
"navigation_bar.favourites": "Favorites",
|
||||||
"navigation_bar.filters": "Muted words",
|
"navigation_bar.filters": "Muted words",
|
||||||
"navigation_bar.follow_requests": "Follow requests",
|
"navigation_bar.follow_requests": "Follow requests",
|
||||||
|
@ -568,19 +563,17 @@
|
||||||
"navigation_bar.follows_and_followers": "Follows and followers",
|
"navigation_bar.follows_and_followers": "Follows and followers",
|
||||||
"navigation_bar.import_export": "Import and export",
|
"navigation_bar.import_export": "Import and export",
|
||||||
"navigation_bar.lists": "Lists",
|
"navigation_bar.lists": "Lists",
|
||||||
|
"navigation_bar.live_feed_local": "Live feed (local)",
|
||||||
|
"navigation_bar.live_feed_public": "Live feed (public)",
|
||||||
"navigation_bar.logout": "Logout",
|
"navigation_bar.logout": "Logout",
|
||||||
"navigation_bar.moderation": "Moderation",
|
"navigation_bar.moderation": "Moderation",
|
||||||
"navigation_bar.more": "More",
|
"navigation_bar.more": "More",
|
||||||
"navigation_bar.mutes": "Muted users",
|
"navigation_bar.mutes": "Muted users",
|
||||||
"navigation_bar.opened_in_classic_interface": "Posts, accounts, and other specific pages are opened by default in the classic web interface.",
|
"navigation_bar.opened_in_classic_interface": "Posts, accounts, and other specific pages are opened by default in the classic web interface.",
|
||||||
"navigation_bar.personal": "Personal",
|
|
||||||
"navigation_bar.pins": "Pinned posts",
|
|
||||||
"navigation_bar.preferences": "Preferences",
|
"navigation_bar.preferences": "Preferences",
|
||||||
"navigation_bar.privacy_and_reach": "Privacy and reach",
|
"navigation_bar.privacy_and_reach": "Privacy and reach",
|
||||||
"navigation_bar.public_timeline": "Federated timeline",
|
|
||||||
"navigation_bar.search": "Search",
|
"navigation_bar.search": "Search",
|
||||||
"navigation_bar.search_trends": "Search / Trending",
|
"navigation_bar.search_trends": "Search / Trending",
|
||||||
"navigation_bar.security": "Security",
|
|
||||||
"navigation_panel.collapse_followed_tags": "Collapse followed hashtags menu",
|
"navigation_panel.collapse_followed_tags": "Collapse followed hashtags menu",
|
||||||
"navigation_panel.collapse_lists": "Collapse list menu",
|
"navigation_panel.collapse_lists": "Collapse list menu",
|
||||||
"navigation_panel.expand_followed_tags": "Expand followed hashtags menu",
|
"navigation_panel.expand_followed_tags": "Expand followed hashtags menu",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user