ux: admin/plugins: resume-plugins button will resort the list so that you can easily see what did actually start
Massimo Melina committed
Mar 5, 2026 at 19:22 UTC
196cf3b5b4b589223a2b03df056142c0684dad15
1 file changed
+11
-5
admin/src/InstalledPlugins.ts
+11
-5
@@ -1,7 +1,7 @@
1
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3
import { apiCall, useApiEx, useApiList } from './api'
4
-import { createElement as h, Fragment, useEffect } from 'react'
4
+import { createElement as h, Fragment, useEffect, useState } from 'react'
5
import { Box, Breakpoint, Link, Paper, Table, TableCell, TableRow, useTheme } from '@mui/material'
6
import { DataTable, DataTableColumn } from './DataTable'
7
import {
@@ -9,7 +9,7 @@ import {
9
} from '@mui/icons-material'
10
import {
11
CFG, Html, HTTP_FAILED_DEPENDENCY, md, newObj, prefix, with_, xlate, formatTime, formatDate, replaceStringToReact,
12
- callable, tryJson, useAutoScroll, NBSP, isPrimitive, HIDE_IN_TESTS
12
+ callable, tryJson, useAutoScroll, NBSP, isPrimitive, HIDE_IN_TESTS, wait
13
} from './misc'
14
import { alertDialog, confirmDialog, formDialog, toast } from './dialog'
15
import _ from 'lodash'
@@ -31,13 +31,19 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
31
const { list, error, setList, initializing } = useApiList(updates ? 'get_plugin_updates' : 'get_plugins', {}, {
32
map(x: any) { x.config &&= tryJson(x.config, s => evalWrapper('()=>('+s+')')()) }
33
})
34
+ const [sortAgain, setSortAgain] = useState(0)
35
useEffect(() => {
36
setList(list =>
37
_.sortBy(list, x => (x.error ? 0 : x.started ? 1 : 2) + treatPluginName(x.repo?.split('/').reverse().join('/') || x.id).toLowerCase()))
37
- }, [list.length]);
38
+ }, [list.length, sortAgain]);
39
const size = 'small'
40
const { pause, pauseButton } = usePauseButton("plugins", () => getSingleConfig(CFG.suspend_plugins).then(x => !x), {
40
- onClick: () => apiCall('set_config', { values: { [CFG.suspend_plugins]: !pause } })
41
+ async onClick() {
42
+ await apiCall('set_config', { values: { [CFG.suspend_plugins]: !pause } })
43
+ if (!pause) return
44
+ await wait(3000)
45
+ setSortAgain(Date.now())
46
+ }
47
})
48
const theme = useTheme()
49
return h(DataTable, {
@@ -124,7 +130,7 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
130
} : {
131
icon: PlayCircle,
132
title: `Start ${id}`,
127
- disabled: pause,
133
+ disabled: pause && "All plugins are paused – Click the Resume button below",
134
size,
135
onClick: () => startPlugin(id),
136
}),