From 5e1c09153cf0fda62774249121b86408055e397e Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sun, 4 Oct 2020 20:59:30 +0800 Subject: [PATCH] feature: allow multi-torrent priority change --- .../src/javascript/actions/TorrentActions.ts | 8 ++-- .../general/filesystem/PriorityMeter.tsx | 18 ++------- .../torrent-details-modal/TorrentHeading.tsx | 2 +- .../torrent-list/TorrentListContextMenu.js | 20 ++++++---- server/models/ClientRequest.js | 9 ----- server/models/client.js | 11 ------ server/routes/api/torrents.ts | 39 +++++++++++++------ server/services/clientGatewayService.ts | 31 +++++++++++++++ shared/types/Action.ts | 12 ++++++ 9 files changed, 89 insertions(+), 61 deletions(-) diff --git a/client/src/javascript/actions/TorrentActions.ts b/client/src/javascript/actions/TorrentActions.ts index 2b6924f7..c9b3353a 100644 --- a/client/src/javascript/actions/TorrentActions.ts +++ b/client/src/javascript/actions/TorrentActions.ts @@ -6,6 +6,7 @@ import type { CheckTorrentsOptions, DeleteTorrentsOptions, MoveTorrentsOptions, + SetTorrentsPriorityOptions, StartTorrentsOptions, StopTorrentsOptions, } from '@shared/types/Action'; @@ -220,12 +221,9 @@ const TorrentActions = { }, ), - setPriority: (hash: TorrentProperties['hash'], priority: number) => + setPriority: (options: SetTorrentsPriorityOptions) => axios - .patch(`${baseURI}api/torrents/${hash}/priority`, { - hash, - priority, - }) + .patch(`${baseURI}api/torrents/priority`, options) .then((json) => json.data) .then( (data) => { diff --git a/client/src/javascript/components/general/filesystem/PriorityMeter.tsx b/client/src/javascript/components/general/filesystem/PriorityMeter.tsx index b64295a1..89cbdd9f 100644 --- a/client/src/javascript/components/general/filesystem/PriorityMeter.tsx +++ b/client/src/javascript/components/general/filesystem/PriorityMeter.tsx @@ -9,8 +9,8 @@ interface PriorityMeterProps extends WrappedComponentProps { maxLevel: number; priorityType: keyof typeof PriorityLevels; showLabel?: boolean; + clickHandled?: boolean; onChange: (id: this['id'], level: this['level']) => void; - bindExternalChangeHandler?: (clickHandler: (() => void) | null) => void; } interface PriorityMeterStates { @@ -36,18 +36,6 @@ class PriorityMeter extends React.Component +
{ - TorrentActions.setPriority(hash as string, level); + TorrentActions.setPriority({hashes: [`${hash}`], priority: level}); }} /> , diff --git a/client/src/javascript/components/torrent-list/TorrentListContextMenu.js b/client/src/javascript/components/torrent-list/TorrentListContextMenu.js index c9e2d09f..d97c6766 100644 --- a/client/src/javascript/components/torrent-list/TorrentListContextMenu.js +++ b/client/src/javascript/components/torrent-list/TorrentListContextMenu.js @@ -7,9 +7,8 @@ import TorrentContextMenuItems from '../../constants/TorrentContextMenuItems'; import TorrentStore from '../../stores/TorrentStore'; import UIActions from '../../actions/UIActions'; -let handleTorrentPriorityChange = (hash, level) => { - TorrentActions.setPriority(hash, level); -}; +const priorityMeterRef = React.createRef(); +let prioritySelected = 1; const handleDetailsClick = (torrent, event) => { UIActions.handleDetailsClick({ @@ -71,7 +70,11 @@ const handleItemClick = (action, event, torrent) => { handleTorrentDownload(torrent, event); break; case 'set-priority': - handleTorrentPriorityChange(event); + priorityMeterRef.current.handleClick(); + TorrentActions.setPriority({ + hashes: selectedTorrents, + priority: prioritySelected, + }); break; default: break; @@ -138,14 +141,15 @@ const getContextMenuItems = (intl, torrent, settings) => { { - handleTorrentPriorityChange = priorityChangeHandler; - }} + ref={priorityMeterRef} level={torrent.priority} maxLevel={3} priorityType="torrent" - onChange={handleTorrentPriorityChange} + onChange={(_id, level) => { + prioritySelected = level; + }} showLabel={false} + clickHandled /> ), }, diff --git a/server/models/ClientRequest.js b/server/models/ClientRequest.js index 07772075..17311319 100644 --- a/server/models/ClientRequest.js +++ b/server/models/ClientRequest.js @@ -238,15 +238,6 @@ class ClientRequest { }); } - setPriority(options) { - const hashes = getEnsuredArray(options.hashes); - - hashes.forEach((hash) => { - this.requests.push(getMethodCall('d.priority.set', [hash, options.priority])); - this.requests.push(getMethodCall('d.update_priorities', [hash])); - }); - } - setSettings(options) { const settings = getEnsuredArray(options.settings); diff --git a/server/models/client.js b/server/models/client.js index f90408e9..22d6e201 100644 --- a/server/models/client.js +++ b/server/models/client.js @@ -229,17 +229,6 @@ const client = { request.send(); }, - setPriority(user, services, hashes, data, callback) { - const request = new ClientRequest(user, services); - - request.setPriority({hashes, priority: data.priority}); - request.onComplete((response, error) => { - services.torrentService.fetchTorrentList(); - callback(response, error); - }); - request.send(); - }, - setSettings(user, services, payloads, callback) { const request = new ClientRequest(user, services); if (payloads.length === 0) return callback({}); diff --git a/server/routes/api/torrents.ts b/server/routes/api/torrents.ts index 0b07b51f..84c1c50f 100644 --- a/server/routes/api/torrents.ts +++ b/server/routes/api/torrents.ts @@ -1,11 +1,12 @@ import express from 'express'; -import type { +import { AddTorrentByFileOptions, AddTorrentByURLOptions, CheckTorrentsOptions, DeleteTorrentsOptions, MoveTorrentsOptions, + SetTorrentsPriorityOptions, StartTorrentsOptions, StopTorrentsOptions, } from '@shared/types/Action'; @@ -167,6 +168,31 @@ router.post('/delete', (req, res) => { }); }); +/** + * PATCH /api/torrents/priority + * @summary Sets priority of torrents. + * @tags Torrent + * @security AuthenticatedUser + * @param {SetTorrentsPriorityOptions} request.body.required - options - application/json + * @return {object} 200 - success response - application/json + * @return {Error} 500 - failure response - application/json + */ +router.patch('/priority', (req, res) => { + const {hashes, priority} = req.body; + const callback = ajaxUtil.getResponseFn(res); + + req.services?.clientGatewayService + .setTorrentsPriority({hashes, priority}) + .then((response) => { + req.services?.torrentService.fetchTorrentList(); + return response; + }) + .then(callback) + .catch((err) => { + callback(null, err); + }); +}); + /** * PATCH /api/torrents/taxonomy * @summary Sets tags of torrents. @@ -258,15 +284,4 @@ router.get('/:hash/mediainfo', (req, res) => { mediainfo.getMediainfo(req.services, req.params.hash, ajaxUtil.getResponseFn(res)); }); -/** - * PATCH /api/torrents/{hash}/priority - * @summary Sets priority of a torrent. - * @tags Torrent - * @security AuthenticatedUser - * @param {string} hash.path - */ -router.patch('/:hash/priority', (req, res) => { - client.setPriority(req.user, req.services, req.params.hash, req.body, ajaxUtil.getResponseFn(res)); -}); - export default router; diff --git a/server/services/clientGatewayService.ts b/server/services/clientGatewayService.ts index 16bfc6e5..97caa6a7 100644 --- a/server/services/clientGatewayService.ts +++ b/server/services/clientGatewayService.ts @@ -9,6 +9,7 @@ import type { CheckTorrentsOptions, DeleteTorrentsOptions, MoveTorrentsOptions, + SetTorrentsPriorityOptions, StartTorrentsOptions, StopTorrentsOptions, } from '@shared/types/Action'; @@ -257,6 +258,36 @@ class ClientGatewayService extends BaseService { }, this.processClientRequestError); } + /** + * Sets priority of torrents + * + * @param {SetTorrentsPriorityOptions} options - An object of options... + * @return {Promise} - Resolves with RPC call response or rejects with error. + */ + async setTorrentsPriority({hashes, priority}: SetTorrentsPriorityOptions) { + if (this.services == null || this.services.clientRequestManager == null) { + return Promise.reject(); + } + + const methodCalls = hashes.reduce((accumulator: MultiMethodCalls, hash) => { + accumulator.push({ + methodName: 'd.priority.set', + params: [hash, `${priority}`], + }); + + accumulator.push({ + methodName: 'd.update_priorities', + params: [hash], + }); + + return accumulator; + }, []); + + return this.services.clientRequestManager + .methodCall('system.multicall', [methodCalls]) + .then(this.processClientRequestSuccess, this.processClientRequestError); + } + /** * Starts torrents * diff --git a/shared/types/Action.ts b/shared/types/Action.ts index bae253ac..c87263b9 100644 --- a/shared/types/Action.ts +++ b/shared/types/Action.ts @@ -67,3 +67,15 @@ export interface StopTorrentsOptions { // An array of string representing hashes of torrents to be stopped hashes: Array; } + +// PATCH /api/torrents/priority +export interface SetTorrentsPriorityOptions { + // An array of string representing hashes of torrents to operated on + hashes: Array; + // Number representing priority: + // 0 - DON'T_DOWNLOAD + // 1 - LOW + // 2 - NORMAL + // 3 - HIGH + priority: number; +}