Skip to content

feat(tracker): add per-domain stats inclusion toggle for merged trackers#781

Merged
s0up4200 merged 1 commit intomainfrom
feat/tracker-stats-per-domain-inclusion
Dec 14, 2025
Merged

feat(tracker): add per-domain stats inclusion toggle for merged trackers#781
s0up4200 merged 1 commit intomainfrom
feat/tracker-stats-per-domain-inclusion

Conversation

@s0up4200
Copy link
Collaborator

@s0up4200 s0up4200 commented Dec 14, 2025

Summary

  • Add per-domain checkbox to control which domains contribute to combined stats when merging trackers
  • Add ScrollArea for scrollable domain list when many domains are merged
  • Add X button to remove domains from within the customize dialog
  • Add toast notifications for mutation failures

This addresses the use case where:

  • Same tracker with multiple URLs (e.g., TorrentLeech): should NOT sum stats (would double-count)
  • Different trackers grouped together (e.g., Public Trackers): may want to sum stats

Primary domain is always included. Secondary domains are only included if explicitly checked.

Empty includedInStats means only primary domain stats shown, which is backwards compatible with existing customizations.

Test plan

  • Create new tracker customization with multiple domains, verify checkbox behavior
  • Edit existing customization, verify includedInStats persists correctly
  • Verify stats calculation changes based on checkbox state
  • Test import/export includes includedInStats field
  • Verify existing customizations continue to work (only primary stats shown)
  • Verify toast appears on mutation failures

Summary by CodeRabbit

  • New Features

    • Added ability to selectively include secondary domains in tracker statistics. Users can now configure which secondary domains' data contributes to combined stat totals through domain inclusion toggles.
  • Improvements

    • Enhanced error notifications for tracker customization operations.

✏️ Tip: You can customize this high-level summary in your review settings.

Add ability to control which domains contribute to combined stats when
trackers are merged. This allows users to avoid double-counting when
the same tracker has multiple URLs (e.g., TorrentLeech) while still
being able to sum stats for different trackers grouped together
(e.g., Public Trackers).

- Add includedInStats field to TrackerCustomization model
- Add database migration for included_in_stats column
- Add checkbox per domain in customize dialog (primary always included)
- Add ScrollArea for long domain lists in dialog
- Add X button to remove domains from within dialog
- Add toast notifications for mutation failures
- Backend sanitizes includedInStats to only valid secondary domains

Empty includedInStats means only primary domain stats shown (backwards
compatible with existing customizations).
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 14, 2025

Walkthrough

Adds an IncludedInStats field to tracker customizations, enabling secondary domains to be selectively included in combined statistics. Changes include database migration, backend model and API handler updates to sanitize and persist the field, TypeScript type additions, enhanced error handling in mutation hooks, and Dashboard UI modifications for domain management and two-pass stats aggregation.

Changes

Cohort / File(s) Summary
Database and Models
internal/database/migrations/034_add_tracker_customization_included_stats.sql, internal/models/tracker_customization.go
Added included_in_stats column (TEXT, comma-separated domains) to tracker_customizations table. Extended List, Get, Create, and Update queries to select, scan, and persist the new column; added string/slice conversions via splitDomains/joinDomains helpers.
API Handler
internal/api/handlers/tracker_customizations.go
Added IncludedInStats field to TrackerCustomizationPayload. Introduced sanitizeIncludedInStats() helper to filter included domains against valid secondary domains. Extended toModel() to compute and attach sanitized IncludedInStats, trim DisplayName, and precompute Domains.
Frontend Types
web/src/types/index.ts
Added optional includedInStats?: string[] property to TrackerCustomization and TrackerCustomizationInput types.
Frontend Hooks
web/src/hooks/useTrackerCustomizations.ts
Enhanced error handling in create, update, and delete mutation hooks to display user-facing toast notifications on failure.
Frontend UI
web/src/pages/Dashboard.tsx
Added ScrollArea import for scrollable domain lists. Introduced two-pass stats aggregation: Pass 1 creates primary/standalone entries, Pass 2 merges stats from explicitly included secondary domains. Extended tracker customization dialog with domain management UI (per-domain inclusion toggles, removal, primary-domain labels). Updated create/update/import/export cycles to propagate includedInStats.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~45 minutes

  • web/src/pages/Dashboard.tsx: Two-pass aggregation logic for merging secondary domain stats into primary entries; ensure correct stat accumulation and domain filtering.
  • internal/models/tracker_customization.go: String/slice conversion patterns (splitDomains/joinDomains) applied across four database operations; verify consistency in data transformation.
  • internal/api/handlers/tracker_customizations.go: Validation logic in sanitizeIncludedInStats() to exclude primary domains and ensure existence in domains list; confirm filtering rules are correct.

