mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2025-02-17 15:52:04 +03:00
perf: add translations cron (#1367)
This commit is contained in:
parent
8f8caad25e
commit
02d97f5283
89 changed files with 6858 additions and 1285 deletions
4
.github/dependabot.yaml
vendored
4
.github/dependabot.yaml
vendored
|
@ -13,5 +13,5 @@ updates:
|
|||
interval: 'weekly'
|
||||
groups:
|
||||
all:
|
||||
patterns:
|
||||
- "*"
|
||||
patterns:
|
||||
- '*'
|
||||
|
|
32
.github/workflows/translations.yml
vendored
Normal file
32
.github/workflows/translations.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
name: Update Translations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# At 00:00 on Sunday.
|
||||
- cron: '0 0 * * 0'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-translations:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Update locales
|
||||
run: |
|
||||
curl -H 'X-API-KEY: ${{ secrets.TOLGEE_TOKEN }}' 'https://app.tolgee.io/v2/projects/export' -o locales.zip
|
||||
unzip -o -d ./src/locales locales.zip
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'chore: update translations'
|
||||
branch: 'update-tolgee-translations'
|
||||
title: 'chore: update translations'
|
||||
delete-branch: true
|
150
CHANGELOG.md
150
CHANGELOG.md
|
@ -2,118 +2,142 @@
|
|||
|
||||
## [2.2.0](https://github.com/WDaan/VueTorrent/compare/v2.1.1...v2.2.0) (2023-11-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **AddTorrentDialog:** Rework dialog to add missing parameters ([#1323](https://github.com/WDaan/VueTorrent/issues/1323)) ([f69851c](https://github.com/WDaan/VueTorrent/commit/f69851cc39bd7ca47f426a5eb5d900c5c428b758))
|
||||
* **ConnectionStatusDialog:** Add DHT node and active peer connections ([#1312](https://github.com/WDaan/VueTorrent/issues/1312)) ([6f01c00](https://github.com/WDaan/VueTorrent/commit/6f01c008e88ad3c4a45fab7f8624416975756033))
|
||||
* **Content:** Add menu to set file priority ([#1333](https://github.com/WDaan/VueTorrent/issues/1333)) ([f83fe06](https://github.com/WDaan/VueTorrent/commit/f83fe0691a939a99ed4490d22d8aba9c1994d67d))
|
||||
* **Overview:** Add keyboard shortcuts ([#1335](https://github.com/WDaan/VueTorrent/issues/1335)) ([15a20a3](https://github.com/WDaan/VueTorrent/commit/15a20a3a4e68d86ddf54c0ee13463ed2288ddfc9))
|
||||
* **preferences:** Update settings page to include missing preferences ([#1296](https://github.com/WDaan/VueTorrent/issues/1296)) ([e034071](https://github.com/WDaan/VueTorrent/commit/e0340710cc7dce842d260edaf0848e241a36208b))
|
||||
* **RSS:** Add conf to use ID instead of link ([#1334](https://github.com/WDaan/VueTorrent/issues/1334)) ([6af7537](https://github.com/WDaan/VueTorrent/commit/6af75375571fadd650d1342c132e34d3ec6c3f49))
|
||||
|
||||
- **AddTorrentDialog:** Rework dialog to add missing parameters ([#1323](https://github.com/WDaan/VueTorrent/issues/1323))
|
||||
([f69851c](https://github.com/WDaan/VueTorrent/commit/f69851cc39bd7ca47f426a5eb5d900c5c428b758))
|
||||
- **ConnectionStatusDialog:** Add DHT node and active peer connections ([#1312](https://github.com/WDaan/VueTorrent/issues/1312))
|
||||
([6f01c00](https://github.com/WDaan/VueTorrent/commit/6f01c008e88ad3c4a45fab7f8624416975756033))
|
||||
- **Content:** Add menu to set file priority ([#1333](https://github.com/WDaan/VueTorrent/issues/1333))
|
||||
([f83fe06](https://github.com/WDaan/VueTorrent/commit/f83fe0691a939a99ed4490d22d8aba9c1994d67d))
|
||||
- **Overview:** Add keyboard shortcuts ([#1335](https://github.com/WDaan/VueTorrent/issues/1335))
|
||||
([15a20a3](https://github.com/WDaan/VueTorrent/commit/15a20a3a4e68d86ddf54c0ee13463ed2288ddfc9))
|
||||
- **preferences:** Update settings page to include missing preferences ([#1296](https://github.com/WDaan/VueTorrent/issues/1296))
|
||||
([e034071](https://github.com/WDaan/VueTorrent/commit/e0340710cc7dce842d260edaf0848e241a36208b))
|
||||
- **RSS:** Add conf to use ID instead of link ([#1334](https://github.com/WDaan/VueTorrent/issues/1334))
|
||||
([6af7537](https://github.com/WDaan/VueTorrent/commit/6af75375571fadd650d1342c132e34d3ec6c3f49))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **AddTorrentDialog:** Add autocomplete attribute ([#1331](https://github.com/WDaan/VueTorrent/issues/1331)) ([aaa4cc1](https://github.com/WDaan/VueTorrent/commit/aaa4cc16e9e7cac207a8286ce950e924c7718327))
|
||||
* **AddTorrentDialog:** Prevent undefined values from being sent through API ([#1330](https://github.com/WDaan/VueTorrent/issues/1330)) ([6575ade](https://github.com/WDaan/VueTorrent/commit/6575ade19e0bb6443bc8e29187cf952ff4f67262))
|
||||
* authentication race condition ([#1319](https://github.com/WDaan/VueTorrent/issues/1319)) ([153268f](https://github.com/WDaan/VueTorrent/commit/153268f30d3f2f8c618083caebd51894a42bc32a))
|
||||
* **dashboard:** Fix span selection not using filters ([#1311](https://github.com/WDaan/VueTorrent/issues/1311)) ([06d1815](https://github.com/WDaan/VueTorrent/commit/06d1815f002b01843518a6bbf54b976c35be1054))
|
||||
* reduce title size [#1288](https://github.com/WDaan/VueTorrent/issues/1288) ([aab5cc1](https://github.com/WDaan/VueTorrent/commit/aab5cc16edd7247196daf298a366e0d369cfb932))
|
||||
* reduce title size [#1288](https://github.com/WDaan/VueTorrent/issues/1288) ([0c7701a](https://github.com/WDaan/VueTorrent/commit/0c7701a4d2cd46b7851760e46dc7cf85ef0b6f5a))
|
||||
* **Settings/Speed:** Fix speed values conversion ([#1332](https://github.com/WDaan/VueTorrent/issues/1332)) ([02c0496](https://github.com/WDaan/VueTorrent/commit/02c049692bb6fc88f1ca76faa1b271118eb7eb4a))
|
||||
* **settings:** Update disabled state in Bittorrent tab ([#1301](https://github.com/WDaan/VueTorrent/issues/1301)) ([f1cefe4](https://github.com/WDaan/VueTorrent/commit/f1cefe4e3ced36b81feab03e7e5fdf852b7b131e))
|
||||
* **TRC:** Use all selected torrents for transfer limits ([#1329](https://github.com/WDaan/VueTorrent/issues/1329)) ([3614081](https://github.com/WDaan/VueTorrent/commit/3614081f198e1bedd35a2fbf54aa18a366594cf6))
|
||||
|
||||
- **AddTorrentDialog:** Add autocomplete attribute ([#1331](https://github.com/WDaan/VueTorrent/issues/1331))
|
||||
([aaa4cc1](https://github.com/WDaan/VueTorrent/commit/aaa4cc16e9e7cac207a8286ce950e924c7718327))
|
||||
- **AddTorrentDialog:** Prevent undefined values from being sent through API ([#1330](https://github.com/WDaan/VueTorrent/issues/1330))
|
||||
([6575ade](https://github.com/WDaan/VueTorrent/commit/6575ade19e0bb6443bc8e29187cf952ff4f67262))
|
||||
- authentication race condition ([#1319](https://github.com/WDaan/VueTorrent/issues/1319))
|
||||
([153268f](https://github.com/WDaan/VueTorrent/commit/153268f30d3f2f8c618083caebd51894a42bc32a))
|
||||
- **dashboard:** Fix span selection not using filters ([#1311](https://github.com/WDaan/VueTorrent/issues/1311))
|
||||
([06d1815](https://github.com/WDaan/VueTorrent/commit/06d1815f002b01843518a6bbf54b976c35be1054))
|
||||
- reduce title size [#1288](https://github.com/WDaan/VueTorrent/issues/1288) ([aab5cc1](https://github.com/WDaan/VueTorrent/commit/aab5cc16edd7247196daf298a366e0d369cfb932))
|
||||
- reduce title size [#1288](https://github.com/WDaan/VueTorrent/issues/1288) ([0c7701a](https://github.com/WDaan/VueTorrent/commit/0c7701a4d2cd46b7851760e46dc7cf85ef0b6f5a))
|
||||
- **Settings/Speed:** Fix speed values conversion ([#1332](https://github.com/WDaan/VueTorrent/issues/1332))
|
||||
([02c0496](https://github.com/WDaan/VueTorrent/commit/02c049692bb6fc88f1ca76faa1b271118eb7eb4a))
|
||||
- **settings:** Update disabled state in Bittorrent tab ([#1301](https://github.com/WDaan/VueTorrent/issues/1301))
|
||||
([f1cefe4](https://github.com/WDaan/VueTorrent/commit/f1cefe4e3ced36b81feab03e7e5fdf852b7b131e))
|
||||
- **TRC:** Use all selected torrents for transfer limits ([#1329](https://github.com/WDaan/VueTorrent/issues/1329))
|
||||
([3614081](https://github.com/WDaan/VueTorrent/commit/3614081f198e1bedd35a2fbf54aa18a366594cf6))
|
||||
|
||||
### Improvements
|
||||
|
||||
* **stores:** Rework store structure to prevent circular imports ([#1325](https://github.com/WDaan/VueTorrent/issues/1325)) ([179af5a](https://github.com/WDaan/VueTorrent/commit/179af5a1d6886b9543b9170ae697f1011af501b9))
|
||||
- **stores:** Rework store structure to prevent circular imports ([#1325](https://github.com/WDaan/VueTorrent/issues/1325))
|
||||
([179af5a](https://github.com/WDaan/VueTorrent/commit/179af5a1d6886b9543b9170ae697f1011af501b9))
|
||||
|
||||
## [2.1.1](https://github.com/WDaan/VueTorrent/compare/v2.1.0...v2.1.1) (2023-11-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Navbar:** Add missing bind on right drawer setting ([#1294](https://github.com/WDaan/VueTorrent/issues/1294)) ([672ab08](https://github.com/WDaan/VueTorrent/commit/672ab0863f3ee41a5fb2fd17bdba81306fb91be3))
|
||||
* **RightClickMenu:** Fix target not being selected on long press ([#1295](https://github.com/WDaan/VueTorrent/issues/1295)) ([d80cc35](https://github.com/WDaan/VueTorrent/commit/d80cc35e94f3caa94520abf5ed83ba29b7d3bc2c))
|
||||
* **settings:** Update drag handling to completed properties ([#1286](https://github.com/WDaan/VueTorrent/issues/1286)) ([dd53e6f](https://github.com/WDaan/VueTorrent/commit/dd53e6fc9d299b506b8c3f28c19ee131aa811430))
|
||||
|
||||
- **Navbar:** Add missing bind on right drawer setting ([#1294](https://github.com/WDaan/VueTorrent/issues/1294))
|
||||
([672ab08](https://github.com/WDaan/VueTorrent/commit/672ab0863f3ee41a5fb2fd17bdba81306fb91be3))
|
||||
- **RightClickMenu:** Fix target not being selected on long press ([#1295](https://github.com/WDaan/VueTorrent/issues/1295))
|
||||
([d80cc35](https://github.com/WDaan/VueTorrent/commit/d80cc35e94f3caa94520abf5ed83ba29b7d3bc2c))
|
||||
- **settings:** Update drag handling to completed properties ([#1286](https://github.com/WDaan/VueTorrent/issues/1286))
|
||||
([dd53e6f](https://github.com/WDaan/VueTorrent/commit/dd53e6fc9d299b506b8c3f28c19ee131aa811430))
|
||||
|
||||
### Improvements
|
||||
|
||||
* **MagnetHandler:** Open add dialog on magnet link ([#1293](https://github.com/WDaan/VueTorrent/issues/1293)) ([0c546f1](https://github.com/WDaan/VueTorrent/commit/0c546f1b373b34162ea437c16a7a0574321a8a7f))
|
||||
- **MagnetHandler:** Open add dialog on magnet link ([#1293](https://github.com/WDaan/VueTorrent/issues/1293))
|
||||
([0c546f1](https://github.com/WDaan/VueTorrent/commit/0c546f1b373b34162ea437c16a7a0574321a8a7f))
|
||||
|
||||
## [2.1.0](https://github.com/WDaan/VueTorrent/compare/v2.0.1...v2.1.0) (2023-11-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **filters:** Allow to disable filters temporarily ([6f9ee5d](https://github.com/WDaan/VueTorrent/commit/6f9ee5d0e36bd0a9e1707f50edc84d8979ae7a51))
|
||||
* **localization:** Bringing back Russian locale ([#1281](https://github.com/WDaan/VueTorrent/issues/1281)) ([20dc684](https://github.com/WDaan/VueTorrent/commit/20dc6843aa587dd571362efa34cd6cc986af4591))
|
||||
* **ShareLimit:** Add torrent share limit dialog ([ed0991e](https://github.com/WDaan/VueTorrent/commit/ed0991e0a5b3985dbea40d343dc6a3c8224e1f32))
|
||||
* **title:** Ability to set custom browser tab title ([1f58005](https://github.com/WDaan/VueTorrent/commit/1f58005109ab5b8a1cf6d9575246e24a105cc3a8))
|
||||
|
||||
- **filters:** Allow to disable filters temporarily ([6f9ee5d](https://github.com/WDaan/VueTorrent/commit/6f9ee5d0e36bd0a9e1707f50edc84d8979ae7a51))
|
||||
- **localization:** Bringing back Russian locale ([#1281](https://github.com/WDaan/VueTorrent/issues/1281))
|
||||
([20dc684](https://github.com/WDaan/VueTorrent/commit/20dc6843aa587dd571362efa34cd6cc986af4591))
|
||||
- **ShareLimit:** Add torrent share limit dialog ([ed0991e](https://github.com/WDaan/VueTorrent/commit/ed0991e0a5b3985dbea40d343dc6a3c8224e1f32))
|
||||
- **title:** Ability to set custom browser tab title ([1f58005](https://github.com/WDaan/VueTorrent/commit/1f58005109ab5b8a1cf6d9575246e24a105cc3a8))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TorrentCard:** Fix properties not being persisted ([#1252](https://github.com/WDaan/VueTorrent/issues/1252)) ([c61b957](https://github.com/WDaan/VueTorrent/commit/c61b957683c5ee6591b27de755fdad062e93e16f))
|
||||
|
||||
- **TorrentCard:** Fix properties not being persisted ([#1252](https://github.com/WDaan/VueTorrent/issues/1252))
|
||||
([c61b957](https://github.com/WDaan/VueTorrent/commit/c61b957683c5ee6591b27de755fdad062e93e16f))
|
||||
|
||||
### Improvements
|
||||
|
||||
* **faker:** Improve torrent mocking ([#1187](https://github.com/WDaan/VueTorrent/issues/1187)) ([8b1f641](https://github.com/WDaan/VueTorrent/commit/8b1f641fca79ad580bcb6d94f41ad0f52c495e80))
|
||||
* **localization:** Integrate Tolgee inside CI ([#1276](https://github.com/WDaan/VueTorrent/issues/1276)) ([86e12da](https://github.com/WDaan/VueTorrent/commit/86e12da8d0f3ef5e2f7b335277590f8769daf104))
|
||||
* **TorrentCard:** Only process drag on handle ([#1253](https://github.com/WDaan/VueTorrent/issues/1253)) ([681e59f](https://github.com/WDaan/VueTorrent/commit/681e59f7c76eb5b984aa968782a81d08fd271cc3))
|
||||
* **Torrent:** Wrap title ([55c2ef8](https://github.com/WDaan/VueTorrent/commit/55c2ef811543ebcc84124d3304689f2901064e77))
|
||||
- **faker:** Improve torrent mocking ([#1187](https://github.com/WDaan/VueTorrent/issues/1187))
|
||||
([8b1f641](https://github.com/WDaan/VueTorrent/commit/8b1f641fca79ad580bcb6d94f41ad0f52c495e80))
|
||||
- **localization:** Integrate Tolgee inside CI ([#1276](https://github.com/WDaan/VueTorrent/issues/1276))
|
||||
([86e12da](https://github.com/WDaan/VueTorrent/commit/86e12da8d0f3ef5e2f7b335277590f8769daf104))
|
||||
- **TorrentCard:** Only process drag on handle ([#1253](https://github.com/WDaan/VueTorrent/issues/1253))
|
||||
([681e59f](https://github.com/WDaan/VueTorrent/commit/681e59f7c76eb5b984aa968782a81d08fd271cc3))
|
||||
- **Torrent:** Wrap title ([55c2ef8](https://github.com/WDaan/VueTorrent/commit/55c2ef811543ebcc84124d3304689f2901064e77))
|
||||
|
||||
## [2.0.1](https://github.com/WDaan/VueTorrent/compare/v2.0.0...v2.0.1) (2023-11-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dashboard:** Take filters into account when selecting all torrents ([9f4aa4a](https://github.com/WDaan/VueTorrent/commit/9f4aa4a119046d72eb5c2ad0047205c32c426c7a))
|
||||
* **settings:** Add DnD exception on settings page ([d91070b](https://github.com/WDaan/VueTorrent/commit/d91070b4a28508d1ea7c4ad7e6e595f358194657))
|
||||
|
||||
- **dashboard:** Take filters into account when selecting all torrents ([9f4aa4a](https://github.com/WDaan/VueTorrent/commit/9f4aa4a119046d72eb5c2ad0047205c32c426c7a))
|
||||
- **settings:** Add DnD exception on settings page ([d91070b](https://github.com/WDaan/VueTorrent/commit/d91070b4a28508d1ea7c4ad7e6e595f358194657))
|
||||
|
||||
### Improvements
|
||||
|
||||
* **settings reset:** Clear sessionStorage in addition to localStorage ([4eaaa33](https://github.com/WDaan/VueTorrent/commit/4eaaa33711f00fcb32515f58fedd6450d83f7cea))
|
||||
- **settings reset:** Clear sessionStorage in addition to localStorage ([4eaaa33](https://github.com/WDaan/VueTorrent/commit/4eaaa33711f00fcb32515f58fedd6450d83f7cea))
|
||||
|
||||
## [2.0.0](https://github.com/WDaan/VueTorrent/compare/v1.8.0...v2.0.0) (2023-11-03)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* Vue3 Rewrite ([#757](https://github.com/WDaan/VueTorrent/issues/757))
|
||||
- Vue3 Rewrite ([#757](https://github.com/WDaan/VueTorrent/issues/757))
|
||||
|
||||
### Features
|
||||
|
||||
* **dashboard:** Add DL / UL Speed average to DashboardItems ([#1203](https://github.com/WDaan/VueTorrent/issues/1203)) ([7af47f9](https://github.com/WDaan/VueTorrent/commit/7af47f9e3d375be39fe133f10c69eeee5fa3ff43))
|
||||
* **filters:** Allow multiple selection ([#1202](https://github.com/WDaan/VueTorrent/issues/1202)) ([41318c3](https://github.com/WDaan/VueTorrent/commit/41318c3d85da44833b7ce1e2afba9a613b07c624))
|
||||
* **transfer limit:** Add callbacks for download / upload torrent limit ([#1217](https://github.com/WDaan/VueTorrent/issues/1217)) ([1792df9](https://github.com/WDaan/VueTorrent/commit/1792df965ba78c83264b315b6f1ecbaca4b08e04))
|
||||
* Vue3 Rewrite ([#757](https://github.com/WDaan/VueTorrent/issues/757)) ([575b071](https://github.com/WDaan/VueTorrent/commit/575b071f6db9edc01412fab45109d3f4d203552d))
|
||||
|
||||
- **dashboard:** Add DL / UL Speed average to DashboardItems ([#1203](https://github.com/WDaan/VueTorrent/issues/1203))
|
||||
([7af47f9](https://github.com/WDaan/VueTorrent/commit/7af47f9e3d375be39fe133f10c69eeee5fa3ff43))
|
||||
- **filters:** Allow multiple selection ([#1202](https://github.com/WDaan/VueTorrent/issues/1202))
|
||||
([41318c3](https://github.com/WDaan/VueTorrent/commit/41318c3d85da44833b7ce1e2afba9a613b07c624))
|
||||
- **transfer limit:** Add callbacks for download / upload torrent limit ([#1217](https://github.com/WDaan/VueTorrent/issues/1217))
|
||||
([1792df9](https://github.com/WDaan/VueTorrent/commit/1792df965ba78c83264b315b6f1ecbaca4b08e04))
|
||||
- Vue3 Rewrite ([#757](https://github.com/WDaan/VueTorrent/issues/757)) ([575b071](https://github.com/WDaan/VueTorrent/commit/575b071f6db9edc01412fab45109d3f4d203552d))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **AddTorrentDialog:** Dialog was never initialized with default values ([#1214](https://github.com/WDaan/VueTorrent/issues/1214)) ([44fd8d3](https://github.com/WDaan/VueTorrent/commit/44fd8d38619b7a468f8f0a7e04c71cf9cd94683b))
|
||||
* **AddTorrentDialog:** Fix persistence not working ([#1213](https://github.com/WDaan/VueTorrent/issues/1213)) ([9ee6533](https://github.com/WDaan/VueTorrent/commit/9ee65335e129139a4cff4ba307d94b8075f66558))
|
||||
* **AddTorrent:** Error while accessing preferences ([#1216](https://github.com/WDaan/VueTorrent/issues/1216)) ([c760072](https://github.com/WDaan/VueTorrent/commit/c76007241dbd604f6e31bc506b88a065dc57d920))
|
||||
* Chinese translations([#1189](https://github.com/WDaan/VueTorrent/issues/1189)) ([3f34cfc](https://github.com/WDaan/VueTorrent/commit/3f34cfcfdb9b9ff0a0c1030e2cb82fd671c562a0))
|
||||
* **dashboard:** Sort not working anymore ([#1211](https://github.com/WDaan/VueTorrent/issues/1211)) ([b2bbcb9](https://github.com/WDaan/VueTorrent/commit/b2bbcb987e7569bfb58bf01930f4d6cbcb9e95c3))
|
||||
* **rss:** Update overflow rules to handle long name without spaces ([#1228](https://github.com/WDaan/VueTorrent/issues/1228)) ([e2ce2e8](https://github.com/WDaan/VueTorrent/commit/e2ce2e86f5ff59499834a91b8de6c3bc8aa1e156))
|
||||
|
||||
- **AddTorrentDialog:** Dialog was never initialized with default values ([#1214](https://github.com/WDaan/VueTorrent/issues/1214))
|
||||
([44fd8d3](https://github.com/WDaan/VueTorrent/commit/44fd8d38619b7a468f8f0a7e04c71cf9cd94683b))
|
||||
- **AddTorrentDialog:** Fix persistence not working ([#1213](https://github.com/WDaan/VueTorrent/issues/1213))
|
||||
([9ee6533](https://github.com/WDaan/VueTorrent/commit/9ee65335e129139a4cff4ba307d94b8075f66558))
|
||||
- **AddTorrent:** Error while accessing preferences ([#1216](https://github.com/WDaan/VueTorrent/issues/1216))
|
||||
([c760072](https://github.com/WDaan/VueTorrent/commit/c76007241dbd604f6e31bc506b88a065dc57d920))
|
||||
- Chinese translations([#1189](https://github.com/WDaan/VueTorrent/issues/1189)) ([3f34cfc](https://github.com/WDaan/VueTorrent/commit/3f34cfcfdb9b9ff0a0c1030e2cb82fd671c562a0))
|
||||
- **dashboard:** Sort not working anymore ([#1211](https://github.com/WDaan/VueTorrent/issues/1211))
|
||||
([b2bbcb9](https://github.com/WDaan/VueTorrent/commit/b2bbcb987e7569bfb58bf01930f4d6cbcb9e95c3))
|
||||
- **rss:** Update overflow rules to handle long name without spaces ([#1228](https://github.com/WDaan/VueTorrent/issues/1228))
|
||||
([e2ce2e8](https://github.com/WDaan/VueTorrent/commit/e2ce2e86f5ff59499834a91b8de6c3bc8aa1e156))
|
||||
|
||||
### Improvements
|
||||
|
||||
* add Chinese translations ([#1185](https://github.com/WDaan/VueTorrent/issues/1185)) ([c50f1df](https://github.com/WDaan/VueTorrent/commit/c50f1df4d6027588e6d8fc9465d0bfeafd934f83))
|
||||
* **AddTorrentDialog:** Add loading prop to add button ([#1192](https://github.com/WDaan/VueTorrent/issues/1192)) ([ac3bb69](https://github.com/WDaan/VueTorrent/commit/ac3bb69a13e9b2bef3030f0b500ee37f1c79b0c5))
|
||||
* **AddTorrentDialog:** persist form in sessionStorage ([#1193](https://github.com/WDaan/VueTorrent/issues/1193)) ([e59f6bf](https://github.com/WDaan/VueTorrent/commit/e59f6bf206e7ace0fbc5eead955ada5caa63bd4a))
|
||||
* **filters:** Reorder states ([197b9d7](https://github.com/WDaan/VueTorrent/commit/197b9d7d029c6669cccfb4c4fc183d62fed45de6))
|
||||
* **rss:** Improve duplicate RSS article handling ([#1191](https://github.com/WDaan/VueTorrent/issues/1191)) ([ee01382](https://github.com/WDaan/VueTorrent/commit/ee0138277177dbd9c5054ed81fb8ab11d5b919f0))
|
||||
* **rss:** Right click mark article as read ([#1210](https://github.com/WDaan/VueTorrent/issues/1210)) ([ee03b5c](https://github.com/WDaan/VueTorrent/commit/ee03b5cb58125df8fb073e264cc61bfda85ccd3b))
|
||||
* **TorrentCard:** Darken selected item background ([#1215](https://github.com/WDaan/VueTorrent/issues/1215)) ([8214a0e](https://github.com/WDaan/VueTorrent/commit/8214a0ebd43637bbe3eb7098f5b0ff5a5d0951b8))
|
||||
- add Chinese translations ([#1185](https://github.com/WDaan/VueTorrent/issues/1185))
|
||||
([c50f1df](https://github.com/WDaan/VueTorrent/commit/c50f1df4d6027588e6d8fc9465d0bfeafd934f83))
|
||||
- **AddTorrentDialog:** Add loading prop to add button ([#1192](https://github.com/WDaan/VueTorrent/issues/1192))
|
||||
([ac3bb69](https://github.com/WDaan/VueTorrent/commit/ac3bb69a13e9b2bef3030f0b500ee37f1c79b0c5))
|
||||
- **AddTorrentDialog:** persist form in sessionStorage ([#1193](https://github.com/WDaan/VueTorrent/issues/1193))
|
||||
([e59f6bf](https://github.com/WDaan/VueTorrent/commit/e59f6bf206e7ace0fbc5eead955ada5caa63bd4a))
|
||||
- **filters:** Reorder states ([197b9d7](https://github.com/WDaan/VueTorrent/commit/197b9d7d029c6669cccfb4c4fc183d62fed45de6))
|
||||
- **rss:** Improve duplicate RSS article handling ([#1191](https://github.com/WDaan/VueTorrent/issues/1191))
|
||||
([ee01382](https://github.com/WDaan/VueTorrent/commit/ee0138277177dbd9c5054ed81fb8ab11d5b919f0))
|
||||
- **rss:** Right click mark article as read ([#1210](https://github.com/WDaan/VueTorrent/issues/1210))
|
||||
([ee03b5c](https://github.com/WDaan/VueTorrent/commit/ee03b5cb58125df8fb073e264cc61bfda85ccd3b))
|
||||
- **TorrentCard:** Darken selected item background ([#1215](https://github.com/WDaan/VueTorrent/issues/1215))
|
||||
([8214a0e](https://github.com/WDaan/VueTorrent/commit/8214a0ebd43637bbe3eb7098f5b0ff5a5d0951b8))
|
||||
|
||||
## [1.8.0](https://github.com/WDaan/VueTorrent/compare/v1.7.4...v1.8.0) (2023-10-04)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<p>The sleekest looking WebUI for qBittorrent made with Vue.js!</p>
|
||||
|
||||
Join us on [Discord](https://discord.gg/KDQP7fR467)
|
||||
|
||||
</div>
|
||||
|
||||
![Vue](https://img.shields.io/badge/Vue-%5E3.3.4-brightgreen) ![qBittorrent](https://img.shields.io/badge/qBittorrent-4.4%2B-brightgreen)
|
||||
|
@ -117,5 +118,6 @@ but before you do that:
|
|||
<a href="https://www.buymeacoffee.com/wdaan"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=wdaan&button_colour=FFDD00&font_colour=000000&font_family=Arial&outline_colour=000000&coffee_colour=ffffff"></a>
|
||||
|
||||
## Contributors
|
||||
|
||||
- [@m4ximuel](https://github.com/m4ximuel)
|
||||
- [@Larsluph](https://github.com/Larsluph)
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
{
|
||||
"name": "Second torrent"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
BIN
locales.zip
Normal file
BIN
locales.zip
Normal file
Binary file not shown.
25
src/App.vue
25
src/App.vue
|
@ -4,17 +4,7 @@ import DnDZone from '@/components/DnDZone.vue'
|
|||
import Navbar from '@/components/Navbar/Navbar.vue'
|
||||
import { TitleOptions } from '@/constants/vuetorrent'
|
||||
import { formatPercent, formatSpeed } from '@/helpers'
|
||||
import {
|
||||
useAddTorrentStore,
|
||||
useAppStore,
|
||||
useAuthStore,
|
||||
useDialogStore,
|
||||
useLogStore,
|
||||
useMaindataStore,
|
||||
usePreferenceStore,
|
||||
useTorrentStore,
|
||||
useVueTorrentStore
|
||||
} from '@/stores'
|
||||
import { useAddTorrentStore, useAppStore, useAuthStore, useDialogStore, useLogStore, useMaindataStore, usePreferenceStore, useTorrentStore, useVueTorrentStore } from '@/stores'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import { onBeforeMount, watch, watchEffect } from 'vue'
|
||||
|
@ -88,8 +78,8 @@ watchEffect(() => {
|
|||
case TitleOptions.GLOBAL_SPEED:
|
||||
document.title =
|
||||
'[' +
|
||||
`D: ${ formatSpeed(serverState.value?.dl_info_speed ?? 0, useBitSpeed.value) }, ` +
|
||||
`U: ${ formatSpeed(serverState.value?.up_info_speed ?? 0, useBitSpeed.value) }` +
|
||||
`D: ${formatSpeed(serverState.value?.dl_info_speed ?? 0, useBitSpeed.value)}, ` +
|
||||
`U: ${formatSpeed(serverState.value?.up_info_speed ?? 0, useBitSpeed.value)}` +
|
||||
'] VueTorrent'
|
||||
break
|
||||
case TitleOptions.FIRST_TORRENT_STATUS:
|
||||
|
@ -97,9 +87,9 @@ watchEffect(() => {
|
|||
if (torrent) {
|
||||
document.title =
|
||||
'[' +
|
||||
`D: ${ formatSpeed(torrent.dlspeed, useBitSpeed.value) }, ` +
|
||||
`U: ${ formatSpeed(torrent.upspeed, useBitSpeed.value) }, ` +
|
||||
`${ formatPercent(torrent.progress) }` +
|
||||
`D: ${formatSpeed(torrent.dlspeed, useBitSpeed.value)}, ` +
|
||||
`U: ${formatSpeed(torrent.upspeed, useBitSpeed.value)}, ` +
|
||||
`${formatPercent(torrent.progress)}` +
|
||||
'] VueTorrent'
|
||||
} else {
|
||||
document.title = '[N/A] VueTorrent'
|
||||
|
@ -118,8 +108,7 @@ watchEffect(() => {
|
|||
|
||||
<template>
|
||||
<v-app class="text-noselect">
|
||||
<component v-for="dialog in dialogStore.dialogs" :is="dialog.component"
|
||||
v-bind="{ guid: dialog.guid, ...dialog.props }" />
|
||||
<component v-for="dialog in dialogStore.dialogs" :is="dialog.component" v-bind="{ guid: dialog.guid, ...dialog.props }" />
|
||||
<Navbar v-if="authStore.isAuthenticated" />
|
||||
<v-main>
|
||||
<router-view />
|
||||
|
|
|
@ -11,8 +11,7 @@ function openAddTorrentDialog() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<v-bottom-navigation :active="addTorrentStore.pendingTorrentsCount > 0" class="pointer"
|
||||
v-touch="{ up: openAddTorrentDialog }" @click="openAddTorrentDialog">
|
||||
<v-bottom-navigation :active="addTorrentStore.pendingTorrentsCount > 0" class="pointer" v-touch="{ up: openAddTorrentDialog }" @click="openAddTorrentDialog">
|
||||
<v-list-item :title="$t('navbar.addPanel.torrentsPendingCount', addTorrentStore.pendingTorrentsCount)" />
|
||||
<v-spacer />
|
||||
<v-list-item>
|
||||
|
|
|
@ -12,11 +12,8 @@ const vueTorrentStore = useVueTorrentStore()
|
|||
<v-row data-testid="card-wrapper" :class="[`text-${color}`]">
|
||||
<v-col data-testid="card-title" cols="7" class="text-subtitle-1">{{ title }}</v-col>
|
||||
<v-col cols="5" class="">
|
||||
<span data-testid="card-value"
|
||||
class="text-subtitle-1 roboto">{{ formatDataValue(value, vueTorrentStore.useBinarySize) }}</span>
|
||||
<span data-testid="card-unit" class="font-weight-light text-caption ml-1 text-subtitle-1">{{
|
||||
formatDataUnit(value, vueTorrentStore.useBinarySize)
|
||||
}}</span>
|
||||
<span data-testid="card-value" class="text-subtitle-1 roboto">{{ formatDataValue(value, vueTorrentStore.useBinarySize) }}</span>
|
||||
<span data-testid="card-unit" class="font-weight-light text-caption ml-1 text-subtitle-1">{{ formatDataUnit(value, vueTorrentStore.useBinarySize) }}</span>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-sheet>
|
||||
|
|
|
@ -36,6 +36,4 @@ defineExpose({
|
|||
<v-combobox v-model="_value" ref="field" :items="historyValue" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -27,11 +27,8 @@ const vueTorrentStore = useVueTorrentStore()
|
|||
<v-icon class="" :icon="icon" :color="color" />
|
||||
</v-col>
|
||||
<v-col cols="8" class="d-flex flex-column align-center justify-center">
|
||||
<span class="text-subtitle-1 roboto"
|
||||
:class="`text-${color}`">{{ formatSpeedValue(value, vueTorrentStore.useBitSpeed) }}</span>
|
||||
<span class="text-caption" :class="`text-${color}`">{{
|
||||
formatSpeedUnit(value, vueTorrentStore.useBitSpeed)
|
||||
}}</span>
|
||||
<span class="text-subtitle-1 roboto" :class="`text-${color}`">{{ formatSpeedValue(value, vueTorrentStore.useBitSpeed) }}</span>
|
||||
<span class="text-caption" :class="`text-${color}`">{{ formatSpeedUnit(value, vueTorrentStore.useBitSpeed) }}</span>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-sheet>
|
||||
|
@ -44,4 +41,4 @@ const vueTorrentStore = useVueTorrentStore()
|
|||
font-family: 'Roboto Mono', sans-serif !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -11,7 +11,7 @@ const vuetorrentStore = useVueTorrentStore()
|
|||
<template>
|
||||
<div class="d-flex flex-column">
|
||||
<div class="text-caption text-grey">
|
||||
{{ $t(`torrent.properties.${ title }`) }}
|
||||
{{ $t(`torrent.properties.${title}`) }}
|
||||
</div>
|
||||
<div>
|
||||
{{ formatDataValue(torrent[value], vuetorrentStore.useBinarySize) }}
|
||||
|
|
|
@ -11,7 +11,7 @@ const vueTorrentStore = useVueTorrentStore()
|
|||
<template>
|
||||
<div class="d-flex flex-column">
|
||||
<div class="text-caption text-grey">
|
||||
{{ $t(`torrent.properties.${ title }`) }}
|
||||
{{ $t(`torrent.properties.${title}`) }}
|
||||
</div>
|
||||
<div>
|
||||
<span v-if="torrent[value] > 0">
|
||||
|
|
|
@ -11,7 +11,7 @@ const vuetorrentStore = useVueTorrentStore()
|
|||
<template>
|
||||
<div class="d-flex flex-column">
|
||||
<div class="text-caption text-grey">
|
||||
{{ $t(`torrent.properties.${ title }`) }}
|
||||
{{ $t(`torrent.properties.${title}`) }}
|
||||
</div>
|
||||
<div>
|
||||
{{ formatSpeedValue(torrent[value], vuetorrentStore.useBitSpeed) }}
|
||||
|
|
|
@ -116,7 +116,7 @@ async function exportTorrents() {
|
|||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.style.opacity = '0'
|
||||
link.setAttribute('download', `${ hash }.torrent`)
|
||||
link.setAttribute('download', `${hash}.torrent`)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
|
@ -280,8 +280,7 @@ const menuData = computed<TRCMenuEntry[]>(() => [
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<v-menu v-if="trcVisible" v-model="trcVisible" activator="parent" :close-on-content-click="true"
|
||||
transition="slide-y-transition" scroll-strategy="none">
|
||||
<v-menu v-if="trcVisible" v-model="trcVisible" activator="parent" :close-on-content-click="true" transition="slide-y-transition" scroll-strategy="none">
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<div class="d-flex justify-space-around">
|
||||
|
@ -294,8 +293,7 @@ const menuData = computed<TRCMenuEntry[]>(() => [
|
|||
|
||||
<v-tooltip location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn density="compact" variant="plain" icon="mdi-fast-forward" v-bind="props"
|
||||
@click="forceResumeTorrents" />
|
||||
<v-btn density="compact" variant="plain" icon="mdi-fast-forward" v-bind="props" @click="forceResumeTorrents" />
|
||||
</template>
|
||||
<span>Force Resume</span>
|
||||
</v-tooltip>
|
||||
|
@ -309,8 +307,7 @@ const menuData = computed<TRCMenuEntry[]>(() => [
|
|||
|
||||
<v-tooltip location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn color="red" density="compact" variant="plain" icon="mdi-delete-forever" v-bind="props"
|
||||
@click="deleteTorrents" />
|
||||
<v-btn color="red" density="compact" variant="plain" icon="mdi-delete-forever" v-bind="props" @click="deleteTorrents" />
|
||||
</template>
|
||||
<span>Delete</span>
|
||||
</v-tooltip>
|
||||
|
|
|
@ -61,13 +61,11 @@ const isTorrentSelected = computed(() => dashboardStore.isTorrentInSelection(pro
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<v-card :class="`sideborder ${torrent.state} pointer`"
|
||||
:color="isTorrentSelected ? `torrent-${torrent.state}-darken-3` : undefined" width="100%" @click="onClick">
|
||||
<v-card :class="`sideborder ${torrent.state} pointer`" :color="isTorrentSelected ? `torrent-${torrent.state}-darken-3` : undefined" width="100%" @click="onClick">
|
||||
<v-card-title class="text-wrap text-subtitle-1 pt-1 pb-0">{{ torrent.name }}</v-card-title>
|
||||
<v-card-text class="pa-2 pt-0">
|
||||
<div class="d-flex gap flex-wrap">
|
||||
<component :is="getComponent(ppt.type)" :torrent="torrent" v-bind="ppt.props"
|
||||
v-for="ppt in torrentProperties" />
|
||||
<component :is="getComponent(ppt.type)" :torrent="torrent" v-bind="ppt.props" v-for="ppt in torrentProperties" />
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
|
|
@ -9,12 +9,15 @@ import { computed, ref } from 'vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
import { toast } from 'vue3-toastify'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
guid: string
|
||||
openSuddenly?: boolean
|
||||
}>(), {
|
||||
openSuddenly: false
|
||||
})
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
guid: string
|
||||
openSuddenly?: boolean
|
||||
}>(),
|
||||
{
|
||||
openSuddenly: false
|
||||
}
|
||||
)
|
||||
|
||||
const { isOpened } = useDialog(props.guid)
|
||||
const { t } = useI18n()
|
||||
|
@ -45,12 +48,12 @@ const savePathField = ref<typeof HistoryField>()
|
|||
|
||||
const cookie = computed({
|
||||
get: () => form.value.cookie,
|
||||
set: value => form.value.cookie = value || undefined
|
||||
set: value => (form.value.cookie = value || undefined)
|
||||
})
|
||||
|
||||
const rename = computed({
|
||||
get: () => form.value.rename,
|
||||
set: value => form.value.rename = value || undefined
|
||||
set: value => (form.value.rename = value || undefined)
|
||||
})
|
||||
|
||||
const tagSearch = ref('')
|
||||
|
@ -62,14 +65,14 @@ const tags = computed({
|
|||
return []
|
||||
}
|
||||
},
|
||||
set: (value: string[]) => form.value.tags = value.join(',')
|
||||
set: (value: string[]) => (form.value.tags = value.join(','))
|
||||
})
|
||||
|
||||
const categorySearch = ref('')
|
||||
const categories = computed(() => maindataStore.categories.map(c => c.name))
|
||||
const category = computed<string | undefined>({
|
||||
get: () => form.value.category || categorySearch.value || undefined,
|
||||
set: value => form.value.category = value || undefined
|
||||
set: value => (form.value.category = value || undefined)
|
||||
})
|
||||
|
||||
const downloadPath = computed({
|
||||
|
@ -82,7 +85,7 @@ const downloadPath = computed({
|
|||
|
||||
const startNow = computed({
|
||||
get: () => !form.value.paused,
|
||||
set: value => form.value.paused = !value
|
||||
set: value => (form.value.paused = !value)
|
||||
})
|
||||
|
||||
const dlLimit = computed({
|
||||
|
@ -127,36 +130,41 @@ const upLimit = computed({
|
|||
|
||||
const ratioLimit = computed({
|
||||
get: () => form.value.ratioLimit,
|
||||
set: val => form.value.ratioLimit = val || undefined
|
||||
set: val => (form.value.ratioLimit = val || undefined)
|
||||
})
|
||||
|
||||
const seedingTimeLimit = computed({
|
||||
get: () => form.value.seedingTimeLimit,
|
||||
set: val => form.value.seedingTimeLimit = val || undefined
|
||||
set: val => (form.value.seedingTimeLimit = val || undefined)
|
||||
})
|
||||
|
||||
const inactiveSeedingTimeLimit = computed({
|
||||
get: () => form.value.inactiveSeedingTimeLimit,
|
||||
set: val => form.value.inactiveSeedingTimeLimit = val || undefined
|
||||
set: val => (form.value.inactiveSeedingTimeLimit = val || undefined)
|
||||
})
|
||||
|
||||
function submit() {
|
||||
if (!isFormValid.value) return
|
||||
|
||||
toast.promise(torrentStore.addTorrents(files.value, urls.value, form.value), {
|
||||
pending: t('dialogs.add.pending'),
|
||||
error: t('dialogs.add.error', addTorrentStore.pendingTorrentsCount),
|
||||
success: t('dialogs.add.success', addTorrentStore.pendingTorrentsCount)
|
||||
}, {
|
||||
autoClose: 1500
|
||||
})
|
||||
.then(() => {
|
||||
cookieField.value?.saveValueToHistory()
|
||||
dlPathField.value?.saveValueToHistory()
|
||||
savePathField.value?.saveValueToHistory()
|
||||
addTorrentStore.resetForm()
|
||||
close()
|
||||
})
|
||||
toast
|
||||
.promise(
|
||||
torrentStore.addTorrents(files.value, urls.value, form.value),
|
||||
{
|
||||
pending: t('dialogs.add.pending'),
|
||||
error: t('dialogs.add.error', addTorrentStore.pendingTorrentsCount),
|
||||
success: t('dialogs.add.success', addTorrentStore.pendingTorrentsCount)
|
||||
},
|
||||
{
|
||||
autoClose: 1500
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
cookieField.value?.saveValueToHistory()
|
||||
dlPathField.value?.saveValueToHistory()
|
||||
savePathField.value?.saveValueToHistory()
|
||||
addTorrentStore.resetForm()
|
||||
close()
|
||||
})
|
||||
}
|
||||
|
||||
function close() {
|
||||
|
@ -169,8 +177,11 @@ const onCategoryChanged = () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog v-model="isOpened" :class="$vuetify.display.mobile ? '' : 'w-75'"
|
||||
:fullscreen="$vuetify.display.mobile" :transition="openSuddenly ? 'none' : 'dialog-bottom-transition'">
|
||||
<v-dialog
|
||||
v-model="isOpened"
|
||||
:class="$vuetify.display.mobile ? '' : 'w-75'"
|
||||
:fullscreen="$vuetify.display.mobile"
|
||||
:transition="openSuddenly ? 'none' : 'dialog-bottom-transition'">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-toolbar color="transparent">
|
||||
|
@ -182,10 +193,17 @@ const onCategoryChanged = () => {
|
|||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-file-input v-model="files" :label="t('dialogs.add.files')"
|
||||
:show-size="vueTorrentStore.useBinarySize ? 1024 : 1000"
|
||||
accept=".torrent" counter multiple
|
||||
persistent-clear persistent-hint prepend-icon="" variant="outlined">
|
||||
<v-file-input
|
||||
v-model="files"
|
||||
:label="t('dialogs.add.files')"
|
||||
:show-size="vueTorrentStore.useBinarySize ? 1024 : 1000"
|
||||
accept=".torrent"
|
||||
counter
|
||||
multiple
|
||||
persistent-clear
|
||||
persistent-hint
|
||||
prepend-icon=""
|
||||
variant="outlined">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-paperclip</v-icon>
|
||||
</template>
|
||||
|
@ -195,8 +213,7 @@ const onCategoryChanged = () => {
|
|||
{{ filename }}
|
||||
</v-chip>
|
||||
</template>
|
||||
<span v-if="fileNames.length === fileOverflowDisplayLimit + 1"
|
||||
class="text-overline text-grey-darken-2 ml-2">
|
||||
<span v-if="fileNames.length === fileOverflowDisplayLimit + 1" class="text-overline text-grey-darken-2 ml-2">
|
||||
{{ t('dialogs.add.fileOverflow', fileNames.length - fileOverflowDisplayLimit) }}
|
||||
</span>
|
||||
</template>
|
||||
|
@ -206,8 +223,14 @@ const onCategoryChanged = () => {
|
|||
<v-icon color="accent">mdi-link</v-icon>
|
||||
</template>
|
||||
</v-textarea>
|
||||
<HistoryField v-if="!!urls" v-model="cookie" :historyKey="HistoryKey.COOKIE" ref="cookieField" clearable
|
||||
:label="$t('dialogs.add.cookie')" :placeholder="$t('dialogs.add.cookiePlaceholder')">
|
||||
<HistoryField
|
||||
v-if="!!urls"
|
||||
v-model="cookie"
|
||||
:historyKey="HistoryKey.COOKIE"
|
||||
ref="cookieField"
|
||||
clearable
|
||||
:label="$t('dialogs.add.cookie')"
|
||||
:placeholder="$t('dialogs.add.cookiePlaceholder')">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-cookie</v-icon>
|
||||
</template>
|
||||
|
@ -220,8 +243,17 @@ const onCategoryChanged = () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-combobox v-model="tags" v-model:search="tagSearch" :hide-no-data="false" :items="maindataStore.tags"
|
||||
:label="t('dialogs.add.tags')" chips clearable hide-details multiple autocomplete="tags">
|
||||
<v-combobox
|
||||
v-model="tags"
|
||||
v-model:search="tagSearch"
|
||||
:hide-no-data="false"
|
||||
:items="maindataStore.tags"
|
||||
:label="t('dialogs.add.tags')"
|
||||
chips
|
||||
clearable
|
||||
hide-details
|
||||
multiple
|
||||
autocomplete="tags">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-tag</v-icon>
|
||||
</template>
|
||||
|
@ -239,9 +271,16 @@ const onCategoryChanged = () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-combobox v-model="category" v-model:search="categorySearch" :hide-no-data="false" :items="categories"
|
||||
:label="$t('dialogs.add.category')" clearable hide-details autocomplete="categories"
|
||||
@update:modelValue="onCategoryChanged">
|
||||
<v-combobox
|
||||
v-model="category"
|
||||
v-model:search="categorySearch"
|
||||
:hide-no-data="false"
|
||||
:items="categories"
|
||||
:label="$t('dialogs.add.category')"
|
||||
clearable
|
||||
hide-details
|
||||
autocomplete="categories"
|
||||
@update:modelValue="onCategoryChanged">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-label</v-icon>
|
||||
</template>
|
||||
|
@ -259,8 +298,13 @@ const onCategoryChanged = () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<HistoryField v-model="downloadPath" :history-key="HistoryKey.TORRENT_PATH" ref="dlPathField"
|
||||
:disabled="form.autoTMM" :label="t('dialogs.add.downloadPath')" hide-details>
|
||||
<HistoryField
|
||||
v-model="downloadPath"
|
||||
:history-key="HistoryKey.TORRENT_PATH"
|
||||
ref="dlPathField"
|
||||
:disabled="form.autoTMM"
|
||||
:label="t('dialogs.add.downloadPath')"
|
||||
hide-details>
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-tray-arrow-down</v-icon>
|
||||
</template>
|
||||
|
@ -268,8 +312,13 @@ const onCategoryChanged = () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<HistoryField v-model="form.savepath" :history-key="HistoryKey.TORRENT_PATH" ref="savePathField"
|
||||
:disabled="form.autoTMM" :label="t('dialogs.add.savePath')" hide-details>
|
||||
<HistoryField
|
||||
v-model="form.savepath"
|
||||
:history-key="HistoryKey.TORRENT_PATH"
|
||||
ref="savePathField"
|
||||
:disabled="form.autoTMM"
|
||||
:label="t('dialogs.add.savePath')"
|
||||
hide-details>
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-content-save</v-icon>
|
||||
</template>
|
||||
|
@ -277,42 +326,46 @@ const onCategoryChanged = () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-select v-model="form.contentLayout" :items="contentLayoutOptions"
|
||||
:label="t('constants.contentLayout.title')" color="accent" hide-details rounded="xl"
|
||||
variant="solo-filled" />
|
||||
<v-select
|
||||
v-model="form.contentLayout"
|
||||
:items="contentLayoutOptions"
|
||||
:label="t('constants.contentLayout.title')"
|
||||
color="accent"
|
||||
hide-details
|
||||
rounded="xl"
|
||||
variant="solo-filled" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="6">
|
||||
<v-select v-model="form.stopCondition" :items="stopConditionOptions"
|
||||
:label="t('constants.stopCondition.title')" color="accent" hide-details rounded="xl"
|
||||
variant="solo-filled" />
|
||||
<v-select
|
||||
v-model="form.stopCondition"
|
||||
:items="stopConditionOptions"
|
||||
:label="t('constants.stopCondition.title')"
|
||||
color="accent"
|
||||
hide-details
|
||||
rounded="xl"
|
||||
variant="solo-filled" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="mx-3">
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="startNow" :label="t('dialogs.add.startNow')" color="accent"
|
||||
density="compact" hide-details />
|
||||
<v-checkbox v-model="startNow" :label="t('dialogs.add.startNow')" color="accent" density="compact" hide-details />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="form.addToTopOfQueue" :label="t('dialogs.add.addToTopOfQueue')" color="accent"
|
||||
density="compact" hide-details />
|
||||
<v-checkbox v-model="form.addToTopOfQueue" :label="t('dialogs.add.addToTopOfQueue')" color="accent" density="compact" hide-details />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="form.skip_checking" :label="t('dialogs.add.skipChecking')" color="accent"
|
||||
density="compact" hide-details />
|
||||
<v-checkbox v-model="form.skip_checking" :label="t('dialogs.add.skipChecking')" color="accent" density="compact" hide-details />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="form.autoTMM" :label="t('dialogs.add.autoTMM')" color="accent"
|
||||
density="compact" hide-details />
|
||||
<v-checkbox v-model="form.autoTMM" :label="t('dialogs.add.autoTMM')" color="accent" density="compact" hide-details />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="form.sequentialDownload" :label="t('dialogs.add.sequentialDownload')" color="accent"
|
||||
density="compact" hide-details />
|
||||
<v-checkbox v-model="form.sequentialDownload" :label="t('dialogs.add.sequentialDownload')" color="accent" density="compact" hide-details />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="form.firstLastPiecePrio" :label="t('dialogs.add.firstLastPiecePrio')" color="accent"
|
||||
density="compact" hide-details />
|
||||
<v-checkbox v-model="form.firstLastPiecePrio" :label="t('dialogs.add.firstLastPiecePrio')" color="accent" density="compact" hide-details />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
@ -323,16 +376,14 @@ const onCategoryChanged = () => {
|
|||
<v-expansion-panel-text>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="dlLimit" :label="$t('dialogs.add.dlLimit')"
|
||||
hide-details suffix="KiB/s">
|
||||
<v-text-field v-model="dlLimit" :label="$t('dialogs.add.dlLimit')" hide-details suffix="KiB/s">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-download</v-icon>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="upLimit" :label="$t('dialogs.add.upLimit')"
|
||||
hide-details suffix="KiB/s">
|
||||
<v-text-field v-model="upLimit" :label="$t('dialogs.add.upLimit')" hide-details suffix="KiB/s">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent">mdi-upload</v-icon>
|
||||
</template>
|
||||
|
@ -340,21 +391,23 @@ const onCategoryChanged = () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field v-model="ratioLimit"
|
||||
:hint="$t('dialogs.add.limitHint')" :label="$t('dialogs.add.ratioLimit')"
|
||||
type="number" />
|
||||
<v-text-field v-model="ratioLimit" :hint="$t('dialogs.add.limitHint')" :label="$t('dialogs.add.ratioLimit')" type="number" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field v-model="seedingTimeLimit"
|
||||
:label="$t('dialogs.add.seedingTimeLimit')"
|
||||
:hint="$t('dialogs.add.limitHint')"
|
||||
:suffix="$t('units.minutes')" type="number" />
|
||||
<v-text-field
|
||||
v-model="seedingTimeLimit"
|
||||
:label="$t('dialogs.add.seedingTimeLimit')"
|
||||
:hint="$t('dialogs.add.limitHint')"
|
||||
:suffix="$t('units.minutes')"
|
||||
type="number" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field v-model="inactiveSeedingTimeLimit"
|
||||
:label="$t('dialogs.add.inactiveSeedingTimeLimit')"
|
||||
:hint="$t('dialogs.add.limitHint')"
|
||||
:suffix="$t('units.minutes')" type="number" />
|
||||
<v-text-field
|
||||
v-model="inactiveSeedingTimeLimit"
|
||||
:label="$t('dialogs.add.inactiveSeedingTimeLimit')"
|
||||
:hint="$t('dialogs.add.limitHint')"
|
||||
:suffix="$t('units.minutes')"
|
||||
type="number" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-expansion-panel-text>
|
||||
|
@ -367,8 +420,7 @@ const onCategoryChanged = () => {
|
|||
<v-card-actions class="justify-center">
|
||||
<v-btn :text="$t('dialogs.add.resetForm')" color="error" variant="flat" @click="addTorrentStore.resetForm()" />
|
||||
<v-spacer />
|
||||
<v-btn :disabled="!isFormValid" :text="$t('dialogs.add.submit')" color="accent"
|
||||
type="submit" variant="elevated" @click="submit" />
|
||||
<v-btn :disabled="!isFormValid" :text="$t('dialogs.add.submit')" color="accent" type="submit" variant="elevated" @click="submit" />
|
||||
<v-btn :text="$t('common.close')" color="" variant="flat" @click="close" />
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
|
|
@ -49,15 +49,12 @@ onBeforeMount(() => {
|
|||
<template>
|
||||
<v-dialog v-model="isOpened">
|
||||
<v-card>
|
||||
<v-card-title>{{ $t(`dialogs.category.title.${ initialCategory ? 'edit' : 'create' }`) }}</v-card-title>
|
||||
<v-card-title>{{ $t(`dialogs.category.title.${initialCategory ? 'edit' : 'create'}`) }}</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form v-model="isFormValid" ref="form" @submit.prevent @keydown.enter.prevent="submit">
|
||||
<v-text-field v-if="!!initialCategory" :model-value="initialCategory.name" disabled
|
||||
:label="$t('dialogs.category.oldName')" />
|
||||
<v-text-field v-model="formData.name" :rules="nameRules" :autofocus="!initialCategory"
|
||||
:label="$t('dialogs.category.name')" />
|
||||
<v-text-field v-model="formData.savePath" :autofocus="!!initialCategory"
|
||||
:label="$t('dialogs.category.savePath')" />
|
||||
<v-text-field v-if="!!initialCategory" :model-value="initialCategory.name" disabled :label="$t('dialogs.category.oldName')" />
|
||||
<v-text-field v-model="formData.name" :rules="nameRules" :autofocus="!initialCategory" :label="$t('dialogs.category.name')" />
|
||||
<v-text-field v-model="formData.savePath" :autofocus="!!initialCategory" :label="$t('dialogs.category.savePath')" />
|
||||
<v-scroll-x-transition>
|
||||
<div class="text-warning" v-if="!!initialCategory && initialCategory.name !== formData.name">
|
||||
<v-icon>mdi-alert</v-icon>
|
||||
|
|
|
@ -71,8 +71,7 @@ onUnmounted(() => {
|
|||
<div class="d-flex flex-wrap gap">
|
||||
<span class="pa-1 border wrap-anywhere" v-for="torrent in selection">{{ torrent.name }}</span>
|
||||
</div>
|
||||
<v-checkbox v-model="vuetorrentStore.deleteWithFiles" hide-details
|
||||
:label="$t('dialogs.delete.deleteWithFiles')" />
|
||||
<v-checkbox v-model="vuetorrentStore.deleteWithFiles" hide-details :label="$t('dialogs.delete.deleteWithFiles')" />
|
||||
<v-scroll-x-transition>
|
||||
<div class="text-red" v-show="vuetorrentStore.deleteWithFiles">
|
||||
<v-icon>mdi-alert</v-icon>
|
||||
|
|
|
@ -9,7 +9,7 @@ import { VForm } from 'vuetify/components'
|
|||
|
||||
const props = defineProps<{
|
||||
guid: string
|
||||
hashes: string[],
|
||||
hashes: string[]
|
||||
mode: 'dl' | 'save'
|
||||
}>()
|
||||
|
||||
|
@ -65,9 +65,14 @@ onBeforeMount(() => {
|
|||
<v-card-text>
|
||||
<v-form v-model="isFormValid" ref="form" @submit.prevent>
|
||||
<v-text-field v-if="oldPath" :model-value="oldPath" disabled :label="$t('dialogs.moveTorrent.oldPath')" />
|
||||
<HistoryField v-model="formData.newPath" :historyKey="HistoryKey.TORRENT_PATH" ref="field"
|
||||
:rules="rules" autofocus :label="$t('dialogs.moveTorrent.newPath')"
|
||||
@keydown.enter="submit" />
|
||||
<HistoryField
|
||||
v-model="formData.newPath"
|
||||
:historyKey="HistoryKey.TORRENT_PATH"
|
||||
ref="field"
|
||||
:rules="rules"
|
||||
autofocus
|
||||
:label="$t('dialogs.moveTorrent.newPath')"
|
||||
@keydown.enter="submit" />
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
|
|
|
@ -65,8 +65,7 @@ onBeforeMount(() => {
|
|||
<v-card-text>
|
||||
<v-form v-model="isFormValid" ref="form" @submit.prevent>
|
||||
<v-text-field v-if="oldName" :model-value="oldName" disabled :label="$t('dialogs.moveTorrentFile.oldName')" />
|
||||
<v-text-field v-model="formData.newName" ref="input" :rules="rules" autofocus
|
||||
:label="$t('dialogs.moveTorrent.newPath')" @keydown.enter="submit" />
|
||||
<v-text-field v-model="formData.newName" ref="input" :rules="rules" autofocus :label="$t('dialogs.moveTorrent.newPath')" @keydown.enter="submit" />
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
|
|
|
@ -83,8 +83,7 @@ function closeInstallDialog() {
|
|||
|
||||
<v-spacer />
|
||||
|
||||
<v-btn :text="$t('dialogs.pluginManager.update')" color="accent" class="mr-2" :loading="updateLoading"
|
||||
@click="updatePlugins" />
|
||||
<v-btn :text="$t('dialogs.pluginManager.update')" color="accent" class="mr-2" :loading="updateLoading" @click="updatePlugins" />
|
||||
<v-dialog v-model="installisOpened">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn v-bind="props" color="primary">
|
||||
|
@ -107,8 +106,7 @@ function closeInstallDialog() {
|
|||
</v-dialog>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-data-table :headers="headers" items-per-page="-1" :items="searchEngineStore.searchPlugins"
|
||||
:sort-by="[{ key: 'fullName', order: 'asc' }]" :loading="loading">
|
||||
<v-data-table :headers="headers" items-per-page="-1" :items="searchEngineStore.searchPlugins" :sort-by="[{ key: 'fullName', order: 'asc' }]" :loading="loading">
|
||||
<template v-slot:item.enabled="{ item }">
|
||||
<v-checkbox-btn :model-value="item.enabled" @click="onTogglePlugin(item)" />
|
||||
</template>
|
||||
|
|
|
@ -54,8 +54,7 @@ onMounted(() => {
|
|||
<v-card-text>
|
||||
<v-form v-model="isFormValid" ref="form" @submit.prevent>
|
||||
<v-text-field v-if="oldName" :model-value="oldName" disabled :label="$t('dialogs.renameTorrent.oldName')" />
|
||||
<v-text-field v-model="formData.newName" ref="field" :rules="rules" autofocus
|
||||
:label="$t('dialogs.renameTorrent.newName')" @keydown.enter="submit" />
|
||||
<v-text-field v-model="formData.newName" ref="field" :rules="rules" autofocus :label="$t('dialogs.renameTorrent.newName')" @keydown.enter="submit" />
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
|
|
|
@ -45,7 +45,7 @@ onBeforeMount(() => {
|
|||
<template>
|
||||
<v-dialog v-model="isOpened">
|
||||
<v-card>
|
||||
<v-card-title>{{ $t(`dialogs.rss.feed.title.${ initialFeed ? 'edit' : 'create' }`) }}</v-card-title>
|
||||
<v-card-title>{{ $t(`dialogs.rss.feed.title.${initialFeed ? 'edit' : 'create'}`) }}</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form v-model="isFormValid" ref="form" @submit.prevent>
|
||||
<v-text-field v-model="formData.name" :label="$t('dialogs.rss.feed.name')" />
|
||||
|
|
|
@ -50,10 +50,13 @@ const contentLayoutOptions = [
|
|||
{ title: t('constants.contentLayout.nosubfolder'), value: ContentLayout.NO_SUBFOLDER }
|
||||
]
|
||||
const categories = computed(() => {
|
||||
return [{ title: t('common.none'), value: '' }, ...maindataStore.categories.map(category => ({
|
||||
title: category.name,
|
||||
value: category.name
|
||||
}))]
|
||||
return [
|
||||
{ title: t('common.none'), value: '' },
|
||||
...maindataStore.categories.map(category => ({
|
||||
title: category.name,
|
||||
value: category.name
|
||||
}))
|
||||
]
|
||||
})
|
||||
|
||||
const lastMatch = computed(() => {
|
||||
|
@ -145,26 +148,19 @@ onBeforeMount(async () => {
|
|||
<v-text-field v-model="formData.mustContain" :label="$t('dialogs.rss.rule.mustContain')" />
|
||||
<v-text-field v-model="formData.mustNotContain" :label="$t('dialogs.rss.rule.mustNotContain')" />
|
||||
<v-checkbox v-model="formData.smartFilter" hide-details :label="$t('dialogs.rss.rule.smartFilter')" />
|
||||
<v-text-field v-model="formData.episodeFilter"
|
||||
:placeholder="$t('dialogs.rss.rule.episodeFilterPlaceholder')"
|
||||
:label="$t('dialogs.rss.rule.episodeFilter')" />
|
||||
<v-text-field v-model="formData.episodeFilter" :placeholder="$t('dialogs.rss.rule.episodeFilterPlaceholder')" :label="$t('dialogs.rss.rule.episodeFilter')" />
|
||||
|
||||
<v-divider class="mb-4" />
|
||||
|
||||
<v-select v-model="formData.assignedCategory" :items="categories"
|
||||
:label="$t('dialogs.rss.rule.assignedCategory')" />
|
||||
<v-text-field v-model="formData.savePath" :placeholder="$t('dialogs.rss.rule.savePathPlaceholder')"
|
||||
:label="$t('dialogs.rss.rule.savePath')" />
|
||||
<v-text-field v-model="formData.ignoreDays" type="number" :hint="$t('dialogs.rss.rule.ignoreDaysHint')"
|
||||
:label="$t('dialogs.rss.rule.ignoreDays')" />
|
||||
<v-select v-model="formData.assignedCategory" :items="categories" :label="$t('dialogs.rss.rule.assignedCategory')" />
|
||||
<v-text-field v-model="formData.savePath" :placeholder="$t('dialogs.rss.rule.savePathPlaceholder')" :label="$t('dialogs.rss.rule.savePath')" />
|
||||
<v-text-field v-model="formData.ignoreDays" type="number" :hint="$t('dialogs.rss.rule.ignoreDaysHint')" :label="$t('dialogs.rss.rule.ignoreDays')" />
|
||||
<v-text-field v-model="lastMatch" disabled :label="$t('dialogs.rss.rule.lastMatch.label')" />
|
||||
|
||||
<v-divider />
|
||||
|
||||
<v-select v-model="formData.addPaused" :items="addPausedOptions"
|
||||
:label="$t('constants.addPaused.title')" />
|
||||
<v-select v-model="formData.torrentContentLayout" :items="contentLayoutOptions"
|
||||
:label="$t('constants.contentLayout.title')" />
|
||||
<v-select v-model="formData.addPaused" :items="addPausedOptions" :label="$t('constants.addPaused.title')" />
|
||||
<v-select v-model="formData.torrentContentLayout" :items="contentLayoutOptions" :label="$t('constants.contentLayout.title')" />
|
||||
|
||||
<v-list-subheader>{{ $t('dialogs.rss.rule.affectedFeedsSubheader') }}</v-list-subheader>
|
||||
|
||||
|
@ -177,8 +173,7 @@ onBeforeMount(async () => {
|
|||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-checkbox v-for="item in rssStore.feeds" v-model="formData.affectedFeeds" multiple hide-details
|
||||
:label="item.name" :value="item.url" />
|
||||
<v-checkbox v-for="item in rssStore.feeds" v-model="formData.affectedFeeds" multiple hide-details :label="item.name" :value="item.url" />
|
||||
</v-col>
|
||||
|
||||
<v-divider :vertical="!$vuetify.display.mobile" />
|
||||
|
@ -191,8 +186,7 @@ onBeforeMount(async () => {
|
|||
<v-list-subheader inset v-else-if="item.type === 'subheader'">{{ item.value }}</v-list-subheader>
|
||||
<v-list-item v-else class="mb-3">{{ item.value }}</v-list-item>
|
||||
</template>
|
||||
<v-list-item v-if="matchingArticles.length === 0"
|
||||
:title="$t('dialogs.rss.rule.matchingArticles.noMatch')" />
|
||||
<v-list-item v-if="matchingArticles.length === 0" :title="$t('dialogs.rss.rule.matchingArticles.noMatch')" />
|
||||
</v-list>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
|
|
@ -44,10 +44,12 @@ async function submit() {
|
|||
await maindataStore.setShareLimit(props.hashes, DISABLED, DISABLED, DISABLED)
|
||||
break
|
||||
case 'enabled':
|
||||
await maindataStore.setShareLimit(props.hashes,
|
||||
await maindataStore.setShareLimit(
|
||||
props.hashes,
|
||||
ratioLimitEnabled.value ? ratioLimit.value : DISABLED,
|
||||
seedingTimeLimitEnabled.value ? seedingTimeLimit.value : DISABLED,
|
||||
inactiveSeedingTimeLimitEnabled.value ? inactiveSeedingTimeLimit.value : DISABLED)
|
||||
inactiveSeedingTimeLimitEnabled.value ? inactiveSeedingTimeLimit.value : DISABLED
|
||||
)
|
||||
break
|
||||
}
|
||||
close()
|
||||
|
@ -95,27 +97,25 @@ onBeforeMount(async () => {
|
|||
<v-row>
|
||||
<v-col cols="12" class="d-flex align-center">
|
||||
<span><v-checkbox-btn v-model="ratioLimitEnabled" :disabled="isFieldsDisabled" /></span>
|
||||
<v-text-field v-model="ratioLimit"
|
||||
:disabled="isFieldsDisabled || !ratioLimitEnabled"
|
||||
density="compact"
|
||||
hide-details
|
||||
:label="$t('dialogs.share_limit.ratio_limit')" />
|
||||
<v-text-field v-model="ratioLimit" :disabled="isFieldsDisabled || !ratioLimitEnabled" density="compact" hide-details :label="$t('dialogs.share_limit.ratio_limit')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="d-flex align-center">
|
||||
<span><v-checkbox-btn v-model="seedingTimeLimitEnabled" :disabled="isFieldsDisabled" /></span>
|
||||
<v-text-field v-model="seedingTimeLimit"
|
||||
:disabled="isFieldsDisabled || !seedingTimeLimitEnabled"
|
||||
density="compact"
|
||||
hide-details
|
||||
:label="$t('dialogs.share_limit.seeding_time_limit')" />
|
||||
<v-text-field
|
||||
v-model="seedingTimeLimit"
|
||||
:disabled="isFieldsDisabled || !seedingTimeLimitEnabled"
|
||||
density="compact"
|
||||
hide-details
|
||||
:label="$t('dialogs.share_limit.seeding_time_limit')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="d-flex align-center">
|
||||
<span><v-checkbox-btn v-model="inactiveSeedingTimeLimitEnabled" :disabled="isFieldsDisabled" /></span>
|
||||
<v-text-field v-model="inactiveSeedingTimeLimit"
|
||||
:disabled="isFieldsDisabled || !inactiveSeedingTimeLimitEnabled"
|
||||
density="compact"
|
||||
hide-details
|
||||
:label="$t('dialogs.share_limit.inactive_seeding_time_limit')" />
|
||||
<v-text-field
|
||||
v-model="inactiveSeedingTimeLimit"
|
||||
:disabled="isFieldsDisabled || !inactiveSeedingTimeLimitEnabled"
|
||||
density="compact"
|
||||
hide-details
|
||||
:label="$t('dialogs.share_limit.inactive_seeding_time_limit')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-form>
|
||||
|
@ -129,6 +129,4 @@ onBeforeMount(async () => {
|
|||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -55,14 +55,15 @@ onBeforeMount(async () => {
|
|||
<v-card :title="$t(`dialogs.speed_limit.${mode}`)">
|
||||
<v-card-text>
|
||||
<v-form v-model="isFormValid" @submit.prevent @keydown.enter.prevent="submit">
|
||||
<v-text-field v-model="value"
|
||||
type="number"
|
||||
autofocus
|
||||
clearable
|
||||
:label="$t('dialogs.speed_limit.label')"
|
||||
prepend-inner-icon="mdi-speedometer"
|
||||
suffix="kB/s"
|
||||
@keydown.enter.prevent="submit" />
|
||||
<v-text-field
|
||||
v-model="value"
|
||||
type="number"
|
||||
autofocus
|
||||
clearable
|
||||
:label="$t('dialogs.speed_limit.label')"
|
||||
prepend-inner-icon="mdi-speedometer"
|
||||
suffix="kB/s"
|
||||
@keydown.enter.prevent="submit" />
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
|
@ -74,6 +75,4 @@ onBeforeMount(async () => {
|
|||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -44,12 +44,11 @@ onBeforeMount(() => {
|
|||
<template>
|
||||
<v-dialog v-model="isOpened">
|
||||
<v-card>
|
||||
<v-card-title>{{ $t(`dialogs.tag.title.${ initialTag ? 'rename' : 'create' }`) }}</v-card-title>
|
||||
<v-card-title>{{ $t(`dialogs.tag.title.${initialTag ? 'rename' : 'create'}`) }}</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form v-model="isFormValid" ref="form" @submit.prevent @keydown.enter.prevent="submit">
|
||||
<v-text-field v-if="initialTag" :model-value="initialTag" disabled :label="$t('dialogs.tag.oldName')" />
|
||||
<v-text-field v-model="tagName" :rules="rules" autofocus :hint="$t('dialogs.tag.hint')"
|
||||
:label="$t('dialogs.tag.name')" />
|
||||
<v-text-field v-model="tagName" :rules="rules" autofocus :hint="$t('dialogs.tag.hint')" :label="$t('dialogs.tag.name')" />
|
||||
<v-scroll-x-transition>
|
||||
<div class="text-warning" v-if="!!initialTag && initialTag !== tagName">
|
||||
<v-icon>mdi-alert</v-icon>
|
||||
|
|
|
@ -12,9 +12,11 @@ const dndZoneRef = ref<HTMLDivElement>()
|
|||
|
||||
function onDragEnter() {
|
||||
if (
|
||||
(route.name as string) === 'login'
|
||||
|| (route.name as string) === 'settings' && route.params.tab === 'vuetorrent' && route.params.subtab === 'torrentCard'
|
||||
|| !authStore.isAuthenticated) return
|
||||
(route.name as string) === 'login' ||
|
||||
((route.name as string) === 'settings' && route.params.tab === 'vuetorrent' && route.params.subtab === 'torrentCard') ||
|
||||
!authStore.isAuthenticated
|
||||
)
|
||||
return
|
||||
isOverDropZone.value = true
|
||||
}
|
||||
|
||||
|
@ -24,10 +26,11 @@ function onDrop(files: File[] | null, event: DragEvent) {
|
|||
if (!event.dataTransfer) return
|
||||
|
||||
// Handle .torrent files
|
||||
const torrentFiles = (files || [])
|
||||
.filter(file => file.type === 'application/x-bittorrent' || file.name.endsWith('.torrent'))
|
||||
const links = event.dataTransfer.getData('text/plain').split('\n')
|
||||
.filter(link => link.startsWith('magnet:') || link.startsWith('http'))
|
||||
const torrentFiles = (files || []).filter(file => file.type === 'application/x-bittorrent' || file.name.endsWith('.torrent'))
|
||||
const links = event.dataTransfer
|
||||
.getData('text/plain')
|
||||
.split('\n')
|
||||
.filter(link => link.startsWith('magnet:') || link.startsWith('http'))
|
||||
|
||||
torrentFiles.forEach(addTorrentStore.pushTorrentToQueue)
|
||||
links.forEach(addTorrentStore.pushTorrentToQueue)
|
||||
|
@ -85,4 +88,4 @@ onUnmounted(() => {
|
|||
border: 2px solid rgb(var(--v-theme-accent));
|
||||
border-radius: 48px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -21,8 +21,7 @@ const toggleDrawer = () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer v-model="isDrawerOpen" :location="vueTorrentStore.isDrawerRight ? 'right' : 'left'"
|
||||
color="primary" disable-route-watcher>
|
||||
<v-navigation-drawer v-model="isDrawerOpen" :location="vueTorrentStore.isDrawerRight ? 'right' : 'left'" color="primary" disable-route-watcher>
|
||||
<v-list class="clean-px px-2 pt-0">
|
||||
<v-list-item v-if="vueTorrentStore.showCurrentSpeed">
|
||||
<CurrentSpeed />
|
||||
|
|
|
@ -40,7 +40,7 @@ const connectionStatusText = computed(() => {
|
|||
key = 'unknown'
|
||||
}
|
||||
|
||||
return t('navbar.side.bottom_actions.conn_status', { status: t(`constants.connectionStatus.${ key }`) })
|
||||
return t('navbar.side.bottom_actions.conn_status', { status: t(`constants.connectionStatus.${key}`) })
|
||||
})
|
||||
|
||||
const logout = async () => {
|
||||
|
|
|
@ -16,8 +16,7 @@ const maindataStore = useMaindataStore()
|
|||
<v-sheet color="primary" class="mx-2">
|
||||
<v-row class="pt-0">
|
||||
<v-col class="px-1 pt-1">
|
||||
<SpeedCard icon="mdi-chevron-down" color="download"
|
||||
:value="maindataStore.serverState?.dl_info_speed ?? 0" />
|
||||
<SpeedCard icon="mdi-chevron-down" color="download" :value="maindataStore.serverState?.dl_info_speed ?? 0" />
|
||||
</v-col>
|
||||
<v-col class="px-1 pt-1">
|
||||
<SpeedCard icon="mdi-chevron-up" color="upload" :value="maindataStore.serverState?.up_info_speed ?? 0" />
|
||||
|
|
|
@ -6,34 +6,14 @@ import { computed } from 'vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
const {
|
||||
categories: _categories,
|
||||
tags: _tags,
|
||||
trackers: _trackers
|
||||
} = storeToRefs(useMaindataStore())
|
||||
const {
|
||||
statusFilter,
|
||||
categoryFilter,
|
||||
tagFilter,
|
||||
trackerFilter
|
||||
} = storeToRefs(useTorrentStore())
|
||||
const { categories: _categories, tags: _tags, trackers: _trackers } = storeToRefs(useMaindataStore())
|
||||
const { statusFilter, categoryFilter, tagFilter, trackerFilter } = storeToRefs(useTorrentStore())
|
||||
const vueTorrentStore = useVueTorrentStore()
|
||||
|
||||
const statuses = computed(() => Object.values(TorrentState).map(state => (
|
||||
{ title: t(`torrent.state.${ state }`), value: state }
|
||||
)))
|
||||
const categories = computed(() => [
|
||||
{ title: t('navbar.side.filters.uncategorized'), value: '' },
|
||||
..._categories.value.map(c => ({ title: c.name, value: c.name }))
|
||||
])
|
||||
const tags = computed(() => [
|
||||
{ title: t('navbar.side.filters.untagged'), value: null },
|
||||
..._tags.value.map(tag => ({ title: tag, value: tag }))
|
||||
])
|
||||
const trackers = computed(() => [
|
||||
{ title: t('navbar.side.filters.untracked'), value: '' },
|
||||
..._trackers.value.map(tracker => ({ title: tracker, value: tracker }))
|
||||
])
|
||||
const statuses = computed(() => Object.values(TorrentState).map(state => ({ title: t(`torrent.state.${state}`), value: state })))
|
||||
const categories = computed(() => [{ title: t('navbar.side.filters.uncategorized'), value: '' }, ..._categories.value.map(c => ({ title: c.name, value: c.name }))])
|
||||
const tags = computed(() => [{ title: t('navbar.side.filters.untagged'), value: null }, ..._tags.value.map(tag => ({ title: tag, value: tag }))])
|
||||
const trackers = computed(() => [{ title: t('navbar.side.filters.untracked'), value: '' }, ..._trackers.value.map(tracker => ({ title: tracker, value: tracker }))])
|
||||
|
||||
function selectAllStatuses() {
|
||||
statusFilter.value = []
|
||||
|
@ -58,19 +38,23 @@ function selectAllTrackers() {
|
|||
<v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-normal text-caption">
|
||||
{{ t('navbar.side.filters.state') }}
|
||||
</v-list-item-title>
|
||||
<v-select v-model="statusFilter" :items="statuses" :placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary"
|
||||
class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
|
||||
<v-select
|
||||
v-model="statusFilter"
|
||||
:items="statuses"
|
||||
:placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary"
|
||||
class="text-accent pt-1"
|
||||
density="compact"
|
||||
hide-details
|
||||
multiple
|
||||
variant="solo">
|
||||
<template v-slot:prepend-item>
|
||||
<v-list-item :title="$t('common.disable')" @click="selectAllStatuses" />
|
||||
<v-divider />
|
||||
</template>
|
||||
<template v-slot:selection="{ item, index }">
|
||||
<span v-if="index === 0 && statusFilter.length === 1"
|
||||
class="text-accent">{{ t(`torrent.state.${ item.props.value }`) }}</span>
|
||||
<span v-else-if="index === 0" class="text-accent">{{
|
||||
t('navbar.side.filters.activeFilter', statusFilter.length)
|
||||
}}</span>
|
||||
<span v-if="index === 0 && statusFilter.length === 1" class="text-accent">{{ t(`torrent.state.${item.props.value}`) }}</span>
|
||||
<span v-else-if="index === 0" class="text-accent">{{ t('navbar.side.filters.activeFilter', statusFilter.length) }}</span>
|
||||
</template>
|
||||
</v-select>
|
||||
</v-list-item>
|
||||
|
@ -79,8 +63,16 @@ function selectAllTrackers() {
|
|||
<v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">
|
||||
{{ t('navbar.side.filters.category') }}
|
||||
</v-list-item-title>
|
||||
<v-select v-model="categoryFilter" :items="categories" :placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary" class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
|
||||
<v-select
|
||||
v-model="categoryFilter"
|
||||
:items="categories"
|
||||
:placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary"
|
||||
class="text-accent pt-1"
|
||||
density="compact"
|
||||
hide-details
|
||||
multiple
|
||||
variant="solo">
|
||||
<template v-slot:prepend-item>
|
||||
<v-list-item :title="$t('common.disable')" @click="selectAllCategories" />
|
||||
<v-divider />
|
||||
|
@ -100,8 +92,16 @@ function selectAllTrackers() {
|
|||
<v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">
|
||||
{{ t('navbar.side.filters.tag') }}
|
||||
</v-list-item-title>
|
||||
<v-select v-model="tagFilter" :items="tags" :placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary" class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
|
||||
<v-select
|
||||
v-model="tagFilter"
|
||||
:items="tags"
|
||||
:placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary"
|
||||
class="text-accent pt-1"
|
||||
density="compact"
|
||||
hide-details
|
||||
multiple
|
||||
variant="solo">
|
||||
<template v-slot:prepend-item>
|
||||
<v-list-item :title="$t('common.disable')" @click="selectAllTags" />
|
||||
<v-divider />
|
||||
|
@ -117,13 +117,20 @@ function selectAllTrackers() {
|
|||
</v-select>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item v-if="vueTorrentStore.showTrackerFilter"
|
||||
:class="{ 'px-0': true, 'pb-3': vueTorrentStore.showTrackerFilter }">
|
||||
<v-list-item v-if="vueTorrentStore.showTrackerFilter" :class="{ 'px-0': true, 'pb-3': vueTorrentStore.showTrackerFilter }">
|
||||
<v-list-item-title class="px-0 text-uppercase white--text ml-1 font-weight-light text-subtitle-2">
|
||||
{{ t('navbar.side.filters.tracker') }}
|
||||
</v-list-item-title>
|
||||
<v-select v-model="trackerFilter" :items="trackers" :placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary" class="text-accent pt-1" density="compact" hide-details multiple variant="solo">
|
||||
<v-select
|
||||
v-model="trackerFilter"
|
||||
:items="trackers"
|
||||
:placeholder="t('navbar.side.filters.disabled')"
|
||||
bg-color="secondary"
|
||||
class="text-accent pt-1"
|
||||
density="compact"
|
||||
hide-details
|
||||
multiple
|
||||
variant="solo">
|
||||
<template v-slot:prepend-item>
|
||||
<v-list-item :title="$t('common.disable')" @click="selectAllTrackers" />
|
||||
<v-divider />
|
||||
|
|
|
@ -18,10 +18,7 @@ const ratio = computed(() => (props.session ? undefined : maindataStore.serverSt
|
|||
|
||||
<template>
|
||||
<v-card variant="flat" color="primary">
|
||||
<v-card-title class="px-0 pb-0 text-uppercase white--text ml-1 font-weight-normal text-caption">{{
|
||||
title
|
||||
}}
|
||||
</v-card-title>
|
||||
<v-card-title class="px-0 pb-0 text-uppercase white--text ml-1 font-weight-normal text-caption">{{ title }} </v-card-title>
|
||||
<v-card-text class="px-0 pb-0">
|
||||
<div class="d-flex flex-column gap">
|
||||
<DataCard :title="$t('navbar.side.stats.downloaded')" :value="download" color="download" icon="mdi-arrow-down" />
|
||||
|
|
|
@ -20,11 +20,11 @@ const {
|
|||
|
||||
const globalFilterActive = computed(
|
||||
() =>
|
||||
isTextFilterActive.value && isTextFilterPresent.value ||
|
||||
isStatusFilterActive.value && isStatusFilterPresent.value ||
|
||||
isCategoryFilterActive.value && isCategoryFilterPresent.value ||
|
||||
isTagFilterActive.value && isTagFilterPresent.value ||
|
||||
isTrackerFilterActive.value && isTrackerFilterPresent.value
|
||||
(isTextFilterActive.value && isTextFilterPresent.value) ||
|
||||
(isStatusFilterActive.value && isStatusFilterPresent.value) ||
|
||||
(isCategoryFilterActive.value && isCategoryFilterPresent.value) ||
|
||||
(isTagFilterActive.value && isTagFilterPresent.value) ||
|
||||
(isTrackerFilterActive.value && isTrackerFilterPresent.value)
|
||||
)
|
||||
|
||||
const isTextFilterPresent = computed(() => textFilter.value.length > 0)
|
||||
|
@ -33,13 +33,13 @@ const isCategoryFilterPresent = computed(() => categoryFilter.value.length > 0)
|
|||
const isTagFilterPresent = computed(() => tagFilter.value.length > 0)
|
||||
const isTrackerFilterPresent = computed(() => trackerFilter.value.length > 0)
|
||||
|
||||
const globalFilterColor = computed(() => globalFilterActive.value ? 'active-global' : 'active-global-disabled')
|
||||
const textFilterColor = computed(() => isTextFilterActive.value ? 'active-text' : 'active-text-disabled')
|
||||
const singleStatusFilterColor = computed(() => isStatusFilterActive.value ? `torrent-${ statusFilter.value[0] }` : `torrent-${ statusFilter.value[0] }-darken-2`)
|
||||
const statusFilterColor = computed(() => isStatusFilterActive.value ? 'active-status' : 'active-status-disabled')
|
||||
const categoryFilterColor = computed(() => isCategoryFilterActive.value ? 'active-category' : 'active-category-disabled')
|
||||
const tagFilterColor = computed(() => isTagFilterActive.value ? 'active-tag' : 'active-tag-disabled')
|
||||
const trackerFilterColor = computed(() => isTrackerFilterActive.value ? 'active-tracker' : 'active-tracker-disabled')
|
||||
const globalFilterColor = computed(() => (globalFilterActive.value ? 'active-global' : 'active-global-disabled'))
|
||||
const textFilterColor = computed(() => (isTextFilterActive.value ? 'active-text' : 'active-text-disabled'))
|
||||
const singleStatusFilterColor = computed(() => (isStatusFilterActive.value ? `torrent-${statusFilter.value[0]}` : `torrent-${statusFilter.value[0]}-darken-2`))
|
||||
const statusFilterColor = computed(() => (isStatusFilterActive.value ? 'active-status' : 'active-status-disabled'))
|
||||
const categoryFilterColor = computed(() => (isCategoryFilterActive.value ? 'active-category' : 'active-category-disabled'))
|
||||
const tagFilterColor = computed(() => (isTagFilterActive.value ? 'active-tag' : 'active-tag-disabled'))
|
||||
const trackerFilterColor = computed(() => (isTrackerFilterActive.value ? 'active-tracker' : 'active-tracker-disabled'))
|
||||
|
||||
const filterPresentCount = computed(
|
||||
() =>
|
||||
|
@ -128,13 +128,9 @@ function resetTrackerFilter() {
|
|||
<v-menu close-delay="0" open-delay="0" open-on-click open-on-hover open-on-focus>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-slide-x-transition>
|
||||
<v-chip v-if="filterPresentCount > 0" v-bind="props" class="ml-6" :color="globalFilterColor" variant="elevated"
|
||||
closable @click:close="resetAllFilters()">
|
||||
<v-chip v-if="filterPresentCount > 0" v-bind="props" class="ml-6" :color="globalFilterColor" variant="elevated" closable @click:close="resetAllFilters()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleAllFilters()">{{
|
||||
globalFilterActive ? 'mdi-filter' : 'mdi-filter-off'
|
||||
}}
|
||||
</v-icon>
|
||||
<v-icon class="mr-1" @click="toggleAllFilters()">{{ globalFilterActive ? 'mdi-filter' : 'mdi-filter-off' }} </v-icon>
|
||||
</template>
|
||||
{{ t('navbar.top.active_filters.menu_label', filterActiveCount) }}
|
||||
</v-chip>
|
||||
|
@ -142,54 +138,38 @@ function resetTrackerFilter() {
|
|||
</template>
|
||||
|
||||
<div class="d-flex flex-column gap mt-3">
|
||||
<v-chip v-if="isTextFilterPresent" :color="textFilterColor" variant="elevated"
|
||||
closable @click:close="resetTextFilter()">
|
||||
<v-chip v-if="isTextFilterPresent" :color="textFilterColor" variant="elevated" closable @click:close="resetTextFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleTextFilter()">{{
|
||||
isTextFilterActive ? 'mdi-filter' : 'mdi-filter-off'
|
||||
}}
|
||||
</v-icon>
|
||||
<v-icon class="mr-1" @click="toggleTextFilter()">{{ isTextFilterActive ? 'mdi-filter' : 'mdi-filter-off' }} </v-icon>
|
||||
</template>
|
||||
{{ t('navbar.top.active_filters.text', { value: textFilter }) }}
|
||||
</v-chip>
|
||||
|
||||
<template v-if="isStatusFilterPresent">
|
||||
<v-chip v-if="statusFilter.length === 1" :color="singleStatusFilterColor" variant="elevated"
|
||||
closable @click:close="resetStatusFilter()">
|
||||
<v-chip v-if="statusFilter.length === 1" :color="singleStatusFilterColor" variant="elevated" closable @click:close="resetStatusFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleStatusFilter()">{{
|
||||
isStatusFilterActive ? 'mdi-filter' : 'mdi-filter-off'
|
||||
}}
|
||||
</v-icon>
|
||||
<v-icon class="mr-1" @click="toggleStatusFilter()">{{ isStatusFilterActive ? 'mdi-filter' : 'mdi-filter-off' }} </v-icon>
|
||||
</template>
|
||||
{{ t('navbar.top.active_filters.state', { value: t(`torrent.state.${ statusFilter[0] }`) }) }}
|
||||
{{ t('navbar.top.active_filters.state', { value: t(`torrent.state.${statusFilter[0]}`) }) }}
|
||||
</v-chip>
|
||||
<v-chip v-else :color="statusFilterColor" variant="elevated"
|
||||
closable @click:close="resetStatusFilter()">
|
||||
<v-chip v-else :color="statusFilterColor" variant="elevated" closable @click:close="resetStatusFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleStatusFilter()">{{
|
||||
isStatusFilterActive ? 'mdi-filter' : 'mdi-filter-off'
|
||||
}}
|
||||
</v-icon>
|
||||
<v-icon class="mr-1" @click="toggleStatusFilter()">{{ isStatusFilterActive ? 'mdi-filter' : 'mdi-filter-off' }} </v-icon>
|
||||
</template>
|
||||
{{ t('navbar.top.active_filters.multiple_state', statusFilter.length) }}
|
||||
</v-chip>
|
||||
</template>
|
||||
|
||||
<template v-if="isCategoryFilterPresent">
|
||||
<v-chip v-if="categoryFilter.length === 1" :color="categoryFilterColor" variant="elevated"
|
||||
closable @click:close="resetCategoryFilter()">
|
||||
<v-chip v-if="categoryFilter.length === 1" :color="categoryFilterColor" variant="elevated" closable @click:close="resetCategoryFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleCategoryFilter()">
|
||||
{{ isCategoryFilterActive ? 'mdi-filter' : 'mdi-filter-off' }}
|
||||
</v-icon>
|
||||
</template>
|
||||
{{
|
||||
t('navbar.top.active_filters.category', { value: categoryFilter[0] === '' ? t('navbar.side.filters.uncategorized') : categoryFilter[0] })
|
||||
}}
|
||||
{{ t('navbar.top.active_filters.category', { value: categoryFilter[0] === '' ? t('navbar.side.filters.uncategorized') : categoryFilter[0] }) }}
|
||||
</v-chip>
|
||||
<v-chip v-else :color="categoryFilterColor" variant="elevated"
|
||||
closable @click:close="resetCategoryFilter()">
|
||||
<v-chip v-else :color="categoryFilterColor" variant="elevated" closable @click:close="resetCategoryFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleCategoryFilter()">
|
||||
{{ isCategoryFilterActive ? 'mdi-filter' : 'mdi-filter-off' }}
|
||||
|
@ -200,44 +180,30 @@ function resetTrackerFilter() {
|
|||
</template>
|
||||
|
||||
<template v-if="isTagFilterPresent">
|
||||
<v-chip v-if="tagFilter.length === 1" :color="tagFilterColor" variant="elevated"
|
||||
closable @click:close="resetTagFilter()">
|
||||
<v-chip v-if="tagFilter.length === 1" :color="tagFilterColor" variant="elevated" closable @click:close="resetTagFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleTagFilter()">{{
|
||||
isTagFilterActive ? 'mdi-filter' : 'mdi-filter-off'
|
||||
}}
|
||||
</v-icon>
|
||||
<v-icon class="mr-1" @click="toggleTagFilter()">{{ isTagFilterActive ? 'mdi-filter' : 'mdi-filter-off' }} </v-icon>
|
||||
</template>
|
||||
{{
|
||||
t('navbar.top.active_filters.tag', { value: tagFilter[0] === null ? t('navbar.side.filters.untagged') : tagFilter[0] })
|
||||
}}
|
||||
{{ t('navbar.top.active_filters.tag', { value: tagFilter[0] === null ? t('navbar.side.filters.untagged') : tagFilter[0] }) }}
|
||||
</v-chip>
|
||||
<v-chip v-else :color="tagFilterColor" variant="elevated"
|
||||
closable @click:close="resetTagFilter()">
|
||||
<v-chip v-else :color="tagFilterColor" variant="elevated" closable @click:close="resetTagFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleTagFilter()">{{
|
||||
isTagFilterActive ? 'mdi-filter' : 'mdi-filter-off'
|
||||
}}
|
||||
</v-icon>
|
||||
<v-icon class="mr-1" @click="toggleTagFilter()">{{ isTagFilterActive ? 'mdi-filter' : 'mdi-filter-off' }} </v-icon>
|
||||
</template>
|
||||
{{ t('navbar.top.active_filters.multiple_tag', tagFilter.length) }}
|
||||
</v-chip>
|
||||
</template>
|
||||
|
||||
<template v-if="isTrackerFilterPresent">
|
||||
<v-chip v-if="trackerFilter.length === 1" :color="trackerFilterColor" variant="elevated"
|
||||
closable @click:close="resetTrackerFilter()">
|
||||
<v-chip v-if="trackerFilter.length === 1" :color="trackerFilterColor" variant="elevated" closable @click:close="resetTrackerFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleTrackerFilter()">
|
||||
{{ isTrackerFilterActive ? 'mdi-filter' : 'mdi-filter-off' }}
|
||||
</v-icon>
|
||||
</template>
|
||||
{{
|
||||
t('navbar.top.active_filters.tracker', { value: trackerFilter[0] === '' ? t('navbar.side.filters.untracked') : trackerFilter[0] })
|
||||
}}
|
||||
{{ t('navbar.top.active_filters.tracker', { value: trackerFilter[0] === '' ? t('navbar.side.filters.untracked') : trackerFilter[0] }) }}
|
||||
</v-chip>
|
||||
<v-chip v-else :color="trackerFilterColor" variant="elevated"
|
||||
closable @click:close="resetTrackerFilter()">
|
||||
<v-chip v-else :color="trackerFilterColor" variant="elevated" closable @click:close="resetTrackerFilter()">
|
||||
<template v-slot:prepend>
|
||||
<v-icon class="mr-1" @click="toggleTrackerFilter()">
|
||||
{{ isTrackerFilterActive ? 'mdi-filter' : 'mdi-filter-off' }}
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
DiskIOMode,
|
||||
DiskIOType,
|
||||
ResumeDataStorageType,
|
||||
UploadChokingAlgorithm,
|
||||
UploadSlotsBehavior,
|
||||
UtpTcpMixedMode
|
||||
} from '@/constants/qbit/AppPreferences'
|
||||
import { DiskIOMode, DiskIOType, ResumeDataStorageType, UploadChokingAlgorithm, UploadSlotsBehavior, UtpTcpMixedMode } from '@/constants/qbit/AppPreferences'
|
||||
import { qbit } from '@/services'
|
||||
import { usePreferenceStore } from '@/stores'
|
||||
import { computed, onBeforeMount, ref } from 'vue'
|
||||
|
@ -19,10 +12,12 @@ const resumeDataStorageTypeOptions = [
|
|||
{ title: t('settings.advanced.qbittorrent.resumeDataStorageType.legacy'), value: ResumeDataStorageType.LEGACY },
|
||||
{ title: t('settings.advanced.qbittorrent.resumeDataStorageType.sqlite'), value: ResumeDataStorageType.SQLITE }
|
||||
]
|
||||
const networkInterfaceOptions = ref([{
|
||||
title: t('settings.advanced.qbittorrent.networking.networkInterfaces.any'),
|
||||
value: ''
|
||||
}])
|
||||
const networkInterfaceOptions = ref([
|
||||
{
|
||||
title: t('settings.advanced.qbittorrent.networking.networkInterfaces.any'),
|
||||
value: ''
|
||||
}
|
||||
])
|
||||
const ipAddressesOptions = ref([
|
||||
{ title: t('settings.advanced.qbittorrent.networking.ipAddress.all'), value: '' },
|
||||
{ title: t('settings.advanced.qbittorrent.networking.ipAddress.allIPv4'), value: '0.0.0.0' },
|
||||
|
@ -80,18 +75,20 @@ onBeforeMount(async () => {
|
|||
<v-list>
|
||||
<v-list-subheader>
|
||||
{{ t('settings.advanced.qbittorrent.subheader') }} (<a
|
||||
href="https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent#Advanced"
|
||||
target="_blank"
|
||||
>{{ t('settings.advanced.openDoc') }}</a
|
||||
>)
|
||||
href="https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent#Advanced"
|
||||
target="_blank"
|
||||
>{{ t('settings.advanced.openDoc') }}</a
|
||||
>)
|
||||
</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-select v-model="preferenceStore.preferences!.resume_data_storage_type" hide-details
|
||||
:items="resumeDataStorageTypeOptions"
|
||||
:label="$t('settings.advanced.qbittorrent.resumeDataStorageType.label')" />
|
||||
<v-select
|
||||
v-model="preferenceStore.preferences!.resume_data_storage_type"
|
||||
hide-details
|
||||
:items="resumeDataStorageTypeOptions"
|
||||
:label="$t('settings.advanced.qbittorrent.resumeDataStorageType.label')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field
|
||||
|
@ -111,16 +108,11 @@ onBeforeMount(async () => {
|
|||
:label="t('settings.advanced.qbittorrent.allocatedRam')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="torrentFileSizeLimit"
|
||||
type="number"
|
||||
hide-details
|
||||
suffix="MiB"
|
||||
:label="$t('settings.advanced.qbittorrent.torrentFileSizeLimit')" />
|
||||
<v-text-field v-model="torrentFileSizeLimit" type="number" hide-details suffix="MiB" :label="$t('settings.advanced.qbittorrent.torrentFileSizeLimit')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.recheck_completed_torrents" hide-details
|
||||
:label="t('settings.advanced.qbittorrent.recheckOnCompletion')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.recheck_completed_torrents" hide-details :label="t('settings.advanced.qbittorrent.recheckOnCompletion')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field
|
||||
|
@ -132,12 +124,10 @@ onBeforeMount(async () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.resolve_peer_countries" hide-details
|
||||
:label="t('settings.advanced.qbittorrent.resolveCountries')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.resolve_peer_countries" hide-details :label="t('settings.advanced.qbittorrent.resolveCountries')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.reannounce_when_address_changed" hide-details
|
||||
:label="t('settings.advanced.qbittorrent.reannounceOnIpPortChanged')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.reannounce_when_address_changed" hide-details :label="t('settings.advanced.qbittorrent.reannounceOnIpPortChanged')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -170,8 +160,7 @@ onBeforeMount(async () => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" class="py-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_embedded_tracker" hide-details
|
||||
:label="t('settings.advanced.qbittorrent.embeddedTracker.enable')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_embedded_tracker" hide-details :label="t('settings.advanced.qbittorrent.embeddedTracker.enable')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="py-0">
|
||||
<v-text-field
|
||||
|
@ -205,17 +194,14 @@ onBeforeMount(async () => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.async_io_threads" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.asyncIoThreads')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.async_io_threads" type="number" hide-details :label="t('settings.advanced.libtorrent.threads.asyncIoThreads')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.hashing_threads" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.hashingThreads')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.hashing_threads" type="number" hide-details :label="t('settings.advanced.libtorrent.threads.hashingThreads')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.file_pool_size" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.filePoolSize')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.file_pool_size" type="number" hide-details :label="t('settings.advanced.libtorrent.threads.filePoolSize')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field
|
||||
|
@ -234,8 +220,7 @@ onBeforeMount(async () => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.disk_cache" type="number" hide-details suffix="MiB"
|
||||
:label="t('settings.advanced.libtorrent.disk.diskCache')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.disk_cache" type="number" hide-details suffix="MiB" :label="t('settings.advanced.libtorrent.disk.diskCache')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field
|
||||
|
@ -256,8 +241,7 @@ onBeforeMount(async () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="4">
|
||||
<v-select v-model="preferenceStore.preferences!.disk_io_type" hide-details :items="diskIoTypeOptions"
|
||||
:label="t('settings.advanced.libtorrent.disk.diskIoType')" />
|
||||
<v-select v-model="preferenceStore.preferences!.disk_io_type" hide-details :items="diskIoTypeOptions" :label="t('settings.advanced.libtorrent.disk.diskIoType')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-select
|
||||
|
@ -281,25 +265,28 @@ onBeforeMount(async () => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.bdecode_depth_limit" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.bdecodeDepthLimit')" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.bdecode_depth_limit"
|
||||
type="number"
|
||||
hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.bdecodeDepthLimit')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.bdecode_token_limit" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.bdecodeTokenLimit')" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.bdecode_token_limit"
|
||||
type="number"
|
||||
hide-details
|
||||
:label="t('settings.advanced.libtorrent.threads.bdecodeTokenLimit')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="4">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_coalesce_read_write" hide-details
|
||||
:label="t('settings.advanced.libtorrent.coalesceReadsWrites')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_coalesce_read_write" hide-details :label="t('settings.advanced.libtorrent.coalesceReadsWrites')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_piece_extent_affinity" hide-details
|
||||
:label="t('settings.advanced.libtorrent.pieceExtentAffinity')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_piece_extent_affinity" hide-details :label="t('settings.advanced.libtorrent.pieceExtentAffinity')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_upload_suggestions" hide-details
|
||||
:label="t('settings.advanced.libtorrent.sendUploadPieceSuggestions')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.enable_upload_suggestions" hide-details :label="t('settings.advanced.libtorrent.sendUploadPieceSuggestions')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="4">
|
||||
|
@ -336,20 +323,23 @@ onBeforeMount(async () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field v-model="preferenceStore.preferences!.socket_send_buffer_size" type="number"
|
||||
:label="t('settings.advanced.libtorrent.socketSendBufferSize')"
|
||||
:hint="$t('settings.advanced.libtorrent.socketSendBufferSizeHint')"
|
||||
suffix="kiB" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.socket_send_buffer_size"
|
||||
type="number"
|
||||
:label="t('settings.advanced.libtorrent.socketSendBufferSize')"
|
||||
:hint="$t('settings.advanced.libtorrent.socketSendBufferSizeHint')"
|
||||
suffix="kiB" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field v-model="preferenceStore.preferences!.socket_receive_buffer_size" type="number"
|
||||
:label="t('settings.advanced.libtorrent.socketReceiveBufferSize')"
|
||||
:hint="$t('settings.advanced.libtorrent.socketReceiveBufferSizeHint')"
|
||||
suffix="kiB" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.socket_receive_buffer_size"
|
||||
type="number"
|
||||
:label="t('settings.advanced.libtorrent.socketReceiveBufferSize')"
|
||||
:hint="$t('settings.advanced.libtorrent.socketReceiveBufferSizeHint')"
|
||||
suffix="kiB" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field v-model="preferenceStore.preferences!.socket_backlog_size" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.socketBacklogSize')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.socket_backlog_size" type="number" hide-details :label="t('settings.advanced.libtorrent.socketBacklogSize')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -382,8 +372,7 @@ onBeforeMount(async () => {
|
|||
:label="t('settings.advanced.libtorrent.networking.upnpLeaseDuration')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.peer_tos" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.networking.peerTos')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.peer_tos" type="number" hide-details :label="t('settings.advanced.libtorrent.networking.peerTos')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
|
@ -402,8 +391,7 @@ onBeforeMount(async () => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.idn_support_enabled" hide-details
|
||||
:label="t('settings.advanced.libtorrent.security.idnSupport')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.idn_support_enabled" hide-details :label="t('settings.advanced.libtorrent.security.idnSupport')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox
|
||||
|
@ -419,8 +407,7 @@ onBeforeMount(async () => {
|
|||
:label="t('settings.advanced.libtorrent.security.validateHTTPSTrackerCertificate')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.ssrf_mitigation" hide-details
|
||||
:label="t('settings.advanced.libtorrent.security.mitigateSSRF')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.ssrf_mitigation" hide-details :label="t('settings.advanced.libtorrent.security.mitigateSSRF')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-checkbox
|
||||
|
@ -451,17 +438,14 @@ onBeforeMount(async () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.announce_to_all_trackers" hide-details
|
||||
:label="t('settings.advanced.libtorrent.announceAllTrackers')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.announce_to_all_trackers" hide-details :label="t('settings.advanced.libtorrent.announceAllTrackers')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.announce_to_all_tiers" hide-details
|
||||
:label="t('settings.advanced.libtorrent.announceAllTiers')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.announce_to_all_tiers" hide-details :label="t('settings.advanced.libtorrent.announceAllTiers')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<v-text-field v-model="preferenceStore.preferences!.announce_ip" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.announceIP')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.announce_ip" type="number" hide-details :label="t('settings.advanced.libtorrent.announceIP')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
|
@ -472,13 +456,11 @@ onBeforeMount(async () => {
|
|||
:label="t('settings.advanced.libtorrent.maxConcurrentHTTPAnnounces')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.stop_tracker_timeout" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.stopTrackerTimeout')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.stop_tracker_timeout" type="number" hide-details :label="t('settings.advanced.libtorrent.stopTrackerTimeout')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field v-model="preferenceStore.preferences!.peer_turnover" type="number" hide-details suffix="%"
|
||||
:label="t('settings.advanced.libtorrent.peerTurnover')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.peer_turnover" type="number" hide-details suffix="%" :label="t('settings.advanced.libtorrent.peerTurnover')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field
|
||||
|
@ -498,8 +480,7 @@ onBeforeMount(async () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<v-text-field v-model="preferenceStore.preferences!.request_queue_size" type="number" hide-details
|
||||
:label="t('settings.advanced.libtorrent.requestQueueSize')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.request_queue_size" type="number" hide-details :label="t('settings.advanced.libtorrent.requestQueueSize')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
|
|
@ -20,13 +20,14 @@ const fileLogAgeTypeOptions = [
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.file_log_enabled" hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_enabled')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.file_log_enabled" hide-details :label="$t('settings.behavior.logs.file_log_enabled')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.file_log_path"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled"
|
||||
hide-details :label="$t('settings.behavior.logs.file_log_path')" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.file_log_path"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_path')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -36,36 +37,42 @@ const fileLogAgeTypeOptions = [
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.file_log_backup_enabled"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_backup_enabled')" />
|
||||
<v-checkbox
|
||||
v-model="preferenceStore.preferences!.file_log_backup_enabled"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_backup_enabled')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.file_log_max_size"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled || !preferenceStore.preferences!.file_log_backup_enabled"
|
||||
type="number"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_max_size')"
|
||||
suffix="kiB" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.file_log_max_size"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled || !preferenceStore.preferences!.file_log_backup_enabled"
|
||||
type="number"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_max_size')"
|
||||
suffix="kiB" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.file_log_delete_old"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_delete_old')" />
|
||||
<v-checkbox
|
||||
v-model="preferenceStore.preferences!.file_log_delete_old"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_delete_old')" />
|
||||
</v-col>
|
||||
<v-col cols="3">
|
||||
<v-text-field v-model="preferenceStore.preferences!.file_log_age"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled || !preferenceStore.preferences!.file_log_delete_old"
|
||||
hide-details :label="$t('settings.behavior.logs.file_log_age')" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.file_log_age"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled || !preferenceStore.preferences!.file_log_delete_old"
|
||||
hide-details
|
||||
:label="$t('settings.behavior.logs.file_log_age')" />
|
||||
</v-col>
|
||||
<v-col cols="3">
|
||||
<v-select v-model="preferenceStore.preferences!.file_log_age_type"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled || !preferenceStore.preferences!.file_log_delete_old"
|
||||
:items="fileLogAgeTypeOptions"
|
||||
hide-details />
|
||||
<v-select
|
||||
v-model="preferenceStore.preferences!.file_log_age_type"
|
||||
:disabled="!preferenceStore.preferences!.file_log_enabled || !preferenceStore.preferences!.file_log_delete_old"
|
||||
:items="fileLogAgeTypeOptions"
|
||||
hide-details />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -73,12 +80,9 @@ const fileLogAgeTypeOptions = [
|
|||
<v-divider class="mt-3" />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.performance_warning" hide-details
|
||||
:label="$t('settings.behavior.performance_warning')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.performance_warning" hide-details :label="$t('settings.behavior.performance_warning')" />
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -25,28 +25,23 @@ const thenTypes = ref([
|
|||
<v-list-subheader>{{ t('settings.bittorrent.privacy.subheader') }}</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.dht" hide-details
|
||||
:label="t('settings.bittorrent.privacy.enableDHT')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.dht" hide-details :label="t('settings.bittorrent.privacy.enableDHT')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.pex" hide-details
|
||||
:label="t('settings.bittorrent.privacy.enablePeX')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.pex" hide-details :label="t('settings.bittorrent.privacy.enablePeX')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.lsd" hide-details
|
||||
:label="t('settings.bittorrent.privacy.enableLPD')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.lsd" hide-details :label="t('settings.bittorrent.privacy.enableLPD')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-select v-model="preferenceStore.preferences!.encryption" hide-details :items="encyptionModeOptions"
|
||||
:label="t('settings.bittorrent.privacy.encryptionMode')" />
|
||||
<v-select v-model="preferenceStore.preferences!.encryption" hide-details :items="encyptionModeOptions" :label="t('settings.bittorrent.privacy.encryptionMode')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.anonymous_mode" hide-details
|
||||
:label="t('settings.bittorrent.privacy.enableAnonymous')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.anonymous_mode" hide-details :label="t('settings.bittorrent.privacy.enableAnonymous')" />
|
||||
<a href="https://github.com/qbittorrent/qBittorrent/wiki/Anonymous-Mode" target="_blank">
|
||||
{{ t('settings.bittorrent.privacy.moreInfo') }}
|
||||
</a>
|
||||
|
@ -55,8 +50,7 @@ const thenTypes = ref([
|
|||
<v-divider />
|
||||
|
||||
<v-list-item class="my-3">
|
||||
<v-text-field v-model="preferenceStore.preferences!.max_active_checking_torrents" type="number" hide-details
|
||||
:label="t('settings.bittorrent.maxActiveCheckingTorrents')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.max_active_checking_torrents" type="number" hide-details :label="t('settings.bittorrent.maxActiveCheckingTorrents')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
@ -64,8 +58,7 @@ const thenTypes = ref([
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" class="pb-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.queueing_enabled" hide-details
|
||||
:label="t('settings.bittorrent.torrentQueueing.subheader')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.queueing_enabled" hide-details :label="t('settings.bittorrent.torrentQueueing.subheader')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6" md="4">
|
||||
|
@ -141,12 +134,10 @@ const thenTypes = ref([
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.max_ratio_enabled" hide-details
|
||||
:label="t('settings.bittorrent.seedLimits.whenRatioReaches')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.max_ratio_enabled" hide-details :label="t('settings.bittorrent.seedLimits.whenRatioReaches')" />
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.max_ratio"
|
||||
:disabled="!preferenceStore.preferences!.max_ratio_enabled" type="number" hide-details />
|
||||
<v-text-field v-model="preferenceStore.preferences!.max_ratio" :disabled="!preferenceStore.preferences!.max_ratio_enabled" type="number" hide-details />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -154,8 +145,7 @@ const thenTypes = ref([
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.max_seeding_time_enabled" hide-details
|
||||
:label="t('settings.bittorrent.seedLimits.whenSeedingTimeReaches')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.max_seeding_time_enabled" hide-details :label="t('settings.bittorrent.seedLimits.whenSeedingTimeReaches')" />
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-text-field
|
||||
|
@ -171,8 +161,10 @@ const thenTypes = ref([
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.max_inactive_seeding_time_enabled" hide-details
|
||||
:label="t('settings.bittorrent.seedLimits.whenInactiveSeedingTimeReaches')" />
|
||||
<v-checkbox
|
||||
v-model="preferenceStore.preferences!.max_inactive_seeding_time_enabled"
|
||||
hide-details
|
||||
:label="t('settings.bittorrent.seedLimits.whenInactiveSeedingTimeReaches')" />
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-text-field
|
||||
|
@ -192,7 +184,11 @@ const thenTypes = ref([
|
|||
<v-col>
|
||||
<v-select
|
||||
v-model="preferenceStore.preferences!.max_ratio_act"
|
||||
:disabled="!preferenceStore.preferences!.max_ratio_enabled && !preferenceStore.preferences!.max_seeding_time_enabled && !preferenceStore.preferences!.max_inactive_seeding_time_enabled"
|
||||
:disabled="
|
||||
!preferenceStore.preferences!.max_ratio_enabled &&
|
||||
!preferenceStore.preferences!.max_seeding_time_enabled &&
|
||||
!preferenceStore.preferences!.max_inactive_seeding_time_enabled
|
||||
"
|
||||
hide-details
|
||||
:items="thenTypes" />
|
||||
</v-col>
|
||||
|
@ -202,8 +198,7 @@ const thenTypes = ref([
|
|||
<v-divider class="mt-3" />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.add_trackers_enabled" hide-details
|
||||
:label="t('settings.bittorrent.autoAddTrackers')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.add_trackers_enabled" hide-details :label="t('settings.bittorrent.autoAddTrackers')" />
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-textarea
|
||||
|
|
|
@ -70,8 +70,7 @@ watch(
|
|||
<template>
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<v-select v-model="preferenceStore.preferences!.bittorrent_protocol" hide-details :items="bittorrent_protocol"
|
||||
:label="t('settings.connection.protocol')" />
|
||||
<v-select v-model="preferenceStore.preferences!.bittorrent_protocol" hide-details :items="bittorrent_protocol" :label="t('settings.connection.protocol')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-divider class="mt-3" />
|
||||
|
@ -80,21 +79,16 @@ watch(
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.listen_port" type="number" hide-details
|
||||
:label="t('settings.connection.listeningPort.incomingConnectionPort')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.listen_port" type="number" hide-details :label="t('settings.connection.listeningPort.incomingConnectionPort')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" class="d-flex align-center justify-center">
|
||||
<v-btn color="primary" @click="generateRandomPort">{{
|
||||
t('settings.connection.listeningPort.randomPort')
|
||||
}}
|
||||
</v-btn>
|
||||
<v-btn color="primary" @click="generateRandomPort">{{ t('settings.connection.listeningPort.randomPort') }} </v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.upnp" hide-details
|
||||
:label="t('settings.connection.listeningPort.useUPnP')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.upnp" hide-details :label="t('settings.connection.listeningPort.useUPnP')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
@ -158,19 +152,10 @@ watch(
|
|||
<v-select v-model="preferenceStore.preferences!.proxy_type" hide-details :items="proxyTypes" />
|
||||
</v-col>
|
||||
<v-col cols="6" md="4">
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.proxy_ip"
|
||||
:disabled="isProxyDisabled"
|
||||
hide-details
|
||||
:label="t('settings.connection.proxy.host')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.proxy_ip" :disabled="isProxyDisabled" hide-details :label="t('settings.connection.proxy.host')" />
|
||||
</v-col>
|
||||
<v-col cols="6" md="4">
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.proxy_port"
|
||||
:disabled="isProxyDisabled"
|
||||
type="number"
|
||||
hide-details
|
||||
:label="t('settings.connection.proxy.port')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.proxy_port" :disabled="isProxyDisabled" type="number" hide-details :label="t('settings.connection.proxy.port')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -178,11 +163,7 @@ watch(
|
|||
<v-list-item>
|
||||
<v-row no-gutters>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-checkbox
|
||||
v-model="preferenceStore.preferences!.proxy_bittorrent"
|
||||
:disabled="isProxyDisabled"
|
||||
hide-details
|
||||
:label="t('settings.connection.proxy.bittorrent')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.proxy_bittorrent" :disabled="isProxyDisabled" hide-details :label="t('settings.connection.proxy.bittorrent')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-checkbox
|
||||
|
@ -192,18 +173,10 @@ watch(
|
|||
:label="t('settings.connection.proxy.peerConnections')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-checkbox
|
||||
v-model="preferenceStore.preferences!.proxy_rss"
|
||||
:disabled="isProxyDisabled || isProxySocks4"
|
||||
hide-details
|
||||
:label="t('settings.connection.proxy.rss')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.proxy_rss" :disabled="isProxyDisabled || isProxySocks4" hide-details :label="t('settings.connection.proxy.rss')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-checkbox
|
||||
v-model="preferenceStore.preferences!.proxy_misc"
|
||||
:disabled="isProxyDisabled || isProxySocks4"
|
||||
hide-details
|
||||
:label="t('settings.connection.proxy.misc')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.proxy_misc" :disabled="isProxyDisabled || isProxySocks4" hide-details :label="t('settings.connection.proxy.misc')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -251,15 +224,12 @@ watch(
|
|||
<v-list-subheader>{{ t('settings.connection.ipFiltering.subheader') }}</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.ip_filter_enabled" hide-details
|
||||
:label="t('settings.connection.ipFiltering.filterPath')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.ip_filter_path"
|
||||
:disabled="!preferenceStore.preferences!.ip_filter_enabled" hide-details />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.ip_filter_enabled" hide-details :label="t('settings.connection.ipFiltering.filterPath')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.ip_filter_path" :disabled="!preferenceStore.preferences!.ip_filter_enabled" hide-details />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.ip_filter_trackers" hide-details
|
||||
:label="t('settings.connection.ipFiltering.applyToTrackers')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.ip_filter_trackers" hide-details :label="t('settings.connection.ipFiltering.applyToTrackers')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
|
@ -267,8 +237,7 @@ watch(
|
|||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-textarea v-model="preferenceStore.preferences!.banned_IPs" auto-grow clearable persistent-hint
|
||||
:hint="t('settings.connection.ipFiltering.bannedIpsHint')" />
|
||||
<v-textarea v-model="preferenceStore.preferences!.banned_IPs" auto-grow clearable persistent-hint :hint="t('settings.connection.ipFiltering.bannedIpsHint')" />
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
|
|
|
@ -147,33 +147,25 @@ const closeDeleteDialog = async () => {
|
|||
<v-list-subheader>{{ t('settings.downloads.whenAddTorrent.subheader') }}</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-select v-model="preferenceStore.preferences!.torrent_content_layout" hide-details :items="contentLayoutOptions"
|
||||
:label="t('constants.contentLayout.title')" />
|
||||
<v-select v-model="preferenceStore.preferences!.torrent_content_layout" hide-details :items="contentLayoutOptions" :label="t('constants.contentLayout.title')" />
|
||||
|
||||
<v-checkbox v-model="preferenceStore.preferences!.add_to_top_of_queue" hide-details
|
||||
:label="t('settings.downloads.whenAddTorrent.addToTopOfQueue')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.add_to_top_of_queue" hide-details :label="t('settings.downloads.whenAddTorrent.addToTopOfQueue')" />
|
||||
|
||||
<v-checkbox v-model="preferenceStore.preferences!.merge_trackers" hide-details
|
||||
:label="t('settings.downloads.whenAddTorrent.mergeTrackers')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.merge_trackers" hide-details :label="t('settings.downloads.whenAddTorrent.mergeTrackers')" />
|
||||
|
||||
<v-checkbox v-model="preferenceStore.preferences!.start_paused_enabled" hide-details
|
||||
:label="t('settings.downloads.whenAddTorrent.doNotAutoStart')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.start_paused_enabled" hide-details :label="t('settings.downloads.whenAddTorrent.doNotAutoStart')" />
|
||||
|
||||
<v-select v-model="preferenceStore.preferences!.torrent_stop_condition" hide-details :items="stopConditionOptions"
|
||||
:label="t('constants.stopCondition.title')" />
|
||||
<v-select v-model="preferenceStore.preferences!.torrent_stop_condition" hide-details :items="stopConditionOptions" :label="t('constants.stopCondition.title')" />
|
||||
|
||||
<v-checkbox v-model="preferenceStore.preferences!.auto_delete_mode" hide-details
|
||||
:label="t('settings.downloads.whenAddTorrent.autoDeleteMode')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.auto_delete_mode" hide-details :label="t('settings.downloads.whenAddTorrent.autoDeleteMode')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.preallocate_all" hide-details
|
||||
:label="t('settings.downloads.publicSettings.preAllocateDisk')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.preallocate_all" hide-details :label="t('settings.downloads.publicSettings.preAllocateDisk')" />
|
||||
|
||||
<v-checkbox v-model="preferenceStore.preferences!.incomplete_files_ext" hide-details
|
||||
:label="t('settings.downloads.publicSettings.appendQBExtension')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.incomplete_files_ext" hide-details :label="t('settings.downloads.publicSettings.appendQBExtension')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
@ -212,8 +204,7 @@ const closeDeleteDialog = async () => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
<v-text-field v-model="preferenceStore.preferences!.save_path" hide-details
|
||||
:label="t('settings.downloads.saveManagement.defaultSavePath')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.save_path" hide-details :label="t('settings.downloads.saveManagement.defaultSavePath')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12">
|
||||
|
@ -274,8 +265,7 @@ const closeDeleteDialog = async () => {
|
|||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-text-field v-model="monitoredFoldersEditedItem.monitoredFolderPath"
|
||||
:label="t('settings.downloads.monitoredFolders.monitoredFolderPath')" />
|
||||
<v-text-field v-model="monitoredFoldersEditedItem.monitoredFolderPath" :label="t('settings.downloads.monitoredFolders.monitoredFolderPath')" />
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-select
|
||||
|
@ -329,8 +319,7 @@ const closeDeleteDialog = async () => {
|
|||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.excluded_file_names_enabled" hide-details
|
||||
:label="t('settings.downloads.excludedFileNames.label')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.excluded_file_names_enabled" hide-details :label="t('settings.downloads.excludedFileNames.label')" />
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-textarea
|
||||
|
@ -345,8 +334,7 @@ const closeDeleteDialog = async () => {
|
|||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.mail_notification_enabled" hide-details
|
||||
:label="t('settings.downloads.mailNotification.enabled')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.mail_notification_enabled" hide-details :label="t('settings.downloads.mailNotification.enabled')" />
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-text-field
|
||||
|
@ -401,8 +389,8 @@ const closeDeleteDialog = async () => {
|
|||
!preferenceStore.preferences!.mail_notification_enabled || !preferenceStore.preferences!.mail_notification_auth_enabled
|
||||
? ''
|
||||
: showPassword
|
||||
? 'mdi-eye'
|
||||
: 'mdi-eye-off'
|
||||
? 'mdi-eye'
|
||||
: 'mdi-eye-off'
|
||||
"
|
||||
@click:append="showPassword = !showPassword" />
|
||||
</v-col>
|
||||
|
@ -415,15 +403,13 @@ const closeDeleteDialog = async () => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.autorun_on_torrent_added_enabled" hide-details
|
||||
:label="t('settings.downloads.runExternalProgram.onAddedEnabled')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.autorun_on_torrent_added_enabled" hide-details :label="t('settings.downloads.runExternalProgram.onAddedEnabled')" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.autorun_on_torrent_added_program"
|
||||
:disabled="!preferenceStore.preferences!.autorun_on_torrent_added_enabled"
|
||||
hide-details
|
||||
:label="t('settings.downloads.runExternalProgram.onAddedLabel')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.autorun_enabled" hide-details
|
||||
:label="t('settings.downloads.runExternalProgram.onFinishedEnabled')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.autorun_enabled" hide-details :label="t('settings.downloads.runExternalProgram.onFinishedEnabled')" />
|
||||
<v-text-field
|
||||
v-model="preferenceStore.preferences!.autorun_program"
|
||||
:disabled="!preferenceStore.preferences!.autorun_enabled"
|
||||
|
|
|
@ -85,8 +85,7 @@ watch(
|
|||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6" class="d-flex align-center justify-center">
|
||||
<v-btn color="accent" :loading="loading" :disabled="rssStore.feeds.length === 0"
|
||||
:text="$t('settings.rss.feeds.refreshAll')" @click="refreshAllFeeds" />
|
||||
<v-btn color="accent" :loading="loading" :disabled="rssStore.feeds.length === 0" :text="$t('settings.rss.feeds.refreshAll')" @click="refreshAllFeeds" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import { usePreferenceStore, useVueTorrentStore } from '@/stores'
|
||||
|
||||
const preferenceStore = usePreferenceStore()
|
||||
|
@ -11,8 +10,7 @@ const vuetorrentStore = useVueTorrentStore()
|
|||
<v-list-subheader>{{ $t('settings.rss.general.reader.subheader') }}</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.rss_processing_enabled" hide-details
|
||||
:label="$t('settings.rss.general.reader.enableProcessing')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.rss_processing_enabled" hide-details :label="$t('settings.rss.general.reader.enableProcessing')" />
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
|
@ -24,8 +22,7 @@ const vuetorrentStore = useVueTorrentStore()
|
|||
:label="$t('settings.rss.general.reader.feedsRefreshInterval')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.rss_max_articles_per_feed" type="number"
|
||||
:label="$t('settings.rss.general.reader.maximumArticlesPerFeed')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.rss_max_articles_per_feed" type="number" :label="$t('settings.rss.general.reader.maximumArticlesPerFeed')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -34,8 +31,7 @@ const vuetorrentStore = useVueTorrentStore()
|
|||
<v-list-subheader>{{ $t('settings.rss.general.autoDownloader.subheader') }}</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.rss_auto_downloading_enabled" hide-details class="ma-0 pa-0"
|
||||
:label="$t('settings.rss.general.autoDownloader.enable')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.rss_auto_downloading_enabled" hide-details class="ma-0 pa-0" :label="$t('settings.rss.general.autoDownloader.enable')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
@ -60,9 +56,7 @@ const vuetorrentStore = useVueTorrentStore()
|
|||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="vuetorrentStore.useIdForRssLinks"
|
||||
hide-details
|
||||
:label="$t('settings.rss.general.useIdForRssLinks')" />
|
||||
<v-checkbox v-model="vuetorrentStore.useIdForRssLinks" hide-details :label="$t('settings.rss.general.useIdForRssLinks')" />
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
|
|
|
@ -22,20 +22,20 @@ const schedulerOptions = ref([
|
|||
|
||||
const upLimit = computed({
|
||||
get: () => preferenceStore.preferences!.up_limit / 1024,
|
||||
set: (value: number) => preferenceStore.preferences!.up_limit = value * 1024
|
||||
set: (value: number) => (preferenceStore.preferences!.up_limit = value * 1024)
|
||||
})
|
||||
const dlLimit = computed({
|
||||
get: () => preferenceStore.preferences!.dl_limit / 1024,
|
||||
set: (value: number) => preferenceStore.preferences!.dl_limit = value * 1024
|
||||
set: (value: number) => (preferenceStore.preferences!.dl_limit = value * 1024)
|
||||
})
|
||||
|
||||
const altUpLimit = computed({
|
||||
get: () => preferenceStore.preferences!.alt_up_limit / 1024,
|
||||
set: (value: number) => preferenceStore.preferences!.alt_up_limit = value * 1024
|
||||
set: (value: number) => (preferenceStore.preferences!.alt_up_limit = value * 1024)
|
||||
})
|
||||
const altDlLimit = computed({
|
||||
get: () => preferenceStore.preferences!.alt_dl_limit / 1024,
|
||||
set: (value: number) => preferenceStore.preferences!.alt_dl_limit = value * 1024
|
||||
set: (value: number) => (preferenceStore.preferences!.alt_dl_limit = value * 1024)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -48,12 +48,10 @@ const altDlLimit = computed({
|
|||
|
||||
<v-row class="mx-1">
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="upLimit" hide-details suffix="kiB/s"
|
||||
:label="t('settings.speed.upload')" />
|
||||
<v-text-field v-model="upLimit" hide-details suffix="kiB/s" :label="t('settings.speed.upload')" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="dlLimit" hide-details suffix="kiB/s"
|
||||
:label="t('settings.speed.download')" />
|
||||
<v-text-field v-model="dlLimit" hide-details suffix="kiB/s" :label="t('settings.speed.download')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
@ -69,12 +67,10 @@ const altDlLimit = computed({
|
|||
|
||||
<v-row class="mx-1">
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="altUpLimit" hide-details suffix="kiB/s"
|
||||
:label="t('settings.speed.upload')" />
|
||||
<v-text-field v-model="altUpLimit" hide-details suffix="kiB/s" :label="t('settings.speed.upload')" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="altDlLimit" hide-details suffix="kiB/s"
|
||||
:label="t('settings.speed.download')" />
|
||||
<v-text-field v-model="altDlLimit" hide-details suffix="kiB/s" :label="t('settings.speed.download')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
@ -88,8 +84,7 @@ const altDlLimit = computed({
|
|||
<v-divider class="mt-2" />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.scheduler_enabled" hide-details
|
||||
:label="t('settings.speed.scheduler.subheader')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.scheduler_enabled" hide-details :label="t('settings.speed.scheduler.subheader')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
|
@ -98,12 +93,10 @@ const altDlLimit = computed({
|
|||
<v-list-subheader>{{ t('settings.speed.scheduler.from') }}</v-list-subheader>
|
||||
</v-col>
|
||||
<v-col cols="4" md="2">
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_from_hour"
|
||||
:disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_from_hour" :disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
</v-col>
|
||||
<v-col cols="4" md="2">
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_from_min"
|
||||
:disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_from_min" :disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
</v-col>
|
||||
|
||||
<v-spacer />
|
||||
|
@ -112,12 +105,10 @@ const altDlLimit = computed({
|
|||
<v-list-subheader>{{ t('settings.speed.scheduler.to') }}</v-list-subheader>
|
||||
</v-col>
|
||||
<v-col cols="4" md="2">
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_to_hour"
|
||||
:disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_to_hour" :disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
</v-col>
|
||||
<v-col cols="4" md="2">
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_to_min"
|
||||
:disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.schedule_to_min" :disabled="!preferenceStore.preferences!.scheduler_enabled" type="number" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -136,18 +127,15 @@ const altDlLimit = computed({
|
|||
<v-list-subheader>{{ t('settings.speed.subheader.settings') }}</v-list-subheader>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.limit_utp_rate" hide-details
|
||||
:label="t('settings.speed.settings.applyToUtp')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.limit_utp_rate" hide-details :label="t('settings.speed.settings.applyToUtp')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.limit_tcp_overhead" hide-details
|
||||
:label="t('settings.speed.settings.applyToTransportOverhead')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.limit_tcp_overhead" hide-details :label="t('settings.speed.settings.applyToTransportOverhead')" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.limit_lan_peers" hide-details
|
||||
:label="t('settings.speed.settings.applyToPeersOnLan')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.limit_lan_peers" hide-details :label="t('settings.speed.settings.applyToPeersOnLan')" />
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</template>
|
||||
|
|
|
@ -11,10 +11,9 @@ defineEmits<{ update: [value: void] }>()
|
|||
<v-icon icon="mdi-drag-vertical" class="dnd-handle" />
|
||||
</td>
|
||||
<td>
|
||||
<v-btn density="compact" :icon="property.active ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'"
|
||||
variant="flat" @click="$emit('update')" />
|
||||
<v-btn density="compact" :icon="property.active ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'" variant="flat" @click="$emit('update')" />
|
||||
</td>
|
||||
<td>{{ $t(`torrent.properties.${ property.name }`) }}</td>
|
||||
<td>{{ $t(`torrent.properties.${property.name}`) }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -18,13 +18,7 @@ const titleOptionsList = [
|
|||
{ title: t('constants.titleOptions.custom'), value: TitleOptions.CUSTOM }
|
||||
]
|
||||
|
||||
const paginationSizes = ref([
|
||||
{ title: t('settings.vuetorrent.general.paginationSize.infinite_scroll'), value: -1 },
|
||||
5,
|
||||
15,
|
||||
30,
|
||||
50
|
||||
])
|
||||
const paginationSizes = ref([{ title: t('settings.vuetorrent.general.paginationSize.infinite_scroll'), value: -1 }, 5, 15, 30, 50])
|
||||
|
||||
const theme = computed({
|
||||
get() {
|
||||
|
@ -86,57 +80,45 @@ onBeforeMount(() => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.showCurrentSpeed" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.showCurrentSpeed')" />
|
||||
<v-checkbox v-model="vueTorrentStore.showCurrentSpeed" hide-details density="compact" :label="t('settings.vuetorrent.general.showCurrentSpeed')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.showSpeedGraph" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.showSpeedGraph')" />
|
||||
<v-checkbox v-model="vueTorrentStore.showSpeedGraph" hide-details density="compact" :label="t('settings.vuetorrent.general.showSpeedGraph')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.showAlltimeStat" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.showAlltimeStat')" />
|
||||
<v-checkbox v-model="vueTorrentStore.showAlltimeStat" hide-details density="compact" :label="t('settings.vuetorrent.general.showAlltimeStat')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.showSessionStat" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.showSessionStat')" />
|
||||
<v-checkbox v-model="vueTorrentStore.showSessionStat" hide-details density="compact" :label="t('settings.vuetorrent.general.showSessionStat')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.showFreeSpace" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.showFreeSpace')" />
|
||||
<v-checkbox v-model="vueTorrentStore.showFreeSpace" hide-details density="compact" :label="t('settings.vuetorrent.general.showFreeSpace')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.showTrackerFilter" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.showTrackerFilter')" />
|
||||
<v-checkbox v-model="vueTorrentStore.showTrackerFilter" hide-details density="compact" :label="t('settings.vuetorrent.general.showTrackerFilter')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.isDrawerRight" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.isDrawerRight')" />
|
||||
<v-checkbox v-model="vueTorrentStore.isDrawerRight" hide-details density="compact" :label="t('settings.vuetorrent.general.isDrawerRight')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.isPaginationOnTop" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.isPaginationOnTop')" />
|
||||
<v-checkbox v-model="vueTorrentStore.isPaginationOnTop" hide-details density="compact" :label="t('settings.vuetorrent.general.isPaginationOnTop')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.openSideBarOnStart" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.openSideBarOnStart')" />
|
||||
<v-checkbox v-model="vueTorrentStore.openSideBarOnStart" hide-details density="compact" :label="t('settings.vuetorrent.general.openSideBarOnStart')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.isShutdownButtonVisible" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.isShutdownButtonVisible')" />
|
||||
<v-checkbox v-model="vueTorrentStore.isShutdownButtonVisible" hide-details density="compact" :label="t('settings.vuetorrent.general.isShutdownButtonVisible')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.useBinarySize" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.useBinarySize')" />
|
||||
<v-checkbox v-model="vueTorrentStore.useBinarySize" hide-details density="compact" :label="t('settings.vuetorrent.general.useBinarySize')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-checkbox v-model="vueTorrentStore.useBitSpeed" hide-details density="compact"
|
||||
:label="t('settings.vuetorrent.general.useBitSpeed')" />
|
||||
<v-checkbox v-model="vueTorrentStore.useBitSpeed" hide-details density="compact" :label="t('settings.vuetorrent.general.useBitSpeed')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -144,26 +126,21 @@ onBeforeMount(() => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field v-model="vueTorrentStore.refreshInterval" type="number" hide-details suffix="ms"
|
||||
:label="t('settings.vuetorrent.general.refreshInterval')" />
|
||||
<v-text-field v-model="vueTorrentStore.refreshInterval" type="number" hide-details suffix="ms" :label="t('settings.vuetorrent.general.refreshInterval')" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field v-model="vueTorrentStore.fileContentInterval" type="number" hide-details suffix="ms"
|
||||
:label="t('settings.vuetorrent.general.fileContentInterval')" />
|
||||
<v-text-field v-model="vueTorrentStore.fileContentInterval" type="number" hide-details suffix="ms" :label="t('settings.vuetorrent.general.fileContentInterval')" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-text-field v-model="historyStore.historySize" type="number" hide-details
|
||||
:label="t('settings.vuetorrent.general.historySize')" />
|
||||
<v-text-field v-model="historyStore.historySize" type="number" hide-details :label="t('settings.vuetorrent.general.historySize')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="vueTorrentStore.canvasRenderThreshold" type="number"
|
||||
:label="t('settings.vuetorrent.general.canvasRenderThreshold')" />
|
||||
<v-text-field v-model="vueTorrentStore.canvasRenderThreshold" type="number" :label="t('settings.vuetorrent.general.canvasRenderThreshold')" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="vueTorrentStore.canvasRefreshThreshold" type="number"
|
||||
:label="t('settings.vuetorrent.general.canvasRefreshThreshold')" />
|
||||
<v-text-field v-model="vueTorrentStore.canvasRefreshThreshold" type="number" :label="t('settings.vuetorrent.general.canvasRefreshThreshold')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -171,20 +148,19 @@ onBeforeMount(() => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-select v-model="vueTorrentStore.language" flat hide-details :items="LOCALES"
|
||||
:label="t('settings.vuetorrent.general.language')" />
|
||||
<v-select v-model="vueTorrentStore.language" flat hide-details :items="LOCALES" :label="t('settings.vuetorrent.general.language')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-select v-model="vueTorrentStore.paginationSize" flat hide-details :items="paginationSizes"
|
||||
:label="t('settings.vuetorrent.general.paginationSize.label')" />
|
||||
<v-select v-model="vueTorrentStore.paginationSize" flat hide-details :items="paginationSizes" :label="t('settings.vuetorrent.general.paginationSize.label')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-select v-model="vueTorrentStore.uiTitleType" flat hide-details :items="titleOptionsList"
|
||||
:label="t('settings.vuetorrent.general.vueTorrentTitle')" />
|
||||
<v-select v-model="vueTorrentStore.uiTitleType" flat hide-details :items="titleOptionsList" :label="t('settings.vuetorrent.general.vueTorrentTitle')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" md="3">
|
||||
<v-text-field :disabled="vueTorrentStore.uiTitleType !== TitleOptions.CUSTOM"
|
||||
v-model="vueTorrentStore.uiTitleCustom" :label="t('settings.vuetorrent.general.customTitle')" />
|
||||
<v-text-field
|
||||
:disabled="vueTorrentStore.uiTitleType !== TitleOptions.CUSTOM"
|
||||
v-model="vueTorrentStore.uiTitleCustom"
|
||||
:label="t('settings.vuetorrent.general.customTitle')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -195,21 +171,15 @@ onBeforeMount(() => {
|
|||
<h3>
|
||||
{{ t('settings.vuetorrent.general.currentVersion') }}
|
||||
<span v-if="!vueTorrentVersion">undefined</span>
|
||||
<a v-else-if="vueTorrentVersion === 'DEV'" target="_blank"
|
||||
href="https://github.com/WDaan/VueTorrent/">{{ vueTorrentVersion }}</a>
|
||||
<a v-else target="_blank" :href="`https://github.com/WDaan/VueTorrent/releases/tag/v${vueTorrentVersion}`">{{
|
||||
vueTorrentVersion
|
||||
}}</a>
|
||||
<a v-else-if="vueTorrentVersion === 'DEV'" target="_blank" href="https://github.com/WDaan/VueTorrent/">{{ vueTorrentVersion }}</a>
|
||||
<a v-else target="_blank" :href="`https://github.com/WDaan/VueTorrent/releases/tag/v${vueTorrentVersion}`">{{ vueTorrentVersion }}</a>
|
||||
</h3>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" md="3" class="d-flex align-center justify-center">
|
||||
<h3>
|
||||
{{ t('settings.vuetorrent.general.qbittorrentVersion') }}
|
||||
<a target="_blank"
|
||||
:href="`https://github.com/qbittorrent/qBittorrent/releases/tag/release-${appStore.version}`">{{
|
||||
appStore.version
|
||||
}}</a>
|
||||
<a target="_blank" :href="`https://github.com/qbittorrent/qBittorrent/releases/tag/release-${appStore.version}`">{{ appStore.version }}</a>
|
||||
</h3>
|
||||
</v-col>
|
||||
|
||||
|
@ -218,8 +188,7 @@ onBeforeMount(() => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" md="3">
|
||||
<v-text-field v-model="vueTorrentStore.dateFormat" placeholder="DD/MM/YYYY, HH:mm:ss" hint="using Dayjs"
|
||||
:label="t('settings.vuetorrent.general.dateFormat')" />
|
||||
<v-text-field v-model="vueTorrentStore.dateFormat" placeholder="DD/MM/YYYY, HH:mm:ss" hint="using Dayjs" :label="t('settings.vuetorrent.general.dateFormat')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -227,10 +196,7 @@ onBeforeMount(() => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6" class="d-flex align-center justify-center">
|
||||
<v-btn color="primary" @click="registerMagnetHandler">{{
|
||||
t('settings.vuetorrent.general.registerMagnet')
|
||||
}}
|
||||
</v-btn>
|
||||
<v-btn color="primary" @click="registerMagnetHandler">{{ t('settings.vuetorrent.general.registerMagnet') }} </v-btn>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6" class="d-flex align-center justify-center">
|
||||
|
|
|
@ -36,17 +36,14 @@ watch(webUiPassword, newValue => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="9">
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_address" hide-details
|
||||
:label="t('settings.webUI.interface.ipAddress')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_address" hide-details :label="t('settings.webUI.interface.ipAddress')" />
|
||||
</v-col>
|
||||
<v-col cols="3">
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_port" hide-details
|
||||
:label="t('settings.webUI.interface.port')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_port" hide-details :label="t('settings.webUI.interface.port')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" class="pt-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_upnp" hide-details
|
||||
:label="t('settings.webUI.interface.useUPnP')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_upnp" hide-details :label="t('settings.webUI.interface.useUPnP')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
@ -72,8 +69,7 @@ watch(webUiPassword, newValue => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="6">
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_username" hide-details
|
||||
:label="t('settings.webUI.authentication.username')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_username" hide-details :label="t('settings.webUI.authentication.username')" />
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6">
|
||||
<PasswordField
|
||||
|
@ -86,12 +82,10 @@ watch(webUiPassword, newValue => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="12" class="py-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.bypass_local_auth" hide-details
|
||||
:label="t('settings.webUI.authentication.bypassLocalhost')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.bypass_local_auth" hide-details :label="t('settings.webUI.authentication.bypassLocalhost')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="pt-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.bypass_auth_subnet_whitelist_enabled" hide-details
|
||||
:label="t('settings.webUI.authentication.bypassWhitelist')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.bypass_auth_subnet_whitelist_enabled" hide-details :label="t('settings.webUI.authentication.bypassWhitelist')" />
|
||||
<v-textarea
|
||||
v-model="preferenceStore.preferences!.bypass_auth_subnet_whitelist"
|
||||
:disabled="!preferenceStore.preferences!.bypass_auth_subnet_whitelist_enabled"
|
||||
|
@ -105,8 +99,7 @@ watch(webUiPassword, newValue => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_max_auth_fail_count" type="number" hide-details
|
||||
:label="t('settings.webUI.authentication.maxAttempts')" />
|
||||
<v-text-field v-model="preferenceStore.preferences!.web_ui_max_auth_fail_count" type="number" hide-details :label="t('settings.webUI.authentication.maxAttempts')" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="4">
|
||||
|
@ -134,8 +127,7 @@ watch(webUiPassword, newValue => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="12" class="pb-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.use_https" hide-details
|
||||
:label="t('settings.webUI.https.subheader')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.use_https" hide-details :label="t('settings.webUI.https.subheader')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="pt-0">
|
||||
<v-text-field
|
||||
|
@ -155,8 +147,7 @@ watch(webUiPassword, newValue => {
|
|||
</v-list-item>
|
||||
|
||||
<v-list-item>
|
||||
<a href="https://httpd.apache.org/docs/current/ssl/ssl_faq.html#aboutcerts"
|
||||
target="_blank">{{ t('settings.webUI.https.tip') }}</a>
|
||||
<a href="https://httpd.apache.org/docs/current/ssl/ssl_faq.html#aboutcerts" target="_blank">{{ t('settings.webUI.https.tip') }}</a>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
|
@ -172,8 +163,7 @@ watch(webUiPassword, newValue => {
|
|||
:label="t('settings.webUI.security.clickjacking')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="py-0">
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_csrf_protection_enabled" hide-details
|
||||
density="compact" :label="t('settings.webUI.security.csrf')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_csrf_protection_enabled" hide-details density="compact" :label="t('settings.webUI.security.csrf')" />
|
||||
</v-col>
|
||||
<v-col cols="12" class="py-0">
|
||||
<v-checkbox
|
||||
|
@ -205,8 +195,7 @@ watch(webUiPassword, newValue => {
|
|||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_use_custom_http_headers_enabled" hide-details
|
||||
:label="t('settings.webUI.customHeaders')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_use_custom_http_headers_enabled" hide-details :label="t('settings.webUI.customHeaders')" />
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-textarea
|
||||
|
@ -222,8 +211,7 @@ watch(webUiPassword, newValue => {
|
|||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_reverse_proxy_enabled" hide-details
|
||||
:label="t('settings.webUI.reverseProxySupport')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.web_ui_reverse_proxy_enabled" hide-details :label="t('settings.webUI.reverseProxySupport')" />
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-text-field
|
||||
|
@ -238,14 +226,12 @@ watch(webUiPassword, newValue => {
|
|||
<v-divider />
|
||||
|
||||
<v-list-item>
|
||||
<v-checkbox v-model="preferenceStore.preferences!.dyndns_enabled" hide-details
|
||||
:label="t('settings.webUI.dynDns.subheader')" />
|
||||
<v-checkbox v-model="preferenceStore.preferences!.dyndns_enabled" hide-details :label="t('settings.webUI.dynDns.subheader')" />
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="8">
|
||||
<v-select v-model="dynDnsProvider" :disabled="!preferenceStore.preferences!.dyndns_enabled" density="compact"
|
||||
hide-details :items="dynDnsProviderOptions" />
|
||||
<v-select v-model="dynDnsProvider" :disabled="!preferenceStore.preferences!.dyndns_enabled" density="compact" hide-details :items="dynDnsProviderOptions" />
|
||||
</v-col>
|
||||
<v-col cols="4">
|
||||
<v-btn :disabled="!preferenceStore.preferences!.dyndns_enabled" @click="registerDynDNS">
|
||||
|
|
|
@ -16,7 +16,7 @@ const dialogStore = useDialogStore()
|
|||
const maindataStore = useMaindataStore()
|
||||
const { fileContentInterval } = storeToRefs(useVueTorrentStore())
|
||||
|
||||
const { pause: pauseTimer, resume: resumeTimer } = useIntervalFn(updateFileTree, fileContentInterval,{
|
||||
const { pause: pauseTimer, resume: resumeTimer } = useIntervalFn(updateFileTree, fileContentInterval, {
|
||||
immediate: false,
|
||||
immediateCallback: true
|
||||
})
|
||||
|
@ -38,15 +38,15 @@ const fileSelection = computed({
|
|||
const oldValue = cachedFiles.value.filter(f => f.priority !== FilePriority.DO_NOT_DOWNLOAD).map(f => f.index)
|
||||
|
||||
const filesToExclude = oldValue
|
||||
.filter(index => !newValue.includes(index))
|
||||
.map(index => cachedFiles.value.find(f => f.index === index))
|
||||
.filter(f => f && f.priority !== FilePriority.DO_NOT_DOWNLOAD)
|
||||
.map(f => (f as TorrentFile).index)
|
||||
.filter(index => !newValue.includes(index))
|
||||
.map(index => cachedFiles.value.find(f => f.index === index))
|
||||
.filter(f => f && f.priority !== FilePriority.DO_NOT_DOWNLOAD)
|
||||
.map(f => (f as TorrentFile).index)
|
||||
const filesToInclude = newValue
|
||||
.filter(index => !oldValue.includes(index))
|
||||
.map(index => cachedFiles.value.find(f => f.index === index))
|
||||
.filter(f => f && f.priority === FilePriority.DO_NOT_DOWNLOAD)
|
||||
.map(f => (f as TorrentFile).index)
|
||||
.filter(index => !oldValue.includes(index))
|
||||
.map(index => cachedFiles.value.find(f => f.index === index))
|
||||
.filter(f => f && f.priority === FilePriority.DO_NOT_DOWNLOAD)
|
||||
.map(f => (f as TorrentFile).index)
|
||||
|
||||
if (filesToExclude.length) {
|
||||
await maindataStore.setTorrentFilePriority(props.torrent.hash, filesToExclude, FilePriority.DO_NOT_DOWNLOAD)
|
||||
|
@ -111,8 +111,7 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<v-card :loading="loading" flat>
|
||||
<RootNode v-model:opened="openedItems" v-model:selected="fileSelection" :root="tree"
|
||||
@renameFolder="renameNode" @renameFile="renameNode" @setFilePriority="setFilePriority" />
|
||||
<RootNode v-model:opened="openedItems" v-model:selected="fileSelection" :root="tree" @renameFolder="renameNode" @renameFile="renameNode" @setFilePriority="setFilePriority" />
|
||||
<!--
|
||||
TODO: add treeview after merge
|
||||
https://github.com/vuetifyjs/vuetify/issues/13518
|
||||
|
|
|
@ -10,7 +10,7 @@ defineProps<{
|
|||
node: TreeFile
|
||||
}>()
|
||||
defineEmits<{
|
||||
renameFile: [node: TreeFile],
|
||||
renameFile: [node: TreeFile]
|
||||
setFilePriority: [node: TreeFile, priority: FilePriority]
|
||||
}>()
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ defineProps<{
|
|||
}>()
|
||||
defineEmits<{
|
||||
renameFolder: [node: TreeFolder]
|
||||
renameFile: [node: TreeFile],
|
||||
renameFile: [node: TreeFile]
|
||||
setFilePriority: [node: TreeFile, priority: FilePriority]
|
||||
}>()
|
||||
|
||||
|
@ -48,21 +48,24 @@ function getNodeDescription(node: TreeRoot | TreeFolder) {
|
|||
:value="node.type === 'root' ? '(root)' : node.fullName">
|
||||
<template v-slot:append="{ isActive }">
|
||||
<span class="mr-2">{{ getNodeDescription(node) }}</span>
|
||||
<v-btn v-if="node.type === 'folder'" color="accent" size="x-small" icon="mdi-pencil"
|
||||
@click.stop="$emit('renameFolder', node)" />
|
||||
<v-btn v-if="node.type === 'folder'" color="accent" size="x-small" icon="mdi-pencil" @click.stop="$emit('renameFolder', node)" />
|
||||
<v-icon :icon="isActive ? 'mdi-chevron-up' : 'mdi-chevron-down'" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
||||
<template v-for="child in node.children">
|
||||
<FolderNode v-if="child.type === 'folder'" :node="child as TreeFolder"
|
||||
@renameFolder="n => $emit('renameFolder', n)"
|
||||
@renameFile="n => $emit('renameFile', n)"
|
||||
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
|
||||
<FileNode v-if="child.type === 'file'" :node="child as TreeFile"
|
||||
@renameFile="n => $emit('renameFile', n)"
|
||||
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
|
||||
<FolderNode
|
||||
v-if="child.type === 'folder'"
|
||||
:node="child as TreeFolder"
|
||||
@renameFolder="n => $emit('renameFolder', n)"
|
||||
@renameFile="n => $emit('renameFile', n)"
|
||||
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
|
||||
<FileNode
|
||||
v-if="child.type === 'file'"
|
||||
:node="child as TreeFile"
|
||||
@renameFile="n => $emit('renameFile', n)"
|
||||
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
|
||||
</template>
|
||||
</v-list-group>
|
||||
</template>
|
||||
|
|
|
@ -8,17 +8,18 @@ defineProps<{
|
|||
}>()
|
||||
defineEmits<{
|
||||
renameFolder: [node: TreeFolder]
|
||||
renameFile: [node: TreeFile],
|
||||
renameFile: [node: TreeFile]
|
||||
setFilePriority: [node: TreeFile, priority: FilePriority]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-list density="compact" select-strategy="classic">
|
||||
<FolderNode :node="root"
|
||||
@renameFolder="n => $emit('renameFolder', n)"
|
||||
@renameFile="n => $emit('renameFile', n)"
|
||||
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
|
||||
<FolderNode
|
||||
:node="root"
|
||||
@renameFolder="n => $emit('renameFolder', n)"
|
||||
@renameFile="n => $emit('renameFile', n)"
|
||||
@setFilePriority="(n, prio) => $emit('setFilePriority', n, prio)" />
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ const longTextPpts = [
|
|||
<v-expansion-panel-text>
|
||||
<v-row>
|
||||
<InfoBase v-for="ppt in datetimePpts">
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ ppt.title }`) }}</template>
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
|
||||
<template v-if="torrent[ppt.text] > 0" v-slot:text>
|
||||
{{ dayjs(torrent[ppt.text] * 1000).format(vuetorrentStore.dateFormat ?? 'DD/MM/YYYY, HH:mm:ss') }}
|
||||
</template>
|
||||
|
@ -127,7 +127,7 @@ const longTextPpts = [
|
|||
<v-expansion-panel-text>
|
||||
<v-row>
|
||||
<InfoBase v-for="ppt in durationPpts">
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ ppt.title }`) }}</template>
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
|
||||
<template v-slot:text>{{ dayjs.duration(torrent[ppt.text], 's').humanize() }}</template>
|
||||
</InfoBase>
|
||||
</v-row>
|
||||
|
@ -139,36 +139,31 @@ const longTextPpts = [
|
|||
<v-row>
|
||||
<InfoBase>
|
||||
<template v-slot:title>
|
||||
<v-checkbox v-model="auto_tmm" hide-details density="compact"
|
||||
:label="$t('torrent.properties.auto_tmm')" />
|
||||
<v-checkbox v-model="auto_tmm" hide-details density="compact" :label="$t('torrent.properties.auto_tmm')" />
|
||||
</template>
|
||||
</InfoBase>
|
||||
|
||||
<InfoBase>
|
||||
<template v-slot:title>
|
||||
<v-checkbox v-model="f_l_piece_prio" hide-details density="compact"
|
||||
:label="$t('torrent.properties.f_l_piece_prio')" />
|
||||
<v-checkbox v-model="f_l_piece_prio" hide-details density="compact" :label="$t('torrent.properties.f_l_piece_prio')" />
|
||||
</template>
|
||||
</InfoBase>
|
||||
|
||||
<InfoBase>
|
||||
<template v-slot:title>
|
||||
<v-checkbox v-model="forced" hide-details density="compact"
|
||||
:label="$t('torrent.properties.forced')" />
|
||||
<v-checkbox v-model="forced" hide-details density="compact" :label="$t('torrent.properties.forced')" />
|
||||
</template>
|
||||
</InfoBase>
|
||||
|
||||
<InfoBase>
|
||||
<template v-slot:title>
|
||||
<v-checkbox v-model="seq_dl" hide-details density="compact"
|
||||
:label="$t('torrent.properties.seq_dl')" />
|
||||
<v-checkbox v-model="seq_dl" hide-details density="compact" :label="$t('torrent.properties.seq_dl')" />
|
||||
</template>
|
||||
</InfoBase>
|
||||
|
||||
<InfoBase>
|
||||
<template v-slot:title>
|
||||
<v-checkbox v-model="super_seeding" hide-details density="compact"
|
||||
:label="$t('torrent.properties.super_seeding')" />
|
||||
<v-checkbox v-model="super_seeding" hide-details density="compact" :label="$t('torrent.properties.super_seeding')" />
|
||||
</template>
|
||||
</InfoBase>
|
||||
</v-row>
|
||||
|
@ -179,7 +174,7 @@ const longTextPpts = [
|
|||
<v-expansion-panel-text>
|
||||
<v-row>
|
||||
<InfoBase v-for="ppt in dataPpts">
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ ppt.title }`) }}</template>
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
|
||||
<template v-slot:text>{{ formatData(torrent[ppt.text], vuetorrentStore.useBinarySize) }}</template>
|
||||
</InfoBase>
|
||||
</v-row>
|
||||
|
@ -190,7 +185,7 @@ const longTextPpts = [
|
|||
<v-expansion-panel-text>
|
||||
<v-row>
|
||||
<InfoBase v-for="ppt in speedPpts">
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ ppt.title }`) }}</template>
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
|
||||
<template v-slot:text>{{ formatSpeed(torrent[ppt.text], vuetorrentStore.useBitSpeed) }}</template>
|
||||
</InfoBase>
|
||||
</v-row>
|
||||
|
@ -201,7 +196,7 @@ const longTextPpts = [
|
|||
<v-expansion-panel-text>
|
||||
<v-row>
|
||||
<InfoBase v-for="ppt in textPpts">
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ ppt.title }`) }}</template>
|
||||
<template v-slot:title>{{ $t(`torrent.properties.${ppt.title}`) }}</template>
|
||||
<template v-slot:text>{{ torrent[ppt.text] }}</template>
|
||||
</InfoBase>
|
||||
</v-row>
|
||||
|
|
|
@ -2,16 +2,7 @@
|
|||
import MoveTorrentDialog from '@/components/Dialogs/MoveTorrentDialog.vue'
|
||||
import MoveTorrentFileDialog from '@/components/Dialogs/MoveTorrentFileDialog.vue'
|
||||
import { FilePriority, PieceState, TorrentState } from '@/constants/qbit'
|
||||
import {
|
||||
formatData,
|
||||
formatDataUnit,
|
||||
formatDataValue,
|
||||
formatPercent,
|
||||
formatSpeed,
|
||||
getDomainBody,
|
||||
splitByUrl,
|
||||
stringContainsUrl
|
||||
} from '@/helpers'
|
||||
import { formatData, formatDataUnit, formatDataValue, formatPercent, formatSpeed, getDomainBody, splitByUrl, stringContainsUrl } from '@/helpers'
|
||||
import { useDialogStore, useMaindataStore, useTorrentStore, useVueTorrentStore } from '@/stores'
|
||||
import { TorrentFile } from '@/types/qbit/models'
|
||||
import { Torrent } from '@/types/vuetorrent'
|
||||
|
@ -42,8 +33,8 @@ const torrentPieceOwned = ref(0)
|
|||
const torrentPieceCount = ref(0)
|
||||
const uploadSpeedAvg = ref(0)
|
||||
|
||||
const torrentStateColor = computed(() => `torrent-${ props.torrent.state }`)
|
||||
const pieceSize = computed(() => `${ parseInt(formatDataValue(torrentPieceSize.value, true)) } ${ formatDataUnit(torrentPieceSize.value, true) }`)
|
||||
const torrentStateColor = computed(() => `torrent-${props.torrent.state}`)
|
||||
const pieceSize = computed(() => `${parseInt(formatDataValue(torrentPieceSize.value, true))} ${formatDataUnit(torrentPieceSize.value, true)}`)
|
||||
const isFetchingMetadata = computed(() => props.torrent.state === TorrentState.META_DL)
|
||||
const shouldRenderPieceState = computed(() => !isFetchingMetadata.value && torrentPieceCount.value > 0 && torrentPieceCount.value < vuetorrentStore.canvasRenderThreshold)
|
||||
const shouldRefreshPieceState = computed(() => shouldRenderPieceState.value && torrentPieceCount.value < vuetorrentStore.canvasRefreshThreshold)
|
||||
|
@ -138,15 +129,19 @@ function openMoveTorrentFileDialog() {
|
|||
})
|
||||
}
|
||||
|
||||
const { resume: resumeTimer, pause: pauseTimer } = useIntervalFn(async () => {
|
||||
await updateTorrentFiles()
|
||||
if (shouldRefreshPieceState.value) {
|
||||
await renderTorrentPieceStates()
|
||||
const { resume: resumeTimer, pause: pauseTimer } = useIntervalFn(
|
||||
async () => {
|
||||
await updateTorrentFiles()
|
||||
if (shouldRefreshPieceState.value) {
|
||||
await renderTorrentPieceStates()
|
||||
}
|
||||
},
|
||||
vuetorrentStore.fileContentInterval,
|
||||
{
|
||||
immediate: true,
|
||||
immediateCallback: true
|
||||
}
|
||||
}, vuetorrentStore.fileContentInterval, {
|
||||
immediate: true,
|
||||
immediateCallback: true
|
||||
})
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.isActive,
|
||||
|
@ -217,8 +212,7 @@ onUnmounted(() => {
|
|||
<v-col cols="12" md="6">
|
||||
<v-row>
|
||||
<v-col cols="4">
|
||||
<v-progress-circular :color="torrentStateColor" :indeterminate="isFetchingMetadata" :size="100"
|
||||
:model-value="torrent?.progress * 100 ?? 0" :width="15">
|
||||
<v-progress-circular :color="torrentStateColor" :indeterminate="isFetchingMetadata" :size="100" :model-value="torrent?.progress * 100 ?? 0" :width="15">
|
||||
<template v-slot>
|
||||
<span v-if="isFetchingMetadata">{{ $t('torrentDetail.overview.fetchingMetadata') }}</span>
|
||||
<v-icon v-else-if="torrent.progress === 1" icon="mdi-check" size="x-large" />
|
||||
|
@ -273,8 +267,7 @@ onUnmounted(() => {
|
|||
<div>{{ $t('torrentDetail.overview.fileCount') }}:</div>
|
||||
<div>{{ selectedFileCount }} / {{ torrentFileCount }}</div>
|
||||
<div v-if="selectedFileCount === 1">{{ torrentFileName }}</div>
|
||||
<v-btn v-if="selectedFileCount === 1" icon="mdi-pencil" color="accent" size="x-small"
|
||||
@click="openMoveTorrentFileDialog" />
|
||||
<v-btn v-if="selectedFileCount === 1" icon="mdi-pencil" color="accent" size="x-small" @click="openMoveTorrentFileDialog" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
@ -295,7 +288,7 @@ onUnmounted(() => {
|
|||
<v-row>
|
||||
<v-col cols="6">
|
||||
<div>{{ $t('torrent.properties.state') }}:</div>
|
||||
<v-chip variant="flat" :color="torrentStateColor">{{ $t(`torrent.state.${ torrent.state }`) }}</v-chip>
|
||||
<v-chip variant="flat" :color="torrentStateColor">{{ $t(`torrent.state.${torrent.state}`) }}</v-chip>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<div>{{ $t('torrent.properties.category') }}:</div>
|
||||
|
|
|
@ -72,8 +72,7 @@ watch(() => props.isActive, setupTimer)
|
|||
<div>
|
||||
<v-list-item-title class="overflow-visible text-select">
|
||||
<span v-if="peer.country_code">
|
||||
<img v-if="isWindows" :alt="codeToFlag(peer.country_code).char" :src="codeToFlag(peer.country_code).url"
|
||||
:title="peer.country" style="max-width: 32px" />
|
||||
<img v-if="isWindows" :alt="codeToFlag(peer.country_code).char" :src="codeToFlag(peer.country_code).url" :title="peer.country" style="max-width: 32px" />
|
||||
<span v-else :title="peer.country">{{ codeToFlag(peer.country_code).char }}</span>
|
||||
</span>
|
||||
<span>{{ peer.ip }}</span>
|
||||
|
|
|
@ -162,8 +162,7 @@ watch(() => props.isActive, setupTimer)
|
|||
|
||||
<v-card-text>
|
||||
<v-form v-model="editTrackerDialog.isFormValid" @submit.prevent>
|
||||
<v-text-field :model-value="editTrackerDialog.oldUrl" disabled
|
||||
:label="$t('torrentDetail.trackers.editTracker.oldUrl')" />
|
||||
<v-text-field :model-value="editTrackerDialog.oldUrl" disabled :label="$t('torrentDetail.trackers.editTracker.oldUrl')" />
|
||||
<v-text-field
|
||||
v-model="editTrackerDialog.newUrl"
|
||||
id="input"
|
||||
|
@ -176,9 +175,7 @@ watch(() => props.isActive, setupTimer)
|
|||
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn color="error" :disabled="!editTrackerDialog.isFormValid"
|
||||
@click="editTrackerDialog.isVisible = false">{{ t('common.cancel') }}
|
||||
</v-btn>
|
||||
<v-btn color="error" :disabled="!editTrackerDialog.isFormValid" @click="editTrackerDialog.isVisible = false">{{ t('common.cancel') }} </v-btn>
|
||||
<v-btn color="accent" @click="editTracker">{{ t('common.ok') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
@ -221,8 +218,7 @@ watch(() => props.isActive, setupTimer)
|
|||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-btn variant="flat" :disabled="torrentTrackers.length === 3" :text="t('torrentDetail.trackers.reannounce')"
|
||||
color="primary" @click="reannounceTrackers" />
|
||||
<v-btn variant="flat" :disabled="torrentTrackers.length === 3" :text="t('torrentDetail.trackers.reannounce')" color="primary" @click="reannounceTrackers" />
|
||||
</div>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
|
|
@ -2,18 +2,10 @@ import { useOffsetPagination } from '@vueuse/core'
|
|||
import { computed, MaybeRef, MaybeRefOrGetter, toValue } from 'vue'
|
||||
|
||||
export function useArrayPagination<T>(items: MaybeRefOrGetter<T[]>, pageSize: MaybeRefOrGetter<number>, page: MaybeRef<number> = 1) {
|
||||
const {
|
||||
currentPage,
|
||||
currentPageSize,
|
||||
pageCount,
|
||||
isFirstPage,
|
||||
isLastPage,
|
||||
next,
|
||||
prev,
|
||||
} = useOffsetPagination({
|
||||
const { currentPage, currentPageSize, pageCount, isFirstPage, isLastPage, next, prev } = useOffsetPagination({
|
||||
total: () => toValue(items).length,
|
||||
page,
|
||||
pageSize: () => toValue(pageSize) === -1 ? toValue(items).length : toValue(pageSize),
|
||||
pageSize: () => (toValue(pageSize) === -1 ? toValue(items).length : toValue(pageSize))
|
||||
})
|
||||
|
||||
const paginatedResults = computed(() => {
|
||||
|
@ -32,4 +24,4 @@ export function useArrayPagination<T>(items: MaybeRefOrGetter<T[]>, pageSize: Ma
|
|||
prev,
|
||||
paginatedResults
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ export function useTorrentBuilder() {
|
|||
seq_dl: data.seq_dl,
|
||||
size: data.size,
|
||||
state: data.state,
|
||||
stateString: t(`torrent.state.${ data.state }`),
|
||||
stateString: t(`torrent.state.${data.state}`),
|
||||
super_seeding: data.super_seeding,
|
||||
tags: data.tags.length > 0 ? data.tags.split(', ').map(t => t.trim()) : [],
|
||||
time_active: data.time_active,
|
||||
|
@ -97,7 +97,7 @@ export function useTorrentBuilder() {
|
|||
infohash_v2: data.infohash_v2 || faker.string.uuid(),
|
||||
last_activity: data.last_activity || faker.number.int({ min: 0, max: 50 }),
|
||||
magnet: data.magnet_uri || faker.internet.url(),
|
||||
name: data.name || `Torrent ${ index + 1 }`,
|
||||
name: data.name || `Torrent ${index + 1}`,
|
||||
num_leechs: data.num_leechs || faker.number.int(available_peers),
|
||||
num_seeds: data.num_seeds || faker.number.int(available_seeds),
|
||||
priority: data.priority || FilePriority.NORMAL,
|
||||
|
@ -111,7 +111,7 @@ export function useTorrentBuilder() {
|
|||
seq_dl: data.seq_dl || faker.datatype.boolean(),
|
||||
size: data.size || faker.number.int({ min: 1000, max: total_size }),
|
||||
state,
|
||||
stateString: t(`torrent.state.${ state }`),
|
||||
stateString: t(`torrent.state.${state}`),
|
||||
super_seeding: data.super_seeding || faker.datatype.boolean(),
|
||||
tags: data.tags || '',
|
||||
time_active: data.time_active || faker.number.int({ min: 1000, max: 900000 }),
|
||||
|
@ -133,8 +133,8 @@ export function useTorrentBuilder() {
|
|||
// @ts-expect-error: Type is missing the following properties from type 'Torrent': ...
|
||||
return Object.freeze({
|
||||
...data,
|
||||
avgDownloadSpeed: data.downloaded / ((dlDuration == 0) ? -1 : dlDuration),
|
||||
avgUploadSpeed: data.uploaded / ((ulDuration == 0) ? -1 : ulDuration),
|
||||
avgDownloadSpeed: data.downloaded / (dlDuration == 0 ? -1 : dlDuration),
|
||||
avgUploadSpeed: data.uploaded / (ulDuration == 0 ? -1 : ulDuration),
|
||||
globalSpeed: data.dlspeed + data.upspeed,
|
||||
globalVolume: data.downloaded + data.uploaded
|
||||
})
|
||||
|
|
|
@ -13,4 +13,4 @@ export enum FilterState {
|
|||
CHECKING = 'checking',
|
||||
MOVING = 'moving',
|
||||
ERRORED = 'errored'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export enum TorrentOperatingMode {
|
||||
AUTO_MANAGED = 'AutoManaged',
|
||||
FORCED = 'Forced'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,4 @@ import { TorrentOperatingMode } from './TorrentOperatingMode'
|
|||
import { TorrentState } from './TorrentState'
|
||||
import { TrackerStatus } from './TrackerStatus'
|
||||
|
||||
export {
|
||||
AppPreferences,
|
||||
ConnectionStatus,
|
||||
FilterState,
|
||||
LogType,
|
||||
PieceState,
|
||||
FilePriority,
|
||||
SortOptions,
|
||||
TrackerStatus,
|
||||
TorrentOperatingMode,
|
||||
TorrentState
|
||||
}
|
||||
export { AppPreferences, ConnectionStatus, FilterState, LogType, PieceState, FilePriority, SortOptions, TrackerStatus, TorrentOperatingMode, TorrentState }
|
||||
|
|
|
@ -2,4 +2,4 @@ export enum HistoryKey {
|
|||
COOKIE = 'cookie',
|
||||
SEARCH_ENGINE_QUERY = 'searchEngineQuery',
|
||||
TORRENT_PATH = 'torrentPath'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,4 +3,4 @@ export enum TitleOptions {
|
|||
GLOBAL_SPEED,
|
||||
FIRST_TORRENT_STATUS,
|
||||
CUSTOM
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
import {
|
||||
capitalize,
|
||||
codeToFlag,
|
||||
extractHostname,
|
||||
getDomainBody,
|
||||
splitByUrl,
|
||||
stringContainsUrl,
|
||||
titleCase,
|
||||
uuidFromRaw
|
||||
} from './text'
|
||||
import { capitalize, codeToFlag, extractHostname, getDomainBody, splitByUrl, stringContainsUrl, titleCase, uuidFromRaw } from './text'
|
||||
import { expect, test } from 'vitest'
|
||||
|
||||
test('helpers/text/titleCase', () => {
|
||||
|
@ -81,7 +72,7 @@ test('helpers/text/codeToFlag', () => {
|
|||
test('helpers/text/uuidFromRaw', () => {
|
||||
expect(uuidFromRaw(0n)).toBe('00000000-0000-0000-0000-000000000000')
|
||||
expect(uuidFromRaw(1n)).toBe('00000000-0000-0000-0000-000000000001')
|
||||
expect(uuidFromRaw(0xAAAAAn)).toBe('00000000-0000-0000-0000-0000000aaaaa')
|
||||
expect(uuidFromRaw(0x00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn)).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff')
|
||||
expect(uuidFromRaw(0xABCDEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFn)).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff')
|
||||
expect(uuidFromRaw(0xaaaaan)).toBe('00000000-0000-0000-0000-0000000aaaaa')
|
||||
expect(uuidFromRaw(0x00000ffffffffffffffffffffffffffffffffn)).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff')
|
||||
expect(uuidFromRaw(0xabcdeffffffffffffffffffffffffffffffffn)).toBe('ffffffff-ffff-ffff-ffff-ffffffffffff')
|
||||
})
|
||||
|
|
|
@ -85,6 +85,6 @@ export function codeToFlag(code: string) {
|
|||
}
|
||||
|
||||
export function uuidFromRaw(bits: bigint) {
|
||||
let bitString = bits.toString(16).slice(-32).padStart(32, "0");
|
||||
return `${bitString.slice(-32, -24)}-${bitString.slice(-24, -20)}-${bitString.slice(-20, -16)}-${bitString.slice(-16, -12)}-${bitString.slice(-12)}`;
|
||||
let bitString = bits.toString(16).slice(-32).padStart(32, '0')
|
||||
return `${bitString.slice(-32, -24)}-${bitString.slice(-24, -20)}-${bitString.slice(-20, -16)}-${bitString.slice(-16, -12)}-${bitString.slice(-12)}`
|
||||
}
|
||||
|
|
1190
src/locales/en.json
1190
src/locales/en.json
File diff suppressed because it is too large
Load diff
1103
src/locales/fr.json
1103
src/locales/fr.json
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
|||
import en from './en.json'
|
||||
import fr from './fr.json'
|
||||
import nl from './nl.json'
|
||||
import ru from './ru.json'
|
||||
import zh_hans from './zh-Hans.json'
|
||||
import zh_hant from './zh-Hant.json'
|
||||
|
@ -12,6 +13,7 @@ type LocaleDef = {
|
|||
export enum Locales {
|
||||
EN = 'en',
|
||||
FR = 'fr',
|
||||
NL = 'nl',
|
||||
RU = 'ru',
|
||||
ZH_HANS = 'zh-Hans',
|
||||
ZH_HANT = 'zh-Hant'
|
||||
|
@ -20,6 +22,7 @@ export enum Locales {
|
|||
export const LOCALES: LocaleDef[] = [
|
||||
{ title: 'English', value: Locales.EN },
|
||||
{ title: 'Français', value: Locales.FR },
|
||||
{ title: 'Nederlands', value: Locales.NL },
|
||||
{ title: 'Русский', value: Locales.RU },
|
||||
{ title: '简体中文', value: Locales.ZH_HANS },
|
||||
{ title: '繁體中文', value: Locales.ZH_HANT }
|
||||
|
@ -28,6 +31,7 @@ export const LOCALES: LocaleDef[] = [
|
|||
export const messages: Record<Locales, any> = {
|
||||
[Locales.EN]: en,
|
||||
[Locales.FR]: fr,
|
||||
[Locales.NL]: nl,
|
||||
[Locales.RU]: ru,
|
||||
[Locales.ZH_HANS]: zh_hans,
|
||||
[Locales.ZH_HANT]: zh_hant
|
||||
|
|
20
src/locales/nl.json
Normal file
20
src/locales/nl.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"common": {
|
||||
"cancel": "Annuleren",
|
||||
"close": "Sluiten",
|
||||
"delete": "Verwijderen",
|
||||
"disable": "Uitschakelen",
|
||||
"emptyList": "Niets te zien hier!",
|
||||
"none": "(Geen)",
|
||||
"save": "Opslaan",
|
||||
"selectAll": "Alles selecteren"
|
||||
},
|
||||
"constants": {
|
||||
"bittorrentProtocols": {
|
||||
"tcp_utp": "TCP en μTP"
|
||||
},
|
||||
"connectionStatus": {
|
||||
"connected": "Verbonden"
|
||||
}
|
||||
}
|
||||
}
|
1075
src/locales/ru.json
1075
src/locales/ru.json
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -16,12 +16,7 @@ import { useDisplay } from 'vuetify'
|
|||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const display = useDisplay()
|
||||
const {
|
||||
currentPage: dashboardPage,
|
||||
isSelectionMultiple,
|
||||
selectedTorrents,
|
||||
torrentCountString
|
||||
} = storeToRefs(useDashboardStore())
|
||||
const { currentPage: dashboardPage, isSelectionMultiple, selectedTorrents, torrentCountString } = storeToRefs(useDashboardStore())
|
||||
const dashboardStore = useDashboardStore()
|
||||
const dialogStore = useDialogStore()
|
||||
const maindataStore = useMaindataStore()
|
||||
|
@ -99,11 +94,7 @@ const torrentTitleFilter = computed({
|
|||
}, 300)
|
||||
})
|
||||
|
||||
const {
|
||||
paginatedResults: paginatedTorrents,
|
||||
currentPage,
|
||||
pageCount
|
||||
} = useArrayPagination(filteredTorrents, vuetorrentStore.paginationSize, dashboardPage)
|
||||
const { paginatedResults: paginatedTorrents, currentPage, pageCount } = useArrayPagination(filteredTorrents, vuetorrentStore.paginationSize, dashboardPage)
|
||||
const hasSearchFilter = computed(() => !!torrentStore.textFilter && torrentStore.textFilter.length > 0)
|
||||
|
||||
const isAllTorrentsSelected = computed(() => filteredTorrents.value.length <= selectedTorrents.value.length)
|
||||
|
@ -272,32 +263,49 @@ function endPress() {
|
|||
<v-row class="ma-0 pa-0 mb-2">
|
||||
<v-expand-x-transition>
|
||||
<v-card v-show="isSearchFilterVisible" color="transparent">
|
||||
<v-text-field id="searchInput" v-model="torrentTitleFilter" :label="t('dashboard.searchInputLabel')" clearable
|
||||
density="compact" hide-details prepend-inner-icon="mdi-magnify" rounded="pill" single-line
|
||||
style="width: 200px" variant="solo" @click:clear="resetInput()" />
|
||||
<v-text-field
|
||||
id="searchInput"
|
||||
v-model="torrentTitleFilter"
|
||||
:label="t('dashboard.searchInputLabel')"
|
||||
clearable
|
||||
density="compact"
|
||||
hide-details
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
rounded="pill"
|
||||
single-line
|
||||
style="width: 200px"
|
||||
variant="solo"
|
||||
@click:clear="resetInput()" />
|
||||
</v-card>
|
||||
</v-expand-x-transition>
|
||||
<v-tooltip :text="t('dashboard.toggleSearchFilter')" location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn :icon="isSearchFilterVisible ? 'mdi-chevron-left-circle' : 'mdi-text-box-search'" v-bind="props"
|
||||
variant="plain" @click="toggleSearchFilter()" />
|
||||
<v-btn :icon="isSearchFilterVisible ? 'mdi-chevron-left-circle' : 'mdi-text-box-search'" v-bind="props" variant="plain" @click="toggleSearchFilter()" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip :text="t('dashboard.toggleSelectMode')" location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn :icon="isSelectionMultiple ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'" v-bind="props"
|
||||
variant="plain" @click="toggleSelectMode" />
|
||||
<v-btn :icon="isSelectionMultiple ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'" v-bind="props" variant="plain" @click="toggleSelectMode" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<v-tooltip :text="t('dashboard.toggleSortOrder')" location="top">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn :icon="sortOptions.reverseOrder ? 'mdi-arrow-up-thin' : 'mdi-arrow-down-thin'" v-bind="props"
|
||||
variant="plain" @click="sortOptions.reverseOrder = !sortOptions.reverseOrder" />
|
||||
<v-btn
|
||||
:icon="sortOptions.reverseOrder ? 'mdi-arrow-up-thin' : 'mdi-arrow-down-thin'"
|
||||
v-bind="props"
|
||||
variant="plain"
|
||||
@click="sortOptions.reverseOrder = !sortOptions.reverseOrder" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<div class="pa-0" style="width: 10em">
|
||||
<v-autocomplete v-model="sortOptions.sortBy" :items="torrentSortOptions" :label="t('dashboard.sortLabel')"
|
||||
auto-select-first density="compact" hide-details variant="solo-filled" />
|
||||
<v-autocomplete
|
||||
v-model="sortOptions.sortBy"
|
||||
:items="torrentSortOptions"
|
||||
:label="t('dashboard.sortLabel')"
|
||||
auto-select-first
|
||||
density="compact"
|
||||
hide-details
|
||||
variant="solo-filled" />
|
||||
</div>
|
||||
<v-col class="align-center justify-center">
|
||||
<span class="text-uppercase" style="float: right; font-size: 0.8em">
|
||||
|
@ -310,8 +318,13 @@ function endPress() {
|
|||
<v-card v-show="isSelectionMultiple" color="transparent">
|
||||
<v-tooltip :text="t('common.selectAll')" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn :icon="isAllTorrentsSelected ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'"
|
||||
class="text-grey" color="transparent" style="left: -8px" v-bind="props" @click="toggleSelectAll" />
|
||||
<v-btn
|
||||
:icon="isAllTorrentsSelected ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'"
|
||||
class="text-grey"
|
||||
color="transparent"
|
||||
style="left: -8px"
|
||||
v-bind="props"
|
||||
@click="toggleSelectAll" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<span class="text-grey">{{ t('dashboard.selectAll') }}</span>
|
||||
|
@ -324,21 +337,28 @@ function endPress() {
|
|||
<div v-else>
|
||||
<v-list id="torrentList" class="pa-0" color="transparent">
|
||||
<v-list-item v-if="vuetorrentStore.isPaginationOnTop && !vuetorrentStore.isInfiniteScrollActive">
|
||||
<v-pagination v-model="currentPage" :length="pageCount" next-icon="mdi-menu-right" prev-icon="mdi-menu-left"
|
||||
@input="scrollToTop" />
|
||||
<v-pagination v-model="currentPage" :length="pageCount" next-icon="mdi-menu-right" prev-icon="mdi-menu-left" @input="scrollToTop" />
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item v-for="torrent in paginatedTorrents" :id="`torrent-${torrent.hash}`"
|
||||
:class="display.mobile ? 'mb-2' : 'mb-4'" class="pa-0" @contextmenu="onRightClick($event, torrent)"
|
||||
@touchcancel="endPress" @touchend="endPress" @touchmove="endPress"
|
||||
@touchstart="startPress($event, torrent)"
|
||||
@dblclick.prevent="goToInfo(torrent.hash)">
|
||||
<v-list-item
|
||||
v-for="torrent in paginatedTorrents"
|
||||
:id="`torrent-${torrent.hash}`"
|
||||
:class="display.mobile ? 'mb-2' : 'mb-4'"
|
||||
class="pa-0"
|
||||
@contextmenu="onRightClick($event, torrent)"
|
||||
@touchcancel="endPress"
|
||||
@touchend="endPress"
|
||||
@touchmove="endPress"
|
||||
@touchstart="startPress($event, torrent)"
|
||||
@dblclick.prevent="goToInfo(torrent.hash)">
|
||||
<div class="d-flex align-center">
|
||||
<v-expand-x-transition>
|
||||
<v-card v-show="isSelectionMultiple" class="mr-3" color="transparent">
|
||||
<v-btn
|
||||
:icon="dashboardStore.isTorrentInSelection(torrent.hash) ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline'"
|
||||
color="transparent" variant="flat" @click="toggleSelectTorrent(torrent.hash)" />
|
||||
color="transparent"
|
||||
variant="flat"
|
||||
@click="toggleSelectTorrent(torrent.hash)" />
|
||||
</v-card>
|
||||
</v-expand-x-transition>
|
||||
<Torrent :torrent="torrent" />
|
||||
|
@ -346,8 +366,7 @@ function endPress() {
|
|||
</v-list-item>
|
||||
|
||||
<v-list-item v-if="!vuetorrentStore.isPaginationOnTop && !vuetorrentStore.isInfiniteScrollActive">
|
||||
<v-pagination v-model="currentPage" :length="pageCount" next-icon="mdi-menu-right" prev-icon="mdi-menu-left"
|
||||
@input="scrollToTop" />
|
||||
<v-pagination v-model="currentPage" :length="pageCount" next-icon="mdi-menu-right" prev-icon="mdi-menu-left" @input="scrollToTop" />
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
|
|
|
@ -47,10 +47,7 @@ const redirectOnSuccess = () => {
|
|||
|
||||
onMounted(async () => {
|
||||
if (route.query.username && route.query.password) {
|
||||
await authStore.login(
|
||||
route.query.username as string,
|
||||
route.query.password as string
|
||||
)
|
||||
await authStore.login(route.query.username as string, route.query.password as string)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -68,8 +65,7 @@ watchEffect(() => {
|
|||
<v-card-subtitle>{{ t('login.subtitle') }}</v-card-subtitle>
|
||||
<v-card-text>
|
||||
<v-form v-model="rulesOk" @submit.prevent="login">
|
||||
<v-text-field v-model="loginForm.username" :label="t('login.username')" autofocus :rules="rules.username"
|
||||
@keydown.enter.prevent="login" variant="outlined">
|
||||
<v-text-field v-model="loginForm.username" :label="t('login.username')" autofocus :rules="rules.username" @keydown.enter.prevent="login" variant="outlined">
|
||||
<template v-slot:prepend>
|
||||
<v-icon color="accent" icon="mdi-account" />
|
||||
</template>
|
||||
|
|
|
@ -41,7 +41,7 @@ const goHome = () => {
|
|||
router.push({ name: 'dashboard' })
|
||||
}
|
||||
const getLogTypeClassName = (log: Log) => {
|
||||
return `logtype-${ LogType[log?.type]?.toLowerCase() }`
|
||||
return `logtype-${LogType[log?.type]?.toLowerCase()}`
|
||||
}
|
||||
const getLogTypeName = (log: Log) => {
|
||||
return LogType[log.type]
|
||||
|
@ -91,13 +91,11 @@ onUnmounted(() => {
|
|||
<v-list-item>
|
||||
<v-row>
|
||||
<v-col cols="6">
|
||||
<v-select v-model="logTypeFilter" :items="logTypeOptions" :label="$t('logs.filters.type')" hide-details
|
||||
multiple chips>
|
||||
<v-select v-model="logTypeFilter" :items="logTypeOptions" :label="$t('logs.filters.type')" hide-details multiple chips>
|
||||
<template v-slot:prepend-item>
|
||||
<v-list-item :title="$t('common.selectAll')" @click="toggleSelectAll">
|
||||
<template v-slot:prepend>
|
||||
<v-checkbox-btn :indeterminate="someTypesSelected && !allTypesSelected"
|
||||
:model-value="someTypesSelected" />
|
||||
<v-checkbox-btn :indeterminate="someTypesSelected && !allTypesSelected" :model-value="someTypesSelected" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-divider />
|
||||
|
@ -106,8 +104,7 @@ onUnmounted(() => {
|
|||
</v-col>
|
||||
|
||||
<v-col cols="6">
|
||||
<v-select v-model="sortBy" :items="headers" :label="$t('logs.filters.sortBy.label')" hide-details multiple
|
||||
chips />
|
||||
<v-select v-model="sortBy" :items="headers" :label="$t('logs.filters.sortBy.label')" hide-details multiple chips />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-list-item>
|
||||
|
|
|
@ -17,4 +17,4 @@ onBeforeMount(async () => {
|
|||
}
|
||||
await router.push({ name: 'dashboard' })
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -90,7 +90,8 @@ onUnmounted(() => {
|
|||
<v-row align="center" justify="center" no-gutters>
|
||||
<v-col>
|
||||
<h1 class="subtitle-1 ml-2" style="font-size: 1.6em !important">
|
||||
{{ t('rssArticles.title') }} </h1>
|
||||
{{ t('rssArticles.title') }}
|
||||
</h1>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<div class="d-flex justify-end">
|
||||
|
@ -124,26 +125,16 @@ onUnmounted(() => {
|
|||
<template v-for="(article, index) in paginatedResults">
|
||||
<v-divider v-if="index > 0" color="white" />
|
||||
|
||||
<v-list-item :class="{ 'rss-read': article.isRead }" @click="showDescription(article)"
|
||||
@contextmenu="markAsRead(article)">
|
||||
<v-list-item :class="{ 'rss-read': article.isRead }" @click="showDescription(article)" @contextmenu="markAsRead(article)">
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<v-list-item-title class="wrap-anywhere" style="white-space: unset">{{
|
||||
article.title
|
||||
}}
|
||||
</v-list-item-title>
|
||||
<v-list-item-title class="wrap-anywhere" style="white-space: unset">{{ article.title }} </v-list-item-title>
|
||||
|
||||
<v-list-item-subtitle class="d-block">
|
||||
<div>{{ article.parsedDate.toLocaleString() }}</div>
|
||||
<div>{{
|
||||
t('rssArticles.item.feedName', { name: rssStore.getFeedNames(article.id).join(' | ') })
|
||||
}}
|
||||
</div>
|
||||
<div>{{ t('rssArticles.item.feedName', { name: rssStore.getFeedNames(article.id).join(' | ') }) }}</div>
|
||||
<div v-if="article.author">{{ t('rssArticles.item.author', { author: article.author }) }}</div>
|
||||
<div v-if="article.category">{{
|
||||
t('rssArticles.item.category', { category: article.category })
|
||||
}}
|
||||
</div>
|
||||
<div v-if="article.category">{{ t('rssArticles.item.category', { category: article.category }) }}</div>
|
||||
</v-list-item-subtitle>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -53,10 +53,10 @@ const plugins = computed(() => {
|
|||
]
|
||||
|
||||
searchEngineStore.searchPlugins
|
||||
.filter((plugin: SearchPlugin) => plugin.enabled)
|
||||
.forEach((plugin: SearchPlugin) => {
|
||||
plugins.push({ title: plugin.name, value: plugin.name })
|
||||
})
|
||||
.filter((plugin: SearchPlugin) => plugin.enabled)
|
||||
.forEach((plugin: SearchPlugin) => {
|
||||
plugins.push({ title: plugin.name, value: plugin.name })
|
||||
})
|
||||
|
||||
return plugins
|
||||
})
|
||||
|
@ -173,8 +173,7 @@ onBeforeUnmount(() => {
|
|||
<v-spacer />
|
||||
|
||||
<v-btn icon="mdi-plus-circle-outline" variant="plain" color="accent" @click="createNewTab" />
|
||||
<v-btn icon="mdi-minus-circle-outline" variant="plain" color="error" :disabled="searchData.length === 1"
|
||||
@click="deleteTab" />
|
||||
<v-btn icon="mdi-minus-circle-outline" variant="plain" color="error" :disabled="searchData.length === 1" @click="deleteTab" />
|
||||
</v-container>
|
||||
</v-row>
|
||||
|
||||
|
@ -182,9 +181,16 @@ onBeforeUnmount(() => {
|
|||
<v-list-item>
|
||||
<v-row class="mt-1">
|
||||
<v-col cols="12" md="6">
|
||||
<HistoryField v-model="selectedTab.query" :history-key="HistoryKey.SEARCH_ENGINE_QUERY" ref="queryInput"
|
||||
autofocus density="compact" hide-details clearable
|
||||
:label="$t('searchEngine.query')" @keydown.enter.prevent="runNewSearch" />
|
||||
<HistoryField
|
||||
v-model="selectedTab.query"
|
||||
:history-key="HistoryKey.SEARCH_ENGINE_QUERY"
|
||||
ref="queryInput"
|
||||
autofocus
|
||||
density="compact"
|
||||
hide-details
|
||||
clearable
|
||||
:label="$t('searchEngine.query')"
|
||||
@keydown.enter.prevent="runNewSearch" />
|
||||
</v-col>
|
||||
|
||||
<v-col cols="6" sm="5" md="2">
|
||||
|
@ -222,14 +228,11 @@ onBeforeUnmount(() => {
|
|||
<v-divider class="my-3" />
|
||||
|
||||
<v-list-item>
|
||||
<v-data-table :headers="headers" :items="filteredResults"
|
||||
:footer-props="{ itemsPerPageOptions: [10, 25, 50, 100, -1] }"
|
||||
:items-per-page.sync="selectedTab.itemsPerPage">
|
||||
<v-data-table :headers="headers" :items="filteredResults" :footer-props="{ itemsPerPageOptions: [10, 25, 50, 100, -1] }" :items-per-page.sync="selectedTab.itemsPerPage">
|
||||
<template v-slot:top>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-text-field v-model="selectedTab.filters.title" density="compact" hide-details
|
||||
:label="$t('searchEngine.filters.title.label')" />
|
||||
<v-text-field v-model="selectedTab.filters.title" density="compact" hide-details :label="$t('searchEngine.filters.title.label')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
|
|
@ -101,7 +101,6 @@ watchEffect(() => {
|
|||
onMounted(() => {
|
||||
document.addEventListener('keydown', handleKeyboardShortcut)
|
||||
updateTabHandle()
|
||||
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('keydown', handleKeyboardShortcut)
|
||||
|
@ -126,15 +125,14 @@ onBeforeUnmount(() => {
|
|||
|
||||
<v-row class="ma-0 pa-0">
|
||||
<v-tabs v-model="tab" bg-color="primary" grow show-arrows>
|
||||
<v-tab v-for="{text, value} in tabs" :key="value" :value="value" :href="`#/settings/${value}`" :text="text" />
|
||||
<v-tab v-for="{ text, value } in tabs" :key="value" :value="value" :href="`#/settings/${value}`" :text="text" />
|
||||
</v-tabs>
|
||||
</v-row>
|
||||
|
||||
<v-window v-model="tab" :touch="false">
|
||||
<v-window-item value="vuetorrent">
|
||||
<v-tabs v-model="innerTabV" grow color="accent" show-arrows>
|
||||
<v-tab v-for="{text, value} in tabsV" :value="value" :text="text"
|
||||
:href="`#/settings/vuetorrent/${value}`" :class="{ 'text-accent': innerTabV === value }" />
|
||||
<v-tab v-for="{ text, value } in tabsV" :value="value" :text="text" :href="`#/settings/vuetorrent/${value}`" :class="{ 'text-accent': innerTabV === value }" />
|
||||
<!-- the class attribute is a workaround for https://github.com/vuetifyjs/vuetify/issues/18756 -->
|
||||
</v-tabs>
|
||||
|
||||
|
@ -170,8 +168,7 @@ onBeforeUnmount(() => {
|
|||
|
||||
<v-window-item value="rss">
|
||||
<v-tabs v-model="innerTabR" grow color="accent" bg-color="transparent">
|
||||
<v-tab v-for="{text, value} in tabsR" :key="value" :value="value" :text="text"
|
||||
:href="`#/settings/rss/${value}`" :class="{ 'text-accent': innerTabR === value }" />
|
||||
<v-tab v-for="{ text, value } in tabsR" :key="value" :value="value" :text="text" :href="`#/settings/rss/${value}`" :class="{ 'text-accent': innerTabR === value }" />
|
||||
<!-- the class attribute is a workaround for https://github.com/vuetifyjs/vuetify/issues/18756 -->
|
||||
</v-tabs>
|
||||
<v-window v-model="innerTabR" :touch="false">
|
||||
|
|
|
@ -2,7 +2,6 @@ import { routes } from '@/pages'
|
|||
import { useAuthStore } from '@/stores'
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(process.env.BASE_URL),
|
||||
routes
|
||||
|
|
|
@ -91,7 +91,27 @@ export default createVuetify({
|
|||
theme: {
|
||||
defaultTheme: Theme.LIGHT,
|
||||
variations: {
|
||||
colors: ['torrent-error', 'torrent-missingFiles', 'torrent-uploading', 'torrent-forcedUP', 'torrent-pausedUP', 'torrent-queuedUP', 'torrent-stalledUP', 'torrent-checkingUP', 'torrent-allocating', 'torrent-downloading', 'torrent-forcedDL', 'torrent-metaDL', 'torrent-pausedDL', 'torrent-queuedDL', 'torrent-stalledDL', 'torrent-checkingDL', 'torrent-checkingResumeData', 'torrent-moving', 'torrent-unknown'],
|
||||
colors: [
|
||||
'torrent-error',
|
||||
'torrent-missingFiles',
|
||||
'torrent-uploading',
|
||||
'torrent-forcedUP',
|
||||
'torrent-pausedUP',
|
||||
'torrent-queuedUP',
|
||||
'torrent-stalledUP',
|
||||
'torrent-checkingUP',
|
||||
'torrent-allocating',
|
||||
'torrent-downloading',
|
||||
'torrent-forcedDL',
|
||||
'torrent-metaDL',
|
||||
'torrent-pausedDL',
|
||||
'torrent-queuedDL',
|
||||
'torrent-stalledDL',
|
||||
'torrent-checkingDL',
|
||||
'torrent-checkingResumeData',
|
||||
'torrent-moving',
|
||||
'torrent-unknown'
|
||||
],
|
||||
lighten: 3,
|
||||
darken: 3
|
||||
},
|
||||
|
|
|
@ -3,7 +3,9 @@ import { AddTorrentPayload } from '@/types/qbit/payloads'
|
|||
import { defineStore } from 'pinia'
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
|
||||
export const useAddTorrentStore = defineStore('addTorrents', () => {
|
||||
export const useAddTorrentStore = defineStore(
|
||||
'addTorrents',
|
||||
() => {
|
||||
const preferenceStore = usePreferenceStore()
|
||||
|
||||
const isFirstInit = ref(true)
|
||||
|
@ -80,4 +82,5 @@ export const useAddTorrentStore = defineStore('addTorrents', () => {
|
|||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
|
|
|
@ -5,118 +5,117 @@ import { useI18n } from 'vue-i18n'
|
|||
import { useTorrentStore } from './torrents'
|
||||
import { useVueTorrentStore } from './vuetorrent'
|
||||
|
||||
export const useDashboardStore = defineStore(
|
||||
'dashboard',
|
||||
() => {
|
||||
const currentPage = ref(1)
|
||||
const isSelectionMultiple = ref(false)
|
||||
const selectedTorrents = ref<string[]>([])
|
||||
const latestSelectedTorrent = ref<string>()
|
||||
export const useDashboardStore = defineStore('dashboard', () => {
|
||||
const currentPage = ref(1)
|
||||
const isSelectionMultiple = ref(false)
|
||||
const selectedTorrents = ref<string[]>([])
|
||||
const latestSelectedTorrent = ref<string>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const torrentStore = useTorrentStore()
|
||||
const vuetorrentStore = useVueTorrentStore()
|
||||
const { t } = useI18n()
|
||||
const torrentStore = useTorrentStore()
|
||||
const vuetorrentStore = useVueTorrentStore()
|
||||
|
||||
const torrentCountString = computed(() => {
|
||||
if (selectedTorrents.value.length) {
|
||||
const selectedSize = selectedTorrents.value
|
||||
const torrentCountString = computed(() => {
|
||||
if (selectedTorrents.value.length) {
|
||||
const selectedSize = selectedTorrents.value
|
||||
.map(hash => torrentStore.getTorrentByHash(hash))
|
||||
.filter(torrent => torrent !== undefined)
|
||||
.map(torrent => torrent!.size)
|
||||
.reduce((partial, size) => partial + size, 0)
|
||||
|
||||
return t('dashboard.selectedTorrentsCount', {
|
||||
count: selectedTorrents.value.length,
|
||||
total: torrentStore.filteredTorrents.length,
|
||||
size: formatData(selectedSize, vuetorrentStore.useBinarySize)
|
||||
})
|
||||
} else {
|
||||
return t('dashboard.torrentsCount', torrentStore.filteredTorrents.length)
|
||||
}
|
||||
})
|
||||
return t('dashboard.selectedTorrentsCount', {
|
||||
count: selectedTorrents.value.length,
|
||||
total: torrentStore.filteredTorrents.length,
|
||||
size: formatData(selectedSize, vuetorrentStore.useBinarySize)
|
||||
})
|
||||
} else {
|
||||
return t('dashboard.torrentsCount', torrentStore.filteredTorrents.length)
|
||||
}
|
||||
})
|
||||
|
||||
function isTorrentInSelection(hash: string) {
|
||||
return selectedTorrents.value.includes(hash)
|
||||
function isTorrentInSelection(hash: string) {
|
||||
return selectedTorrents.value.includes(hash)
|
||||
}
|
||||
|
||||
function selectTorrent(hash: string) {
|
||||
if (!isTorrentInSelection(hash)) {
|
||||
selectedTorrents.value.push(hash)
|
||||
}
|
||||
|
||||
function selectTorrent(hash: string) {
|
||||
if (!isTorrentInSelection(hash)) {
|
||||
selectedTorrents.value.push(hash)
|
||||
}
|
||||
latestSelectedTorrent.value = hash
|
||||
}
|
||||
|
||||
latestSelectedTorrent.value = hash
|
||||
function selectTorrents(...hashes: string[]) {
|
||||
isSelectionMultiple.value = true
|
||||
hashes.forEach(selectTorrent)
|
||||
}
|
||||
|
||||
function unselectTorrent(hash: string) {
|
||||
const index = selectedTorrents.value.indexOf(hash)
|
||||
if (index >= 0) {
|
||||
selectedTorrents.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
function selectTorrents(...hashes: string[]) {
|
||||
isSelectionMultiple.value = true
|
||||
hashes.forEach(selectTorrent)
|
||||
function toggleSelect(hash: string) {
|
||||
if (isTorrentInSelection(hash)) {
|
||||
unselectTorrent(hash)
|
||||
} else {
|
||||
selectTorrent(hash)
|
||||
}
|
||||
}
|
||||
|
||||
function unselectTorrent(hash: string) {
|
||||
const index = selectedTorrents.value.indexOf(hash)
|
||||
if (index >= 0) {
|
||||
selectedTorrents.value.splice(index, 1)
|
||||
}
|
||||
function spanTorrentSelection(endHash: string) {
|
||||
if (!latestSelectedTorrent.value) return
|
||||
|
||||
const latestIndex = torrentStore.getTorrentIndexByHash(latestSelectedTorrent.value)
|
||||
const endIndex = torrentStore.getTorrentIndexByHash(endHash)
|
||||
|
||||
const start = Math.min(endIndex, latestIndex)
|
||||
const end = Math.max(endIndex, latestIndex)
|
||||
const hashes = torrentStore.filteredTorrents.slice(start, end + 1).map(t => t.hash)
|
||||
selectTorrents(...hashes)
|
||||
}
|
||||
|
||||
function selectAllTorrents() {
|
||||
isSelectionMultiple.value = true
|
||||
selectedTorrents.value.splice(0, selectedTorrents.value.length, ...torrentStore.torrents.map(t => t.hash))
|
||||
latestSelectedTorrent.value = torrentStore.torrents[0]?.hash
|
||||
}
|
||||
|
||||
function unselectAllTorrents() {
|
||||
selectedTorrents.value = []
|
||||
}
|
||||
|
||||
watch(selectedTorrents, newValue => {
|
||||
if (newValue.length === 0) {
|
||||
latestSelectedTorrent.value = undefined
|
||||
}
|
||||
})
|
||||
|
||||
function toggleSelect(hash: string) {
|
||||
if (isTorrentInSelection(hash)) {
|
||||
unselectTorrent(hash)
|
||||
} else {
|
||||
selectTorrent(hash)
|
||||
}
|
||||
}
|
||||
|
||||
function spanTorrentSelection(endHash: string) {
|
||||
if (!latestSelectedTorrent.value) return
|
||||
|
||||
const latestIndex = torrentStore.getTorrentIndexByHash(latestSelectedTorrent.value)
|
||||
const endIndex = torrentStore.getTorrentIndexByHash(endHash)
|
||||
|
||||
const start = Math.min(endIndex, latestIndex)
|
||||
const end = Math.max(endIndex, latestIndex)
|
||||
const hashes = torrentStore.filteredTorrents.slice(start, end + 1).map(t => t.hash)
|
||||
selectTorrents(...hashes)
|
||||
}
|
||||
|
||||
function selectAllTorrents() {
|
||||
isSelectionMultiple.value = true
|
||||
selectedTorrents.value.splice(0, selectedTorrents.value.length, ...torrentStore.torrents.map(t => t.hash))
|
||||
latestSelectedTorrent.value = torrentStore.torrents[0]?.hash
|
||||
}
|
||||
|
||||
function unselectAllTorrents() {
|
||||
selectedTorrents.value = []
|
||||
}
|
||||
|
||||
watch(selectedTorrents, newValue => {
|
||||
if (newValue.length === 0) {
|
||||
latestSelectedTorrent.value = undefined
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => torrentStore.filteredTorrents, newValue => {
|
||||
watch(
|
||||
() => torrentStore.filteredTorrents,
|
||||
newValue => {
|
||||
const pageCount = Math.ceil(newValue.length / vuetorrentStore.paginationSize)
|
||||
if (pageCount < currentPage.value) {
|
||||
currentPage.value = Math.max(1, pageCount)
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
currentPage,
|
||||
isSelectionMultiple,
|
||||
selectedTorrents,
|
||||
latestSelectedTorrent,
|
||||
torrentCountString,
|
||||
isTorrentInSelection,
|
||||
selectTorrent,
|
||||
selectTorrents,
|
||||
unselectTorrent,
|
||||
spanTorrentSelection,
|
||||
selectAllTorrents,
|
||||
unselectAllTorrents,
|
||||
toggleSelect
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
)
|
||||
return {
|
||||
currentPage,
|
||||
isSelectionMultiple,
|
||||
selectedTorrents,
|
||||
latestSelectedTorrent,
|
||||
torrentCountString,
|
||||
isTorrentInSelection,
|
||||
selectTorrent,
|
||||
selectTorrents,
|
||||
unselectTorrent,
|
||||
spanTorrentSelection,
|
||||
selectAllTorrents,
|
||||
unselectAllTorrents,
|
||||
toggleSelect
|
||||
}
|
||||
})
|
||||
|
|
|
@ -4,44 +4,48 @@ import { reactive, ref } from 'vue'
|
|||
|
||||
type History = Partial<Record<HistoryKey, string[]>>
|
||||
|
||||
export const useHistoryStore = defineStore('history', () => {
|
||||
const _history = reactive<History>({})
|
||||
const historySize = ref(3)
|
||||
export const useHistoryStore = defineStore(
|
||||
'history',
|
||||
() => {
|
||||
const _history = reactive<History>({})
|
||||
const historySize = ref(3)
|
||||
|
||||
function pushValueToHistory(key: HistoryKey, value: string) {
|
||||
const historyValue = getHistory(key)
|
||||
historyValue.splice(0, 0, value)
|
||||
function pushValueToHistory(key: HistoryKey, value: string) {
|
||||
const historyValue = getHistory(key)
|
||||
historyValue.splice(0, 0, value)
|
||||
|
||||
const valueIndex = historyValue.indexOf(value, 1)
|
||||
if (valueIndex !== -1) {
|
||||
historyValue.splice(valueIndex, 1)
|
||||
}
|
||||
|
||||
if (historyValue.length > historySize.value) {
|
||||
historyValue.splice(historySize.value, historyValue.length - historySize.value)
|
||||
}
|
||||
|
||||
_history[key] = historyValue
|
||||
}
|
||||
|
||||
function getHistory(key: HistoryKey) {
|
||||
return _history[key] || []
|
||||
}
|
||||
|
||||
return {
|
||||
_history,
|
||||
historySize,
|
||||
pushValueToHistory,
|
||||
getHistory
|
||||
}
|
||||
}, {
|
||||
persist: {
|
||||
enabled: true,
|
||||
strategies: [
|
||||
{
|
||||
storage: localStorage,
|
||||
key: 'vuetorrent_history'
|
||||
const valueIndex = historyValue.indexOf(value, 1)
|
||||
if (valueIndex !== -1) {
|
||||
historyValue.splice(valueIndex, 1)
|
||||
}
|
||||
]
|
||||
|
||||
if (historyValue.length > historySize.value) {
|
||||
historyValue.splice(historySize.value, historyValue.length - historySize.value)
|
||||
}
|
||||
|
||||
_history[key] = historyValue
|
||||
}
|
||||
|
||||
function getHistory(key: HistoryKey) {
|
||||
return _history[key] || []
|
||||
}
|
||||
|
||||
return {
|
||||
_history,
|
||||
historySize,
|
||||
pushValueToHistory,
|
||||
getHistory
|
||||
}
|
||||
},
|
||||
{
|
||||
persist: {
|
||||
enabled: true,
|
||||
strategies: [
|
||||
{
|
||||
storage: localStorage,
|
||||
key: 'vuetorrent_history'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
|
|
@ -28,4 +28,4 @@ export {
|
|||
useSearchEngineStore,
|
||||
useTorrentStore,
|
||||
useVueTorrentStore
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,10 +122,10 @@ export const useMaindataStore = defineStore('maindata', () => {
|
|||
|
||||
if (vueTorrentStore.showTrackerFilter) {
|
||||
trackers.value = data
|
||||
.map(t => t.tracker)
|
||||
.map(url => extractHostname(url))
|
||||
.filter((domain, index, self) => index === self.indexOf(domain) && domain)
|
||||
.sort()
|
||||
.map(t => t.tracker)
|
||||
.map(url => extractHostname(url))
|
||||
.filter((domain, index, self) => index === self.indexOf(domain) && domain)
|
||||
.sort()
|
||||
}
|
||||
|
||||
// update torrents
|
||||
|
|
|
@ -19,7 +19,7 @@ export const useRssStore = defineStore(
|
|||
})
|
||||
|
||||
const unreadArticles = computed(() => _articles.value.filter(article => !article.isRead))
|
||||
const articles = computed(() => filters.unread ? unreadArticles.value : _articles.value)
|
||||
const articles = computed(() => (filters.unread ? unreadArticles.value : _articles.value))
|
||||
|
||||
async function refreshFeed(feedName: string) {
|
||||
await qbit.refreshFeed(feedName)
|
||||
|
|
|
@ -7,194 +7,198 @@ import { Torrent } from '@/types/vuetorrent'
|
|||
import { defineStore } from 'pinia'
|
||||
import { computed, MaybeRefOrGetter, reactive, ref, toValue } from 'vue'
|
||||
|
||||
export const useTorrentStore = defineStore('torrents', () => {
|
||||
const torrents = ref<Torrent[]>([])
|
||||
export const useTorrentStore = defineStore(
|
||||
'torrents',
|
||||
() => {
|
||||
const torrents = ref<Torrent[]>([])
|
||||
|
||||
const isTextFilterActive = ref(true)
|
||||
const isStatusFilterActive = ref(true)
|
||||
const isCategoryFilterActive = ref(true)
|
||||
const isTagFilterActive = ref(true)
|
||||
const isTrackerFilterActive = ref(true)
|
||||
const isTextFilterActive = ref(true)
|
||||
const isStatusFilterActive = ref(true)
|
||||
const isCategoryFilterActive = ref(true)
|
||||
const isTagFilterActive = ref(true)
|
||||
const isTrackerFilterActive = ref(true)
|
||||
|
||||
const textFilter = ref('')
|
||||
const statusFilter = ref<TorrentState[]>([])
|
||||
const categoryFilter = ref<string[]>([])
|
||||
const tagFilter = ref<(string | null)[]>([])
|
||||
const trackerFilter = ref<(string | null)[]>([])
|
||||
const textFilter = ref('')
|
||||
const statusFilter = ref<TorrentState[]>([])
|
||||
const categoryFilter = ref<string[]>([])
|
||||
const tagFilter = ref<(string | null)[]>([])
|
||||
const trackerFilter = ref<(string | null)[]>([])
|
||||
|
||||
const torrentsWithFilters = computed(() => {
|
||||
return torrents.value.filter(torrent => {
|
||||
if (statusFilter.value.length > 0 && isStatusFilterActive.value && !statusFilter.value.includes(torrent.state)) return false
|
||||
if (categoryFilter.value.length > 0 && isCategoryFilterActive.value && !categoryFilter.value.includes(torrent.category)) return false
|
||||
if (tagFilter.value.length > 0 && isTagFilterActive.value) {
|
||||
if (torrent.tags.length === 0 && tagFilter.value.includes(null)) return true
|
||||
if (!torrent.tags.some(tag => tagFilter.value.includes(tag))) return false
|
||||
}
|
||||
if (trackerFilter.value.length > 0 && isTrackerFilterActive.value && !trackerFilter.value.includes(extractHostname(torrent.tracker))) return false
|
||||
|
||||
return true
|
||||
})
|
||||
})
|
||||
const filteredTorrents = computed(() => searchQuery.results.value)
|
||||
|
||||
const sortOptions = reactive({
|
||||
isCustomSortEnabled: false,
|
||||
sortBy: SortOptions.DEFAULT,
|
||||
reverseOrder: false
|
||||
})
|
||||
const getTorrentsPayload = computed<GetTorrentPayload>(() => {
|
||||
return {
|
||||
sort: sortOptions.isCustomSortEnabled ? SortOptions.DEFAULT : sortOptions.sortBy,
|
||||
reverse: sortOptions.reverseOrder
|
||||
}
|
||||
})
|
||||
|
||||
const searchQuery = useSearchQuery(
|
||||
torrentsWithFilters,
|
||||
() => isTextFilterActive.value ? textFilter.value : null,
|
||||
torrent => torrent.name,
|
||||
results => {
|
||||
if (sortOptions.isCustomSortEnabled) {
|
||||
if (sortOptions.sortBy === 'priority') {
|
||||
results.sort((a, b) => {
|
||||
if (a.priority > 0 && b.priority > 0) return a.priority - b.priority
|
||||
else if (a.priority <= 0 && b.priority <= 0) return a.added_on - b.added_on
|
||||
else if (a.priority <= 0) return 1
|
||||
else return -1
|
||||
})
|
||||
} else {
|
||||
results.sort((a, b) => a[sortOptions.sortBy] - b[sortOptions.sortBy] || a.added_on - b.added_on)
|
||||
const torrentsWithFilters = computed(() => {
|
||||
return torrents.value.filter(torrent => {
|
||||
if (statusFilter.value.length > 0 && isStatusFilterActive.value && !statusFilter.value.includes(torrent.state)) return false
|
||||
if (categoryFilter.value.length > 0 && isCategoryFilterActive.value && !categoryFilter.value.includes(torrent.category)) return false
|
||||
if (tagFilter.value.length > 0 && isTagFilterActive.value) {
|
||||
if (torrent.tags.length === 0 && tagFilter.value.includes(null)) return true
|
||||
if (!torrent.tags.some(tag => tagFilter.value.includes(tag))) return false
|
||||
}
|
||||
if (sortOptions.reverseOrder) results.reverse()
|
||||
if (trackerFilter.value.length > 0 && isTrackerFilterActive.value && !trackerFilter.value.includes(extractHostname(torrent.tracker))) return false
|
||||
|
||||
return true
|
||||
})
|
||||
})
|
||||
const filteredTorrents = computed(() => searchQuery.results.value)
|
||||
|
||||
const sortOptions = reactive({
|
||||
isCustomSortEnabled: false,
|
||||
sortBy: SortOptions.DEFAULT,
|
||||
reverseOrder: false
|
||||
})
|
||||
const getTorrentsPayload = computed<GetTorrentPayload>(() => {
|
||||
return {
|
||||
sort: sortOptions.isCustomSortEnabled ? SortOptions.DEFAULT : sortOptions.sortBy,
|
||||
reverse: sortOptions.reverseOrder
|
||||
}
|
||||
return results
|
||||
})
|
||||
|
||||
const searchQuery = useSearchQuery(
|
||||
torrentsWithFilters,
|
||||
() => (isTextFilterActive.value ? textFilter.value : null),
|
||||
torrent => torrent.name,
|
||||
results => {
|
||||
if (sortOptions.isCustomSortEnabled) {
|
||||
if (sortOptions.sortBy === 'priority') {
|
||||
results.sort((a, b) => {
|
||||
if (a.priority > 0 && b.priority > 0) return a.priority - b.priority
|
||||
else if (a.priority <= 0 && b.priority <= 0) return a.added_on - b.added_on
|
||||
else if (a.priority <= 0) return 1
|
||||
else return -1
|
||||
})
|
||||
} else {
|
||||
results.sort((a, b) => a[sortOptions.sortBy] - b[sortOptions.sortBy] || a.added_on - b.added_on)
|
||||
}
|
||||
if (sortOptions.reverseOrder) results.reverse()
|
||||
}
|
||||
return results
|
||||
}
|
||||
)
|
||||
|
||||
async function setTorrentCategory(hashes: string[], category: string) {
|
||||
await qbit.setCategory(hashes, category)
|
||||
}
|
||||
)
|
||||
|
||||
async function setTorrentCategory(hashes: string[], category: string) {
|
||||
await qbit.setCategory(hashes, category)
|
||||
}
|
||||
async function addTorrentTags(hashes: string[], tags: string[]) {
|
||||
await qbit.addTorrentTag(hashes, tags)
|
||||
}
|
||||
|
||||
async function addTorrentTags(hashes: string[], tags: string[]) {
|
||||
await qbit.addTorrentTag(hashes, tags)
|
||||
}
|
||||
async function removeTorrentTags(hashes: string[], tags: string[]) {
|
||||
await qbit.removeTorrentTag(hashes, tags)
|
||||
}
|
||||
|
||||
async function removeTorrentTags(hashes: string[], tags: string[]) {
|
||||
await qbit.removeTorrentTag(hashes, tags)
|
||||
}
|
||||
function getTorrentByHash(hash: string) {
|
||||
return torrents.value.find(t => t.hash === hash)
|
||||
}
|
||||
|
||||
function getTorrentByHash(hash: string) {
|
||||
return torrents.value.find(t => t.hash === hash)
|
||||
}
|
||||
function getTorrentIndexByHash(hash: string) {
|
||||
return filteredTorrents.value.findIndex(t => t.hash === hash)
|
||||
}
|
||||
|
||||
function getTorrentIndexByHash(hash: string) {
|
||||
return filteredTorrents.value.findIndex(t => t.hash === hash)
|
||||
}
|
||||
async function deleteTorrents(hashes: string[], deleteWithFiles: boolean) {
|
||||
await qbit.deleteTorrents(hashes, deleteWithFiles)
|
||||
}
|
||||
|
||||
async function deleteTorrents(hashes: string[], deleteWithFiles: boolean) {
|
||||
await qbit.deleteTorrents(hashes, deleteWithFiles)
|
||||
}
|
||||
async function moveTorrents(mode: 'dl' | 'save', hashes: string[], newPath: string) {
|
||||
switch (mode) {
|
||||
case 'dl':
|
||||
return await qbit.setTorrentDownloadPath(hashes, newPath)
|
||||
case 'save':
|
||||
return await qbit.setTorrentSavePath(hashes, newPath)
|
||||
}
|
||||
}
|
||||
|
||||
async function moveTorrents(mode: 'dl' | 'save', hashes: string[], newPath: string) {
|
||||
switch (mode) {
|
||||
case 'dl':
|
||||
return await qbit.setTorrentDownloadPath(hashes, newPath)
|
||||
case 'save':
|
||||
return await qbit.setTorrentSavePath(hashes, newPath)
|
||||
async function addTorrents(torrents: File[], urls: string, payload: AddTorrentPayload) {
|
||||
return await qbit.addTorrents(torrents, urls, payload)
|
||||
}
|
||||
|
||||
async function getTorrentProperties(hash: string) {
|
||||
return await qbit.getTorrentProperties(hash)
|
||||
}
|
||||
|
||||
async function renameTorrent(hash: string, newName: string) {
|
||||
await qbit.setTorrentName(hash, newName)
|
||||
}
|
||||
|
||||
async function resumeTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.resumeTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function forceResumeTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.forceStartTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function pauseTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.pauseTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function recheckTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.recheckTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function setTorrentPriority(hashes: string[], priority: 'increasePrio' | 'decreasePrio' | 'topPrio' | 'bottomPrio') {
|
||||
await qbit.setTorrentPriority(hashes, priority)
|
||||
}
|
||||
|
||||
async function exportTorrent(hash: string) {
|
||||
return await qbit.exportTorrent(hash)
|
||||
}
|
||||
|
||||
return {
|
||||
torrents,
|
||||
isTextFilterActive,
|
||||
isStatusFilterActive,
|
||||
isCategoryFilterActive,
|
||||
isTagFilterActive,
|
||||
isTrackerFilterActive,
|
||||
textFilter,
|
||||
statusFilter,
|
||||
categoryFilter,
|
||||
tagFilter,
|
||||
trackerFilter,
|
||||
torrentsWithFilters,
|
||||
filteredTorrents,
|
||||
sortOptions,
|
||||
getTorrentsPayload,
|
||||
searchQuery,
|
||||
setTorrentCategory,
|
||||
addTorrentTags,
|
||||
removeTorrentTags,
|
||||
getTorrentByHash,
|
||||
getTorrentIndexByHash,
|
||||
deleteTorrents,
|
||||
moveTorrents,
|
||||
addTorrents,
|
||||
getTorrentProperties,
|
||||
renameTorrent,
|
||||
resumeTorrents,
|
||||
forceResumeTorrents,
|
||||
pauseTorrents,
|
||||
recheckTorrents,
|
||||
setTorrentPriority,
|
||||
exportTorrent
|
||||
}
|
||||
},
|
||||
{
|
||||
persist: {
|
||||
enabled: true,
|
||||
strategies: [
|
||||
{
|
||||
storage: localStorage,
|
||||
key: 'vuetorrent_torrents',
|
||||
paths: [
|
||||
'isTextFilterActive',
|
||||
'textFilter',
|
||||
'isStatusFilterActive',
|
||||
'statusFilter',
|
||||
'isCategoryFilterActive',
|
||||
'categoryFilter',
|
||||
'isTagFilterActive',
|
||||
'tagFilter',
|
||||
'isTrackerFilterActive',
|
||||
'trackerFilter',
|
||||
'sortOptions'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
async function addTorrents(torrents: File[], urls: string, payload: AddTorrentPayload) {
|
||||
return await qbit.addTorrents(torrents, urls, payload)
|
||||
}
|
||||
|
||||
async function getTorrentProperties(hash: string) {
|
||||
return await qbit.getTorrentProperties(hash)
|
||||
}
|
||||
|
||||
async function renameTorrent(hash: string, newName: string) {
|
||||
await qbit.setTorrentName(hash, newName)
|
||||
}
|
||||
|
||||
async function resumeTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.resumeTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function forceResumeTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.forceStartTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function pauseTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.pauseTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function recheckTorrents(hashes: MaybeRefOrGetter<string[]>) {
|
||||
await qbit.recheckTorrents(toValue(hashes))
|
||||
}
|
||||
|
||||
async function setTorrentPriority(hashes: string[], priority: 'increasePrio' | 'decreasePrio' | 'topPrio' | 'bottomPrio') {
|
||||
await qbit.setTorrentPriority(hashes, priority)
|
||||
}
|
||||
|
||||
async function exportTorrent(hash: string) {
|
||||
return await qbit.exportTorrent(hash)
|
||||
}
|
||||
|
||||
return {
|
||||
torrents,
|
||||
isTextFilterActive,
|
||||
isStatusFilterActive,
|
||||
isCategoryFilterActive,
|
||||
isTagFilterActive,
|
||||
isTrackerFilterActive,
|
||||
textFilter,
|
||||
statusFilter,
|
||||
categoryFilter,
|
||||
tagFilter,
|
||||
trackerFilter,
|
||||
torrentsWithFilters,
|
||||
filteredTorrents,
|
||||
sortOptions,
|
||||
getTorrentsPayload,
|
||||
searchQuery,
|
||||
setTorrentCategory,
|
||||
addTorrentTags,
|
||||
removeTorrentTags,
|
||||
getTorrentByHash,
|
||||
getTorrentIndexByHash,
|
||||
deleteTorrents,
|
||||
moveTorrents,
|
||||
addTorrents,
|
||||
getTorrentProperties,
|
||||
renameTorrent,
|
||||
resumeTorrents,
|
||||
forceResumeTorrents,
|
||||
pauseTorrents,
|
||||
recheckTorrents,
|
||||
setTorrentPriority,
|
||||
exportTorrent
|
||||
}
|
||||
}, {
|
||||
persist: {
|
||||
enabled: true,
|
||||
strategies: [
|
||||
{
|
||||
storage: localStorage,
|
||||
key: 'vuetorrent_torrents',
|
||||
paths: [
|
||||
'isTextFilterActive',
|
||||
'textFilter',
|
||||
'isStatusFilterActive',
|
||||
'statusFilter',
|
||||
'isCategoryFilterActive',
|
||||
'categoryFilter',
|
||||
'isTagFilterActive',
|
||||
'tagFilter',
|
||||
'isTrackerFilterActive',
|
||||
'trackerFilter',
|
||||
'sortOptions'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
import {
|
||||
DashboardProperty,
|
||||
PropertyData,
|
||||
propsData,
|
||||
propsMetadata,
|
||||
TitleOptions,
|
||||
TorrentProperty
|
||||
} from '@/constants/vuetorrent'
|
||||
import { DashboardProperty, PropertyData, propsData, propsMetadata, TitleOptions, TorrentProperty } from '@/constants/vuetorrent'
|
||||
import { Theme } from '@/plugins/vuetify'
|
||||
import { useMediaQuery } from '@vueuse/core'
|
||||
import { defineStore } from 'pinia'
|
||||
|
|
|
@ -116,7 +116,7 @@ export default interface AppPreferences {
|
|||
dyndns_username: string
|
||||
/** Port used for embedded tracker */
|
||||
embedded_tracker_port: number
|
||||
/** Enable port forwarding for embedded tracker */
|
||||
/** Enable port forwarding for embedded tracker */
|
||||
embedded_tracker_port_forwarding: boolean
|
||||
/** True enables coalesce reads & writes */
|
||||
enable_coalesce_read_write: boolean
|
||||
|
|
|
@ -52,8 +52,8 @@ export default interface Torrent {
|
|||
upspeed: number
|
||||
|
||||
// computed
|
||||
avgDownloadSpeed: number,
|
||||
avgUploadSpeed: number,
|
||||
avgDownloadSpeed: number
|
||||
avgUploadSpeed: number
|
||||
globalSpeed: number
|
||||
globalVolume: number
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue