diff --git a/client/src/javascript/components/modals/torrent-details-modal/TorrentContents.tsx b/client/src/javascript/components/modals/torrent-details-modal/TorrentContents.tsx index c0f10328..ff764d2d 100644 --- a/client/src/javascript/components/modals/torrent-details-modal/TorrentContents.tsx +++ b/client/src/javascript/components/modals/torrent-details-modal/TorrentContents.tsx @@ -1,8 +1,7 @@ -import {observable, runInAction} from 'mobx'; import classnames from 'classnames'; -import {FormattedMessage, injectIntl, WrappedComponentProps} from 'react-intl'; +import {FormattedMessage, useIntl} from 'react-intl'; import {observer} from 'mobx-react'; -import * as React from 'react'; +import {FC, useEffect, useState} from 'react'; import type {TorrentContent, TorrentContentSelection, TorrentContentSelectionTree} from '@shared/types/TorrentContent'; @@ -15,199 +14,180 @@ import TorrentActions from '../../../actions/TorrentActions'; import TorrentStore from '../../../stores/TorrentStore'; import UIStore from '../../../stores/UIStore'; -@observer -class TorrentContents extends React.Component { - contents = observable.array([]); - itemsTree = observable.object({}); - selectedIndices = observable.array([]); - polling = setInterval(() => { - // TODO: itemsTree is not regenerated as that would override user's selection. - // As a result, percentage of contents of an active torrent is not updated. - // this.fetchTorrentContents(); - }, ConfigStore.pollInterval); +const TorrentContents: FC = observer(() => { + const [contents, setContents] = useState([]); + const [itemsTree, setItemsTree] = useState({}); + const [selectedIndices, setSelectedIndices] = useState([]); + const intl = useIntl(); - constructor(props: WrappedComponentProps) { - super(props); - - this.fetchTorrentContents(true); - } - - componentWillUnmount() { - clearInterval(this.polling); - } - - fetchTorrentContents = (populateTree = false) => { + useEffect(() => { if (UIStore.activeModal?.id === 'torrent-details') { - TorrentActions.fetchTorrentContents(UIStore.activeModal?.hash).then((contents) => { - if (contents != null) { - runInAction(() => { - this.contents.replace(contents); - if (populateTree) { - this.itemsTree = selectionTree.getSelectionTree(this.contents); - } - }); + TorrentActions.fetchTorrentContents(UIStore.activeModal?.hash).then((fetchedContents) => { + if (fetchedContents != null) { + setContents(fetchedContents); + setItemsTree(selectionTree.getSelectionTree(fetchedContents)); } }); } - }; + }, []); - handleDownloadButtonClick = (hash: string, event: React.MouseEvent): void => { - event.preventDefault(); - const {baseURI} = ConfigStore; - const link = document.createElement('a'); + if (UIStore.activeModal?.id !== 'torrent-details') { + return null; + } - link.download = ''; - link.href = `${baseURI}api/torrents/${hash}/contents/${this.selectedIndices.join(',')}/data`; - link.style.display = 'none'; + const {hash} = UIStore?.activeModal; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - }; + let directoryHeadingIconContent = null; + let fileDetailContent = null; - handleFormChange = (hash: string, {event}: {event: Event | React.FormEvent}): void => { - if (event.target != null && (event.target as HTMLInputElement).name === 'file-priority') { - const inputElement = event.target as HTMLInputElement; - if (inputElement.name === 'file-priority') { - TorrentActions.setFilePriority(hash, { - indices: this.selectedIndices, - priority: Number(inputElement.value), - }); - } - } - }; - - handleItemSelect = (selectedItem: TorrentContentSelection) => { - runInAction(() => { - this.itemsTree = selectionTree.applySelection(this.itemsTree, selectedItem); - this.selectedIndices.replace(selectionTree.getSelectedItems(this.itemsTree)); - }); - }; - - handleSelectAllClick = () => { - runInAction(() => { - this.itemsTree = selectionTree.getSelectionTree( - this.contents, - this.selectedIndices.length < this.contents.length, - ); - this.selectedIndices.replace(selectionTree.getSelectedItems(this.itemsTree)); - }); - }; - - render() { - if (UIStore.activeModal?.id !== 'torrent-details') { - return null; - } - - const {hash} = UIStore?.activeModal; - - let directoryHeadingIconContent = null; - let fileDetailContent = null; - - let allSelected = false; - if (this.contents?.length > 0) { - allSelected = this.selectedIndices.length >= this.contents.length; - directoryHeadingIconContent = ( -
-
+
- - - -
-
- -
-
- ); - fileDetailContent = ( - - ); - } else { - directoryHeadingIconContent = ; - fileDetailContent = ( -
- -
- ); - } - - const directoryHeadingClasses = classnames( - 'directory-tree__node', - 'directory-tree__parent-directory torrent-details__section__heading', - { - 'directory-tree__node--selected': allSelected, - }, - ); - - const directoryHeading = ( -
-
- {directoryHeadingIconContent} -
{TorrentStore.torrents?.[hash].directory}
+
); - - const wrapperClasses = classnames('inverse directory-tree__wrapper', { - 'directory-tree__wrapper--toolbar-visible': this.selectedIndices.length > 0, - }); - - return ( -
this.handleFormChange(hash, e)}> -
- - - {this.selectedIndices.length} - ), - }} - /> - - - - -
-
- {directoryHeading} - {fileDetailContent} -
-
+ fileDetailContent = ( + { + const newItemsTree = selectionTree.applySelection(itemsTree, selectedItem); + setItemsTree(newItemsTree); + setSelectedIndices(selectionTree.getSelectedItems(newItemsTree)); + }} + hash={hash} + itemsTree={itemsTree} + /> + ); + } else { + directoryHeadingIconContent = ; + fileDetailContent = ( +
+ +
); } -} -export default injectIntl(TorrentContents); + const directoryHeadingClasses = classnames( + 'directory-tree__node', + 'directory-tree__parent-directory torrent-details__section__heading', + { + 'directory-tree__node--selected': allSelected, + }, + ); + + const directoryHeading = ( +
+
+ {directoryHeadingIconContent} +
{TorrentStore.torrents?.[hash].directory}
+
+
+ ); + + const wrapperClasses = classnames('inverse directory-tree__wrapper', { + 'directory-tree__wrapper--toolbar-visible': selectedIndices.length > 0, + }); + + return ( +
{ + if (event.target != null && (event.target as HTMLInputElement).name === 'file-priority') { + const inputElement = event.target as HTMLInputElement; + if (inputElement.name === 'file-priority') { + TorrentActions.setFilePriority(hash, { + indices: selectedIndices, + priority: Number(inputElement.value), + }); + } + } + }}> +
+ + + {selectedIndices.length} + ), + }} + /> + + + + +
+
+ {directoryHeading} + {fileDetailContent} +
+
+ ); +}); + +export default TorrentContents;