[Glitch] Improve the list selection UI for notification requests

Port 98bf2fc27c to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
shrike
Renaud Chaput 2024-08-20 00:11:58 +02:00 committed by Claire
parent f5c0c32edd
commit 4e5d85b637
4 changed files with 60 additions and 89 deletions

View File

@ -7,6 +7,7 @@ import { Helmet } from 'react-helmet';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import ArrowDropDownIcon from '@/material-icons/400-24px/arrow_drop_down.svg?react';
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react'; import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { openModal } from 'flavours/glitch/actions/modal'; import { openModal } from 'flavours/glitch/actions/modal';
@ -15,6 +16,7 @@ import { changeSetting } from 'flavours/glitch/actions/settings';
import { CheckBox } from 'flavours/glitch/components/check_box'; import { CheckBox } from 'flavours/glitch/components/check_box';
import Column from 'flavours/glitch/components/column'; import Column from 'flavours/glitch/components/column';
import ColumnHeader from 'flavours/glitch/components/column_header'; import ColumnHeader from 'flavours/glitch/components/column_header';
import { Icon } from 'flavours/glitch/components/icon';
import ScrollableList from 'flavours/glitch/components/scrollable_list'; import ScrollableList from 'flavours/glitch/components/scrollable_list';
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container'; import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
@ -26,16 +28,14 @@ const messages = defineMessages({
title: { id: 'notification_requests.title', defaultMessage: 'Filtered notifications' }, title: { id: 'notification_requests.title', defaultMessage: 'Filtered notifications' },
maximize: { id: 'notification_requests.maximize', defaultMessage: 'Maximize' }, maximize: { id: 'notification_requests.maximize', defaultMessage: 'Maximize' },
more: { id: 'status.more', defaultMessage: 'More' }, more: { id: 'status.more', defaultMessage: 'More' },
acceptAll: { id: 'notification_requests.accept_all', defaultMessage: 'Accept all' }, acceptMultiple: { id: 'notification_requests.accept_multiple', defaultMessage: '{count, plural, one {Accept # request…} other {Accept # requests…}}' },
dismissAll: { id: 'notification_requests.dismiss_all', defaultMessage: 'Dismiss all' }, dismissMultiple: { id: 'notification_requests.dismiss_multiple', defaultMessage: '{count, plural, one {Dismiss # request…} other {Dismiss # requests…}}' },
acceptMultiple: { id: 'notification_requests.accept_multiple', defaultMessage: '{count, plural, one {Accept # request} other {Accept # requests}}' }, confirmAcceptMultipleTitle: { id: 'notification_requests.confirm_accept_multiple.title', defaultMessage: 'Accept notification requests?' },
dismissMultiple: { id: 'notification_requests.dismiss_multiple', defaultMessage: '{count, plural, one {Dismiss # request} other {Dismiss # requests}}' }, confirmAcceptMultipleMessage: { id: 'notification_requests.confirm_accept_multiple.message', defaultMessage: 'You are about to accept {count, plural, one {one notification request} other {# notification requests}}. Are you sure you want to proceed?' },
confirmAcceptAllTitle: { id: 'notification_requests.confirm_accept_all.title', defaultMessage: 'Accept notification requests?' }, confirmAcceptMultipleButton: { id: 'notification_requests.confirm_accept_multiple.button', defaultMessage: '{count, plural, one {Accept request} other {Accept requests}}' },
confirmAcceptAllMessage: { id: 'notification_requests.confirm_accept_all.message', defaultMessage: 'You are about to accept {count, plural, one {one notification request} other {# notification requests}}. Are you sure you want to proceed?' }, confirmDismissMultipleTitle: { id: 'notification_requests.confirm_dismiss_multiple.title', defaultMessage: 'Dismiss notification requests?' },
confirmAcceptAllButton: { id: 'notification_requests.confirm_accept_all.button', defaultMessage: 'Accept all' }, confirmDismissMultipleMessage: { id: 'notification_requests.confirm_dismiss_multiple.message', defaultMessage: "You are about to dismiss {count, plural, one {one notification request} other {# notification requests}}. You won't be able to easily access {count, plural, one {it} other {them}} again. Are you sure you want to proceed?" },
confirmDismissAllTitle: { id: 'notification_requests.confirm_dismiss_all.title', defaultMessage: 'Dismiss notification requests?' }, confirmDismissMultipleButton: { id: 'notification_requests.confirm_dismiss_multiple.button', defaultMessage: '{count, plural, one {Dismiss request} other {Dismiss requests}}' },
confirmDismissAllMessage: { id: 'notification_requests.confirm_dismiss_all.message', defaultMessage: "You are about to dismiss {count, plural, one {one notification request} other {# notification requests}}. You won't be able to easily access {count, plural, one {it} other {them}} again. Are you sure you want to proceed?" },
confirmDismissAllButton: { id: 'notification_requests.confirm_dismiss_all.button', defaultMessage: 'Dismiss all' },
}); });
const ColumnSettings = () => { const ColumnSettings = () => {
@ -74,45 +74,15 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM
const intl = useIntl(); const intl = useIntl();
const dispatch = useDispatch(); const dispatch = useDispatch();
const notificationRequests = useSelector(state => state.getIn(['notificationRequests', 'items']));
const selectedCount = selectedItems.length; const selectedCount = selectedItems.length;
const handleAcceptAll = useCallback(() => {
const items = notificationRequests.map(request => request.get('id')).toArray();
dispatch(openModal({
modalType: 'CONFIRM',
modalProps: {
title: intl.formatMessage(messages.confirmAcceptAllTitle),
message: intl.formatMessage(messages.confirmAcceptAllMessage, { count: items.length }),
confirm: intl.formatMessage(messages.confirmAcceptAllButton),
onConfirm: () =>
dispatch(acceptNotificationRequests(items)),
},
}));
}, [dispatch, intl, notificationRequests]);
const handleDismissAll = useCallback(() => {
const items = notificationRequests.map(request => request.get('id')).toArray();
dispatch(openModal({
modalType: 'CONFIRM',
modalProps: {
title: intl.formatMessage(messages.confirmDismissAllTitle),
message: intl.formatMessage(messages.confirmDismissAllMessage, { count: items.length }),
confirm: intl.formatMessage(messages.confirmDismissAllButton),
onConfirm: () =>
dispatch(dismissNotificationRequests(items)),
},
}));
}, [dispatch, intl, notificationRequests]);
const handleAcceptMultiple = useCallback(() => { const handleAcceptMultiple = useCallback(() => {
dispatch(openModal({ dispatch(openModal({
modalType: 'CONFIRM', modalType: 'CONFIRM',
modalProps: { modalProps: {
title: intl.formatMessage(messages.confirmAcceptAllTitle), title: intl.formatMessage(messages.confirmAcceptMultipleTitle),
message: intl.formatMessage(messages.confirmAcceptAllMessage, { count: selectedItems.length }), message: intl.formatMessage(messages.confirmAcceptMultipleMessage, { count: selectedItems.length }),
confirm: intl.formatMessage(messages.confirmAcceptAllButton), confirm: intl.formatMessage(messages.confirmAcceptMultipleButton, { count: selectedItems.length}),
onConfirm: () => onConfirm: () =>
dispatch(acceptNotificationRequests(selectedItems)), dispatch(acceptNotificationRequests(selectedItems)),
}, },
@ -123,9 +93,9 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM
dispatch(openModal({ dispatch(openModal({
modalType: 'CONFIRM', modalType: 'CONFIRM',
modalProps: { modalProps: {
title: intl.formatMessage(messages.confirmDismissAllTitle), title: intl.formatMessage(messages.confirmDismissMultipleTitle),
message: intl.formatMessage(messages.confirmDismissAllMessage, { count: selectedItems.length }), message: intl.formatMessage(messages.confirmDismissMultipleMessage, { count: selectedItems.length }),
confirm: intl.formatMessage(messages.confirmDismissAllButton), confirm: intl.formatMessage(messages.confirmDismissMultipleButton, { count: selectedItems.length}),
onConfirm: () => onConfirm: () =>
dispatch(dismissNotificationRequests(selectedItems)), dispatch(dismissNotificationRequests(selectedItems)),
}, },
@ -136,46 +106,45 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM
setSelectionMode((mode) => !mode); setSelectionMode((mode) => !mode);
}, [setSelectionMode]); }, [setSelectionMode]);
const menu = selectedCount === 0 ? const menu = [
[ { text: intl.formatMessage(messages.acceptMultiple, { count: selectedCount }), action: handleAcceptMultiple },
{ text: intl.formatMessage(messages.acceptAll), action: handleAcceptAll }, { text: intl.formatMessage(messages.dismissMultiple, { count: selectedCount }), action: handleDismissMultiple },
{ text: intl.formatMessage(messages.dismissAll), action: handleDismissAll }, ];
] : [
{ text: intl.formatMessage(messages.acceptMultiple, { count: selectedCount }), action: handleAcceptMultiple }, const handleSelectAll = useCallback(() => {
{ text: intl.formatMessage(messages.dismissMultiple, { count: selectedCount }), action: handleDismissMultiple }, setSelectionMode(true);
]; toggleSelectAll();
}, [setSelectionMode, toggleSelectAll]);
return ( return (
<div className='column-header__select-row'> <div className='column-header__select-row'>
{selectionMode && ( <div className='column-header__select-row__checkbox'>
<div className='column-header__select-row__checkbox'> <CheckBox checked={selectAllChecked} indeterminate={selectedCount > 0 && !selectAllChecked} onChange={handleSelectAll} />
<CheckBox checked={selectAllChecked} indeterminate={selectedCount > 0 && !selectAllChecked} onChange={toggleSelectAll} /> </div>
</div> <DropdownMenuContainer
)} items={menu}
<div className='column-header__select-row__selection-mode'> icons='ellipsis-h'
iconComponent={MoreHorizIcon}
direction='right'
title={intl.formatMessage(messages.more)}
>
<button className='dropdown-button column-header__select-row__select-menu' disabled={selectedItems.length === 0}>
<span className='dropdown-button__label'>
{selectedCount} selected
</span>
<Icon id='down' icon={ArrowDropDownIcon} />
</button>
</DropdownMenuContainer>
<div className='column-header__select-row__mode-button'>
<button className='text-btn' tabIndex={0} onClick={handleToggleSelectionMode}> <button className='text-btn' tabIndex={0} onClick={handleToggleSelectionMode}>
{selectionMode ? ( {selectionMode ? (
<FormattedMessage id='notification_requests.exit_selection_mode' defaultMessage='Cancel' /> <FormattedMessage id='notification_requests.exit_selection' defaultMessage='Done' />
) : ) :
( (
<FormattedMessage id='notification_requests.enter_selection_mode' defaultMessage='Select' /> <FormattedMessage id='notification_requests.edit_selection' defaultMessage='Edit' />
)} )}
</button> </button>
</div> </div>
{selectedCount > 0 &&
<div className='column-header__select-row__selected-count'>
{selectedCount} selected
</div>
}
<div className='column-header__select-row__actions'>
<DropdownMenuContainer
items={menu}
icons='ellipsis-h'
iconComponent={MoreHorizIcon}
direction='right'
title={intl.formatMessage(messages.more)}
/>
</div>
</div> </div>
); );
}; };

View File

@ -4422,7 +4422,7 @@ a.status-card {
text-decoration: none; text-decoration: none;
&:hover { &:hover {
background: lighten($ui-base-color, 2%); background: var(--on-surface-color);
} }
} }
@ -4551,19 +4551,18 @@ a.status-card {
display: flex; display: flex;
} }
&__selection-mode { &__select-menu:disabled {
flex-grow: 1; visibility: hidden;
.text-btn:hover {
text-decoration: underline;
}
} }
&__actions { &__mode-button {
.icon-button { margin-left: auto;
border-radius: 4px; color: $highlight-text-color;
border: 1px solid var(--background-border-color); font-weight: bold;
padding: 5px; font-size: 14px;
&:hover {
color: lighten($highlight-text-color, 6%);
} }
} }
} }
@ -4916,6 +4915,7 @@ a.status-card {
padding: 0; padding: 0;
font-family: inherit; font-family: inherit;
font-size: inherit; font-size: inherit;
font-weight: inherit;
color: inherit; color: inherit;
border: 0; border: 0;
background: transparent; background: transparent;
@ -10923,7 +10923,7 @@ noscript {
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: lighten($ui-base-color, 1%); background: var(--on-surface-color);
} }
.notification-request__checkbox { .notification-request__checkbox {

View File

@ -65,4 +65,5 @@ body {
--background-color: #fff; --background-color: #fff;
--background-color-tint: rgba(255, 255, 255, 80%); --background-color-tint: rgba(255, 255, 255, 80%);
--background-filter: blur(10px); --background-filter: blur(10px);
--on-surface-color: #{transparentize($ui-base-color, 0.65)};
} }

View File

@ -115,5 +115,6 @@ $dismiss-overlay-width: 4rem;
--surface-background-color: #{darken($ui-base-color, 4%)}; --surface-background-color: #{darken($ui-base-color, 4%)};
--surface-variant-background-color: #{$ui-base-color}; --surface-variant-background-color: #{$ui-base-color};
--surface-variant-active-background-color: #{lighten($ui-base-color, 4%)}; --surface-variant-active-background-color: #{lighten($ui-base-color, 4%)};
--on-surface-color: #{transparentize($ui-base-color, 0.5)};
--avatar-border-radius: 8px; --avatar-border-radius: 8px;
} }