Correctly handle "torrent finished" events
[qBittorrent.git] / src / webui / www / private / scripts / prop-trackers.js
blob06449dcef776ebe58b52addfc88063eb2f5e53ac
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2009 Christophe Dumez <chris@qbittorrent.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
29 "use strict";
31 window.qBittorrent ??= {};
32 window.qBittorrent.PropTrackers ??= (() => {
33 const exports = () => {
34 return {
35 updateData: updateData,
36 clear: clear
40 let current_hash = "";
42 const torrentTrackersTable = new window.qBittorrent.DynamicTable.TorrentTrackersTable();
43 let loadTrackersDataTimer = -1;
45 const loadTrackersData = () => {
46 if ($("propTrackers").hasClass("invisible")
47 || $("propertiesPanel_collapseToggle").hasClass("panel-expand")) {
48 // Tab changed, don't do anything
49 return;
51 const new_hash = torrentsTable.getCurrentTorrentID();
52 if (new_hash === "") {
53 torrentTrackersTable.clear();
54 clearTimeout(loadTrackersDataTimer);
55 return;
57 if (new_hash !== current_hash) {
58 torrentTrackersTable.clear();
59 current_hash = new_hash;
61 const url = new URI("api/v2/torrents/trackers?hash=" + current_hash);
62 new Request.JSON({
63 url: url,
64 method: "get",
65 noCache: true,
66 onComplete: () => {
67 clearTimeout(loadTrackersDataTimer);
68 loadTrackersDataTimer = loadTrackersData.delay(10000);
70 onSuccess: (trackers) => {
71 const selectedTrackers = torrentTrackersTable.selectedRowsIds();
72 torrentTrackersTable.clear();
74 if (trackers) {
75 trackers.each((tracker) => {
76 let status;
77 switch (tracker.status) {
78 case 0:
79 status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
80 break;
81 case 1:
82 status = "QBT_TR(Not contacted yet)QBT_TR[CONTEXT=TrackerListWidget]";
83 break;
84 case 2:
85 status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
86 break;
87 case 3:
88 status = "QBT_TR(Updating...)QBT_TR[CONTEXT=TrackerListWidget]";
89 break;
90 case 4:
91 status = "QBT_TR(Not working)QBT_TR[CONTEXT=TrackerListWidget]";
92 break;
95 const row = {
96 rowId: tracker.url,
97 tier: (tracker.tier >= 0) ? tracker.tier : "",
98 url: tracker.url,
99 status: status,
100 peers: (tracker.num_peers >= 0) ? tracker.num_peers : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
101 seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
102 leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
103 downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
104 message: tracker.msg,
105 _sortable: !tracker.url.startsWith("** [")
108 torrentTrackersTable.updateRowData(row);
111 torrentTrackersTable.updateTable(false);
113 if (selectedTrackers.length > 0)
114 torrentTrackersTable.reselectRows(selectedTrackers);
117 }).send();
120 const updateData = () => {
121 clearTimeout(loadTrackersDataTimer);
122 loadTrackersDataTimer = -1;
123 loadTrackersData();
126 const torrentTrackersContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
127 targets: "#torrentTrackersTableDiv",
128 menu: "torrentTrackersMenu",
129 actions: {
130 AddTracker: (element, ref) => {
131 addTrackerFN();
133 EditTracker: (element, ref) => {
134 // only allow editing of one row
135 element.firstChild.click();
136 editTrackerFN(element);
138 RemoveTracker: (element, ref) => {
139 removeTrackerFN(element);
142 offsets: {
143 x: 0,
144 y: 2
146 onShow: function() {
147 const selectedTrackers = torrentTrackersTable.selectedRowsIds();
148 const containsStaticTracker = selectedTrackers.some((tracker) => {
149 return (tracker.indexOf("** [") === 0);
152 if (containsStaticTracker || (selectedTrackers.length === 0)) {
153 this.hideItem("EditTracker");
154 this.hideItem("RemoveTracker");
155 this.hideItem("CopyTrackerUrl");
157 else {
158 this.showItem("EditTracker");
159 this.showItem("RemoveTracker");
160 this.showItem("CopyTrackerUrl");
165 const addTrackerFN = () => {
166 if (current_hash.length === 0)
167 return;
168 new MochaUI.Window({
169 id: "trackersPage",
170 icon: "images/qbittorrent-tray.svg",
171 title: "QBT_TR(Add trackers)QBT_TR[CONTEXT=TrackersAdditionDialog]",
172 loadMethod: "iframe",
173 contentURL: "addtrackers.html?hash=" + current_hash,
174 scrollbars: true,
175 resizable: false,
176 maximizable: false,
177 closable: true,
178 paddingVertical: 0,
179 paddingHorizontal: 0,
180 width: 500,
181 height: 260,
182 onCloseComplete: () => {
183 updateData();
188 const editTrackerFN = (element) => {
189 if (current_hash.length === 0)
190 return;
192 const trackerUrl = encodeURIComponent(element.childNodes[1].textContent);
193 new MochaUI.Window({
194 id: "trackersPage",
195 icon: "images/qbittorrent-tray.svg",
196 title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
197 loadMethod: "iframe",
198 contentURL: "edittracker.html?hash=" + current_hash + "&url=" + trackerUrl,
199 scrollbars: true,
200 resizable: false,
201 maximizable: false,
202 closable: true,
203 paddingVertical: 0,
204 paddingHorizontal: 0,
205 width: 500,
206 height: 150,
207 onCloseComplete: () => {
208 updateData();
213 const removeTrackerFN = (element) => {
214 if (current_hash.length === 0)
215 return;
217 const selectedTrackers = torrentTrackersTable.selectedRowsIds();
218 new Request({
219 url: "api/v2/torrents/removeTrackers",
220 method: "post",
221 data: {
222 hash: current_hash,
223 urls: selectedTrackers.map(encodeURIComponent).join("|")
225 onSuccess: () => {
226 updateData();
228 }).send();
231 const clear = () => {
232 torrentTrackersTable.clear();
235 new ClipboardJS("#CopyTrackerUrl", {
236 text: (trigger) => {
237 return torrentTrackersTable.selectedRowsIds().join("\n");
241 torrentTrackersTable.setup("torrentTrackersTableDiv", "torrentTrackersTableFixedHeaderDiv", torrentTrackersContextMenu);
243 return exports();
244 })();
245 Object.freeze(window.qBittorrent.PropTrackers);