diff --git a/src/components/modals/daemon.tsx b/src/components/modals/daemon.tsx
index 7ce584b..9f701fb 100644
--- a/src/components/modals/daemon.tsx
+++ b/src/components/modals/daemon.tsx
@@ -597,7 +597,7 @@ export function DaemonSettingsModal(props: ModalState) {
>
-
+
Polling
Download
diff --git a/src/components/modals/interfacepanel.tsx b/src/components/modals/interfacepanel.tsx
index 08d4655..bc2b2cd 100644
--- a/src/components/modals/interfacepanel.tsx
+++ b/src/components/modals/interfacepanel.tsx
@@ -18,7 +18,7 @@
import React, { useCallback, useEffect, useState } from "react";
import type { ColorScheme } from "@mantine/core";
-import { Checkbox, Grid, MultiSelect, NativeSelect, NumberInput, Textarea, useMantineTheme } from "@mantine/core";
+import { Box, Checkbox, Grid, HoverCard, MultiSelect, NativeSelect, NumberInput, Text, Textarea, useMantineTheme } from "@mantine/core";
import type { UseFormReturnType } from "@mantine/form";
import ColorChooser from "components/colorchooser";
import { useGlobalStyleOverrides } from "themehooks";
@@ -26,6 +26,7 @@ import { DeleteTorrentDataOptions } from "config";
import type { ColorSetting, DeleteTorrentDataOption, StyleOverrides } from "config";
import { ColorSchemeToggle } from "components/miscbuttons";
import { Label } from "./common";
+import * as Icon from "react-bootstrap-icons";
const { TAURI, invoke } = await import(/* webpackChunkName: "taurishim" */"taurishim");
export interface InterfaceFormValues {
@@ -39,6 +40,7 @@ export interface InterfaceFormValues {
numLastSaveDirs: number,
sortLastSaveDirs: boolean,
preconfiguredLabels: string[],
+ ignoredTrackerPrefixes: string[],
defaultTrackers: string[],
},
}
@@ -59,7 +61,7 @@ export function InterfaceSettigsPanel(props: { fo
}
}, []);
- const { setFieldValue } = props.form as unknown as UseFormReturnType;
+ const { setFieldValue, setFieldError, clearFieldError } = props.form as unknown as UseFormReturnType;
useEffect(() => {
setFieldValue("interface.theme", theme.colorScheme);
@@ -101,6 +103,17 @@ export function InterfaceSettigsPanel(props: { fo
setFieldValue("interface.preconfiguredLabels", labels);
}, [setFieldValue]);
+ const setIgnoredTrackerPrefixes = useCallback((prefixes: string[]) => {
+ try {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const _ = new RegExp(`^(?(${prefixes.join("|")})\\d*)\\.[^.]+\\.[^.]+$`, "i");
+ setFieldValue("interface.ignoredTrackerPrefixes", prefixes);
+ clearFieldError("interface.ignoredTrackerPrefixes");
+ } catch (SyntaxError) {
+ setFieldError("interface.ignoredTrackerPrefixes", "Invalid regex");
+ }
+ }, [setFieldValue, setFieldError, clearFieldError]);
+
return (
@@ -161,7 +174,20 @@ export function InterfaceSettigsPanel(props: { fo
data={props.form.values.interface.preconfiguredLabels}
value={props.form.values.interface.preconfiguredLabels}
onChange={setPreconfiguredLabels}
- label="Preconfigured labels"
+ label={
+ Preconfigured labels
+
+
+
+
+
+
+ These labels will always be present in the suggestions list
+ and filters even if no existing torrents have them.
+
+
+
+ }
withinPortal
searchable
creatable
@@ -173,6 +199,39 @@ export function InterfaceSettigsPanel(props: { fo
valueComponent={Label}
/>
+
+
+ Ignored tracker prefixes
+
+
+
+
+
+
+ When subdomain of the tracker looks like one of these strings + (optional) digits,
+ it will be omitted. This affects grouping in filters and display in table columns.
+ You can use regex here for more advanced filtering, the list will be combined
+ using "|".
+
+
+
+ }
+ withinPortal
+ searchable
+ creatable
+ error={props.form.errors["interface.ignoredTrackerPrefixes"]}
+ getCreateLabel={(query) => `+ Add ${query}`}
+ onCreate={(query) => {
+ setIgnoredTrackerPrefixes([...props.form.values.interface.ignoredTrackerPrefixes, query]);
+ return query;
+ }}
+ valueComponent={Label}
+ />
+
@@ -352,15 +352,15 @@ export function AppSettingsModal(props: AppSettingsModalProps) {
title="Application Settings"
>