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:
skomerko 2024-10-12 07:40:18 +02:00 committed by GitHub
parent b1fd61af3a
commit 81509dfb65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 259 additions and 345 deletions

View file

@ -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 {

View file

@ -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>

View file

@ -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();
} }
} }

View file

@ -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();
} }
}); });

View file

@ -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"]);
} }

View file

@ -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))

View file

@ -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() {

View file

@ -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;

View file

@ -43,7 +43,7 @@
}, },
delete: function(element, ref) { delete: function(element, ref) {
deleteFN(); deleteSelectedTorrentsFN();
}, },
setLocation: function(element, ref) { setLocation: function(element, ref) {