diff --git a/src/components/Modtools.jsx b/src/components/Modtools.jsx index c70c3cc..8d94c09 100644 --- a/src/components/Modtools.jsx +++ b/src/components/Modtools.jsx @@ -7,14 +7,17 @@ import React, { useState, useEffect } from 'react'; import { useSelector, shallowEqual } from 'react-redux'; import { t } from 'ttag'; +import useInterval from './hooks/useInterval'; import { getToday, dateToString } from '../core/utils'; const keptState = { - coords: null, - tlcoords: null, - brcoords: null, - tlrcoords: null, - brrcoords: null, + coords: '', + tlcoords: '', + brcoords: '', + tlrcoords: '', + brrcoords: '', + tlccoords: '', + brccoords: '', }; async function submitImageAction( @@ -80,6 +83,26 @@ async function submitRollback( callback(await resp.text()); } +async function submitCanvasCleaner( + action, + canvas, + tlcoords, + brcoords, + callback, +) { + const data = new FormData(); + data.append('cleaneraction', action); + data.append('canvasid', canvas); + data.append('ulcoor', tlcoords); + data.append('brcoor', brcoords); + const resp = await fetch('./api/modtools', { + credentials: 'include', + method: 'POST', + body: data, + }); + callback(await resp.text()); +} + async function submitIPAction( action, callback, @@ -113,6 +136,41 @@ async function getModList( } } +async function getCleanerStats( + callback, +) { + const data = new FormData(); + data.append('cleanerstat', true); + const resp = await fetch('./api/modtools', { + credentials: 'include', + method: 'POST', + body: data, + }); + if (resp.ok) { + callback(await resp.json()); + } else { + callback({ + }); + } +} + +async function getCleanerCancel( + callback, +) { + const data = new FormData(); + data.append('cleanercancel', true); + const resp = await fetch('./api/modtools', { + credentials: 'include', + method: 'POST', + body: data, + }); + if (resp.ok) { + callback(await resp.text()); + } else { + callback(''); + } +} + async function submitRemMod( userId, callback, @@ -151,6 +209,7 @@ function Modtools() { const [selectedCanvas, selectCanvas] = useState(0); const [imageAction, selectImageAction] = useState('build'); + const [cleanAction, selectCleanAction] = useState('spare'); const [iPAction, selectIPAction] = useState('ban'); const [protAction, selectProtAction] = useState('protect'); const [date, selectDate] = useState(maxDate); @@ -159,9 +218,12 @@ function Modtools() { const [brcoords, selectBRCoords] = useState(keptState.brcoords); const [tlrcoords, selectTLRCoords] = useState(keptState.tlrcoords); const [brrcoords, selectBRRCoords] = useState(keptState.brrcoords); - const [modName, selectModName] = useState(null); + const [tlccoords, selectTLCCoords] = useState(keptState.tlrcoords); + const [brccoords, selectBRCCoords] = useState(keptState.brrcoords); + const [modName, selectModName] = useState(''); const [resp, setResp] = useState(null); const [modlist, setModList] = useState([]); + const [cleanerstats, setCleanerStats] = useState({}); const [submitting, setSubmitting] = useState(false); const [ @@ -193,12 +255,40 @@ function Modtools() { // nothing } + let descCleanAction; + switch (cleanAction) { + case 'spare': + // eslint-disable-next-line max-len + descCleanAction = t`Clean spare pixels that are surrounded by unset pixels`; + break; + case 'spareext': + // eslint-disable-next-line max-len + descCleanAction = t`Clean spare pixels that are surrounded by a single other color`; + break; + default: + // nothing + } + useEffect(() => { if (userlvl === 1) { getModList((mods) => setModList(mods)); } + if (userlvl > 0) { + getCleanerStats((stats) => setCleanerStats(stats)); + } }, []); + useInterval(() => { + if (userlvl > 0) { + getCleanerStats((stats) => setCleanerStats(stats)); + } + }, 10000); + + const cleanerStatusString = (!cleanerstats.running) + ? t`Status: Not running` + // eslint-disable-next-line max-len + : `Status: ${cleanerstats.method} from ${cleanerstats.tl} to ${cleanerstats.br} on canvas ${canvases[cleanerstats.canvasId].ident} to ${cleanerstats.percent} done`; + return (
{resp && ( @@ -227,6 +317,7 @@ function Modtools() { )}

Choose Canvas: 

{ const sel = e.target; selectProtAction(sel.options[sel.selectedIndex].value); @@ -328,14 +419,13 @@ function Modtools() { {['protect', 'unprotect'].map((opt) => ( ))}

- Top-left corner (X_Y):  + {t`Top-left corner`} (X_Y): 

- Bottom-right corner (X_Y):  + {t`Bottom-right corner`} (X_Y): 

- Top-left corner (X_Y):  + {t`Top-left corner`} (X_Y): 

- Bottom-right corner (X_Y):  + {t`Bottom-right corner`} (X_Y): 

)} +
+
+

{t`Canvas Cleaner`}

+

+ {t`Apply a filter to clean trash in large canvas areas.`} +

+ +

{descCleanAction}

+

+ {cleanerStatusString} +

+

+ {t`Top-left corner`} (X_Y):  + { + const co = evt.target.value.trim(); + selectTLCCoords(co); + keptState.tlccoords = co; + }} + /> +

+

+ {t`Bottom-right corner`} (X_Y):  + { + const co = evt.target.value.trim(); + selectBRCCoords(co); + keptState.brccoords = co; + }} + /> +

+ + + {(userlvl === 1) && (

@@ -477,6 +676,7 @@ function Modtools() { {t`Do stuff with IPs (one IP per line)`}