From fd01597d9f61104a08b9079fa2ebce2abb343f95 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Mon, 22 Mar 2021 18:15:00 +0800 Subject: [PATCH] client: add a ToggleList component Bug: #216 --- .../components/general/SortableList.tsx | 4 - .../components/general/SortableListItem.tsx | 26 ++---- .../components/general/ToggleList.tsx | 62 ++++++++++++++ .../lists/TorrentContextMenuActionsList.tsx | 81 ++++++------------- .../src/sass/components/_sortable-list.scss | 6 -- 5 files changed, 94 insertions(+), 85 deletions(-) create mode 100644 client/src/javascript/components/general/ToggleList.tsx diff --git a/client/src/javascript/components/general/SortableList.tsx b/client/src/javascript/components/general/SortableList.tsx index 53803cb25..55679c58e 100644 --- a/client/src/javascript/components/general/SortableList.tsx +++ b/client/src/javascript/components/general/SortableList.tsx @@ -15,7 +15,6 @@ interface SortableListProps { className: string; lockedIDs: Array; items: Array; - isDraggable?: boolean; renderItem: (item: ListItem, index: number) => ReactNode; onMouseDown?: (event: MouseEvent) => void; onMove?: (items: this['items']) => void; @@ -27,7 +26,6 @@ const SortableList: FC = ({ id: listID, items, lockedIDs, - isDraggable, renderItem, onMouseDown, onMove, @@ -55,7 +53,6 @@ const SortableList: FC = ({ id={id} index={index} isLocked={lockedIDs.includes(id)} - isDraggable={isDraggable} isVisible={visible} key={id} onDrop={() => { @@ -90,7 +87,6 @@ const SortableList: FC = ({ }; SortableList.defaultProps = { - isDraggable: undefined, onMouseDown: undefined, onMove: undefined, onDrop: undefined, diff --git a/client/src/javascript/components/general/SortableListItem.tsx b/client/src/javascript/components/general/SortableListItem.tsx index a15af3352..ebafc3991 100644 --- a/client/src/javascript/components/general/SortableListItem.tsx +++ b/client/src/javascript/components/general/SortableListItem.tsx @@ -14,7 +14,6 @@ interface SortableListItemProps { isVisible: boolean; isDragging?: boolean; isLocked?: boolean; - isDraggable?: boolean; onDrop: () => void; onMove: (sourceIndex: number, targetIndex: number) => void; connectDragPreview: DragElementWrapper; @@ -31,21 +30,14 @@ const SortableListItem: FC = (props: SortableListItemProp }); }); - let lockedIcon = null; - - if (isLocked) { - lockedIcon = ; - } - - const classes = classnames('sortable-list__item', { - 'sortable-list__item--is-dragging': isDragging, - 'sortable-list__item--is-locked': isLocked, - }); - return connectDragSource( connectDropTarget( -
- {lockedIcon} +
+ {isLocked ? : null} {children}
, ), @@ -60,11 +52,7 @@ export default flow([ return {list, id, index, isVisible}; }, - canDrag({isLocked, isDraggable}: SortableListItemProps) { - if (isDraggable != null) { - return isDraggable; - } - + canDrag({isLocked}: SortableListItemProps) { if (isLocked) { return false; } diff --git a/client/src/javascript/components/general/ToggleList.tsx b/client/src/javascript/components/general/ToggleList.tsx new file mode 100644 index 000000000..d75e83da3 --- /dev/null +++ b/client/src/javascript/components/general/ToggleList.tsx @@ -0,0 +1,62 @@ +import classnames from 'classnames'; +import {FC} from 'react'; +import {Trans} from '@lingui/react'; + +import {Checkbox} from '@client/ui'; +import {Lock} from '@client/ui/icons'; + +interface ToggleListProps { + className?: string; + items: Array<{ + id: string; + isLocked: boolean; + defaultChecked: boolean; + onClick: (checked: boolean) => void; + }>; +} + +const ToggleList: FC = ({className, items}: ToggleListProps) => ( +
+
    + {items.map((item) => { + const {id, isLocked, defaultChecked, onClick} = item; + return ( +
  • + {isLocked ? : null} +
    + + + + {isLocked ? null : ( + + onClick((event.target as HTMLInputElement).checked)}> + + + + )} +
    +
  • + ); + })} +
+
+); + +ToggleList.defaultProps = { + className: undefined, +}; + +export default ToggleList; diff --git a/client/src/javascript/components/modals/settings-modal/lists/TorrentContextMenuActionsList.tsx b/client/src/javascript/components/modals/settings-modal/lists/TorrentContextMenuActionsList.tsx index 909d60b1a..22cf9d6dc 100644 --- a/client/src/javascript/components/modals/settings-modal/lists/TorrentContextMenuActionsList.tsx +++ b/client/src/javascript/components/modals/settings-modal/lists/TorrentContextMenuActionsList.tsx @@ -1,78 +1,47 @@ -import {FC, useState} from 'react'; -import {Trans} from '@lingui/react'; +import {FC, useRef} from 'react'; -import {Checkbox} from '@client/ui'; import SettingStore from '@client/stores/SettingStore'; -import SortableList, {ListItem} from '@client/components/general/SortableList'; +import ToggleList from '@client/components/general/ToggleList'; import TorrentContextMenuActions from '@client/constants/TorrentContextMenuActions'; import type {TorrentContextMenuAction} from '@client/constants/TorrentContextMenuActions'; +import defaultFloodSettings from '@shared/constants/defaultFloodSettings'; + import type {FloodSettings} from '@shared/types/FloodSettings'; interface TorrentContextMenuActionsListProps { onSettingsChange: (changedSettings: Partial) => void; } -const lockedIDs: Array = ['start', 'stop', 'setTaxonomy', 'torrentDetails']; - const TorrentContextMenuActionsList: FC = ({ onSettingsChange, }: TorrentContextMenuActionsListProps) => { - const [torrentContextMenuActions, setTorrentContextMenuActions] = useState( - Object.keys(TorrentContextMenuActions).map((key) => ({ - id: key, - visible: SettingStore.floodSettings.torrentContextMenuActions.some( - (setting) => setting.id === key && setting.visible, - ), + const changedTorrentContextMenuActionsRef = useRef( + defaultFloodSettings.torrentContextMenuActions.map(({id, visible: defaultVisible}) => ({ + id, + visible: + SettingStore.floodSettings.torrentContextMenuActions.find((setting) => setting.id === id)?.visible ?? + defaultVisible, })), ); return ( - { - const {id, visible} = item as FloodSettings['torrentContextMenuActions'][number]; - let checkbox = null; - - if (!lockedIDs.includes(id)) { - checkbox = ( - - { - const newTorrentContextMenuActions = torrentContextMenuActions.map((setting) => ({ - id: setting.id, - visible: setting.id === id ? (event.target as HTMLInputElement).checked : setting.visible, - })); - - onSettingsChange({ - torrentContextMenuActions: newTorrentContextMenuActions as FloodSettings['torrentContextMenuActions'], - }); - setTorrentContextMenuActions(newTorrentContextMenuActions); - }}> - - - - ); - } - - const content = ( -
- - - - {checkbox} -
- ); - - return content; - }} + ({ + id: TorrentContextMenuActions[action as TorrentContextMenuAction], + isLocked: action === 'start' || action === 'stop' || action === 'setTaxonomy' || action === 'torrentDetails', + defaultChecked: changedTorrentContextMenuActionsRef.current.some( + (setting) => setting.id === action && setting.visible, + ), + onClick: () => { + const currentSetting = changedTorrentContextMenuActionsRef.current.find((setting) => setting.id === action); + if (currentSetting != null) { + currentSetting.visible = !currentSetting.visible; + } + onSettingsChange({torrentContextMenuActions: changedTorrentContextMenuActionsRef.current}); + }, + }))} /> ); }; diff --git a/client/src/sass/components/_sortable-list.scss b/client/src/sass/components/_sortable-list.scss index e8a71c8d9..81c779098 100644 --- a/client/src/sass/components/_sortable-list.scss +++ b/client/src/sass/components/_sortable-list.scss @@ -118,10 +118,4 @@ $sortable-list--item--border--preview: darken($sortable-list--item--border, 3%); } } } - - &--torrent-context-menu-items { - .sortable-list__item { - cursor: default; - } - } }