Possibly related PRs

Suggested labels

enhancement, web, database:migrations, database

Poem

🐰 Secondary stats now dance in sight,
Domains join primary in unified flight,
With toggles and filters, clean and bright—
Two-pass aggregation, perfectly tight!
Stats bloom where they're meant to be right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(tracker): add per-domain stats inclusion toggle for merged trackers' accurately and concisely describes the main change: introducing a per-domain toggle mechanism for controlling which domains contribute to combined stats.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tracker-stats-per-domain-inclusion

Comment @coderabbitai help to get the list of available commands and usage tips.

@s0up4200 s0up4200 linked an issue Dec 14, 2025 that may be closed by this pull request
@s0up4200 s0up4200 added this to the v1.10.0 milestone Dec 14, 2025
@s0up4200 s0up4200 added enhancement New feature or request web torrent labels Dec 14, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
web/src/pages/Dashboard.tsx (1)

1983-2023: Well-designed dialog UI with ScrollArea for domain lists.

The per-domain checkbox pattern clearly communicates that:

  • Primary domain (index 0) is always included (checkbox disabled)
  • Secondary domains can be toggled for stats inclusion
  • The "Primary" badge provides visual clarity

The X button to remove domains enhances usability for large merge groups.

For improved screen reader accessibility, consider associating each checkbox with an explicit label using htmlFor and id attributes:

-<Checkbox
-  checked={isIncluded}
-  disabled={isPrimary}
-  onCheckedChange={(checked) => handleToggleStatsInclusion(domain, !!checked)}
-  className="h-4 w-4"
-/>
-<span className={isPrimary ? "font-medium flex-1" : "flex-1"}>{domain}</span>
+<Checkbox
+  id={`include-stats-${domain}`}
+  checked={isIncluded}
+  disabled={isPrimary}
+  onCheckedChange={(checked) => handleToggleStatsInclusion(domain, !!checked)}
+  className="h-4 w-4"
+/>
+<Label htmlFor={`include-stats-${domain}`} className={isPrimary ? "font-medium flex-1 cursor-pointer" : "flex-1 cursor-pointer"}>
+  {domain}
+</Label>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c66ba5 and 5419a45.

📒 Files selected for processing (6)
  • internal/api/handlers/tracker_customizations.go (1 hunks)
  • internal/database/migrations/034_add_tracker_customization_included_stats.sql (1 hunks)
  • internal/models/tracker_customization.go (6 hunks)
  • web/src/hooks/useTrackerCustomizations.ts (4 hunks)
  • web/src/pages/Dashboard.tsx (18 hunks)
  • web/src/types/index.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-12-07T21:15:46.265Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 637
File: internal/api/handlers/tracker_customizations.go:138-154
Timestamp: 2025-12-07T21:15:46.265Z
Learning: In the qui codebase (internal/api/handlers/tracker_customizations.go and internal/models/tracker_customization.go), domain normalization follows a layered pattern: the handler's normalizeDomains performs input sanitization at the API boundary (trim, lowercase, deduplicate), while the store's joinDomains is only for serialization. All domains flow through the handler first, ensuring they're normalized before reaching the store layer.

Applied to files:

  • internal/api/handlers/tracker_customizations.go
  • internal/models/tracker_customization.go
  • web/src/pages/Dashboard.tsx
📚 Learning: 2025-11-25T11:39:54.748Z
Learnt from: s0up4200
Repo: autobrr/qui PR: 637
File: web/src/pages/Dashboard.tsx:805-831
Timestamp: 2025-11-25T11:39:54.748Z
Learning: In web/src/pages/Dashboard.tsx, the TrackerIconImage component intentionally receives displayDomain (incognito-mapped name) instead of the real domain in incognito mode. This causes icon lookups to fail and show only fallback letters, which is desired behavior for privacy - hiding both tracker names and icons when incognito mode is enabled.

Applied to files:

  • web/src/pages/Dashboard.tsx
📚 Learning: 2025-12-03T18:11:08.682Z
Learnt from: finevan
Repo: autobrr/qui PR: 677
File: web/src/components/torrents/AddTorrentDialog.tsx:496-504
Timestamp: 2025-12-03T18:11:08.682Z
Learning: In the AddTorrentDialog component (web/src/components/torrents/AddTorrentDialog.tsx), temporary path settings (useDownloadPath/downloadPath) should be applied per-torrent rather than updating global instance preferences. The UI/UX is designed to suggest that these options apply to the individual torrent being added.

Applied to files:

  • web/src/pages/Dashboard.tsx
🧬 Code graph analysis (2)
internal/models/tracker_customization.go (1)
web/src/types/index.ts (1)
  • TrackerCustomization (320-327)
web/src/pages/Dashboard.tsx (5)
web/src/components/ui/dialog.tsx (3)
  • DialogContent (138-138)
  • DialogDescription (139-139)
  • DialogHeader (141-141)
web/src/components/ui/label.tsx (1)
  • Label (29-29)
web/src/components/ui/scroll-area.tsx (1)
  • ScrollArea (61-61)
web/src/components/ui/checkbox.tsx (1)
  • Checkbox (43-43)
web/src/components/ui/badge.tsx (1)
  • Badge (51-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Run tests
🔇 Additional comments (16)
internal/database/migrations/034_add_tracker_customization_included_stats.sql (1)

1-7: LGTM!

Clean migration that adds the new column with appropriate defaults for backwards compatibility. The TEXT type with empty string default aligns with the existing domains column pattern.

web/src/types/index.ts (1)

320-333: LGTM!

Type definitions correctly mirror the backend model with optional includedInStats arrays. The optional nature preserves backwards compatibility with existing customizations.

web/src/hooks/useTrackerCustomizations.ts (1)

36-40: LGTM!

Toast notifications provide good user feedback on mutation failures. The generic error messages are appropriate to avoid leaking implementation details.

internal/models/tracker_customization.go (3)

16-23: LGTM!

The struct updates follow the established pattern for the domains field. The omitempty JSON tag ensures backwards-compatible serialization where empty arrays are omitted.


33-64: LGTM!

List and Get methods correctly extend the SELECT queries and scan logic to handle the new included_in_stats column, reusing the existing splitDomains helper for consistent deserialization.


86-136: LGTM!

Create and Update methods properly persist the IncludedInStats field using the existing joinDomains helper, which also handles deduplication.

internal/api/handlers/tracker_customizations.go (2)

34-44: LGTM!

The toModel method correctly normalizes domains first, then sanitizes IncludedInStats to ensure only valid secondary domains are persisted.


46-70: Well-implemented sanitization logic.

The sanitizeIncludedInStats function correctly:

  1. Returns nil for empty inputs (avoiding unnecessary allocations)
  2. Excludes the primary domain (index 0) from valid inclusion candidates
  3. Filters to only domains that exist in the customization

This ensures data integrity at the API boundary, consistent with the layered normalization pattern. Based on learnings, this follows the codebase convention where handlers perform input sanitization.

web/src/pages/Dashboard.tsx (8)

910-911: LGTM!

State additions properly track includedInStats for both editing existing customizations and creating new ones. Using a Set for new customizations aligns with the existing selectedDomains pattern.


945-997: Well-designed two-pass aggregation.

The algorithm correctly handles the case where domains may appear in any order in the aggregated map:

  • Pass 1 creates entries for primary domains (always included) and standalone domains
  • Pass 2 merges stats from secondary domains only when explicitly in includedInStats

The if (existing) guard in Pass 2 (line 987) safely handles edge cases where the primary domain has no stats.


1062-1135: LGTM!

The save handler correctly propagates includedInStats through create, update, and merge flows. The merge scenario (lines 1100-1108) appropriately combines existing and new inclusions, relying on backend sanitization for deduplication.


1203-1244: LGTM!

Domain management handlers correctly maintain state consistency:

  • handleRemoveDomainFromDialog removes domains from both the domain list and includedInStats
  • handleToggleStatsInclusion uses case-insensitive filtering before adding to prevent duplicates

The guard newDomains.length > 0 prevents accidentally removing all domains.


1253-1266: LGTM!

Export logic correctly includes includedInStats only when non-empty, keeping the JSON clean and backwards-compatible with older imports that don't have this field.


1325-1347: LGTM!

Import parsing correctly handles the optional includedInStats field with a default empty array, ensuring backwards compatibility with exports from before this feature was added.


1158-1168: LGTM!

The openEditDialog function correctly retrieves the full customization from the query cache to populate includedInStats, with appropriate fallback to an empty array.


1196-1201: LGTM!

Dialog close handler properly resets includedInStats state to prevent stale data when reopening the dialog.

@s0up4200 s0up4200 merged commit cd0deee into main Dec 14, 2025
12 checks passed
@s0up4200 s0up4200 deleted the feat/tracker-stats-per-domain-inclusion branch December 14, 2025 20:10
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Dec 18, 2025
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/autobrr/qui](https://github.com/autobrr/qui) | minor | `v1.9.1` -> `v1.10.0` |

---

### Release Notes

<details>
<summary>autobrr/qui (ghcr.io/autobrr/qui)</summary>

### [`v1.10.0`](https://github.com/autobrr/qui/releases/tag/v1.10.0)

[Compare Source](autobrr/qui@v1.9.1...v1.10.0)

#### Changelog

##### New Features

- [`f2b17e6`](autobrr/qui@f2b17e6): feat(config): add SESSION\_SECRET\_FILE env var ([#&#8203;661](autobrr/qui#661)) ([@&#8203;undefined-landmark](https://github.com/undefined-landmark))
- [`f5ede56`](autobrr/qui@f5ede56): feat(crossseed): add RSS source filters for categories and tags ([#&#8203;757](autobrr/qui#757)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9dee7bb`](autobrr/qui@9dee7bb): feat(crossseed): add Unicode normalization for title and file matching ([#&#8203;742](autobrr/qui#742)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d44058f`](autobrr/qui@d44058f): feat(crossseed): add skip auto-resume settings per mode ([#&#8203;755](autobrr/qui#755)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`9e3534a`](autobrr/qui@9e3534a): feat(crossseed): add webhook source filters for categories and tags ([#&#8203;763](autobrr/qui#763)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c8bbe07`](autobrr/qui@c8bbe07): feat(crossseed): only poll status endpoints when features are enabled ([#&#8203;738](autobrr/qui#738)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`fda8101`](autobrr/qui@fda8101): feat(sidebar): add size tooltips and deduplicate cross-seed sizes ([#&#8203;724](autobrr/qui#724)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e4c0556`](autobrr/qui@e4c0556): feat(torrent): add sequential download toggles ([#&#8203;776](autobrr/qui#776)) ([@&#8203;rare-magma](https://github.com/rare-magma))
- [`2a43f15`](autobrr/qui@2a43f15): feat(torrents): autocomplete paths ([#&#8203;634](autobrr/qui#634)) ([@&#8203;rare-magma](https://github.com/rare-magma))
- [`1c07b33`](autobrr/qui@1c07b33): feat(torrents): replace filtered speeds with global ([#&#8203;745](autobrr/qui#745)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`cd0deee`](autobrr/qui@cd0deee): feat(tracker): add per-domain stats inclusion toggle for merged trackers ([#&#8203;781](autobrr/qui#781)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`b6a6200`](autobrr/qui@b6a6200): feat(web): add Size column to Tracker Breakdown table ([#&#8203;770](autobrr/qui#770)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`560071b`](autobrr/qui@560071b): feat(web): add zebra striping to torrent table ([#&#8203;726](autobrr/qui#726)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f8f65a8`](autobrr/qui@f8f65a8): feat(web): improve auto-search on completion UX ([#&#8203;743](autobrr/qui#743)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e36312f`](autobrr/qui@e36312f): feat(web): improve torrent selection UX with unified click and escape behavior ([#&#8203;782](autobrr/qui#782)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`27c1daa`](autobrr/qui@27c1daa): feat(web): napster theme ([#&#8203;728](autobrr/qui#728)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`e3950de`](autobrr/qui@e3950de): feat(web): new torrent details panel for desktop ([#&#8203;760](autobrr/qui#760)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`6c66ba5`](autobrr/qui@6c66ba5): feat(web): persist tab state in URL for CrossSeed and Settings pages ([#&#8203;775](autobrr/qui#775)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`59884a9`](autobrr/qui@59884a9): feat(web): share tracker customizations with filtersidebar ([#&#8203;717](autobrr/qui#717)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Bug Fixes

- [`fafd278`](autobrr/qui@fafd278): fix(api): add webhook source filter fields to PATCH settings endpoint ([#&#8203;774](autobrr/qui#774)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`bdf0339`](autobrr/qui@bdf0339): fix(api): support apikey query param with custom base URL ([#&#8203;748](autobrr/qui#748)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c3c8d66`](autobrr/qui@c3c8d66): fix(crossseed): compare Site and Sum fields for anime releases ([#&#8203;769](autobrr/qui#769)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`cb4c965`](autobrr/qui@cb4c965): fix(crossseed): detect file name differences and fix hasExtraSourceFiles ([#&#8203;741](autobrr/qui#741)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`fd9e054`](autobrr/qui@fd9e054): fix(crossseed): fix batch completion searches and remove legacy settings ([#&#8203;744](autobrr/qui#744)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`26706a0`](autobrr/qui@26706a0): fix(crossseed): normalize punctuation in title matching ([#&#8203;718](autobrr/qui#718)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`db30566`](autobrr/qui@db30566): fix(crossseed): rename files before folder to avoid path conflicts ([#&#8203;752](autobrr/qui#752)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`8886ac4`](autobrr/qui@8886ac4): fix(crossseed): resolve category creation race condition and relax autoTMM ([#&#8203;767](autobrr/qui#767)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`f8f2a05`](autobrr/qui@f8f2a05): fix(crossseed): support game scene releases with RAR files ([#&#8203;768](autobrr/qui#768)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`918adee`](autobrr/qui@918adee): fix(crossseed): treat x264/H.264/H264/AVC as equivalent codecs ([#&#8203;766](autobrr/qui#766)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`c4b1f0a`](autobrr/qui@c4b1f0a): fix(dashboard): merge tracker customizations with duplicate displayName ([#&#8203;751](autobrr/qui#751)) ([@&#8203;jabloink](https://github.com/jabloink))
- [`3c6e0f9`](autobrr/qui@3c6e0f9): fix(license): remove redundant validation call after activation ([#&#8203;749](autobrr/qui#749)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`a9c7754`](autobrr/qui@a9c7754): fix(reannounce): simplify tracker detection to match qbrr logic ([#&#8203;746](autobrr/qui#746)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`3baa007`](autobrr/qui@3baa007): fix(rss): skip download when torrent already exists by infohash ([#&#8203;715](autobrr/qui#715)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`55d0ccc`](autobrr/qui@55d0ccc): fix(swagger): respect base URL for API docs routes ([#&#8203;758](autobrr/qui#758)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`47695fd`](autobrr/qui@47695fd): fix(web): add height constraint to filter sidebar wrapper for proper scrolling ([#&#8203;778](autobrr/qui#778)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`4b3bfea`](autobrr/qui@4b3bfea): fix(web): default torrent format to v1 in creator dialog ([#&#8203;723](autobrr/qui#723)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2d54b79`](autobrr/qui@2d54b79): fix(web): pin submit button in Services sheet footer ([#&#8203;756](autobrr/qui#756)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`2bcd6a3`](autobrr/qui@2bcd6a3): fix(web): preserve folder collapse state during file tree sync ([#&#8203;740](autobrr/qui#740)) ([@&#8203;ewenjo](https://github.com/ewenjo))
- [`57f3f1d`](autobrr/qui@57f3f1d): fix(web): sort Peers column by total peers instead of connected ([#&#8203;759](autobrr/qui#759)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`53a8818`](autobrr/qui@53a8818): fix(web): sort Seeds column by total seeds instead of connected ([#&#8203;747](autobrr/qui#747)) ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`d171915`](autobrr/qui@d171915): fix(web): sort folders before files in torrent file tree ([#&#8203;764](autobrr/qui#764)) ([@&#8203;s0up4200](https://github.com/s0up4200))

##### Other Changes

- [`172b4aa`](autobrr/qui@172b4aa): chore(assets): replace napster.svg with napster.png for logo update ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`dc83102`](autobrr/qui@dc83102): chore(deps): bump the github group with 3 updates ([#&#8203;761](autobrr/qui#761)) ([@&#8203;dependabot](https://github.com/dependabot)\[bot])
- [`75357d3`](autobrr/qui@75357d3): chore: fix napster logo ([@&#8203;s0up4200](https://github.com/s0up4200))
- [`206c4b2`](autobrr/qui@206c4b2): refactor(web): extract CrossSeed completion to accordion component ([#&#8203;762](autobrr/qui#762)) ([@&#8203;s0up4200](https://github.com/s0up4200))

**Full Changelog**: <autobrr/qui@v1.9.1...v1.10.0>

#### Docker images

- `docker pull ghcr.io/autobrr/qui:v1.10.0`
- `docker pull ghcr.io/autobrr/qui:latest`

#### What to do next?

- Join our [Discord server](https://discord.autobrr.com/qui)

Thank you for using qui!

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4zOS4xIiwidXBkYXRlZEluVmVyIjoiNDIuMzkuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW1hZ2UiXX0=-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/2664
Co-authored-by: Renovate Bot <renovate-bot@alexlebens.net>
Co-committed-by: Renovate Bot <renovate-bot@alexlebens.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Long tracker customizations overflow the screen and can't be edited

1 participant