Improve the list selection UI for notification requests (#31457)
This commit is contained in:
		
							parent
							
								
									a7a2ff6c1d
								
							
						
					
					
						commit
						98bf2fc27c
					
				| @ -7,6 +7,7 @@ import { Helmet } from 'react-helmet'; | ||||
| 
 | ||||
| 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 MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; | ||||
| import { openModal } from 'mastodon/actions/modal'; | ||||
| @ -15,6 +16,7 @@ import { changeSetting } from 'mastodon/actions/settings'; | ||||
| import { CheckBox } from 'mastodon/components/check_box'; | ||||
| import Column from 'mastodon/components/column'; | ||||
| import ColumnHeader from 'mastodon/components/column_header'; | ||||
| import { Icon } from 'mastodon/components/icon'; | ||||
| import ScrollableList from 'mastodon/components/scrollable_list'; | ||||
| import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; | ||||
| 
 | ||||
| @ -26,16 +28,14 @@ const messages = defineMessages({ | ||||
|   title: { id: 'notification_requests.title', defaultMessage: 'Filtered notifications' }, | ||||
|   maximize: { id: 'notification_requests.maximize', defaultMessage: 'Maximize' }, | ||||
|   more: { id: 'status.more', defaultMessage: 'More' }, | ||||
|   acceptAll: { id: 'notification_requests.accept_all', defaultMessage: 'Accept all' }, | ||||
|   dismissAll: { id: 'notification_requests.dismiss_all', defaultMessage: 'Dismiss all' }, | ||||
|   acceptMultiple: { id: 'notification_requests.accept_multiple', defaultMessage: '{count, plural, one {Accept # request} other {Accept # requests}}' }, | ||||
|   dismissMultiple: { id: 'notification_requests.dismiss_multiple', defaultMessage: '{count, plural, one {Dismiss # request} other {Dismiss # requests}}' }, | ||||
|   confirmAcceptAllTitle: { id: 'notification_requests.confirm_accept_all.title', defaultMessage: 'Accept notification 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?' }, | ||||
|   confirmAcceptAllButton: { id: 'notification_requests.confirm_accept_all.button', defaultMessage: 'Accept all' }, | ||||
|   confirmDismissAllTitle: { id: 'notification_requests.confirm_dismiss_all.title', defaultMessage: 'Dismiss notification 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' }, | ||||
|   acceptMultiple: { id: 'notification_requests.accept_multiple', defaultMessage: '{count, plural, one {Accept # request…} other {Accept # requests…}}' }, | ||||
|   dismissMultiple: { id: 'notification_requests.dismiss_multiple', defaultMessage: '{count, plural, one {Dismiss # request…} other {Dismiss # requests…}}' }, | ||||
|   confirmAcceptMultipleTitle: { id: 'notification_requests.confirm_accept_multiple.title', defaultMessage: 'Accept notification 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?' }, | ||||
|   confirmAcceptMultipleButton: { id: 'notification_requests.confirm_accept_multiple.button', defaultMessage: '{count, plural, one {Accept request} other {Accept requests}}' }, | ||||
|   confirmDismissMultipleTitle: { id: 'notification_requests.confirm_dismiss_multiple.title', defaultMessage: 'Dismiss notification requests?' }, | ||||
|   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?" }, | ||||
|   confirmDismissMultipleButton: { id: 'notification_requests.confirm_dismiss_multiple.button', defaultMessage: '{count, plural, one {Dismiss request} other {Dismiss requests}}' }, | ||||
| }); | ||||
| 
 | ||||
| const ColumnSettings = () => { | ||||
| @ -74,45 +74,15 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM | ||||
|   const intl = useIntl(); | ||||
|   const dispatch = useDispatch(); | ||||
| 
 | ||||
|   const notificationRequests = useSelector(state => state.getIn(['notificationRequests', 'items'])); | ||||
| 
 | ||||
|   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(() => { | ||||
|     dispatch(openModal({ | ||||
|       modalType: 'CONFIRM', | ||||
|       modalProps: { | ||||
|         title: intl.formatMessage(messages.confirmAcceptAllTitle), | ||||
|         message: intl.formatMessage(messages.confirmAcceptAllMessage, { count: selectedItems.length }), | ||||
|         confirm: intl.formatMessage(messages.confirmAcceptAllButton), | ||||
|         title: intl.formatMessage(messages.confirmAcceptMultipleTitle), | ||||
|         message: intl.formatMessage(messages.confirmAcceptMultipleMessage, { count: selectedItems.length }), | ||||
|         confirm: intl.formatMessage(messages.confirmAcceptMultipleButton, { count: selectedItems.length}), | ||||
|         onConfirm: () => | ||||
|           dispatch(acceptNotificationRequests(selectedItems)), | ||||
|       }, | ||||
| @ -123,9 +93,9 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM | ||||
|     dispatch(openModal({ | ||||
|       modalType: 'CONFIRM', | ||||
|       modalProps: { | ||||
|         title: intl.formatMessage(messages.confirmDismissAllTitle), | ||||
|         message: intl.formatMessage(messages.confirmDismissAllMessage, { count: selectedItems.length }), | ||||
|         confirm: intl.formatMessage(messages.confirmDismissAllButton), | ||||
|         title: intl.formatMessage(messages.confirmDismissMultipleTitle), | ||||
|         message: intl.formatMessage(messages.confirmDismissMultipleMessage, { count: selectedItems.length }), | ||||
|         confirm: intl.formatMessage(messages.confirmDismissMultipleButton, { count: selectedItems.length}), | ||||
|         onConfirm: () => | ||||
|           dispatch(dismissNotificationRequests(selectedItems)), | ||||
|       }, | ||||
| @ -136,46 +106,45 @@ const SelectRow = ({selectAllChecked, toggleSelectAll, selectedItems, selectionM | ||||
|     setSelectionMode((mode) => !mode); | ||||
|   }, [setSelectionMode]); | ||||
| 
 | ||||
|   const menu = selectedCount === 0 ? | ||||
|     [ | ||||
|       { text: intl.formatMessage(messages.acceptAll), action: handleAcceptAll }, | ||||
|       { text: intl.formatMessage(messages.dismissAll), action: handleDismissAll }, | ||||
|     ] : [ | ||||
|       { text: intl.formatMessage(messages.acceptMultiple, { count: selectedCount }), action: handleAcceptMultiple }, | ||||
|       { text: intl.formatMessage(messages.dismissMultiple, { count: selectedCount }), action: handleDismissMultiple }, | ||||
|     ]; | ||||
|   const menu = [ | ||||
|     { text: intl.formatMessage(messages.acceptMultiple, { count: selectedCount }), action: handleAcceptMultiple }, | ||||
|     { text: intl.formatMessage(messages.dismissMultiple, { count: selectedCount }), action: handleDismissMultiple }, | ||||
|   ]; | ||||
| 
 | ||||
|   const handleSelectAll = useCallback(() => { | ||||
|     setSelectionMode(true); | ||||
|     toggleSelectAll(); | ||||
|   }, [setSelectionMode, toggleSelectAll]); | ||||
| 
 | ||||
|   return ( | ||||
|     <div className='column-header__select-row'> | ||||
|       {selectionMode && ( | ||||
|         <div className='column-header__select-row__checkbox'> | ||||
|           <CheckBox checked={selectAllChecked} indeterminate={selectedCount > 0 && !selectAllChecked} onChange={toggleSelectAll} /> | ||||
|         </div> | ||||
|       )} | ||||
|       <div className='column-header__select-row__selection-mode'> | ||||
|       <div className='column-header__select-row__checkbox'> | ||||
|         <CheckBox checked={selectAllChecked} indeterminate={selectedCount > 0 && !selectAllChecked} onChange={handleSelectAll} /> | ||||
|       </div> | ||||
|       <DropdownMenuContainer | ||||
|         items={menu} | ||||
|         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}> | ||||
|           {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> | ||||
|       </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> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -518,19 +518,17 @@ | ||||
|   "notification.status": "{name} just posted", | ||||
|   "notification.update": "{name} edited a post", | ||||
|   "notification_requests.accept": "Accept", | ||||
|   "notification_requests.accept_all": "Accept all", | ||||
|   "notification_requests.accept_multiple": "{count, plural, one {Accept # request} other {Accept # requests}}", | ||||
|   "notification_requests.confirm_accept_all.button": "Accept all", | ||||
|   "notification_requests.confirm_accept_all.message": "You are about to accept {count, plural, one {one notification request} other {# notification requests}}. Are you sure you want to proceed?", | ||||
|   "notification_requests.confirm_accept_all.title": "Accept notification requests?", | ||||
|   "notification_requests.confirm_dismiss_all.button": "Dismiss all", | ||||
|   "notification_requests.confirm_dismiss_all.message": "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?", | ||||
|   "notification_requests.confirm_dismiss_all.title": "Dismiss notification requests?", | ||||
|   "notification_requests.accept_multiple": "{count, plural, one {Accept # request…} other {Accept # requests…}}", | ||||
|   "notification_requests.confirm_accept_multiple.button": "{count, plural, one {Accept request} other {Accept requests}}", | ||||
|   "notification_requests.confirm_accept_multiple.message": "You are about to accept {count, plural, one {one notification request} other {# notification requests}}. Are you sure you want to proceed?", | ||||
|   "notification_requests.confirm_accept_multiple.title": "Accept notification requests?", | ||||
|   "notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Dismiss request} other {Dismiss requests}}", | ||||
|   "notification_requests.confirm_dismiss_multiple.message": "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?", | ||||
|   "notification_requests.confirm_dismiss_multiple.title": "Dismiss notification requests?", | ||||
|   "notification_requests.dismiss": "Dismiss", | ||||
|   "notification_requests.dismiss_all": "Dismiss all", | ||||
|   "notification_requests.dismiss_multiple": "{count, plural, one {Dismiss # request} other {Dismiss # requests}}", | ||||
|   "notification_requests.enter_selection_mode": "Select", | ||||
|   "notification_requests.exit_selection_mode": "Cancel", | ||||
|   "notification_requests.dismiss_multiple": "{count, plural, one {Dismiss # request…} other {Dismiss # requests…}}", | ||||
|   "notification_requests.edit_selection": "Edit", | ||||
|   "notification_requests.exit_selection": "Done", | ||||
|   "notification_requests.explainer_for_limited_account": "Notifications from this account have been filtered because the account has been limited by a moderator.", | ||||
|   "notification_requests.explainer_for_limited_remote_account": "Notifications from this account have been filtered because the account or its server has been limited by a moderator.", | ||||
|   "notification_requests.maximize": "Maximize", | ||||
|  | ||||
| @ -65,4 +65,5 @@ body { | ||||
|   --background-color: #fff; | ||||
|   --background-color-tint: rgba(255, 255, 255, 80%); | ||||
|   --background-filter: blur(10px); | ||||
|   --on-surface-color: #{transparentize($ui-base-color, 0.65)}; | ||||
| } | ||||
|  | ||||
| @ -4217,7 +4217,7 @@ a.status-card { | ||||
|   text-decoration: none; | ||||
| 
 | ||||
|   &:hover { | ||||
|     background: lighten($ui-base-color, 2%); | ||||
|     background: var(--on-surface-color); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -4346,19 +4346,18 @@ a.status-card { | ||||
|     display: flex; | ||||
|   } | ||||
| 
 | ||||
|   &__selection-mode { | ||||
|     flex-grow: 1; | ||||
| 
 | ||||
|     .text-btn:hover { | ||||
|       text-decoration: underline; | ||||
|     } | ||||
|   &__select-menu:disabled { | ||||
|     visibility: hidden; | ||||
|   } | ||||
| 
 | ||||
|   &__actions { | ||||
|     .icon-button { | ||||
|       border-radius: 4px; | ||||
|       border: 1px solid var(--background-border-color); | ||||
|       padding: 5px; | ||||
|   &__mode-button { | ||||
|     margin-left: auto; | ||||
|     color: $highlight-text-color; | ||||
|     font-weight: bold; | ||||
|     font-size: 14px; | ||||
| 
 | ||||
|     &:hover { | ||||
|       color: lighten($highlight-text-color, 6%); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -4566,6 +4565,7 @@ a.status-card { | ||||
|   padding: 0; | ||||
|   font-family: inherit; | ||||
|   font-size: inherit; | ||||
|   font-weight: inherit; | ||||
|   color: inherit; | ||||
|   border: 0; | ||||
|   background: transparent; | ||||
| @ -10366,7 +10366,7 @@ noscript { | ||||
|     cursor: pointer; | ||||
| 
 | ||||
|     &:hover { | ||||
|       background: lighten($ui-base-color, 1%); | ||||
|       background: var(--on-surface-color); | ||||
|     } | ||||
| 
 | ||||
|     .notification-request__checkbox { | ||||
|  | ||||
| @ -109,5 +109,6 @@ $font-monospace: 'mastodon-font-monospace' !default; | ||||
|   --surface-background-color: #{darken($ui-base-color, 4%)}; | ||||
|   --surface-variant-background-color: #{$ui-base-color}; | ||||
|   --surface-variant-active-background-color: #{lighten($ui-base-color, 4%)}; | ||||
|   --on-surface-color: #{transparentize($ui-base-color, 0.5)}; | ||||
|   --avatar-border-radius: 8px; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user