From 5e71af9751bf06fc2b67ed5a6f2613f55695213b Mon Sep 17 00:00:00 2001 From: "Alexey D. Filimonov" Date: Thu, 15 Feb 2024 09:14:58 +0300 Subject: [PATCH] Move `wipe` to server side. Add UI unsafe buttons (#355) * move 'remove all' function to server side ('wipe') * add UnsafeButton to RemoveAll and CloseServer webui --- server/web/api/torrents.go | 17 +++++++++++++++++ web/src/components/CloseServer.jsx | 9 ++++++--- web/src/components/RemoveAll.jsx | 22 ++++++---------------- web/src/components/UnsafeButton.jsx | 26 ++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 web/src/components/UnsafeButton.jsx diff --git a/server/web/api/torrents.go b/server/web/api/torrents.go index d94a28a..34cef2a 100644 --- a/server/web/api/torrents.go +++ b/server/web/api/torrents.go @@ -72,6 +72,10 @@ func torrents(c *gin.Context) { { dropTorrent(req, c) } + case "wipe": + { + wipeTorrents(req, c) + } } } @@ -184,3 +188,16 @@ func dropTorrent(req torrReqJS, c *gin.Context) { torr.DropTorrent(req.Hash) c.Status(200) } + +func wipeTorrents(req torrReqJS, c *gin.Context) { + torrents := torr.ListTorrent() + for _, t := range torrents { + torr.RemTorrent(t.TorrentSpec.InfoHash.HexString()) + } + // TODO: remove (copied todo from remTorrent()) + if set.BTsets.EnableDLNA { + dlna.Stop() + dlna.Start() + } + c.Status(200) +} diff --git a/web/src/components/CloseServer.jsx b/web/src/components/CloseServer.jsx index 160c1d9..f652c4f 100644 --- a/web/src/components/CloseServer.jsx +++ b/web/src/components/CloseServer.jsx @@ -1,11 +1,12 @@ import { useState } from 'react' import { Button, DialogActions, DialogTitle, ListItemIcon, ListItemText } from '@material-ui/core' import { StyledDialog, StyledMenuButtonWrapper } from 'style/CustomMaterialUiStyles' -import { PowerSettingsNew as PowerSettingsNewIcon } from '@material-ui/icons' +import { PowerSettingsNew as PowerSettingsNewIcon, PowerOff as PowerOffIcon } from '@material-ui/icons' import { shutdownHost } from 'utils/Hosts' import { useTranslation } from 'react-i18next' import { isStandaloneApp } from 'utils/Utils' import useOnStandaloneAppOutsideClick from 'utils/useOnStandaloneAppOutsideClick' +import UnsafeButton from './UnsafeButton' export default function CloseServer({ isOffline, isLoading }) { const { t } = useTranslation() @@ -41,7 +42,9 @@ export default function CloseServer({ isOffline, isLoading }) { {t('Cancel')} - + diff --git a/web/src/components/RemoveAll.jsx b/web/src/components/RemoveAll.jsx index 8fccfc1..faa4874 100644 --- a/web/src/components/RemoveAll.jsx +++ b/web/src/components/RemoveAll.jsx @@ -6,29 +6,17 @@ import DeleteIcon from '@material-ui/icons/Delete' import { useState } from 'react' import { torrentsHost } from 'utils/Hosts' import { useTranslation } from 'react-i18next' +import UnsafeButton from './UnsafeButton' const fnRemoveAll = () => { fetch(torrentsHost(), { method: 'post', - body: JSON.stringify({ action: 'list' }), + body: JSON.stringify({ action: 'wipe' }), headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json', }, }) - .then(res => res.json()) - .then(json => { - json.forEach(torr => { - fetch(torrentsHost(), { - method: 'post', - body: JSON.stringify({ action: 'rem', hash: torr.hash }), - headers: { - Accept: 'application/json, text/plain, */*', - 'Content-Type': 'application/json', - }, - }) - }) - }) } export default function RemoveAll({ isOffline, isLoading }) { @@ -54,7 +42,9 @@ export default function RemoveAll({ isOffline, isLoading }) { {t('Cancel')} - + diff --git a/web/src/components/UnsafeButton.jsx b/web/src/components/UnsafeButton.jsx new file mode 100644 index 0000000..6edd730 --- /dev/null +++ b/web/src/components/UnsafeButton.jsx @@ -0,0 +1,26 @@ +import { Button } from '@material-ui/core'; +import { useEffect, useRef, useState } from 'react'; + +export default function UnsafeButton({ timeout, children, disabled, ...props }) { + const [timeLeft, setTimeLeft] = useState(timeout || 7) + const [buttonDisabled, setButtonDisabled] = useState(disabled || timeLeft > 0) + const handleTimerTick = () => { + const newTimeLeft = timeLeft - 1 + setTimeLeft(newTimeLeft) + if (newTimeLeft <= 0) { + setButtonDisabled(disabled) + } + } + const getTimerText = () => !disabled && timeLeft > 0 ? ` (${timeLeft})` : '' + useEffect(() => { + if (disabled || !timeLeft) { return } + const intervalId = setInterval(handleTimerTick, 1000) + return () => clearInterval(intervalId) + }, [timeLeft]) + + return ( + + ) +}