2022-10-09 22:55:32 +09:00
import PropTypes from 'prop-types' ;
2024-03-11 22:35:23 +09:00
import { Component , useEffect } from 'react' ;
2023-05-24 00:15:17 +09:00
2024-03-11 22:35:23 +09:00
import { defineMessages , injectIntl , useIntl } from 'react-intl' ;
2023-05-24 00:15:17 +09:00
2022-10-09 22:55:32 +09:00
import { Link } from 'react-router-dom' ;
2023-05-24 00:15:17 +09:00
2024-03-11 22:35:23 +09:00
import { useSelector , useDispatch } from 'react-redux' ;
2024-01-16 19:27:26 +09:00
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react' ;
2024-03-11 22:35:23 +09:00
import BookmarksActiveIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react' ;
import BookmarksIcon from '@/material-icons/400-24px/bookmarks.svg?react' ;
2024-03-20 22:31:31 +09:00
import ExploreActiveIcon from '@/material-icons/400-24px/explore-fill.svg?react' ;
2024-02-20 18:10:44 +09:00
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react' ;
2024-08-27 01:42:46 +09:00
import ModerationIcon from '@/material-icons/400-24px/gavel.svg?react' ;
2024-03-11 22:35:23 +09:00
import HomeActiveIcon from '@/material-icons/400-24px/home-fill.svg?react' ;
import HomeIcon from '@/material-icons/400-24px/home.svg?react' ;
import ListAltActiveIcon from '@/material-icons/400-24px/list_alt-fill.svg?react' ;
2024-01-16 19:27:26 +09:00
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react' ;
2024-08-27 01:42:46 +09:00
import AdministrationIcon from '@/material-icons/400-24px/manufacturing.svg?react' ;
2024-01-16 19:27:26 +09:00
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react' ;
2024-03-11 22:35:23 +09:00
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications-fill.svg?react' ;
import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react' ;
import PersonAddActiveIcon from '@/material-icons/400-24px/person_add-fill.svg?react' ;
import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react' ;
2024-01-16 19:27:26 +09:00
import PublicIcon from '@/material-icons/400-24px/public.svg?react' ;
import SearchIcon from '@/material-icons/400-24px/search.svg?react' ;
2024-03-11 22:35:23 +09:00
import SettingsIcon from '@/material-icons/400-24px/settings.svg?react' ;
import StarActiveIcon from '@/material-icons/400-24px/star-fill.svg?react' ;
import StarIcon from '@/material-icons/400-24px/star.svg?react' ;
import { fetchFollowRequests } from 'mastodon/actions/accounts' ;
import { IconWithBadge } from 'mastodon/components/icon_with_badge' ;
2023-05-10 15:58:21 +09:00
import { WordmarkLogo } from 'mastodon/components/logo' ;
2023-10-20 02:44:55 +09:00
import { NavigationPortal } from 'mastodon/components/navigation_portal' ;
2024-05-20 02:07:32 +09:00
import { identityContextPropShape , withIdentity } from 'mastodon/identity_context' ;
2023-07-09 03:00:12 +09:00
import { timelinePreview , trendsEnabled } from 'mastodon/initial_state' ;
2023-07-14 00:18:09 +09:00
import { transientSingleColumn } from 'mastodon/is_mobile' ;
2024-08-27 01:42:46 +09:00
import { canManageReports , canViewAdminDashboard } from 'mastodon/permissions' ;
2024-07-18 23:36:09 +09:00
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications' ;
2023-05-24 00:15:17 +09:00
2022-10-11 04:41:25 +09:00
import ColumnLink from './column_link' ;
2022-11-06 02:28:13 +09:00
import DisabledAccountBanner from './disabled_account_banner' ;
2024-03-11 22:35:23 +09:00
import { ListPanel } from './list_panel' ;
2022-09-29 11:39:33 +09:00
import SignInBanner from './sign_in_banner' ;
2022-10-09 22:55:32 +09:00
const messages = defineMessages ( {
home : { id : 'tabs_bar.home' , defaultMessage : 'Home' } ,
notifications : { id : 'tabs_bar.notifications' , defaultMessage : 'Notifications' } ,
explore : { id : 'explore.title' , defaultMessage : 'Explore' } ,
2023-07-02 07:05:10 +09:00
firehose : { id : 'column.firehose' , defaultMessage : 'Live feeds' } ,
2023-03-30 22:16:20 +09:00
direct : { id : 'navigation_bar.direct' , defaultMessage : 'Private mentions' } ,
2023-07-22 02:09:13 +09:00
favourites : { id : 'navigation_bar.favourites' , defaultMessage : 'Favorites' } ,
2022-10-09 22:55:32 +09:00
bookmarks : { id : 'navigation_bar.bookmarks' , defaultMessage : 'Bookmarks' } ,
lists : { id : 'navigation_bar.lists' , defaultMessage : 'Lists' } ,
preferences : { id : 'navigation_bar.preferences' , defaultMessage : 'Preferences' } ,
2024-08-27 01:42:46 +09:00
administration : { id : 'navigation_bar.administration' , defaultMessage : 'Administration' } ,
moderation : { id : 'navigation_bar.moderation' , defaultMessage : 'Moderation' } ,
2022-10-09 22:55:32 +09:00
followsAndFollowers : { id : 'navigation_bar.follows_and_followers' , defaultMessage : 'Follows and followers' } ,
about : { id : 'navigation_bar.about' , defaultMessage : 'About' } ,
2022-10-26 02:03:16 +09:00
search : { id : 'navigation_bar.search' , defaultMessage : 'Search' } ,
2023-07-14 00:18:09 +09:00
advancedInterface : { id : 'navigation_bar.advanced_interface' , defaultMessage : 'Open in advanced web interface' } ,
2023-08-31 19:18:46 +09:00
openedInClassicInterface : { id : 'navigation_bar.opened_in_classic_interface' , defaultMessage : 'Posts, accounts, and other specific pages are opened by default in the classic web interface.' } ,
2024-03-11 22:35:23 +09:00
followRequests : { id : 'navigation_bar.follow_requests' , defaultMessage : 'Follow requests' } ,
2022-10-09 22:55:32 +09:00
} ) ;
2019-05-26 04:27:00 +09:00
2024-03-11 22:35:23 +09:00
const NotificationsLink = ( ) => {
2024-09-16 22:12:10 +09:00
const count = useSelector ( selectUnreadNotificationGroupsCount ) ;
const intl = useIntl ( ) ;
2024-07-18 23:36:09 +09:00
2024-03-11 22:35:23 +09:00
return (
< ColumnLink
2024-07-18 23:36:09 +09:00
key = 'notifications'
2024-03-11 22:35:23 +09:00
transparent
to = '/notifications'
2024-09-16 22:12:10 +09:00
icon = { < IconWithBadge id = 'bell' icon = { NotificationsIcon } count = { count } className = 'column-link__icon' / > }
activeIcon = { < IconWithBadge id = 'bell' icon = { NotificationsActiveIcon } count = { count } className = 'column-link__icon' / > }
2024-03-11 22:35:23 +09:00
text = { intl . formatMessage ( messages . notifications ) }
/ >
) ;
} ;
const FollowRequestsLink = ( ) => {
const count = useSelector ( state => state . getIn ( [ 'user_lists' , 'follow_requests' , 'items' ] ) ? . size ? ? 0 ) ;
const intl = useIntl ( ) ;
const dispatch = useDispatch ( ) ;
useEffect ( ( ) => {
dispatch ( fetchFollowRequests ( ) ) ;
} , [ dispatch ] ) ;
if ( count === 0 ) {
return null ;
}
return (
< ColumnLink
transparent
to = '/follow_requests'
2024-03-13 21:54:50 +09:00
icon = { < IconWithBadge id = 'user-plus' icon = { PersonAddIcon } count = { count } className = 'column-link__icon' / > }
activeIcon = { < IconWithBadge id = 'user-plus' icon = { PersonAddActiveIcon } count = { count } className = 'column-link__icon' / > }
2024-03-11 22:35:23 +09:00
text = { intl . formatMessage ( messages . followRequests ) }
/ >
) ;
} ;
2023-05-23 17:52:27 +09:00
class NavigationPanel extends Component {
2022-10-09 22:55:32 +09:00
static propTypes = {
2024-05-20 02:07:32 +09:00
identity : identityContextPropShape ,
2022-10-09 22:55:32 +09:00
intl : PropTypes . object . isRequired ,
} ;
2023-07-02 07:05:10 +09:00
isFirehoseActive = ( match , location ) => {
return match || location . pathname . startsWith ( '/public' ) ;
} ;
2022-09-29 11:39:33 +09:00
render ( ) {
2022-10-09 22:55:32 +09:00
const { intl } = this . props ;
2024-08-27 01:42:46 +09:00
const { signedIn , disabledAccountId , permissions } = this . props . identity ;
2019-05-26 04:27:00 +09:00
2023-10-20 02:36:08 +09:00
let banner = undefined ;
2024-09-26 01:36:19 +09:00
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 >
) ;
}
2023-10-20 02:36:08 +09:00
2022-09-29 11:39:33 +09:00
return (
< div className = 'navigation-panel' >
2022-10-05 03:13:23 +09:00
< div className = 'navigation-panel__logo' >
2023-05-10 15:58:21 +09:00
< Link to = '/' className = 'column-link column-link--logo' > < WordmarkLogo / > < / Link >
2022-10-05 03:13:23 +09:00
< / div >
2019-05-26 04:27:00 +09:00
2023-10-20 02:36:08 +09:00
{ banner &&
2023-12-06 22:42:12 +09:00
< div className = 'navigation-panel__banner' >
2023-10-20 02:36:08 +09:00
{ banner }
< / div >
}
2024-09-26 01:36:19 +09:00
< div className = 'navigation-panel__menu' >
{ signedIn && (
< >
< ColumnLink transparent to = '/home' icon = 'home' iconComponent = { HomeIcon } activeIconComponent = { HomeActiveIcon } text = { intl . formatMessage ( messages . home ) } / >
< NotificationsLink / >
< FollowRequestsLink / >
< / >
) }
{ trendsEnabled ? (
< ColumnLink transparent to = '/explore' icon = 'explore' iconComponent = { ExploreIcon } activeIconComponent = { ExploreActiveIcon } text = { intl . formatMessage ( messages . explore ) } / >
) : (
< ColumnLink transparent to = '/search' icon = 'search' iconComponent = { SearchIcon } text = { intl . formatMessage ( messages . search ) } / >
) }
{ ( signedIn || timelinePreview ) && (
< ColumnLink transparent to = '/public/local' isActive = { this . isFirehoseActive } icon = 'globe' iconComponent = { PublicIcon } text = { intl . formatMessage ( messages . firehose ) } / >
) }
{ ! signedIn && (
< div className = 'navigation-panel__sign-in-banner' >
< hr / >
{ disabledAccountId ? < DisabledAccountBanner / > : < SignInBanner / > }
< / div >
) }
{ signedIn && (
< >
< ColumnLink transparent to = '/conversations' icon = 'at' iconComponent = { AlternateEmailIcon } text = { intl . formatMessage ( messages . direct ) } / >
< ColumnLink transparent to = '/bookmarks' icon = 'bookmarks' iconComponent = { BookmarksIcon } activeIconComponent = { BookmarksActiveIcon } text = { intl . formatMessage ( messages . bookmarks ) } / >
< ColumnLink transparent to = '/favourites' icon = 'star' iconComponent = { StarIcon } activeIconComponent = { StarActiveIcon } text = { intl . formatMessage ( messages . favourites ) } / >
< ColumnLink transparent to = '/lists' icon = 'list-ul' iconComponent = { ListAltIcon } activeIconComponent = { ListAltActiveIcon } text = { intl . formatMessage ( messages . lists ) } / >
< ListPanel / >
< hr / >
< ColumnLink transparent href = '/settings/preferences' icon = 'cog' iconComponent = { SettingsIcon } text = { intl . formatMessage ( messages . preferences ) } / >
{ canManageReports ( permissions ) && < ColumnLink optional transparent href = '/admin/reports' icon = 'flag' iconComponent = { ModerationIcon } text = { intl . formatMessage ( messages . moderation ) } / > }
{ canViewAdminDashboard ( permissions ) && < ColumnLink optional transparent href = '/admin/dashboard' icon = 'tachometer' iconComponent = { AdministrationIcon } text = { intl . formatMessage ( messages . administration ) } / > }
< / >
) }
< div className = 'navigation-panel__legal' >
2022-09-29 11:39:33 +09:00
< hr / >
2024-09-26 01:36:19 +09:00
< ColumnLink transparent to = '/about' icon = 'ellipsis-h' iconComponent = { MoreHorizIcon } text = { intl . formatMessage ( messages . about ) } / >
2022-10-05 03:13:23 +09:00
< / div >
< / div >
2024-09-26 01:36:19 +09:00
< div className = 'flex-spacer' / >
2022-10-19 18:30:59 +09:00
< NavigationPortal / >
2022-09-29 11:39:33 +09:00
< / div >
) ;
}
}
2023-03-24 11:17:53 +09:00
2024-05-20 02:07:32 +09:00
export default injectIntl ( withIdentity ( NavigationPanel ) ) ;