diff --git a/src/components/details.tsx b/src/components/details.tsx index bba8474..6b33bcd 100644 --- a/src/components/details.tsx +++ b/src/components/details.tsx @@ -18,7 +18,7 @@ import React, { memo, useCallback, useContext, useEffect, useMemo, useState } from "react"; import type { Torrent, TrackerStats } from "../rpc/torrent"; -import { bytesToHumanReadableStr, ensurePathDelimiter, fileSystemSafeName, secondsToHumanReadableStr, timestampToDateString } from "../trutil"; +import { bytesToHumanReadableStr, ensurePathDelimiter, fileSystemSafeName, secondsToHumanReadableStr, timestampToDateString, torrentProgressbarStyle } from "../trutil"; import { FileTreeTable, useUnwantedFiles } from "./tables/filetreetable"; import { PiecesCanvas } from "./piecescanvas"; import { ProgressBar } from "./progressbar"; @@ -56,11 +56,19 @@ function DownloadBar(props: { torrent: Torrent }) { prefix = "Downloaded"; } + const config = useContext(ConfigContext); const now = Math.floor(percent * 1000); const nowStr = `${prefix}: ${now / 10}%`; + const progressbarStyle = torrentProgressbarStyle(props.torrent, config); + return ( - + ); } diff --git a/src/components/modals/interfacepanel.tsx b/src/components/modals/interfacepanel.tsx index 5c06d6c..08d4655 100644 --- a/src/components/modals/interfacepanel.tsx +++ b/src/components/modals/interfacepanel.tsx @@ -22,8 +22,8 @@ import { Checkbox, Grid, MultiSelect, NativeSelect, NumberInput, Textarea, useMa import type { UseFormReturnType } from "@mantine/form"; import ColorChooser from "components/colorchooser"; import { useGlobalStyleOverrides } from "themehooks"; -import { DeleteTorrentDataOptions, ProgressbarStyleOptions } from "config"; -import type { ProgressbarStyleOption, ColorSetting, DeleteTorrentDataOption, StyleOverrides } from "config"; +import { DeleteTorrentDataOptions } from "config"; +import type { ColorSetting, DeleteTorrentDataOption, StyleOverrides } from "config"; import { ColorSchemeToggle } from "components/miscbuttons"; import { Label } from "./common"; const { TAURI, invoke } = await import(/* webpackChunkName: "taurishim" */"taurishim"); @@ -34,7 +34,8 @@ export interface InterfaceFormValues { styleOverrides: StyleOverrides, skipAddDialog: boolean, deleteTorrentData: DeleteTorrentDataOption, - progressbarStyle: ProgressbarStyleOption, + animatedProgressbars: boolean, + colorfulProgressbars: boolean, numLastSaveDirs: number, sortLastSaveDirs: boolean, preconfiguredLabels: string[], @@ -146,11 +147,14 @@ export function InterfaceSettigsPanel(props: { fo - Progressbars + Progress bars - { setFieldValue("interface.progressbarStyle", e.target.value); }} /> + + + + ; diff --git a/src/components/tables/peerstable.tsx b/src/components/tables/peerstable.tsx index 2cb04f7..3d1f508 100644 --- a/src/components/tables/peerstable.tsx +++ b/src/components/tables/peerstable.tsx @@ -82,8 +82,9 @@ function PercentField(props: TableFieldProps) { return ; + animate={config.values.interface.animatedProgressbars && active} + variant={config.values.interface.colorfulProgressbars && now === 100 ? "green" : "default"} + />; } const Columns = AllFields.map((field): ColumnDef => { diff --git a/src/components/tables/torrenttable.tsx b/src/components/tables/torrenttable.tsx index c7da786..5b4df1e 100644 --- a/src/components/tables/torrenttable.tsx +++ b/src/components/tables/torrenttable.tsx @@ -23,8 +23,7 @@ import { useServerTorrentData, useServerRpcVersion, useServerSelectedTorrents } import type { TorrentAllFieldsType, TorrentFieldsType } from "rpc/transmission"; import { PriorityColors, PriorityStrings, Status, StatusStrings, TorrentMinimumFields } from "rpc/transmission"; import type { ColumnDef, VisibilityState } from "@tanstack/react-table"; -import { bytesToHumanReadableStr, fileSystemSafeName, modKeyString, pathMapFromServer, secondsToHumanReadableStr, timestampToDateString } from "trutil"; -import type { ProgressBarVariant } from "../progressbar"; +import { bytesToHumanReadableStr, fileSystemSafeName, modKeyString, pathMapFromServer, secondsToHumanReadableStr, timestampToDateString, torrentProgressbarStyle } from "trutil"; import { ProgressBar } from "../progressbar"; import type { AccessorFn, CellContext } from "@tanstack/table-core"; import type { TableSelectReducer } from "./common"; @@ -347,24 +346,13 @@ function ByteRateField(props: TableFieldProps) { function PercentBarField(props: TableFieldProps) { const config = useContext(ConfigContext); const now = props.torrent[props.fieldName] * 100; - const active = props.torrent.rateDownload > 0 || props.torrent.rateUpload > 0; - let variant: ProgressBarVariant = "default"; - if (config.values.interface.progressbarStyle === "colorful") { - if ((props.torrent.error !== undefined && props.torrent.error > 0) || - props.torrent.cachedError !== "") variant = "red"; - else { - if (active) variant = "green"; - else if (props.torrent.status === Status.stopped && - props.torrent.sizeWhenDone > 0 && - props.torrent.leftUntilDone === 0) variant = "dark-green"; - } - } + const progressbarStyle = torrentProgressbarStyle(props.torrent, config); return ; + {...progressbarStyle} + />; } const Columns = AllFields.map((f): ColumnDef => { diff --git a/src/config.ts b/src/config.ts index a544197..dae00f8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -95,11 +95,9 @@ export type SectionsVisibility = Array<{ export const WindowMinimizeOptions = ["minimize", "hide"] as const; export const WindowCloseOptions = ["hide", "close", "quit"] as const; export const DeleteTorrentDataOptions = ["default off", "default on", "remember selection"] as const; -export const ProgressbarStyleOptions = ["plain", "animated", "colorful"] as const; export type WindowMinimizeOption = typeof WindowMinimizeOptions[number]; export type WindowCloseOption = typeof WindowCloseOptions[number]; export type DeleteTorrentDataOption = typeof DeleteTorrentDataOptions[number]; -export type ProgressbarStyleOption = typeof ProgressbarStyleOptions[number]; export interface ColorSetting { color: DefaultMantineColor, @@ -162,7 +160,9 @@ interface Settings { preconfiguredLabels: string[], defaultTrackers: string[], styleOverrides: StyleOverrides, - progressbarStyle: ProgressbarStyleOption, + progressbarStyle?: string, // deprecated + animatedProgressbars: boolean, + colorfulProgressbars: boolean, }, configVersion: number, } @@ -285,7 +285,8 @@ const DefaultSettings: Settings = { dark: {}, light: {}, }, - progressbarStyle: "animated", + animatedProgressbars: true, + colorfulProgressbars: false, }, // This field is used to verify config struct compatibility when importing settings // Bump this only when incompatible changes are made that cannot be imported into older @@ -315,6 +316,11 @@ export class Config { this.values.app.openTabs = this.values.openTabs; this.values.openTabs = undefined; } + if (this.values.interface.progressbarStyle !== undefined) { + this.values.interface.animatedProgressbars = this.values.interface.progressbarStyle === "animated"; + this.values.interface.colorfulProgressbars = this.values.interface.progressbarStyle === "colorful"; + this.values.interface.progressbarStyle = undefined; + } } catch (e) { console.log(e); } diff --git a/src/css/progressbar.css b/src/css/progressbar.css index 038e75f..e9e2224 100644 --- a/src/css/progressbar.css +++ b/src/css/progressbar.css @@ -17,6 +17,10 @@ color: white; } +.progressbar.yellow>:first-child { + background: #fab007; +} + .progressbar.red>:first-child { background: #fa5252; } diff --git a/src/trutil.ts b/src/trutil.ts index 9da1caa..1bf5987 100644 --- a/src/trutil.ts +++ b/src/trutil.ts @@ -16,8 +16,11 @@ * along with this program. If not, see . */ -import type { ServerConfig } from "config"; +import type { Config, ServerConfig } from "config"; import { useReducer } from "react"; +import type { ProgressBarVariant } from "./components/progressbar"; +import { Status } from "rpc/transmission"; +import type { Torrent } from "rpc/torrent"; const SISuffixes = ["B", "KB", "MB", "GB", "TB"]; @@ -231,3 +234,31 @@ export function fileSystemSafeName(name: string) { export function * chainedIterables(...iterables: Array>) { for (const iterable of iterables) yield * iterable; } + +export function torrentProgressbarStyle(torrent: Torrent, config: Config) { + const active = torrent.rateDownload > 0 || torrent.rateUpload > 0; + const animate = config.values.interface.animatedProgressbars && active; + + let variant: ProgressBarVariant = "default"; + if (config.values.interface.colorfulProgressbars) { + if ((torrent.error !== undefined && torrent.error > 0) || torrent.cachedError !== "") { + variant = "red"; + } else { + if (torrent.status === Status.stopped && torrent.sizeWhenDone > 0) { + if (torrent.leftUntilDone === 0) { + variant = "dark-green"; + } else { + variant = "yellow"; + } + } else if (torrent.status === Status.seeding) { + variant = "green"; + } else if (torrent.status === Status.queuedToVerify || + torrent.status === Status.queuedToDownload || + torrent.status === Status.queuedToSeed) { + variant = "grey"; + } + } + } + + return { animate, variant }; +}