Skip to content

feat: multi-file torrent upload with per-file editing#696

Merged
tsynik merged 1 commit into
YouROK:masterfrom
staners2:feat/multi-add-torrents
Apr 26, 2026
Merged

feat: multi-file torrent upload with per-file editing#696
tsynik merged 1 commit into
YouROK:masterfrom
staners2:feat/multi-add-torrents

Conversation

@staners2

@staners2 staners2 commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds support for selecting and uploading multiple .torrent files at once, with a dedicated dialog for editing each file's metadata before saving.

New functionality

  • Multi-file upload: Dropzone now accepts multiple .torrent files (drag & drop or file picker)
  • MultiAddDialog: When files are selected, a new dialog displays all files as a scrollable list. Each file has:
    • Poster thumbnail with index number (auto-fetched from TMDB)
    • Editable title field (pre-filled with filename without .torrent extension)
    • Editable poster URL field
    • Category selector
    • Delete button to remove from batch
  • Duplicate filtering: Each file's infohash is parsed client-side and compared against existing torrents in DB. Duplicates are silently filtered out — only new torrents are shown and uploaded
  • Unified flow: Both single and multiple file uploads use the same list-based UI
  • Card separation: Each file displayed as a distinct card with border-radius, shadow and spacing

Code changes

  • New MultiAddDialog component with styled-components (MultiFileRow, MultiFilePoster, MultiFileInfo, MultiFileList)
  • Simplified AddDialog: file uploads delegated to MultiAddDialog, handles only link/magnet/hash and edit mode
  • Simplified LeftSideComponent: no "file selected" state, dropzone always visible
  • Backend upload.go: cleaned up dead multiFile title/poster blanking logic
  • Stable torrent list sort via useMemo (timestamp + hash tiebreaker)
  • TorrentCard memo optimization with custom comparator for visible fields
  • Grid layout fix: minmax(450px, 570px) instead of unstable minmax(max-content, 570px)
  • Null guards for torrents before .map()/.filter() (crash fix on initial render)
  • Removed dead code: LeftSideBottomSectionFileSelected, TorrentIconWrapper, CancelIconWrapper, unused hashRegex export
  • Updated ClickOrDrag text in all 7 locales for multiple file support

Test plan

  • Drop single .torrent file — list with one editable item
  • Drop multiple .torrent files — all shown with individual fields and correct numbering
  • Drop already-added .torrent files — duplicates filtered out, only new shown
  • All files are duplicates — dialog closes (nothing to add)
  • Add via magnet/hash/link — original flow unchanged
  • Edit existing torrent — edit dialog unchanged
  • Verify cards don't jump after adding
  • Test on narrow screen (<700px) — dialog goes fullscreen

@staners2
staners2 force-pushed the feat/multi-add-torrents branch from bbe6318 to 9de64e7 Compare April 10, 2026 13:46

@pavelpikta pavelpikta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi @staners2
Don't need to push chages for static files, static files will udpated before release

@staners2
staners2 force-pushed the feat/multi-add-torrents branch from 9de64e7 to f3d7b47 Compare April 16, 2026 11:21
@staners2
staners2 force-pushed the feat/multi-add-torrents branch from 22cdec8 to 6ef48fc Compare April 16, 2026 12:45
@staners2

Copy link
Copy Markdown
Contributor Author

Does this multi-add visualization work — separating items into "to be added" and "already in database" sections — or do you have any suggestions for a better approach?
image

@pavelpikta

pavelpikta commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Работает ли эта визуализация с множеством добавлений — разделение элементов на разделы «для добавления» и «уже в базе данных» — или у вас есть предложения по лучшему подходу? Изображение

how about to skip torrents that already in database and show only torrents that will be added?

@staners2
staners2 force-pushed the feat/multi-add-torrents branch from 6ef48fc to 6c5f495 Compare April 17, 2026 04:42
…iltering

Multiple .torrent files can be selected/dropped at once. A dedicated
MultiAddDialog shows only new files as a scrollable list with per-file
editable fields: title (pre-filled from filename), poster URL
(auto-fetched from TMDB), and category. Duplicates (matched by infohash)
are silently filtered out and not displayed.

Additional fixes:
- Stable torrent list sort (timestamp + hash tiebreaker via useMemo)
- TorrentCard memo optimization for visible fields only
- Grid layout fix (max-content → 450px minimum)
- Crash fix: null guards for torrents before .map()/.filter()
- Backend: cleaned up upload.go dead multiFile logic
- Removed dead styled-components and unused exports
@staners2
staners2 force-pushed the feat/multi-add-torrents branch from 6c5f495 to ddc321b Compare April 17, 2026 05:07
@staners2

Copy link
Copy Markdown
Contributor Author

Done. Torrents that are already in the database are now skipped, and only the ones to be added are displayed.
image

