[Glitch] Add "More" to the sidebar menu with links to mutes, blocks, and so on

Port f53bb4cd7d to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Eugen Rochko
2025-06-11 18:12:04 +02:00
committed by Claire
parent 3166396a16
commit c3ca5d49cf
6 changed files with 147 additions and 157 deletions

View File

@@ -422,7 +422,7 @@ export const AccountHeader: React.FC<{
return arr; return arr;
} }
if (signedIn && account.id !== me && !account.suspended) { if (signedIn && !account.suspended) {
arr.push({ arr.push({
text: intl.formatMessage(messages.mention, { text: intl.formatMessage(messages.mention, {
name: account.username, name: account.username,
@@ -446,37 +446,7 @@ export const AccountHeader: React.FC<{
arr.push(null); arr.push(null);
} }
if (account.id === me) { if (signedIn) {
arr.push({
text: intl.formatMessage(messages.edit_profile),
href: '/settings/profile',
});
arr.push({
text: intl.formatMessage(messages.preferences),
href: '/settings/preferences',
});
arr.push(null);
arr.push({
text: intl.formatMessage(messages.follow_requests),
to: '/follow_requests',
});
arr.push({
text: intl.formatMessage(messages.favourites),
to: '/favourites',
});
arr.push({ text: intl.formatMessage(messages.lists), to: '/lists' });
arr.push({
text: intl.formatMessage(messages.followed_tags),
to: '/followed_tags',
});
arr.push(null);
arr.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
arr.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
arr.push({
text: intl.formatMessage(messages.domain_blocks),
to: '/domain_blocks',
});
} else if (signedIn) {
if (relationship?.following) { if (relationship?.following) {
if (!relationship.muting) { if (!relationship.muting) {
if (relationship.showing_reblogs) { if (relationship.showing_reblogs) {
@@ -615,8 +585,7 @@ export const AccountHeader: React.FC<{
} }
if ( if (
(account.id !== me && (permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS ||
(permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) ||
(isRemote && (isRemote &&
(permissions & PERMISSION_MANAGE_FEDERATION) === (permissions & PERMISSION_MANAGE_FEDERATION) ===
PERMISSION_MANAGE_FEDERATION) PERMISSION_MANAGE_FEDERATION)
@@ -884,12 +853,14 @@ export const AccountHeader: React.FC<{
<div className='account__header__tabs__buttons'> <div className='account__header__tabs__buttons'>
{!hidden && bellBtn} {!hidden && bellBtn}
{!hidden && shareBtn} {!hidden && shareBtn}
<Dropdown {accountId !== me && (
disabled={menu.length === 0} <Dropdown
items={menu} disabled={menu.length === 0}
icon='ellipsis-v' items={menu}
iconComponent={MoreHorizIcon} icon='ellipsis-v'
/> iconComponent={MoreHorizIcon}
/>
)}
{!hidden && actionBtn} {!hidden && actionBtn}
</div> </div>
</div> </div>

View File

@@ -1,81 +0,0 @@
import { useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { openModal } from 'flavours/glitch/actions/modal';
import { Dropdown } from 'flavours/glitch/components/dropdown_menu';
import { useAppDispatch } from 'flavours/glitch/store';
const messages = defineMessages({
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
preferences: {
id: 'navigation_bar.preferences',
defaultMessage: 'Preferences',
},
follow_requests: {
id: 'navigation_bar.follow_requests',
defaultMessage: 'Follow requests',
},
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' },
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
followed_tags: {
id: 'navigation_bar.followed_tags',
defaultMessage: 'Followed hashtags',
},
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' },
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
});
export const ActionBar: React.FC = () => {
const dispatch = useAppDispatch();
const intl = useIntl();
const menu = useMemo(() => {
const handleLogoutClick = () => {
dispatch(openModal({ modalType: 'CONFIRM_LOG_OUT', modalProps: {} }));
};
return [
{
text: intl.formatMessage(messages.edit_profile),
href: '/settings/profile',
},
{
text: intl.formatMessage(messages.preferences),
href: '/settings/preferences',
},
null,
{
text: intl.formatMessage(messages.follow_requests),
to: '/follow_requests',
},
{ text: intl.formatMessage(messages.favourites), to: '/favourites' },
{ text: intl.formatMessage(messages.bookmarks), to: '/bookmarks' },
{ text: intl.formatMessage(messages.lists), to: '/lists' },
{
text: intl.formatMessage(messages.followed_tags),
to: '/followed_tags',
},
null,
{ text: intl.formatMessage(messages.mutes), to: '/mutes' },
{ text: intl.formatMessage(messages.blocks), to: '/blocks' },
{
text: intl.formatMessage(messages.domain_blocks),
to: '/domain_blocks',
},
{ text: intl.formatMessage(messages.filters), href: '/filters' },
null,
{ text: intl.formatMessage(messages.logout), action: handleLogoutClick },
];
}, [intl, dispatch]);
return <Dropdown items={menu} icon='bars' iconComponent={MoreHorizIcon} />;
};

View File

@@ -9,8 +9,6 @@ import { IconButton } from 'flavours/glitch/components/icon_button';
import { me } from 'flavours/glitch/initial_state'; import { me } from 'flavours/glitch/initial_state';
import { useAppDispatch, useAppSelector } from 'flavours/glitch/store'; import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
import { ActionBar } from './action_bar';
const messages = defineMessages({ const messages = defineMessages({
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' }, cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
}); });
@@ -33,15 +31,14 @@ export const NavigationBar: React.FC = () => {
return ( return (
<div className='navigation-bar'> <div className='navigation-bar'>
<Account id={me} minimal /> <Account id={me} minimal />
{isReplying ? (
{isReplying && (
<IconButton <IconButton
title={intl.formatMessage(messages.cancel)} title={intl.formatMessage(messages.cancel)}
icon='' icon=''
iconComponent={CloseIcon} iconComponent={CloseIcon}
onClick={handleCancelClick} onClick={handleCancelClick}
/> />
) : (
<ActionBar />
)} )}
</div> </div>
); );

View File

@@ -0,0 +1,129 @@
import { useMemo } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { openModal } from 'flavours/glitch/actions/modal';
import { Dropdown } from 'flavours/glitch/components/dropdown_menu';
import { Icon } from 'flavours/glitch/components/icon';
import { useIdentity } from 'flavours/glitch/identity_context';
import type { MenuItem } from 'flavours/glitch/models/dropdown_menu';
import {
canManageReports,
canViewAdminDashboard,
} from 'flavours/glitch/permissions';
import { useAppDispatch } from 'flavours/glitch/store';
const messages = defineMessages({
followedTags: {
id: 'navigation_bar.followed_tags',
defaultMessage: 'Followed hashtags',
},
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
domainBlocks: {
id: 'navigation_bar.domain_blocks',
defaultMessage: 'Blocked domains',
},
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
administration: {
id: 'navigation_bar.administration',
defaultMessage: 'Administration',
},
moderation: { id: 'navigation_bar.moderation', defaultMessage: 'Moderation' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
automatedDeletion: {
id: 'navigation_bar.automated_deletion',
defaultMessage: 'Automated post deletion',
},
accountSettings: {
id: 'navigation_bar.account_settings',
defaultMessage: 'Password and security',
},
importExport: {
id: 'navigation_bar.import_export',
defaultMessage: 'Import and export',
},
privacyAndReach: {
id: 'navigation_bar.privacy_and_reach',
defaultMessage: 'Privacy and reach',
},
});
export const MoreLink: React.FC = () => {
const intl = useIntl();
const { permissions } = useIdentity();
const dispatch = useAppDispatch();
const menu = useMemo(() => {
const arr: MenuItem[] = [
{
text: intl.formatMessage(messages.followedTags),
to: '/followed_tags',
},
null,
{ text: intl.formatMessage(messages.filters), href: '/filters' },
{ text: intl.formatMessage(messages.mutes), to: '/mutes' },
{ text: intl.formatMessage(messages.blocks), to: '/blocks' },
{
text: intl.formatMessage(messages.domainBlocks),
to: '/domain_blocks',
},
];
arr.push(
null,
{
href: '/settings/privacy',
text: intl.formatMessage(messages.privacyAndReach),
},
{
href: '/statuses_cleanup',
text: intl.formatMessage(messages.automatedDeletion),
},
{
href: '/auth/edit',
text: intl.formatMessage(messages.accountSettings),
},
{
href: '/settings/export',
text: intl.formatMessage(messages.importExport),
},
);
if (canManageReports(permissions)) {
arr.push(null, {
href: '/admin/reports',
text: intl.formatMessage(messages.moderation),
});
}
if (canViewAdminDashboard(permissions)) {
arr.push({
href: '/admin/dashboard',
text: intl.formatMessage(messages.administration),
});
}
const handleLogoutClick = () => {
dispatch(openModal({ modalType: 'CONFIRM_LOG_OUT', modalProps: {} }));
};
arr.push(null, {
text: intl.formatMessage(messages.logout),
action: handleLogoutClick,
});
return arr;
}, [intl, dispatch, permissions]);
return (
<Dropdown items={menu}>
<button className='column-link column-link--transparent'>
<Icon id='' icon={MoreHorizIcon} className='column-link__icon' />
<FormattedMessage id='navigation_bar.more' defaultMessage='More' />
</button>
</Dropdown>
);
};

View File

@@ -17,7 +17,6 @@ import BookmarksActiveIcon from '@/material-icons/400-24px/bookmarks-fill.svg?re
import BookmarksIcon from '@/material-icons/400-24px/bookmarks.svg?react'; import BookmarksIcon from '@/material-icons/400-24px/bookmarks.svg?react';
import ExploreActiveIcon from '@/material-icons/400-24px/explore-fill.svg?react'; import ExploreActiveIcon from '@/material-icons/400-24px/explore-fill.svg?react';
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react'; import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
import ModerationIcon from '@/material-icons/400-24px/gavel.svg?react';
import HomeActiveIcon from '@/material-icons/400-24px/home-fill.svg?react'; import HomeActiveIcon from '@/material-icons/400-24px/home-fill.svg?react';
import HomeIcon from '@/material-icons/400-24px/home.svg?react'; import HomeIcon from '@/material-icons/400-24px/home.svg?react';
import InfoIcon from '@/material-icons/400-24px/info.svg?react'; import InfoIcon from '@/material-icons/400-24px/info.svg?react';
@@ -50,16 +49,13 @@ import {
me, me,
} from 'flavours/glitch/initial_state'; } from 'flavours/glitch/initial_state';
import { transientSingleColumn } from 'flavours/glitch/is_mobile'; import { transientSingleColumn } from 'flavours/glitch/is_mobile';
import {
canManageReports,
canViewAdminDashboard,
} from 'flavours/glitch/permissions';
import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications'; import { selectUnreadNotificationGroupsCount } from 'flavours/glitch/selectors/notifications';
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store'; import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
import { ColumnLink } from './column_link'; import { ColumnLink } from './column_link';
import DisabledAccountBanner from './disabled_account_banner'; import DisabledAccountBanner from './disabled_account_banner';
import { ListPanel } from './list_panel'; import { ListPanel } from './list_panel';
import { MoreLink } from './more_link';
import SignInBanner from './sign_in_banner'; import SignInBanner from './sign_in_banner';
const messages = defineMessages({ const messages = defineMessages({
@@ -77,11 +73,6 @@ const messages = defineMessages({
id: 'navigation_bar.preferences', id: 'navigation_bar.preferences',
defaultMessage: 'Preferences', defaultMessage: 'Preferences',
}, },
administration: {
id: 'navigation_bar.administration',
defaultMessage: 'Administration',
},
moderation: { id: 'navigation_bar.moderation', defaultMessage: 'Moderation' },
followsAndFollowers: { followsAndFollowers: {
id: 'navigation_bar.follows_and_followers', id: 'navigation_bar.follows_and_followers',
defaultMessage: 'Follows and followers', defaultMessage: 'Follows and followers',
@@ -250,7 +241,7 @@ const MENU_WIDTH = 284;
export const NavigationPanel: React.FC = () => { export const NavigationPanel: React.FC = () => {
const intl = useIntl(); const intl = useIntl();
const { signedIn, disabledAccountId, permissions } = useIdentity(); const { signedIn, disabledAccountId } = useIdentity();
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');
@@ -489,31 +480,13 @@ export const NavigationPanel: React.FC = () => {
text={intl.formatMessage(messages.app_settings)} text={intl.formatMessage(messages.app_settings)}
/> />
{canManageReports(permissions) && ( <MoreLink />
<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'> <div className='navigation-panel__legal'>
<hr /> <hr />
<ColumnLink <ColumnLink
transparent transparent
to='/about' to='/about'

View File

@@ -6585,6 +6585,7 @@ a.status-card {
@media screen and (max-width: $no-columns-breakpoint) { @media screen and (max-width: $no-columns-breakpoint) {
border-bottom: 0; border-bottom: 0;
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
padding-bottom: env(safe-area-inset-bottom);
} }
} }