mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-10-22 10:46:04 +03:00
WebUI: Improve filter lists
This PR adds following improvements: * Remove unused tracker entries while processing sync data * Take into account filter selection & terms when performing 'Start/stop/delete' context actions in filter lists Now, only filtered torrents will be affected by them, just like in the GUI. * Provide better feedback when performing 'Start/stop/delete' context actions in filter lists Small improvement over GUI - now these actions will be disabled if it's not possible to use them. * Add context menu to status filter list * Fix error when toggling filter title Fixup for small bug introduced in https://github.com/qbittorrent/qBittorrent/pull/21269 PR #21438.
This commit is contained in:
parent
b1fd61af3a
commit
81509dfb65
9 changed files with 259 additions and 345 deletions
|
@ -275,6 +275,10 @@ a.propButton img {
|
||||||
border-top: 1px solid var(--color-border-default);
|
border-top: 1px solid var(--color-border-default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contextMenu .separatorBottom {
|
||||||
|
border-bottom: 1px solid var(--color-border-default);
|
||||||
|
}
|
||||||
|
|
||||||
.contextMenu li {
|
.contextMenu li {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -284,8 +288,7 @@ a.propButton img {
|
||||||
.contextMenu li.disabled {
|
.contextMenu li.disabled {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
filter: grayscale(1);
|
opacity: 0.5;
|
||||||
opacity: 0.6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.contextMenu li.disabled a {
|
.contextMenu li.disabled a {
|
||||||
|
|
|
@ -209,29 +209,34 @@
|
||||||
<a href="#exportTorrent"><img src="images/edit-copy.svg" alt="QBT_TR(Export .torrent)QBT_TR[CONTEXT=TransferListWidget]"> QBT_TR(Export .torrent)QBT_TR[CONTEXT=TransferListWidget]</a>
|
<a href="#exportTorrent"><img src="images/edit-copy.svg" alt="QBT_TR(Export .torrent)QBT_TR[CONTEXT=TransferListWidget]"> QBT_TR(Export .torrent)QBT_TR[CONTEXT=TransferListWidget]</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<ul id="statusesFilterMenu" class="contextMenu">
|
||||||
|
<li><a href="#startTorrents"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=StatusFilterWidget]">QBT_TR(Start torrents)QBT_TR[CONTEXT=StatusFilterWidget]</a></li>
|
||||||
|
<li><a href="#stopTorrents"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=StatusFilterWidget]">QBT_TR(Stop torrents)QBT_TR[CONTEXT=StatusFilterWidget]</a></li>
|
||||||
|
<li><a href="#deleteTorrents"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=StatusFilterWidget]">QBT_TR(Remove torrents)QBT_TR[CONTEXT=StatusFilterWidget]</a></li>
|
||||||
|
</ul>
|
||||||
<ul id="categoriesFilterMenu" class="contextMenu">
|
<ul id="categoriesFilterMenu" class="contextMenu">
|
||||||
<li><a href="#createCategory"><img src="images/list-add.svg" alt="QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#createCategory"><img src="images/list-add.svg" alt="QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li><a href="#createSubcategory"><img src="images/list-add.svg" alt="QBT_TR(Add subcategory...)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Add subcategory...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#createSubcategory"><img src="images/list-add.svg" alt="QBT_TR(Add subcategory...)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Add subcategory...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li><a href="#editCategory"><img src="images/edit-rename.svg" alt="QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#editCategory"><img src="images/edit-rename.svg" alt="QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li><a href="#deleteCategory"><img src="images/list-remove.svg" alt="QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#deleteCategory"><img src="images/list-remove.svg" alt="QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li><a href="#deleteUnusedCategories"><img src="images/list-remove.svg" alt="QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#deleteUnusedCategories" class="separatorBottom"><img src="images/list-remove.svg" alt="QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li class="separator"><a href="#startTorrentsByCategory"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Start torrents)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#startTorrents"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Start torrents)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li><a href="#stopTorrentsByCategory"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Stop torrents)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#stopTorrents"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Stop torrents)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
<li><a href="#deleteTorrentsByCategory"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Remove torrents)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
<li><a href="#deleteTorrents"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=CategoryFilterWidget]"> QBT_TR(Remove torrents)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="tagsFilterMenu" class="contextMenu">
|
<ul id="tagsFilterMenu" class="contextMenu">
|
||||||
<li><a href="#createTag"><img src="images/list-add.svg" alt="QBT_TR(Add tag...)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Add tag...)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
<li><a href="#createTag"><img src="images/list-add.svg" alt="QBT_TR(Add tag...)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Add tag...)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
||||||
<li><a href="#deleteTag"><img src="images/list-remove.svg" alt="QBT_TR(Remove tag)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Remove tag)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
<li><a href="#deleteTag"><img src="images/list-remove.svg" alt="QBT_TR(Remove tag)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Remove tag)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
||||||
<li><a href="#deleteUnusedTags"><img src="images/list-remove.svg" alt="QBT_TR(Remove unused tags)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Remove unused tags)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
<li><a href="#deleteUnusedTags" class="separatorBottom"><img src="images/list-remove.svg" alt="QBT_TR(Remove unused tags)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Remove unused tags)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
||||||
<li class="separator"><a href="#startTorrentsByTag"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Start torrents)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
<li><a href="#startTorrents"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Start torrents)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
||||||
<li><a href="#stopTorrentsByTag"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Stop torrents)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
<li><a href="#stopTorrents"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Stop torrents)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
||||||
<li><a href="#deleteTorrentsByTag"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Remove torrents)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
<li><a href="#deleteTorrents"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=TagFilterWidget]"> QBT_TR(Remove torrents)QBT_TR[CONTEXT=TagFilterWidget]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="trackersFilterMenu" class="contextMenu">
|
<ul id="trackersFilterMenu" class="contextMenu">
|
||||||
<li><a href="#deleteTracker"><img src="images/edit-clear.svg" alt="QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
<li><a href="#deleteTracker" class="separatorBottom"><img src="images/edit-clear.svg" alt="QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Remove tracker)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
||||||
<li class="separator"><a href="#startTorrentsByTracker"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Start torrents)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
<li><a href="#startTorrents"><img src="images/torrent-start.svg" alt="QBT_TR(Start torrents)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Start torrents)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
||||||
<li><a href="#stopTorrentsByTracker"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Stop torrents)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
<li><a href="#stopTorrents"><img src="images/torrent-stop.svg" alt="QBT_TR(Stop torrents)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Stop torrents)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
||||||
<li><a href="#deleteTorrentsByTracker"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Remove torrents)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
<li><a href="#deleteTorrents"><img src="images/list-remove.svg" alt="QBT_TR(Remove torrents)QBT_TR[CONTEXT=TrackerFiltersList]"> QBT_TR(Remove torrents)QBT_TR[CONTEXT=TrackerFiltersList]</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="torrentTrackersMenu" class="contextMenu">
|
<ul id="torrentTrackersMenu" class="contextMenu">
|
||||||
<li><a href="#AddTracker"><img src="images/list-add.svg" alt="QBT_TR(Add trackers...)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Add trackers...)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
|
<li><a href="#AddTracker"><img src="images/list-add.svg" alt="QBT_TR(Add trackers...)QBT_TR[CONTEXT=TrackerListWidget]"> QBT_TR(Add trackers...)QBT_TR[CONTEXT=TrackerListWidget]</a></li>
|
||||||
|
|
|
@ -641,12 +641,6 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
trackerFilterList.appendChild(createLink(TRACKERS_ALL, "QBT_TR(All (%1))QBT_TR[CONTEXT=TrackerFiltersList]", torrentsTable.getRowSize()));
|
trackerFilterList.appendChild(createLink(TRACKERS_ALL, "QBT_TR(All (%1))QBT_TR[CONTEXT=TrackerFiltersList]", torrentsTable.getRowSize()));
|
||||||
trackerFilterList.appendChild(createLink(TRACKERS_TRACKERLESS, "QBT_TR(Trackerless (%1))QBT_TR[CONTEXT=TrackerFiltersList]", trackerlessTorrentsCount));
|
trackerFilterList.appendChild(createLink(TRACKERS_TRACKERLESS, "QBT_TR(Trackerless (%1))QBT_TR[CONTEXT=TrackerFiltersList]", trackerlessTorrentsCount));
|
||||||
|
|
||||||
// Remove unused trackers
|
|
||||||
for (const [key, { trackerTorrentMap }] of trackerList) {
|
|
||||||
if (trackerTorrentMap.size === 0)
|
|
||||||
trackerList.delete(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort trackers by hostname
|
// Sort trackers by hostname
|
||||||
const sortedList = [];
|
const sortedList = [];
|
||||||
trackerList.forEach(({ host, trackerTorrentMap }, hash) => {
|
trackerList.forEach(({ host, trackerTorrentMap }, hash) => {
|
||||||
|
@ -815,8 +809,17 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
const host = window.qBittorrent.Misc.getHost(tracker);
|
const host = window.qBittorrent.Misc.getHost(tracker);
|
||||||
const hash = window.qBittorrent.Misc.genHash(host);
|
const hash = window.qBittorrent.Misc.genHash(host);
|
||||||
const trackerListEntry = trackerList.get(hash);
|
const trackerListEntry = trackerList.get(hash);
|
||||||
if (trackerListEntry)
|
if (trackerListEntry) {
|
||||||
trackerListEntry.trackerTorrentMap.delete(tracker);
|
trackerListEntry.trackerTorrentMap.delete(tracker);
|
||||||
|
// Remove unused trackers
|
||||||
|
if (trackerListEntry.trackerTorrentMap.size === 0) {
|
||||||
|
trackerList.delete(hash);
|
||||||
|
if (selectedTracker === hash) {
|
||||||
|
selectedTracker = TRACKERS_ALL;
|
||||||
|
LocalPreferences.set("selected_tracker", selectedTracker.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateTrackers = true;
|
updateTrackers = true;
|
||||||
}
|
}
|
||||||
|
@ -1647,7 +1650,7 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
return;
|
return;
|
||||||
if (event.target.isContentEditable)
|
if (event.target.isContentEditable)
|
||||||
return;
|
return;
|
||||||
deleteFN();
|
deleteSelectedTorrentsFN();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
},
|
},
|
||||||
"shift+delete": (event) => {
|
"shift+delete": (event) => {
|
||||||
|
@ -1655,7 +1658,7 @@ window.addEventListener("DOMContentLoaded", () => {
|
||||||
return;
|
return;
|
||||||
if (event.target.isContentEditable)
|
if (event.target.isContentEditable)
|
||||||
return;
|
return;
|
||||||
deleteFN(true);
|
deleteSelectedTorrentsFN(true);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
return {
|
return {
|
||||||
ContextMenu: ContextMenu,
|
ContextMenu: ContextMenu,
|
||||||
TorrentsTableContextMenu: TorrentsTableContextMenu,
|
TorrentsTableContextMenu: TorrentsTableContextMenu,
|
||||||
|
StatusesFilterContextMenu: StatusesFilterContextMenu,
|
||||||
CategoriesFilterContextMenu: CategoriesFilterContextMenu,
|
CategoriesFilterContextMenu: CategoriesFilterContextMenu,
|
||||||
TagsFilterContextMenu: TagsFilterContextMenu,
|
TagsFilterContextMenu: TagsFilterContextMenu,
|
||||||
TrackersFilterContextMenu: TrackersFilterContextMenu,
|
TrackersFilterContextMenu: TrackersFilterContextMenu,
|
||||||
|
@ -300,6 +301,31 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const FilterListContextMenu = new Class({
|
||||||
|
Extends: ContextMenu,
|
||||||
|
initialize: function(options) {
|
||||||
|
this.parent(options);
|
||||||
|
this.torrentObserver = new MutationObserver((records, observer) => {
|
||||||
|
this.updateTorrentActions();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
startTorrentObserver: function() {
|
||||||
|
this.torrentObserver.observe(torrentsTable.tableBody, { childList: true });
|
||||||
|
},
|
||||||
|
|
||||||
|
stopTorrentObserver: function() {
|
||||||
|
this.torrentObserver.disconnect();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTorrentActions: function() {
|
||||||
|
const torrentsVisible = torrentsTable.tableBody.children.length > 0;
|
||||||
|
this.setEnabled("startTorrents", torrentsVisible)
|
||||||
|
.setEnabled("stopTorrents", torrentsVisible)
|
||||||
|
.setEnabled("deleteTorrents", torrentsVisible);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const TorrentsTableContextMenu = new Class({
|
const TorrentsTableContextMenu = new Class({
|
||||||
Extends: ContextMenu,
|
Extends: ContextMenu,
|
||||||
|
|
||||||
|
@ -574,8 +600,15 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const StatusesFilterContextMenu = new Class({
|
||||||
|
Extends: FilterListContextMenu,
|
||||||
|
updateMenuItems: function() {
|
||||||
|
this.updateTorrentActions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const CategoriesFilterContextMenu = new Class({
|
const CategoriesFilterContextMenu = new Class({
|
||||||
Extends: ContextMenu,
|
Extends: FilterListContextMenu,
|
||||||
updateMenuItems: function() {
|
updateMenuItems: function() {
|
||||||
const id = Number(this.options.element.id);
|
const id = Number(this.options.element.id);
|
||||||
if ((id !== CATEGORIES_ALL) && (id !== CATEGORIES_UNCATEGORIZED)) {
|
if ((id !== CATEGORIES_ALL) && (id !== CATEGORIES_UNCATEGORIZED)) {
|
||||||
|
@ -591,28 +624,34 @@ window.qBittorrent.ContextMenu ??= (() => {
|
||||||
this.hideItem("deleteCategory");
|
this.hideItem("deleteCategory");
|
||||||
this.hideItem("createSubcategory");
|
this.hideItem("createSubcategory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateTorrentActions();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const TagsFilterContextMenu = new Class({
|
const TagsFilterContextMenu = new Class({
|
||||||
Extends: ContextMenu,
|
Extends: FilterListContextMenu,
|
||||||
updateMenuItems: function() {
|
updateMenuItems: function() {
|
||||||
const id = Number(this.options.element.id);
|
const id = Number(this.options.element.id);
|
||||||
if ((id !== TAGS_ALL) && (id !== TAGS_UNTAGGED))
|
if ((id !== TAGS_ALL) && (id !== TAGS_UNTAGGED))
|
||||||
this.showItem("deleteTag");
|
this.showItem("deleteTag");
|
||||||
else
|
else
|
||||||
this.hideItem("deleteTag");
|
this.hideItem("deleteTag");
|
||||||
|
|
||||||
|
this.updateTorrentActions();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const TrackersFilterContextMenu = new Class({
|
const TrackersFilterContextMenu = new Class({
|
||||||
Extends: ContextMenu,
|
Extends: FilterListContextMenu,
|
||||||
updateMenuItems: function() {
|
updateMenuItems: function() {
|
||||||
const id = Number(this.options.element.id);
|
const id = Number(this.options.element.id);
|
||||||
if ((id !== TRACKERS_ALL) && (id !== TRACKERS_TRACKERLESS))
|
if ((id !== TRACKERS_ALL) && (id !== TRACKERS_TRACKERLESS))
|
||||||
this.showItem("deleteTracker");
|
this.showItem("deleteTracker");
|
||||||
else
|
else
|
||||||
this.hideItem("deleteTracker");
|
this.hideItem("deleteTracker");
|
||||||
|
|
||||||
|
this.updateTorrentActions();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1525,9 +1525,20 @@ window.qBittorrent.DynamicTable ??= (() => {
|
||||||
|
|
||||||
getFilteredTorrentsHashes: function(filterName, categoryHash, tagHash, trackerHash) {
|
getFilteredTorrentsHashes: function(filterName, categoryHash, tagHash, trackerHash) {
|
||||||
const rowsHashes = [];
|
const rowsHashes = [];
|
||||||
|
const useRegex = document.getElementById("torrentsFilterRegexBox").checked;
|
||||||
|
const filterText = document.getElementById("torrentsFilterInput").value.trim().toLowerCase();
|
||||||
|
let filterTerms;
|
||||||
|
try {
|
||||||
|
filterTerms = (filterText.length > 0)
|
||||||
|
? (useRegex ? new RegExp(filterText) : filterText.split(" "))
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
catch (e) { // SyntaxError: Invalid regex pattern
|
||||||
|
return filteredRows;
|
||||||
|
}
|
||||||
|
|
||||||
for (const row of this.rows.values()) {
|
for (const row of this.rows.values()) {
|
||||||
if (this.applyFilter(row, filterName, categoryHash, tagHash, trackerHash, null))
|
if (this.applyFilter(row, filterName, categoryHash, tagHash, trackerHash, filterTerms))
|
||||||
rowsHashes.push(row["rowId"]);
|
rowsHashes.push(row["rowId"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ let setForceStartFN = function() {};
|
||||||
let globalDownloadLimitFN = function() {};
|
let globalDownloadLimitFN = function() {};
|
||||||
let StatisticsLinkFN = function() {};
|
let StatisticsLinkFN = function() {};
|
||||||
let downloadLimitFN = function() {};
|
let downloadLimitFN = function() {};
|
||||||
let deleteFN = function() {};
|
let deleteSelectedTorrentsFN = function() {};
|
||||||
let stopFN = function() {};
|
let stopFN = function() {};
|
||||||
let startFN = function() {};
|
let startFN = function() {};
|
||||||
let autoTorrentManagementFN = function() {};
|
let autoTorrentManagementFN = function() {};
|
||||||
|
@ -124,6 +124,9 @@ let reannounceFN = function() {};
|
||||||
let setLocationFN = function() {};
|
let setLocationFN = function() {};
|
||||||
let renameFN = function() {};
|
let renameFN = function() {};
|
||||||
let renameFilesFN = function() {};
|
let renameFilesFN = function() {};
|
||||||
|
let startVisibleTorrentsFN = function() {};
|
||||||
|
let stopVisibleTorrentsFN = function() {};
|
||||||
|
let deleteVisibleTorrentsFN = function() {};
|
||||||
let torrentNewCategoryFN = function() {};
|
let torrentNewCategoryFN = function() {};
|
||||||
let torrentSetCategoryFN = function() {};
|
let torrentSetCategoryFN = function() {};
|
||||||
let createCategoryFN = function() {};
|
let createCategoryFN = function() {};
|
||||||
|
@ -131,21 +134,12 @@ let createSubcategoryFN = function() {};
|
||||||
let editCategoryFN = function() {};
|
let editCategoryFN = function() {};
|
||||||
let removeCategoryFN = function() {};
|
let removeCategoryFN = function() {};
|
||||||
let deleteUnusedCategoriesFN = function() {};
|
let deleteUnusedCategoriesFN = function() {};
|
||||||
let startTorrentsByCategoryFN = function() {};
|
|
||||||
let stopTorrentsByCategoryFN = function() {};
|
|
||||||
let deleteTorrentsByCategoryFN = function() {};
|
|
||||||
let torrentAddTagsFN = function() {};
|
let torrentAddTagsFN = function() {};
|
||||||
let torrentSetTagsFN = function() {};
|
let torrentSetTagsFN = function() {};
|
||||||
let torrentRemoveAllTagsFN = function() {};
|
let torrentRemoveAllTagsFN = function() {};
|
||||||
let createTagFN = function() {};
|
let createTagFN = function() {};
|
||||||
let removeTagFN = function() {};
|
let removeTagFN = function() {};
|
||||||
let deleteUnusedTagsFN = function() {};
|
let deleteUnusedTagsFN = function() {};
|
||||||
let startTorrentsByTagFN = function() {};
|
|
||||||
let stopTorrentsByTagFN = function() {};
|
|
||||||
let deleteTorrentsByTagFN = function() {};
|
|
||||||
let startTorrentsByTrackerFN = function() {};
|
|
||||||
let stopTorrentsByTrackerFN = function() {};
|
|
||||||
let deleteTorrentsByTrackerFN = function() {};
|
|
||||||
let deleteTrackerFN = function() {};
|
let deleteTrackerFN = function() {};
|
||||||
let copyNameFN = function() {};
|
let copyNameFN = function() {};
|
||||||
let copyInfohashFN = function(policy) {};
|
let copyInfohashFN = function(policy) {};
|
||||||
|
@ -476,7 +470,7 @@ const initializeWindows = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteFN = function(forceDeleteFiles = false) {
|
deleteSelectedTorrentsFN = function(forceDeleteFiles = false) {
|
||||||
const hashes = torrentsTable.selectedRowsIds();
|
const hashes = torrentsTable.selectedRowsIds();
|
||||||
if (hashes.length > 0) {
|
if (hashes.length > 0) {
|
||||||
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_deletion) {
|
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_deletion) {
|
||||||
|
@ -510,6 +504,7 @@ const initializeWindows = function() {
|
||||||
onSuccess: function() {
|
onSuccess: function() {
|
||||||
torrentsTable.deselectAll();
|
torrentsTable.deselectAll();
|
||||||
updateMainData();
|
updateMainData();
|
||||||
|
updatePropertiesPanel();
|
||||||
},
|
},
|
||||||
onFailure: function() {
|
onFailure: function() {
|
||||||
alert("QBT_TR(Unable to delete torrents.)QBT_TR[CONTEXT=HttpServer]");
|
alert("QBT_TR(Unable to delete torrents.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
|
@ -522,7 +517,7 @@ const initializeWindows = function() {
|
||||||
addClickEvent("delete", (e) => {
|
addClickEvent("delete", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
deleteFN();
|
deleteSelectedTorrentsFN();
|
||||||
});
|
});
|
||||||
|
|
||||||
stopFN = function() {
|
stopFN = function() {
|
||||||
|
@ -705,6 +700,86 @@ const initializeWindows = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
startVisibleTorrentsFN = function() {
|
||||||
|
const hashes = torrentsTable.getFilteredTorrentsHashes(selectedStatus, selectedCategory, selectedTag, selectedTracker);
|
||||||
|
if (hashes.length > 0) {
|
||||||
|
new Request({
|
||||||
|
url: "api/v2/torrents/start",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
hashes: hashes.join("|")
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
updateMainData();
|
||||||
|
updatePropertiesPanel();
|
||||||
|
},
|
||||||
|
onFailure: () => {
|
||||||
|
alert("QBT_TR(Unable to start torrents.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
stopVisibleTorrentsFN = function() {
|
||||||
|
const hashes = torrentsTable.getFilteredTorrentsHashes(selectedStatus, selectedCategory, selectedTag, selectedTracker);
|
||||||
|
if (hashes.length > 0) {
|
||||||
|
new Request({
|
||||||
|
url: "api/v2/torrents/stop",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
hashes: hashes.join("|")
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
updateMainData();
|
||||||
|
updatePropertiesPanel();
|
||||||
|
},
|
||||||
|
onFailure: () => {
|
||||||
|
alert("QBT_TR(Unable to stop torrents.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteVisibleTorrentsFN = function() {
|
||||||
|
const hashes = torrentsTable.getFilteredTorrentsHashes(selectedStatus, selectedCategory, selectedTag, selectedTracker);
|
||||||
|
if (hashes.length > 0) {
|
||||||
|
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_deletion) {
|
||||||
|
new MochaUI.Modal({
|
||||||
|
...window.qBittorrent.Dialog.baseModalOptions,
|
||||||
|
id: "confirmDeletionPage",
|
||||||
|
title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
|
||||||
|
data: {
|
||||||
|
hashes: hashes,
|
||||||
|
isDeletingVisibleTorrents: true
|
||||||
|
},
|
||||||
|
contentURL: "views/confirmdeletion.html",
|
||||||
|
onContentLoaded: function(w) {
|
||||||
|
MochaUI.resizeWindow(w, { centered: true });
|
||||||
|
MochaUI.centerWindow(w);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new Request({
|
||||||
|
url: "api/v2/torrents/delete",
|
||||||
|
method: "post",
|
||||||
|
data: {
|
||||||
|
hashes: hashes.join("|"),
|
||||||
|
deleteFiles: false,
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
torrentsTable.deselectAll();
|
||||||
|
updateMainData();
|
||||||
|
updatePropertiesPanel();
|
||||||
|
},
|
||||||
|
onFailure: () => {
|
||||||
|
alert("QBT_TR(Unable to delete torrents.)QBT_TR[CONTEXT=HttpServer]");
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
torrentNewCategoryFN = function() {
|
torrentNewCategoryFN = function() {
|
||||||
const action = "set";
|
const action = "set";
|
||||||
const hashes = torrentsTable.selectedRowsIds();
|
const hashes = torrentsTable.selectedRowsIds();
|
||||||
|
@ -838,74 +913,6 @@ const initializeWindows = function() {
|
||||||
}).send();
|
}).send();
|
||||||
};
|
};
|
||||||
|
|
||||||
startTorrentsByCategoryFN = function(categoryHash) {
|
|
||||||
const hashes = torrentsTable.getFilteredTorrentsHashes("all", categoryHash, TAGS_ALL, TRACKERS_ALL);
|
|
||||||
if (hashes.length) {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/start",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|")
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
updateMainData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
stopTorrentsByCategoryFN = function(categoryHash) {
|
|
||||||
const hashes = torrentsTable.getFilteredTorrentsHashes("all", categoryHash, TAGS_ALL, TRACKERS_ALL);
|
|
||||||
if (hashes.length) {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/stop",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|")
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
updateMainData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteTorrentsByCategoryFN = function(categoryHash) {
|
|
||||||
const hashes = torrentsTable.getFilteredTorrentsHashes("all", categoryHash, TAGS_ALL, TRACKERS_ALL);
|
|
||||||
if (hashes.length > 0) {
|
|
||||||
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_deletion) {
|
|
||||||
new MochaUI.Modal({
|
|
||||||
...window.qBittorrent.Dialog.baseModalOptions,
|
|
||||||
id: "confirmDeletionPage",
|
|
||||||
title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
|
|
||||||
data: { hashes: hashes },
|
|
||||||
contentURL: "views/confirmdeletion.html",
|
|
||||||
onContentLoaded: function(w) {
|
|
||||||
MochaUI.resizeWindow(w, { centered: true });
|
|
||||||
MochaUI.centerWindow(w);
|
|
||||||
},
|
|
||||||
onCloseComplete: function() {
|
|
||||||
// make sure overlay is properly hidden upon modal closing
|
|
||||||
document.getElementById("modalOverlay").style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/delete",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|"),
|
|
||||||
deleteFiles: false,
|
|
||||||
},
|
|
||||||
onSuccess: function() {
|
|
||||||
torrentsTable.deselectAll();
|
|
||||||
updateMainData();
|
|
||||||
},
|
|
||||||
onFailure: function() {
|
|
||||||
alert("QBT_TR(Unable to delete torrents.)QBT_TR[CONTEXT=HttpServer]");
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
torrentAddTagsFN = function() {
|
torrentAddTagsFN = function() {
|
||||||
const action = "set";
|
const action = "set";
|
||||||
const hashes = torrentsTable.selectedRowsIds();
|
const hashes = torrentsTable.selectedRowsIds();
|
||||||
|
@ -1003,203 +1010,6 @@ const initializeWindows = function() {
|
||||||
setTagFilter(TAGS_ALL);
|
setTagFilter(TAGS_ALL);
|
||||||
};
|
};
|
||||||
|
|
||||||
startTorrentsByTagFN = function(tagHash) {
|
|
||||||
const hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, tagHash, TRACKERS_ALL);
|
|
||||||
if (hashes.length) {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/start",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|")
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
updateMainData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
stopTorrentsByTagFN = function(tagHash) {
|
|
||||||
const hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, tagHash, TRACKERS_ALL);
|
|
||||||
if (hashes.length) {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/stop",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|")
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
updateMainData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteTorrentsByTagFN = function(tagHash) {
|
|
||||||
const hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, tagHash, TRACKERS_ALL);
|
|
||||||
if (hashes.length > 0) {
|
|
||||||
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_deletion) {
|
|
||||||
new MochaUI.Modal({
|
|
||||||
...window.qBittorrent.Dialog.baseModalOptions,
|
|
||||||
id: "confirmDeletionPage",
|
|
||||||
title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
|
|
||||||
data: { hashes: hashes },
|
|
||||||
contentURL: "views/confirmdeletion.html",
|
|
||||||
onContentLoaded: function(w) {
|
|
||||||
MochaUI.resizeWindow(w, { centered: true });
|
|
||||||
MochaUI.centerWindow(w);
|
|
||||||
},
|
|
||||||
onCloseComplete: function() {
|
|
||||||
// make sure overlay is properly hidden upon modal closing
|
|
||||||
document.getElementById("modalOverlay").style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/delete",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|"),
|
|
||||||
deleteFiles: false,
|
|
||||||
},
|
|
||||||
onSuccess: function() {
|
|
||||||
torrentsTable.deselectAll();
|
|
||||||
updateMainData();
|
|
||||||
},
|
|
||||||
onFailure: function() {
|
|
||||||
alert("QBT_TR(Unable to delete torrents.)QBT_TR[CONTEXT=HttpServer]");
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
startTorrentsByTrackerFN = function(trackerHash) {
|
|
||||||
const trackerHashInt = Number.parseInt(trackerHash, 10);
|
|
||||||
let hashes = [];
|
|
||||||
switch (trackerHashInt) {
|
|
||||||
case TRACKERS_ALL:
|
|
||||||
hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_ALL);
|
|
||||||
break;
|
|
||||||
case TRACKERS_TRACKERLESS:
|
|
||||||
hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_TRACKERLESS);
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
const uniqueTorrents = new Set();
|
|
||||||
for (const torrents of trackerList.get(trackerHashInt).trackerTorrentMap.values()) {
|
|
||||||
for (const torrent of torrents)
|
|
||||||
uniqueTorrents.add(torrent);
|
|
||||||
}
|
|
||||||
hashes = [...uniqueTorrents];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashes.length > 0) {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/start",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|")
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
updateMainData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
stopTorrentsByTrackerFN = function(trackerHash) {
|
|
||||||
const trackerHashInt = Number.parseInt(trackerHash, 10);
|
|
||||||
let hashes = [];
|
|
||||||
switch (trackerHashInt) {
|
|
||||||
case TRACKERS_ALL:
|
|
||||||
hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_ALL);
|
|
||||||
break;
|
|
||||||
case TRACKERS_TRACKERLESS:
|
|
||||||
hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_TRACKERLESS);
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
const uniqueTorrents = new Set();
|
|
||||||
for (const torrents of trackerList.get(trackerHashInt).trackerTorrentMap.values()) {
|
|
||||||
for (const torrent of torrents)
|
|
||||||
uniqueTorrents.add(torrent);
|
|
||||||
}
|
|
||||||
hashes = [...uniqueTorrents];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashes.length) {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/stop",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|")
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
updateMainData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteTorrentsByTrackerFN = function(trackerHash) {
|
|
||||||
const trackerHashInt = Number.parseInt(trackerHash, 10);
|
|
||||||
let hashes = [];
|
|
||||||
switch (trackerHashInt) {
|
|
||||||
case TRACKERS_ALL:
|
|
||||||
hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_ALL);
|
|
||||||
break;
|
|
||||||
case TRACKERS_TRACKERLESS:
|
|
||||||
hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_TRACKERLESS);
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
const uniqueTorrents = new Set();
|
|
||||||
for (const torrents of trackerList.get(trackerHashInt).trackerTorrentMap.values()) {
|
|
||||||
for (const torrent of torrents)
|
|
||||||
uniqueTorrents.add(torrent);
|
|
||||||
}
|
|
||||||
hashes = [...uniqueTorrents];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashes.length > 0) {
|
|
||||||
if (window.qBittorrent.Cache.preferences.get().confirm_torrent_deletion) {
|
|
||||||
new MochaUI.Modal({
|
|
||||||
...window.qBittorrent.Dialog.baseModalOptions,
|
|
||||||
id: "confirmDeletionPage",
|
|
||||||
title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
|
|
||||||
data: {
|
|
||||||
hashes: hashes,
|
|
||||||
filterList: "tracker"
|
|
||||||
},
|
|
||||||
contentURL: "views/confirmdeletion.html",
|
|
||||||
onContentLoaded: function(w) {
|
|
||||||
MochaUI.resizeWindow(w, { centered: true });
|
|
||||||
MochaUI.centerWindow(w);
|
|
||||||
},
|
|
||||||
onCloseComplete: function() {
|
|
||||||
// make sure overlay is properly hidden upon modal closing
|
|
||||||
document.getElementById("modalOverlay").style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
new Request({
|
|
||||||
url: "api/v2/torrents/delete",
|
|
||||||
method: "post",
|
|
||||||
data: {
|
|
||||||
hashes: hashes.join("|"),
|
|
||||||
deleteFiles: false,
|
|
||||||
},
|
|
||||||
onSuccess: function() {
|
|
||||||
torrentsTable.deselectAll();
|
|
||||||
setTrackerFilter(TRACKERS_ALL);
|
|
||||||
updateMainData();
|
|
||||||
},
|
|
||||||
onFailure: function() {
|
|
||||||
alert("QBT_TR(Unable to delete torrents.)QBT_TR[CONTEXT=HttpServer]");
|
|
||||||
},
|
|
||||||
}).send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteTrackerFN = function(trackerHash) {
|
deleteTrackerFN = function(trackerHash) {
|
||||||
const trackerHashInt = Number.parseInt(trackerHash, 10);
|
const trackerHashInt = Number.parseInt(trackerHash, 10);
|
||||||
if ((trackerHashInt === TRACKERS_ALL) || (trackerHashInt === TRACKERS_TRACKERLESS))
|
if ((trackerHashInt === TRACKERS_ALL) || (trackerHashInt === TRACKERS_TRACKERLESS))
|
||||||
|
|
|
@ -35,8 +35,8 @@
|
||||||
|
|
||||||
const {
|
const {
|
||||||
hashes,
|
hashes,
|
||||||
|
isDeletingVisibleTorrents = false,
|
||||||
forceDeleteFiles = false,
|
forceDeleteFiles = false,
|
||||||
filterList = null
|
|
||||||
} = window.MUI.Windows.instances["confirmDeletionPage"].options.data;
|
} = window.MUI.Windows.instances["confirmDeletionPage"].options.data;
|
||||||
let prefDeleteContentFiles = window.qBittorrent.Cache.preferences.get().delete_torrent_content_files;
|
let prefDeleteContentFiles = window.qBittorrent.Cache.preferences.get().delete_torrent_content_files;
|
||||||
deleteCB.checked = forceDeleteFiles || prefDeleteContentFiles;
|
deleteCB.checked = forceDeleteFiles || prefDeleteContentFiles;
|
||||||
|
@ -72,7 +72,11 @@
|
||||||
cancelButton.addEventListener("click", (e) => { window.qBittorrent.Client.closeWindows(); });
|
cancelButton.addEventListener("click", (e) => { window.qBittorrent.Client.closeWindows(); });
|
||||||
|
|
||||||
confirmButton.addEventListener("click", (e) => {
|
confirmButton.addEventListener("click", (e) => {
|
||||||
torrentsTable.deselectAll();
|
// Some torrents might be removed when waiting for user input, so refetch the torrent list
|
||||||
|
const hashes = isDeletingVisibleTorrents
|
||||||
|
? torrentsTable.getFilteredTorrentsHashes(selectedStatus, selectedCategory, selectedTag, selectedTracker)
|
||||||
|
: torrentsTable.selectedRowsIds();
|
||||||
|
|
||||||
new Request({
|
new Request({
|
||||||
url: "api/v2/torrents/delete",
|
url: "api/v2/torrents/delete",
|
||||||
method: "post",
|
method: "post",
|
||||||
|
@ -81,9 +85,9 @@
|
||||||
"deleteFiles": deleteCB.checked
|
"deleteFiles": deleteCB.checked
|
||||||
},
|
},
|
||||||
onSuccess: function() {
|
onSuccess: function() {
|
||||||
if (filterList === "tracker")
|
torrentsTable.deselectAll();
|
||||||
setTrackerFilter(TRACKERS_ALL);
|
|
||||||
updateMainData();
|
updateMainData();
|
||||||
|
updatePropertiesPanel();
|
||||||
window.qBittorrent.Client.closeWindows();
|
window.qBittorrent.Client.closeWindows();
|
||||||
},
|
},
|
||||||
onFailure: function() {
|
onFailure: function() {
|
||||||
|
|
|
@ -3,20 +3,20 @@
|
||||||
<img src="images/go-down.svg" alt="QBT_TR(Collapse/expand)QBT_TR[CONTEXT=TransferListFiltersWidget]">QBT_TR(Status)QBT_TR[CONTEXT=TransferListFiltersWidget]
|
<img src="images/go-down.svg" alt="QBT_TR(Collapse/expand)QBT_TR[CONTEXT=TransferListFiltersWidget]">QBT_TR(Status)QBT_TR[CONTEXT=TransferListFiltersWidget]
|
||||||
</span>
|
</span>
|
||||||
<ul class="filterList" id="statusFilterList">
|
<ul class="filterList" id="statusFilterList">
|
||||||
<li id="all_filter"><span class="link"><img src="images/filter-all.svg" alt="All">QBT_TR(All (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="all_filter"><span class="link"><img src="images/filter-all.svg" alt="All">QBT_TR(All (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="downloading_filter"><span class="link"><img src="images/downloading.svg" alt="Downloading">QBT_TR(Downloading (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="downloading_filter"><span class="link"><img src="images/downloading.svg" alt="Downloading">QBT_TR(Downloading (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="seeding_filter"><span class="link"><img src="images/upload.svg" alt="Seeding">QBT_TR(Seeding (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="seeding_filter"><span class="link"><img src="images/upload.svg" alt="Seeding">QBT_TR(Seeding (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="completed_filter"><span class="link"><img src="images/checked-completed.svg" alt="Completed">QBT_TR(Completed (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="completed_filter"><span class="link"><img src="images/checked-completed.svg" alt="Completed">QBT_TR(Completed (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="running_filter"><span class="link"><img src="images/torrent-start.svg" alt="Running">QBT_TR(Running (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="running_filter"><span class="link"><img src="images/torrent-start.svg" alt="Running">QBT_TR(Running (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="stopped_filter"><span class="link"><img src="images/stopped.svg" alt="Stopped">QBT_TR(Stopped (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="stopped_filter"><span class="link"><img src="images/stopped.svg" alt="Stopped">QBT_TR(Stopped (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="active_filter"><span class="link"><img src="images/filter-active.svg" alt="Active">QBT_TR(Active (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="active_filter"><span class="link"><img src="images/filter-active.svg" alt="Active">QBT_TR(Active (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="inactive_filter"><span class="link"><img src="images/filter-inactive.svg" alt="Inactive">QBT_TR(Inactive (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="inactive_filter"><span class="link"><img src="images/filter-inactive.svg" alt="Inactive">QBT_TR(Inactive (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="stalled_filter"><span class="link"><img src="images/filter-stalled.svg" alt="Stalled">QBT_TR(Stalled (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="stalled_filter"><span class="link"><img src="images/filter-stalled.svg" alt="Stalled">QBT_TR(Stalled (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="stalled_uploading_filter"><span class="link"><img src="images/stalledUP.svg" alt="Stalled Uploading">QBT_TR(Stalled Uploading (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="stalled_uploading_filter"><span class="link"><img src="images/stalledUP.svg" alt="Stalled Uploading">QBT_TR(Stalled Uploading (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="stalled_downloading_filter"><span class="link"><img src="images/stalledDL.svg" alt="Stalled Downloading">QBT_TR(Stalled Downloading (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="stalled_downloading_filter"><span class="link"><img src="images/stalledDL.svg" alt="Stalled Downloading">QBT_TR(Stalled Downloading (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="checking_filter"><span class="link"><img src="images/force-recheck.svg" alt="Checking">QBT_TR(Checking (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="checking_filter"><span class="link"><img src="images/force-recheck.svg" alt="Checking">QBT_TR(Checking (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="moving_filter"><span class="link"><img src="images/set-location.svg" alt="Moving">QBT_TR(Moving (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="moving_filter"><span class="link"><img src="images/set-location.svg" alt="Moving">QBT_TR(Moving (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
<li id="errored_filter"><span class="link"><img src="images/error.svg" alt="Errored">QBT_TR(Errored (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
<li class="statusesFilterContextMenuTarget" id="errored_filter"><span class="link"><img src="images/error.svg" alt="Errored">QBT_TR(Errored (0))QBT_TR[CONTEXT=StatusFilterWidget]</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="filterWrapper">
|
<div class="filterWrapper">
|
||||||
|
@ -83,6 +83,33 @@
|
||||||
LocalPreferences.set(`category_${filterItemID}_collapsed`, filterItem.classList.toggle("collapsedCategory").toString());
|
LocalPreferences.set(`category_${filterItemID}_collapsed`, filterItem.classList.toggle("collapsedCategory").toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
new window.qBittorrent.ContextMenu.StatusesFilterContextMenu({
|
||||||
|
targets: ".statusesFilterContextMenuTarget",
|
||||||
|
menu: "statusesFilterMenu",
|
||||||
|
actions: {
|
||||||
|
startTorrents: (element, ref) => {
|
||||||
|
startVisibleTorrentsFN();
|
||||||
|
},
|
||||||
|
stopTorrents: (element, ref) => {
|
||||||
|
stopVisibleTorrentsFN();
|
||||||
|
},
|
||||||
|
deleteTorrents: (element, ref) => {
|
||||||
|
deleteVisibleTorrentsFN();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
offsets: {
|
||||||
|
x: -15,
|
||||||
|
y: 2
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
this.startTorrentObserver();
|
||||||
|
setStatusFilter(this.options.element.id.replace("_filter", ""));
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
this.stopTorrentObserver();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const categoriesFilterContextMenu = new window.qBittorrent.ContextMenu.CategoriesFilterContextMenu({
|
const categoriesFilterContextMenu = new window.qBittorrent.ContextMenu.CategoriesFilterContextMenu({
|
||||||
targets: ".categoriesFilterContextMenuTarget",
|
targets: ".categoriesFilterContextMenuTarget",
|
||||||
menu: "categoriesFilterMenu",
|
menu: "categoriesFilterMenu",
|
||||||
|
@ -102,14 +129,14 @@
|
||||||
deleteUnusedCategories: function(element, ref) {
|
deleteUnusedCategories: function(element, ref) {
|
||||||
deleteUnusedCategoriesFN();
|
deleteUnusedCategoriesFN();
|
||||||
},
|
},
|
||||||
startTorrentsByCategory: function(element, ref) {
|
startTorrents: (element, ref) => {
|
||||||
startTorrentsByCategoryFN(Number(element.id));
|
startVisibleTorrentsFN();
|
||||||
},
|
},
|
||||||
stopTorrentsByCategory: function(element, ref) {
|
stopTorrents: (element, ref) => {
|
||||||
stopTorrentsByCategoryFN(Number(element.id));
|
stopVisibleTorrentsFN();
|
||||||
},
|
},
|
||||||
deleteTorrentsByCategory: function(element, ref) {
|
deleteTorrents: (element, ref) => {
|
||||||
deleteTorrentsByCategoryFN(Number(element.id));
|
deleteVisibleTorrentsFN();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
offsets: {
|
offsets: {
|
||||||
|
@ -117,7 +144,11 @@
|
||||||
y: 2
|
y: 2
|
||||||
},
|
},
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
this.options.element.click();
|
this.startTorrentObserver();
|
||||||
|
setCategoryFilter(this.options.element.id);
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
this.stopTorrentObserver();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -134,14 +165,14 @@
|
||||||
deleteUnusedTags: function(element, ref) {
|
deleteUnusedTags: function(element, ref) {
|
||||||
deleteUnusedTagsFN();
|
deleteUnusedTagsFN();
|
||||||
},
|
},
|
||||||
startTorrentsByTag: function(element, ref) {
|
startTorrents: (element, ref) => {
|
||||||
startTorrentsByTagFN(Number(element.id));
|
startVisibleTorrentsFN();
|
||||||
},
|
},
|
||||||
stopTorrentsByTag: function(element, ref) {
|
stopTorrents: (element, ref) => {
|
||||||
stopTorrentsByTagFN(Number(element.id));
|
stopVisibleTorrentsFN();
|
||||||
},
|
},
|
||||||
deleteTorrentsByTag: function(element, ref) {
|
deleteTorrents: (element, ref) => {
|
||||||
deleteTorrentsByTagFN(Number(element.id));
|
deleteVisibleTorrentsFN();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
offsets: {
|
offsets: {
|
||||||
|
@ -149,7 +180,11 @@
|
||||||
y: 2
|
y: 2
|
||||||
},
|
},
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
this.options.element.click();
|
this.startTorrentObserver();
|
||||||
|
setTagFilter(this.options.element.id);
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
this.stopTorrentObserver();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -160,14 +195,14 @@
|
||||||
deleteTracker: function(element, ref) {
|
deleteTracker: function(element, ref) {
|
||||||
deleteTrackerFN(element.id);
|
deleteTrackerFN(element.id);
|
||||||
},
|
},
|
||||||
startTorrentsByTracker: function(element, ref) {
|
startTorrents: (element, ref) => {
|
||||||
startTorrentsByTrackerFN(element.id);
|
startVisibleTorrentsFN();
|
||||||
},
|
},
|
||||||
stopTorrentsByTracker: function(element, ref) {
|
stopTorrents: (element, ref) => {
|
||||||
stopTorrentsByTrackerFN(element.id);
|
stopVisibleTorrentsFN();
|
||||||
},
|
},
|
||||||
deleteTorrentsByTracker: function(element, ref) {
|
deleteTorrents: (element, ref) => {
|
||||||
deleteTorrentsByTrackerFN(element.id);
|
deleteVisibleTorrentsFN();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
offsets: {
|
offsets: {
|
||||||
|
@ -175,7 +210,11 @@
|
||||||
y: 2
|
y: 2
|
||||||
},
|
},
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
this.options.element.click();
|
this.startTorrentObserver();
|
||||||
|
setTrackerFilter(this.options.element.id);
|
||||||
|
},
|
||||||
|
onHide: function() {
|
||||||
|
this.stopTorrentObserver();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -193,7 +232,7 @@
|
||||||
|
|
||||||
document.getElementById("Filters_pad").addEventListener("click", (event) => {
|
document.getElementById("Filters_pad").addEventListener("click", (event) => {
|
||||||
const filterItem = event.target.closest("li");
|
const filterItem = event.target.closest("li");
|
||||||
if (filterItem?.classList?.contains("selectedFilter"))
|
if (!filterItem || filterItem.classList.contains("selectedFilter"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const { id: filterItemID } = filterItem;
|
const { id: filterItemID } = filterItem;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
delete: function(element, ref) {
|
delete: function(element, ref) {
|
||||||
deleteFN();
|
deleteSelectedTorrentsFN();
|
||||||
},
|
},
|
||||||
|
|
||||||
setLocation: function(element, ref) {
|
setLocation: function(element, ref) {
|
||||||
|
|
Loading…
Reference in a new issue