@tsynik
tsynik merged commit b38ebd6 into YouROK:master Apr 26, 2026
freetushkan added a commit to freetushkan/TorrServer that referenced this pull request Jun 17, 2026
* feat: add new telegram bot commands

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* refactor: reorganize telegram bot commands and add new features

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* fix: handle error when starting telegram bot

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* feat: add ParseFromBytes function to handle torrent data from byte slices

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* feat: optimize torrent list API with lightweight status and filtering (YouROK#693)

* Fix: replace ${MAINPID} with $MAINPID in systemd service file (YouROK#689)

systemd не поддерживает фигурные скобки для специальных переменных.
${MAINPID} в ExecStop и ExecReload не раскрывается, kill получает 
пустой аргумент и падает с ошибкой "failed to parse argument: ''".
Сервис уходит в бесконечный цикл перезапусков.

* feat: enhance AddDialog with poster search improvements (YouROK#671)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* feat(nix): add flake with NixOS and Home Manager modules for TorrServer (YouROK#666)

Add Nix flake for TorrServer with offline builds and module system

- Implement fully offline build using fetchYarnDeps and buildGoModule
- Add NixOS module with systemd service, user/group management, and
firewall rules
- Add Home Manager module with user service and proper directory
handling
- Support all TorrServer options: port, auth, SSL, WebDAV, DLNA, cache
limits, etc.
- Fix swag documentation generation with proper parsing flags
- Set Go 1.26 to match project requirements
- Ensure reproducible builds without network access

Tested with NixOS 26.05 (Yarara) and standalone home-manager on Ubuntu
24.04

* fix(script): correct variable syntax in systemd service file (YouROK#703)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* Update helpers.js

* refactor: replace PreloadCacheValue with CacheLegendGrid and CacheLegendDot (YouROK#707)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* feat: update lordicon script source (YouROK#700)

- Changed the script source for Lordicon in index.html to use a relative path.
- Updated icon sources in AddFirstTorrent and NoServerConnection components to use the new relative paths.

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* fix: prevent sidebar burger menu from overlapping torrent cards on mobile (YouROK#695)

On narrow screens (<700px), the sidebar now slides in as a fixed overlay
with a backdrop instead of expanding within the grid and covering content.
On desktop, the grid columns adjust to accommodate the open sidebar.

* feat: multi-file torrent upload with per-file editing and duplicate filtering (YouROK#696)

Multiple .torrent files can be selected/dropped at once. A dedicated
MultiAddDialog shows only new files as a scrollable list with per-file
editable fields: title (pre-filled from filename), poster URL
(auto-fetched from TMDB), and category. Duplicates (matched by infohash)
are silently filtered out and not displayed.

Additional fixes:
- Stable torrent list sort (timestamp + hash tiebreaker via useMemo)
- TorrentCard memo optimization for visible fields only
- Grid layout fix (max-content → 450px minimum)
- Crash fix: null guards for torrents before .map()/.filter()
- Backend: cleaned up upload.go dead multiFile logic
- Removed dead styled-components and unused exports

* update static web

* Revert "feat: optimize torrent list API with lightweight status and filtering (YouROK#693)"

This reverts commit c1e1f96.

* feat: add SOCKS5 proxy support for Telegram API requests (YouROK#712)

- Implemented a new HTTP client that routes traffic through a SOCKS5 proxy if specified in the configuration
- Updated the README to include instructions for configuring the SOCKS5 proxy

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* docs: update Torznab search documentation (YouROK#715)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* chore: update Go version in Dockerfile from `1.26.0` to `1.26.2` (YouROK#716)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* feat: add ForceHTTPS option and HTTP to HTTPS redirection (YouROK#714)

* feat: add ForceHTTPS option and HTTP to HTTPS redirection

- Introduced a new ForceHTTPS flag in the configuration to enforce redirection of all HTTP requests to HTTPS.
- Implemented an HTTP server that handles redirection to HTTPS when the ForceHTTPS option is enabled.

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* docs: update README to include --force-https option details

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

---------

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* fix(tgbot): long markup (YouROK#713)

* refactor(tgbot): file management with pagination

- Added support for paginated file listings in the torrent management system.
- Updated the upload function to handle hash parameters more flexibly.

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* refactor(tgbot): file management with pagination

- Added support for paginated file listings in the torrent management system.
- Updated the upload function to handle hash parameters more flexibly.

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

---------

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* Prevent nil pointer dereference and duplicate cache creation (YouROK#719)

Co-authored-by: VuzzyM <>

* bump torrent v1.2.23 and update godoc

* Update go.sum

* feat(docker): update Go version from `1.26.2` to `1.26.3` (YouROK#728)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* potential fix of YouROK#729 (YouROK#730)

* LPD-bep14-Support (YouROK#732)

Co-authored-by: VuzzyM <>

* Fix critical server hangs (YouROK#731)

- torrent.go: Add nil cache check in expired() and protect against double close
- piece.go: Remove isClosed check in Release() to prevent library deadlock
- apihelper.go: Wait for torrent close via closedChan before deleting files
- cache.go: Fix deadlock in getRemPieces() (copy readers without locking)
- cache.go: Add TryLock() in cleanPieces() to prevent recursive calls

Co-authored-by: @lexandr0s
Co-authored-by: Vuzzy

Co-authored-by: VuzzyM <>

* bump torrent v1.2.24 and web

* bump torrent v1.2.25

* Update SecondarySettingsComponent.jsx

* Response header for Kodi (YouROK#734)

* sync playable files for m3u playlist

* chore(deps): bump github.com/ipld/go-ipld-prime in /server (YouROK#720)

Bumps [github.com/ipld/go-ipld-prime](https://github.com/ipld/go-ipld-prime) from 0.21.0 to 0.23.0.
- [Release notes](https://github.com/ipld/go-ipld-prime/releases)
- [Changelog](https://github.com/ipld/go-ipld-prime/blob/master/CHANGELOG.md)
- [Commits](ipld/go-ipld-prime@v0.21.0...v0.23.0)

---
updated-dependencies:
- dependency-name: github.com/ipld/go-ipld-prime
  dependency-version: 0.23.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump go.opentelemetry.io/otel in /server (YouROK#708)

Bumps [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) from 1.40.0 to 1.41.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.40.0...v1.41.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel
  dependency-version: 1.41.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump path-to-regexp from 0.1.12 to 0.1.13 in /web (YouROK#685)

Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 0.1.12 to 0.1.13.
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/v.0.1.13/History.md)
- [Commits](pillarjs/path-to-regexp@v0.1.12...v.0.1.13)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-version: 0.1.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump brace-expansion from 1.1.12 to 1.1.13 in /web (YouROK#687)

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.12 to 1.1.13.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](juliangruber/brace-expansion@v1.1.12...v1.1.13)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump picomatch from 2.3.1 to 2.3.2 in /web (YouROK#682)

Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](micromatch/picomatch@2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump axios from 1.13.5 to 1.16.0 in /web (YouROK#735)

Bumps [axios](https://github.com/axios/axios) from 1.13.5 to 1.16.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.13.5...v1.16.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.16.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump flatted from 3.3.2 to 3.4.2 in /web (YouROK#679)

Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.2 to 3.4.2.
- [Commits](WebReflection/flatted@v3.3.2...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump yaml from 1.10.2 to 1.10.3 in /web (YouROK#681)

Bumps [yaml](https://github.com/eemeli/yaml) from 1.10.2 to 1.10.3.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](eemeli/yaml@v1.10.2...v1.10.3)

---
updated-dependencies:
- dependency-name: yaml
  dependency-version: 1.10.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump lodash from 4.17.23 to 4.18.1 in /web (YouROK#694)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.18.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump fast-uri from 3.0.5 to 3.1.2 in /web (YouROK#721)

Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.0.5 to 3.1.2.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](fastify/fast-uri@v3.0.5...v3.1.2)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump @babel/plugin-transform-modules-systemjs in /web (YouROK#722)

Bumps [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs) from 7.25.9 to 7.29.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.4/packages/babel-plugin-transform-modules-systemjs)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-modules-systemjs"
  dependency-version: 7.29.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump uuid from 8.3.2 to 14.0.0 in /web (YouROK#706)

Bumps [uuid](https://github.com/uuidjs/uuid) from 8.3.2 to 14.0.0.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](uuidjs/uuid@v8.3.2...v14.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 14.0.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump follow-redirects from 1.15.11 to 1.16.0 in /web (YouROK#702)

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.11 to 1.16.0.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](follow-redirects/follow-redirects@v1.15.11...v1.16.0)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-version: 1.16.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: nikk <1551446+tsynik@users.noreply.github.com>

* update static web

* feat(ci): build with embedded TMDB API Key (YouROK#736)

* feat(ci): build with embedded TMDB API Key

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* refactor(helpers): TMDB settings management

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

---------

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* fx actions build

* fix(helpers): URL normalization and TMDB search URL builder (YouROK#737)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* update static web

* feat(docker): add version argument and update build flags (YouROK#738)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* chore(deps): bump github.com/quic-go/quic-go in /server (YouROK#740)

Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.59.0 to 0.59.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Commits](quic-go/quic-go@v0.59.0...v0.59.1)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-version: 0.59.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(docker): update Go version from `1.26.3` to `1.26.4` (YouROK#741)

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>

* fix: thread-safe SetDefTrackers and robust AddTrackers delimiter handling (YouROK#743)

Co-authored-by: VuzzyM <>

---------

Signed-off-by: Pavel Pikta <devops@pavelpikta.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Pavel Pikta <devops@pavelpikta.com>
Co-authored-by: YouROK <8YouROK8@mail.ru>
Co-authored-by: Dima Aratin <39628042+staners2@users.noreply.github.com>
Co-authored-by: kostiavn <77079302+kostiavn@users.noreply.github.com>
Co-authored-by: GriefNorth <grief.north@gmail.com>
Co-authored-by: nikk gitanes <tsynik@gmail.com>
Co-authored-by: Vuzzy <66425682+VuzzyM@users.noreply.github.com>
Co-authored-by: srgsf <srgsf.github@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: nikk <1551446+tsynik@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants