mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-28 13:28:50 +03:00
Move JavaScript code into explicit namespaces
This cleans up the global namespace by explicitly exporting shared values. All html and JavaScript files have been converted to use explicit exports except for client.js and mocha-init.js
This commit is contained in:
parent
b144d3b797
commit
1439bcc864
32 changed files with 6204 additions and 5838 deletions
|
@ -61,7 +61,7 @@
|
||||||
<p>QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]</p>
|
<p>QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]</p>
|
||||||
<textarea id="peers" rows="10" style="width: 100%;" placeholder="QBT_TR(Format: IPv4:port / [IPv6]:port)QBT_TR[CONTEXT=PeersAdditionDialog]"></textarea>
|
<textarea id="peers" rows="10" style="width: 100%;" placeholder="QBT_TR(Format: IPv4:port / [IPv6]:port)QBT_TR[CONTEXT=PeersAdditionDialog]"></textarea>
|
||||||
<div style="margin-top: 10px; text-align: center;">
|
<div style="margin-top: 10px; text-align: center;">
|
||||||
<button onclick="window.parent.closeWindows();">QBT_TR(Cancel)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
|
<button onclick="parent.closeWindows();">QBT_TR(Cancel)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
|
||||||
<button id="addPeersOk">QBT_TR(Ok)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
|
<button id="addPeersOk">QBT_TR(Ok)QBT_TR[CONTEXT=PeersAdditionDialog]</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="autoTMM" name="autoTMM" onchange="changeTMM(this)">
|
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
|
||||||
<option selected value="false">Manual</option>
|
<option selected value="false">Manual</option>
|
||||||
<option value="true">Automatic</option>
|
<option value="true">Automatic</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="select-watched-folder-editable">
|
<div class="select-watched-folder-editable">
|
||||||
<select id="categorySelect" onchange="changeCategorySelect(this)">
|
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
|
||||||
<option selected value="\other"></option>
|
<option selected value="\other"></option>
|
||||||
</select>
|
</select>
|
||||||
<input name="category" type="text" value="" />
|
<input name="category" type="text" value="" />
|
||||||
|
|
|
@ -30,18 +30,18 @@
|
||||||
}).activate();
|
}).activate();
|
||||||
|
|
||||||
window.addEvent('domready', function() {
|
window.addEvent('domready', function() {
|
||||||
const uriAction = safeTrim(new URI().getData('action'));
|
const uriAction = window.qBittorrent.Misc.safeTrim(new URI().getData('action'));
|
||||||
const uriHashes = safeTrim(new URI().getData('hashes'));
|
const uriHashes = window.qBittorrent.Misc.safeTrim(new URI().getData('hashes'));
|
||||||
const uriCategoryName = safeTrim(new URI().getData('categoryName'));
|
const uriCategoryName = window.qBittorrent.Misc.safeTrim(new URI().getData('categoryName'));
|
||||||
const uriSavePath = safeTrim(new URI().getData('savePath'));
|
const uriSavePath = window.qBittorrent.Misc.safeTrim(new URI().getData('savePath'));
|
||||||
|
|
||||||
if (uriAction === "edit") {
|
if (uriAction === "edit") {
|
||||||
if (!uriCategoryName)
|
if (!uriCategoryName)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
$('categoryName').set('disabled', true);
|
$('categoryName').set('disabled', true);
|
||||||
$('categoryName').set('value', escapeHtml(uriCategoryName));
|
$('categoryName').set('value', window.qBittorrent.Misc.escapeHtml(uriCategoryName));
|
||||||
$('savePath').set('value', escapeHtml(uriSavePath));
|
$('savePath').set('value', window.qBittorrent.Misc.escapeHtml(uriSavePath));
|
||||||
$('savePath').focus();
|
$('savePath').focus();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
}).send();
|
}).send();
|
||||||
},
|
},
|
||||||
onError: function() {
|
onError: function() {
|
||||||
alert("QBT_TR(Unable to create category)QBT_TR[CONTEXT=HttpServer] " + escapeHtml(categoryName));
|
alert("QBT_TR(Unable to create category)QBT_TR[CONTEXT=HttpServer] " + window.qBittorrent.Misc.escapeHtml(categoryName));
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
}).activate();
|
}).activate();
|
||||||
|
|
||||||
window.addEvent('domready', function() {
|
window.addEvent('domready', function() {
|
||||||
const uriAction = safeTrim(new URI().getData('action'));
|
const uriAction = window.qBittorrent.Misc.safeTrim(new URI().getData('action'));
|
||||||
const uriHashes = safeTrim(new URI().getData('hashes'));
|
const uriHashes = window.qBittorrent.Misc.safeTrim(new URI().getData('hashes'));
|
||||||
|
|
||||||
if (uriAction === 'create')
|
if (uriAction === 'create')
|
||||||
$('legendText').innerText = 'QBT_TR(Tag:)QBT_TR[CONTEXT=TagFilterWidget]';
|
$('legendText').innerText = 'QBT_TR(Tag:)QBT_TR[CONTEXT=TagFilterWidget]';
|
||||||
|
|
|
@ -24,21 +24,10 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
this.torrentsTable = new TorrentsTable();
|
this.torrentsTable = new window.qBittorrent.DynamicTable.TorrentsTable();
|
||||||
const torrentTrackersTable = new TorrentTrackersTable();
|
|
||||||
const torrentPeersTable = new TorrentPeersTable();
|
|
||||||
const torrentFilesTable = new TorrentFilesTable();
|
|
||||||
const searchResultsTable = new SearchResultsTable();
|
|
||||||
const searchPluginsTable = new SearchPluginsTable();
|
|
||||||
|
|
||||||
let updatePropertiesPanel = function() {};
|
let updatePropertiesPanel = function() {};
|
||||||
|
|
||||||
let updateTorrentData = function() {};
|
|
||||||
let updateTrackersData = function() {};
|
|
||||||
let updateTorrentPeersData = function() {};
|
|
||||||
let updateWebSeedsData = function() {};
|
|
||||||
let updateTorrentFilesData = function() {};
|
|
||||||
|
|
||||||
this.updateMainData = function() {};
|
this.updateMainData = function() {};
|
||||||
let alternativeSpeedLimits = false;
|
let alternativeSpeedLimits = false;
|
||||||
let queueing_enabled = true;
|
let queueing_enabled = true;
|
||||||
|
@ -365,12 +354,12 @@ window.addEvent('load', function() {
|
||||||
const create_link = function(hash, text, count) {
|
const create_link = function(hash, text, count) {
|
||||||
const html = '<a href="#" onclick="setCategoryFilter(' + hash + ');return false;">'
|
const html = '<a href="#" onclick="setCategoryFilter(' + hash + ');return false;">'
|
||||||
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
|
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
|
||||||
+ escapeHtml(text) + ' (' + count + ')' + '</a>';
|
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>';
|
||||||
const el = new Element('li', {
|
const el = new Element('li', {
|
||||||
id: hash,
|
id: hash,
|
||||||
html: html
|
html: html
|
||||||
});
|
});
|
||||||
categoriesFilterContextMenu.addTarget(el);
|
window.qBittorrent.Filters.categoriesFilterContextMenu.addTarget(el);
|
||||||
return el;
|
return el;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -422,12 +411,12 @@ window.addEvent('load', function() {
|
||||||
const createLink = function(hash, text, count) {
|
const createLink = function(hash, text, count) {
|
||||||
const html = '<a href="#" onclick="setTagFilter(' + hash + ');return false;">'
|
const html = '<a href="#" onclick="setTagFilter(' + hash + ');return false;">'
|
||||||
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
|
+ '<img src="images/qbt-theme/inode-directory.svg"/>'
|
||||||
+ escapeHtml(text) + ' (' + count + ')' + '</a>';
|
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>';
|
||||||
const el = new Element('li', {
|
const el = new Element('li', {
|
||||||
id: hash,
|
id: hash,
|
||||||
html: html
|
html: html
|
||||||
});
|
});
|
||||||
tagsFilterContextMenu.addTarget(el);
|
window.qBittorrent.Filters.tagsFilterContextMenu.addTarget(el);
|
||||||
return el;
|
return el;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -579,11 +568,11 @@ window.addEvent('load', function() {
|
||||||
updateFiltersList();
|
updateFiltersList();
|
||||||
if (update_categories) {
|
if (update_categories) {
|
||||||
updateCategoryList();
|
updateCategoryList();
|
||||||
torrentsTableContextMenu.updateCategoriesSubMenu(category_list);
|
window.qBittorrent.TransferList.contextMenu.updateCategoriesSubMenu(category_list);
|
||||||
}
|
}
|
||||||
if (updateTags) {
|
if (updateTags) {
|
||||||
updateTagList();
|
updateTagList();
|
||||||
torrentsTableContextMenu.updateTagsSubMenu(tagList);
|
window.qBittorrent.TransferList.contextMenu.updateTagsSubMenu(tagList);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (full_update)
|
if (full_update)
|
||||||
|
@ -603,39 +592,39 @@ window.addEvent('load', function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const processServerState = function() {
|
const processServerState = function() {
|
||||||
let transfer_info = friendlyUnit(serverState.dl_info_speed, true);
|
let transfer_info = window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_speed, true);
|
||||||
if (serverState.dl_rate_limit > 0)
|
if (serverState.dl_rate_limit > 0)
|
||||||
transfer_info += " [" + friendlyUnit(serverState.dl_rate_limit, true) + "]";
|
transfer_info += " [" + window.qBittorrent.Misc.friendlyUnit(serverState.dl_rate_limit, true) + "]";
|
||||||
transfer_info += " (" + friendlyUnit(serverState.dl_info_data, false) + ")";
|
transfer_info += " (" + window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_data, false) + ")";
|
||||||
$("DlInfos").set('html', transfer_info);
|
$("DlInfos").set('html', transfer_info);
|
||||||
transfer_info = friendlyUnit(serverState.up_info_speed, true);
|
transfer_info = window.qBittorrent.Misc.friendlyUnit(serverState.up_info_speed, true);
|
||||||
if (serverState.up_rate_limit > 0)
|
if (serverState.up_rate_limit > 0)
|
||||||
transfer_info += " [" + friendlyUnit(serverState.up_rate_limit, true) + "]";
|
transfer_info += " [" + window.qBittorrent.Misc.friendlyUnit(serverState.up_rate_limit, true) + "]";
|
||||||
transfer_info += " (" + friendlyUnit(serverState.up_info_data, false) + ")";
|
transfer_info += " (" + window.qBittorrent.Misc.friendlyUnit(serverState.up_info_data, false) + ")";
|
||||||
$("UpInfos").set('html', transfer_info);
|
$("UpInfos").set('html', transfer_info);
|
||||||
if (speedInTitle) {
|
if (speedInTitle) {
|
||||||
document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", friendlyUnit(serverState.dl_info_speed, true)).replace("%2", friendlyUnit(serverState.up_info_speed, true)).replace("%3", qbtVersion());
|
document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_speed, true)).replace("%2", window.qBittorrent.Misc.friendlyUnit(serverState.up_info_speed, true)).replace("%3", qbtVersion());
|
||||||
document.title += " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]";
|
document.title += " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
document.title = ("qBittorrent " + qbtVersion() + " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]");
|
document.title = ("qBittorrent " + qbtVersion() + " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]");
|
||||||
$('freeSpaceOnDisk').set('html', 'QBT_TR(Free space: %1)QBT_TR[CONTEXT=HttpServer]'.replace("%1", friendlyUnit(serverState.free_space_on_disk)));
|
$('freeSpaceOnDisk').set('html', 'QBT_TR(Free space: %1)QBT_TR[CONTEXT=HttpServer]'.replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.free_space_on_disk)));
|
||||||
$('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR[CONTEXT=StatusBar]'.replace("%1", serverState.dht_nodes));
|
$('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR[CONTEXT=StatusBar]'.replace("%1", serverState.dht_nodes));
|
||||||
|
|
||||||
// Statistics dialog
|
// Statistics dialog
|
||||||
if (document.getElementById("statisticspage")) {
|
if (document.getElementById("statisticspage")) {
|
||||||
$('AlltimeDL').set('html', friendlyUnit(serverState.alltime_dl, false));
|
$('AlltimeDL').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.alltime_dl, false));
|
||||||
$('AlltimeUL').set('html', friendlyUnit(serverState.alltime_ul, false));
|
$('AlltimeUL').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.alltime_ul, false));
|
||||||
$('TotalWastedSession').set('html', friendlyUnit(serverState.total_wasted_session, false));
|
$('TotalWastedSession').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.total_wasted_session, false));
|
||||||
$('GlobalRatio').set('html', serverState.global_ratio);
|
$('GlobalRatio').set('html', serverState.global_ratio);
|
||||||
$('TotalPeerConnections').set('html', serverState.total_peer_connections);
|
$('TotalPeerConnections').set('html', serverState.total_peer_connections);
|
||||||
$('ReadCacheHits').set('html', serverState.read_cache_hits + "%");
|
$('ReadCacheHits').set('html', serverState.read_cache_hits + "%");
|
||||||
$('TotalBuffersSize').set('html', friendlyUnit(serverState.total_buffers_size, false));
|
$('TotalBuffersSize').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.total_buffers_size, false));
|
||||||
$('WriteCacheOverload').set('html', serverState.write_cache_overload + "%");
|
$('WriteCacheOverload').set('html', serverState.write_cache_overload + "%");
|
||||||
$('ReadCacheOverload').set('html', serverState.read_cache_overload + "%");
|
$('ReadCacheOverload').set('html', serverState.read_cache_overload + "%");
|
||||||
$('QueuedIOJobs').set('html', serverState.queued_io_jobs);
|
$('QueuedIOJobs').set('html', serverState.queued_io_jobs);
|
||||||
$('AverageTimeInQueue').set('html', serverState.average_time_queue + " ms");
|
$('AverageTimeInQueue').set('html', serverState.average_time_queue + " ms");
|
||||||
$('TotalQueuedSize').set('html', friendlyUnit(serverState.total_queued_size, false));
|
$('TotalQueuedSize').set('html', window.qBittorrent.Misc.friendlyUnit(serverState.total_queued_size, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverState.connection_status == "connected")
|
if (serverState.connection_status == "connected")
|
||||||
|
@ -790,7 +779,7 @@ window.addEvent('load', function() {
|
||||||
|
|
||||||
const showSearchTab = function() {
|
const showSearchTab = function() {
|
||||||
if (!searchTabInitialized) {
|
if (!searchTabInitialized) {
|
||||||
initSearchTab();
|
window.qBittorrent.Search.init();
|
||||||
searchTabInitialized = true;
|
searchTabInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,16 +867,26 @@ window.addEvent('load', function() {
|
||||||
MochaUI.initializeTabs('propertiesTabs');
|
MochaUI.initializeTabs('propertiesTabs');
|
||||||
|
|
||||||
updatePropertiesPanel = function() {
|
updatePropertiesPanel = function() {
|
||||||
if (!$('prop_general').hasClass('invisible'))
|
if (!$('prop_general').hasClass('invisible')) {
|
||||||
updateTorrentData();
|
if (window.qBittorrent.PropGeneral !== undefined)
|
||||||
else if (!$('prop_trackers').hasClass('invisible'))
|
window.qBittorrent.PropGeneral.updateData();
|
||||||
updateTrackersData();
|
}
|
||||||
else if (!$('prop_peers').hasClass('invisible'))
|
else if (!$('prop_trackers').hasClass('invisible')) {
|
||||||
updateTorrentPeersData();
|
if (window.qBittorrent.PropTrackers !== undefined)
|
||||||
else if (!$('prop_webseeds').hasClass('invisible'))
|
window.qBittorrent.PropTrackers.updateData();
|
||||||
updateWebSeedsData();
|
}
|
||||||
else if (!$('prop_files').hasClass('invisible'))
|
else if (!$('prop_peers').hasClass('invisible')) {
|
||||||
updateTorrentFilesData();
|
if (window.qBittorrent.PropPeers !== undefined)
|
||||||
|
window.qBittorrent.PropPeers.updateData();
|
||||||
|
}
|
||||||
|
else if (!$('prop_webseeds').hasClass('invisible')) {
|
||||||
|
if (window.qBittorrent.PropWebseeds !== undefined)
|
||||||
|
window.qBittorrent.PropWebseeds.updateData();
|
||||||
|
}
|
||||||
|
else if (!$('prop_files').hasClass('invisible')) {
|
||||||
|
if (window.qBittorrent.PropFiles !== undefined)
|
||||||
|
window.qBittorrent.PropFiles.updateData();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$('PropGeneralLink').addEvent('click', function(e) {
|
$('PropGeneralLink').addEvent('click', function(e) {
|
||||||
|
|
|
@ -28,497 +28,515 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let lastShownContextMenu = null;
|
if (window.qBittorrent === undefined) {
|
||||||
const ContextMenu = new Class({
|
window.qBittorrent = {};
|
||||||
//implements
|
}
|
||||||
Implements: [Options, Events],
|
|
||||||
|
|
||||||
//options
|
window.qBittorrent.ContextMenu = (function() {
|
||||||
options: {
|
const exports = function() {
|
||||||
actions: {},
|
return {
|
||||||
menu: 'menu_id',
|
ContextMenu: ContextMenu,
|
||||||
stopEvent: true,
|
TorrentsTableContextMenu: TorrentsTableContextMenu,
|
||||||
targets: 'body',
|
CategoriesFilterContextMenu: CategoriesFilterContextMenu,
|
||||||
offsets: {
|
TagsFilterContextMenu: TagsFilterContextMenu,
|
||||||
x: 0,
|
SearchPluginsTableContextMenu: SearchPluginsTableContextMenu
|
||||||
y: 0
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let lastShownContextMenu = null;
|
||||||
|
const ContextMenu = new Class({
|
||||||
|
//implements
|
||||||
|
Implements: [Options, Events],
|
||||||
|
|
||||||
|
//options
|
||||||
|
options: {
|
||||||
|
actions: {},
|
||||||
|
menu: 'menu_id',
|
||||||
|
stopEvent: true,
|
||||||
|
targets: 'body',
|
||||||
|
offsets: {
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
onShow: $empty,
|
||||||
|
onHide: $empty,
|
||||||
|
onClick: $empty,
|
||||||
|
fadeSpeed: 200,
|
||||||
|
touchTimer: 600
|
||||||
},
|
},
|
||||||
onShow: $empty,
|
|
||||||
onHide: $empty,
|
|
||||||
onClick: $empty,
|
|
||||||
fadeSpeed: 200,
|
|
||||||
touchTimer: 600
|
|
||||||
},
|
|
||||||
|
|
||||||
//initialization
|
//initialization
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
//set options
|
//set options
|
||||||
this.setOptions(options);
|
this.setOptions(options);
|
||||||
|
|
||||||
//option diffs menu
|
//option diffs menu
|
||||||
this.menu = $(this.options.menu);
|
this.menu = $(this.options.menu);
|
||||||
this.targets = $$(this.options.targets);
|
this.targets = $$(this.options.targets);
|
||||||
|
|
||||||
//fx
|
//fx
|
||||||
this.fx = new Fx.Tween(this.menu, {
|
this.fx = new Fx.Tween(this.menu, {
|
||||||
property: 'opacity',
|
property: 'opacity',
|
||||||
duration: this.options.fadeSpeed,
|
duration: this.options.fadeSpeed,
|
||||||
onComplete: function() {
|
onComplete: function() {
|
||||||
if (this.getStyle('opacity')) {
|
if (this.getStyle('opacity')) {
|
||||||
this.setStyle('visibility', 'visible');
|
this.setStyle('visibility', 'visible');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.setStyle('visibility', 'hidden');
|
this.setStyle('visibility', 'hidden');
|
||||||
}
|
}
|
||||||
}.bind(this.menu)
|
}.bind(this.menu)
|
||||||
});
|
});
|
||||||
|
|
||||||
//hide and begin the listener
|
//hide and begin the listener
|
||||||
this.hide().startListener();
|
this.hide().startListener();
|
||||||
|
|
||||||
|
//hide the menu
|
||||||
|
this.menu.setStyles({
|
||||||
|
'position': 'absolute',
|
||||||
|
'top': '-900000px',
|
||||||
|
'display': 'block'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
adjustMenuPosition: function(e) {
|
||||||
|
this.updateMenuItems();
|
||||||
|
|
||||||
|
const scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75;
|
||||||
|
|
||||||
|
if (this.menu.hasClass('scrollableMenu'))
|
||||||
|
this.menu.setStyle('max-height', scrollableMenuMaxHeight);
|
||||||
|
|
||||||
|
// draw the menu off-screen to know the menu dimensions
|
||||||
|
this.menu.setStyles({
|
||||||
|
left: '-999em',
|
||||||
|
top: '-999em'
|
||||||
|
});
|
||||||
|
|
||||||
|
// position the menu
|
||||||
|
let xPosMenu = e.page.x + this.options.offsets.x;
|
||||||
|
let yPosMenu = e.page.y + this.options.offsets.y;
|
||||||
|
if (xPosMenu + this.menu.offsetWidth > document.documentElement.clientWidth)
|
||||||
|
xPosMenu -= this.menu.offsetWidth;
|
||||||
|
if (yPosMenu + this.menu.offsetHeight > document.documentElement.clientHeight)
|
||||||
|
yPosMenu = document.documentElement.clientHeight - this.menu.offsetHeight;
|
||||||
|
if (xPosMenu < 0)
|
||||||
|
xPosMenu = 0;
|
||||||
|
if (yPosMenu < 0)
|
||||||
|
yPosMenu = 0;
|
||||||
|
this.menu.setStyles({
|
||||||
|
left: xPosMenu,
|
||||||
|
top: yPosMenu,
|
||||||
|
position: 'absolute',
|
||||||
|
'z-index': '2000'
|
||||||
|
});
|
||||||
|
|
||||||
|
// position the sub-menu
|
||||||
|
const uls = this.menu.getElementsByTagName('ul');
|
||||||
|
for (let i = 0; i < uls.length; ++i) {
|
||||||
|
const ul = uls[i];
|
||||||
|
if (ul.hasClass('scrollableMenu'))
|
||||||
|
ul.setStyle('max-height', scrollableMenuMaxHeight);
|
||||||
|
const rectParent = ul.parentNode.getBoundingClientRect();
|
||||||
|
const xPosOrigin = rectParent.left;
|
||||||
|
const yPosOrigin = rectParent.bottom;
|
||||||
|
let xPos = xPosOrigin + rectParent.width - 1;
|
||||||
|
let yPos = yPosOrigin - rectParent.height - 1;
|
||||||
|
if (xPos + ul.offsetWidth > document.documentElement.clientWidth)
|
||||||
|
xPos -= (ul.offsetWidth + rectParent.width - 2);
|
||||||
|
if (yPos + ul.offsetHeight > document.documentElement.clientHeight)
|
||||||
|
yPos = document.documentElement.clientHeight - ul.offsetHeight;
|
||||||
|
if (xPos < 0)
|
||||||
|
xPos = 0;
|
||||||
|
if (yPos < 0)
|
||||||
|
yPos = 0;
|
||||||
|
ul.setStyles({
|
||||||
|
'margin-left': xPos - xPosOrigin,
|
||||||
|
'margin-top': yPos - yPosOrigin
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setupEventListeners: function(elem) {
|
||||||
|
elem.addEvent('contextmenu', function(e) {
|
||||||
|
this.triggerMenu(e, elem);
|
||||||
|
}.bind(this));
|
||||||
|
elem.addEvent('click', function(e) {
|
||||||
|
this.hide();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
elem.addEvent('touchstart', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
clearTimeout(this.touchstartTimer);
|
||||||
|
this.hide();
|
||||||
|
|
||||||
|
const touchstartEvent = e;
|
||||||
|
this.touchstartTimer = setTimeout(function() {
|
||||||
|
this.triggerMenu(touchstartEvent, elem);
|
||||||
|
}.bind(this), this.options.touchTimer);
|
||||||
|
}.bind(this));
|
||||||
|
elem.addEvent('touchend', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
clearTimeout(this.touchstartTimer);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
addTarget: function(t) {
|
||||||
|
this.targets[this.targets.length] = t;
|
||||||
|
this.setupEventListeners(t);
|
||||||
|
},
|
||||||
|
|
||||||
|
triggerMenu: function(e, el) {
|
||||||
|
if (this.options.disabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//prevent default, if told to
|
||||||
|
if (this.options.stopEvent) {
|
||||||
|
e.stop();
|
||||||
|
}
|
||||||
|
//record this as the trigger
|
||||||
|
this.options.element = $(el);
|
||||||
|
this.adjustMenuPosition(e);
|
||||||
|
//show the menu
|
||||||
|
this.show();
|
||||||
|
},
|
||||||
|
|
||||||
|
//get things started
|
||||||
|
startListener: function() {
|
||||||
|
/* all elements */
|
||||||
|
this.targets.each(function(el) {
|
||||||
|
this.setupEventListeners(el);
|
||||||
|
}.bind(this), this);
|
||||||
|
|
||||||
|
/* menu items */
|
||||||
|
this.menu.getElements('a').each(function(item) {
|
||||||
|
item.addEvent('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!item.hasClass('disabled')) {
|
||||||
|
this.execute(item.get('href').split('#')[1], $(this.options.element));
|
||||||
|
this.fireEvent('click', [item, e]);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
//hide on body click
|
||||||
|
$(document.body).addEvent('click', function() {
|
||||||
|
this.hide();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
updateMenuItems: function() {},
|
||||||
|
|
||||||
|
//show menu
|
||||||
|
show: function(trigger) {
|
||||||
|
if (lastShownContextMenu && lastShownContextMenu != this)
|
||||||
|
lastShownContextMenu.hide();
|
||||||
|
this.fx.start(1);
|
||||||
|
this.fireEvent('show');
|
||||||
|
this.shown = true;
|
||||||
|
lastShownContextMenu = this;
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
//hide the menu
|
//hide the menu
|
||||||
this.menu.setStyles({
|
hide: function(trigger) {
|
||||||
'position': 'absolute',
|
if (this.shown) {
|
||||||
'top': '-900000px',
|
this.fx.start(0);
|
||||||
'display': 'block'
|
//this.menu.fade('out');
|
||||||
});
|
this.fireEvent('hide');
|
||||||
},
|
this.shown = false;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
adjustMenuPosition: function(e) {
|
setItemChecked: function(item, checked) {
|
||||||
this.updateMenuItems();
|
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
|
||||||
|
checked ? '1' : '0';
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
const scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75;
|
getItemChecked: function(item) {
|
||||||
|
return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity;
|
||||||
|
},
|
||||||
|
|
||||||
if (this.menu.hasClass('scrollableMenu'))
|
//hide an item
|
||||||
this.menu.setStyle('max-height', scrollableMenuMaxHeight);
|
hideItem: function(item) {
|
||||||
|
this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible');
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
// draw the menu off-screen to know the menu dimensions
|
//show an item
|
||||||
this.menu.setStyles({
|
showItem: function(item) {
|
||||||
left: '-999em',
|
this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible');
|
||||||
top: '-999em'
|
return this;
|
||||||
});
|
},
|
||||||
|
|
||||||
// position the menu
|
//disable the entire menu
|
||||||
let xPosMenu = e.page.x + this.options.offsets.x;
|
disable: function() {
|
||||||
let yPosMenu = e.page.y + this.options.offsets.y;
|
this.options.disabled = true;
|
||||||
if (xPosMenu + this.menu.offsetWidth > document.documentElement.clientWidth)
|
return this;
|
||||||
xPosMenu -= this.menu.offsetWidth;
|
},
|
||||||
if (yPosMenu + this.menu.offsetHeight > document.documentElement.clientHeight)
|
|
||||||
yPosMenu = document.documentElement.clientHeight - this.menu.offsetHeight;
|
|
||||||
if (xPosMenu < 0)
|
|
||||||
xPosMenu = 0;
|
|
||||||
if (yPosMenu < 0)
|
|
||||||
yPosMenu = 0;
|
|
||||||
this.menu.setStyles({
|
|
||||||
left: xPosMenu,
|
|
||||||
top: yPosMenu,
|
|
||||||
position: 'absolute',
|
|
||||||
'z-index': '2000'
|
|
||||||
});
|
|
||||||
|
|
||||||
// position the sub-menu
|
//enable the entire menu
|
||||||
const uls = this.menu.getElementsByTagName('ul');
|
enable: function() {
|
||||||
for (let i = 0; i < uls.length; ++i) {
|
this.options.disabled = false;
|
||||||
const ul = uls[i];
|
return this;
|
||||||
if (ul.hasClass('scrollableMenu'))
|
},
|
||||||
ul.setStyle('max-height', scrollableMenuMaxHeight);
|
|
||||||
const rectParent = ul.parentNode.getBoundingClientRect();
|
//execute an action
|
||||||
const xPosOrigin = rectParent.left;
|
execute: function(action, element) {
|
||||||
const yPosOrigin = rectParent.bottom;
|
if (this.options.actions[action]) {
|
||||||
let xPos = xPosOrigin + rectParent.width - 1;
|
this.options.actions[action](element, this, action);
|
||||||
let yPos = yPosOrigin - rectParent.height - 1;
|
}
|
||||||
if (xPos + ul.offsetWidth > document.documentElement.clientWidth)
|
return this;
|
||||||
xPos -= (ul.offsetWidth + rectParent.width - 2);
|
|
||||||
if (yPos + ul.offsetHeight > document.documentElement.clientHeight)
|
|
||||||
yPos = document.documentElement.clientHeight - ul.offsetHeight;
|
|
||||||
if (xPos < 0)
|
|
||||||
xPos = 0;
|
|
||||||
if (yPos < 0)
|
|
||||||
yPos = 0;
|
|
||||||
ul.setStyles({
|
|
||||||
'margin-left': xPos - xPosOrigin,
|
|
||||||
'margin-top': yPos - yPosOrigin
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
|
|
||||||
setupEventListeners: function(elem) {
|
const TorrentsTableContextMenu = new Class({
|
||||||
elem.addEvent('contextmenu', function(e) {
|
Extends: ContextMenu,
|
||||||
this.triggerMenu(e, elem);
|
|
||||||
}.bind(this));
|
|
||||||
elem.addEvent('click', function(e) {
|
|
||||||
this.hide();
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
elem.addEvent('touchstart', function(e) {
|
updateMenuItems: function() {
|
||||||
e.preventDefault();
|
let all_are_seq_dl = true;
|
||||||
clearTimeout(this.touchstartTimer);
|
let there_are_seq_dl = false;
|
||||||
this.hide();
|
let all_are_f_l_piece_prio = true;
|
||||||
|
let there_are_f_l_piece_prio = false;
|
||||||
|
let all_are_downloaded = true;
|
||||||
|
let all_are_paused = true;
|
||||||
|
let there_are_paused = false;
|
||||||
|
let all_are_force_start = true;
|
||||||
|
let there_are_force_start = false;
|
||||||
|
let all_are_super_seeding = true;
|
||||||
|
let all_are_auto_tmm = true;
|
||||||
|
let there_are_auto_tmm = false;
|
||||||
|
const tagsSelectionState = Object.clone(tagList);
|
||||||
|
|
||||||
const touchstartEvent = e;
|
const h = torrentsTable.selectedRowsIds();
|
||||||
this.touchstartTimer = setTimeout(function() {
|
h.each(function(item, index) {
|
||||||
this.triggerMenu(touchstartEvent, elem);
|
const data = torrentsTable.rows.get(item).full_data;
|
||||||
}.bind(this), this.options.touchTimer);
|
|
||||||
}.bind(this));
|
|
||||||
elem.addEvent('touchend', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
clearTimeout(this.touchstartTimer);
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
addTarget: function(t) {
|
if (data['seq_dl'] !== true)
|
||||||
this.targets[this.targets.length] = t;
|
all_are_seq_dl = false;
|
||||||
this.setupEventListeners(t);
|
|
||||||
},
|
|
||||||
|
|
||||||
triggerMenu: function(e, el) {
|
|
||||||
if (this.options.disabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//prevent default, if told to
|
|
||||||
if (this.options.stopEvent) {
|
|
||||||
e.stop();
|
|
||||||
}
|
|
||||||
//record this as the trigger
|
|
||||||
this.options.element = $(el);
|
|
||||||
this.adjustMenuPosition(e);
|
|
||||||
//show the menu
|
|
||||||
this.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
//get things started
|
|
||||||
startListener: function() {
|
|
||||||
/* all elements */
|
|
||||||
this.targets.each(function(el) {
|
|
||||||
this.setupEventListeners(el);
|
|
||||||
}.bind(this), this);
|
|
||||||
|
|
||||||
/* menu items */
|
|
||||||
this.menu.getElements('a').each(function(item) {
|
|
||||||
item.addEvent('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (!item.hasClass('disabled')) {
|
|
||||||
this.execute(item.get('href').split('#')[1], $(this.options.element));
|
|
||||||
this.fireEvent('click', [item, e]);
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
//hide on body click
|
|
||||||
$(document.body).addEvent('click', function() {
|
|
||||||
this.hide();
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
updateMenuItems: function() {},
|
|
||||||
|
|
||||||
//show menu
|
|
||||||
show: function(trigger) {
|
|
||||||
if (lastShownContextMenu && lastShownContextMenu != this)
|
|
||||||
lastShownContextMenu.hide();
|
|
||||||
this.fx.start(1);
|
|
||||||
this.fireEvent('show');
|
|
||||||
this.shown = true;
|
|
||||||
lastShownContextMenu = this;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
//hide the menu
|
|
||||||
hide: function(trigger) {
|
|
||||||
if (this.shown) {
|
|
||||||
this.fx.start(0);
|
|
||||||
//this.menu.fade('out');
|
|
||||||
this.fireEvent('hide');
|
|
||||||
this.shown = false;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
setItemChecked: function(item, checked) {
|
|
||||||
this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity =
|
|
||||||
checked ? '1' : '0';
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
getItemChecked: function(item) {
|
|
||||||
return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity;
|
|
||||||
},
|
|
||||||
|
|
||||||
//hide an item
|
|
||||||
hideItem: function(item) {
|
|
||||||
this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible');
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
//show an item
|
|
||||||
showItem: function(item) {
|
|
||||||
this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible');
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
//disable the entire menu
|
|
||||||
disable: function() {
|
|
||||||
this.options.disabled = true;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
//enable the entire menu
|
|
||||||
enable: function() {
|
|
||||||
this.options.disabled = false;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
//execute an action
|
|
||||||
execute: function(action, element) {
|
|
||||||
if (this.options.actions[action]) {
|
|
||||||
this.options.actions[action](element, this, action);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const TorrentsTableContextMenu = new Class({
|
|
||||||
Extends: ContextMenu,
|
|
||||||
|
|
||||||
updateMenuItems: function() {
|
|
||||||
let all_are_seq_dl = true;
|
|
||||||
let there_are_seq_dl = false;
|
|
||||||
let all_are_f_l_piece_prio = true;
|
|
||||||
let there_are_f_l_piece_prio = false;
|
|
||||||
let all_are_downloaded = true;
|
|
||||||
let all_are_paused = true;
|
|
||||||
let there_are_paused = false;
|
|
||||||
let all_are_force_start = true;
|
|
||||||
let there_are_force_start = false;
|
|
||||||
let all_are_super_seeding = true;
|
|
||||||
let all_are_auto_tmm = true;
|
|
||||||
let there_are_auto_tmm = false;
|
|
||||||
const tagsSelectionState = Object.clone(tagList);
|
|
||||||
|
|
||||||
const h = torrentsTable.selectedRowsIds();
|
|
||||||
h.each(function(item, index) {
|
|
||||||
const data = torrentsTable.rows.get(item).full_data;
|
|
||||||
|
|
||||||
if (data['seq_dl'] !== true)
|
|
||||||
all_are_seq_dl = false;
|
|
||||||
else
|
|
||||||
there_are_seq_dl = true;
|
|
||||||
|
|
||||||
if (data['f_l_piece_prio'] !== true)
|
|
||||||
all_are_f_l_piece_prio = false;
|
|
||||||
else
|
|
||||||
there_are_f_l_piece_prio = true;
|
|
||||||
|
|
||||||
if (data['progress'] != 1.0) // not downloaded
|
|
||||||
all_are_downloaded = false;
|
|
||||||
else if (data['super_seeding'] !== true)
|
|
||||||
all_are_super_seeding = false;
|
|
||||||
|
|
||||||
if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
|
|
||||||
all_are_paused = false;
|
|
||||||
else
|
|
||||||
there_are_paused = true;
|
|
||||||
|
|
||||||
if (data['force_start'] !== true)
|
|
||||||
all_are_force_start = false;
|
|
||||||
else
|
|
||||||
there_are_force_start = true;
|
|
||||||
|
|
||||||
if (data['auto_tmm'] === true)
|
|
||||||
there_are_auto_tmm = true;
|
|
||||||
else
|
|
||||||
all_are_auto_tmm = false;
|
|
||||||
|
|
||||||
const torrentTags = data['tags'].split(', ');
|
|
||||||
for (const key in tagsSelectionState) {
|
|
||||||
const tag = tagsSelectionState[key];
|
|
||||||
const tagExists = torrentTags.contains(tag.name);
|
|
||||||
if ((tag.checked !== undefined) && (tag.checked != tagExists))
|
|
||||||
tag.indeterminate = true;
|
|
||||||
if (tag.checked === undefined)
|
|
||||||
tag.checked = tagExists;
|
|
||||||
else
|
else
|
||||||
tag.checked = tag.checked && tagExists;
|
there_are_seq_dl = true;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let show_seq_dl = true;
|
if (data['f_l_piece_prio'] !== true)
|
||||||
|
all_are_f_l_piece_prio = false;
|
||||||
|
else
|
||||||
|
there_are_f_l_piece_prio = true;
|
||||||
|
|
||||||
if (!all_are_seq_dl && there_are_seq_dl)
|
if (data['progress'] != 1.0) // not downloaded
|
||||||
show_seq_dl = false;
|
all_are_downloaded = false;
|
||||||
|
else if (data['super_seeding'] !== true)
|
||||||
|
all_are_super_seeding = false;
|
||||||
|
|
||||||
let show_f_l_piece_prio = true;
|
if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
|
||||||
|
all_are_paused = false;
|
||||||
|
else
|
||||||
|
there_are_paused = true;
|
||||||
|
|
||||||
if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
|
if (data['force_start'] !== true)
|
||||||
show_f_l_piece_prio = false;
|
all_are_force_start = false;
|
||||||
|
else
|
||||||
|
there_are_force_start = true;
|
||||||
|
|
||||||
if (all_are_downloaded) {
|
if (data['auto_tmm'] === true)
|
||||||
this.hideItem('downloadLimit');
|
there_are_auto_tmm = true;
|
||||||
this.menu.getElement('a[href$=uploadLimit]').parentNode.addClass('separator');
|
else
|
||||||
this.hideItem('sequentialDownload');
|
all_are_auto_tmm = false;
|
||||||
this.hideItem('firstLastPiecePrio');
|
|
||||||
this.showItem('superSeeding');
|
|
||||||
this.setItemChecked('superSeeding', all_are_super_seeding);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!show_seq_dl && show_f_l_piece_prio)
|
|
||||||
this.menu.getElement('a[href$=firstLastPiecePrio]').parentNode.addClass('separator');
|
|
||||||
else
|
|
||||||
this.menu.getElement('a[href$=firstLastPiecePrio]').parentNode.removeClass('separator');
|
|
||||||
|
|
||||||
if (show_seq_dl)
|
const torrentTags = data['tags'].split(', ');
|
||||||
this.showItem('sequentialDownload');
|
for (const key in tagsSelectionState) {
|
||||||
else
|
const tag = tagsSelectionState[key];
|
||||||
|
const tagExists = torrentTags.contains(tag.name);
|
||||||
|
if ((tag.checked !== undefined) && (tag.checked != tagExists))
|
||||||
|
tag.indeterminate = true;
|
||||||
|
if (tag.checked === undefined)
|
||||||
|
tag.checked = tagExists;
|
||||||
|
else
|
||||||
|
tag.checked = tag.checked && tagExists;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let show_seq_dl = true;
|
||||||
|
|
||||||
|
if (!all_are_seq_dl && there_are_seq_dl)
|
||||||
|
show_seq_dl = false;
|
||||||
|
|
||||||
|
let show_f_l_piece_prio = true;
|
||||||
|
|
||||||
|
if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio)
|
||||||
|
show_f_l_piece_prio = false;
|
||||||
|
|
||||||
|
if (all_are_downloaded) {
|
||||||
|
this.hideItem('downloadLimit');
|
||||||
|
this.menu.getElement('a[href$=uploadLimit]').parentNode.addClass('separator');
|
||||||
this.hideItem('sequentialDownload');
|
this.hideItem('sequentialDownload');
|
||||||
|
|
||||||
if (show_f_l_piece_prio)
|
|
||||||
this.showItem('firstLastPiecePrio');
|
|
||||||
else
|
|
||||||
this.hideItem('firstLastPiecePrio');
|
this.hideItem('firstLastPiecePrio');
|
||||||
|
this.showItem('superSeeding');
|
||||||
this.setItemChecked('sequentialDownload', all_are_seq_dl);
|
this.setItemChecked('superSeeding', all_are_super_seeding);
|
||||||
this.setItemChecked('firstLastPiecePrio', all_are_f_l_piece_prio);
|
|
||||||
|
|
||||||
this.showItem('downloadLimit');
|
|
||||||
this.menu.getElement('a[href$=uploadLimit]').parentNode.removeClass('separator');
|
|
||||||
this.hideItem('superSeeding');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showItem('start');
|
|
||||||
this.showItem('pause');
|
|
||||||
this.showItem('forceStart');
|
|
||||||
if (all_are_paused)
|
|
||||||
this.hideItem('pause');
|
|
||||||
else if (all_are_force_start)
|
|
||||||
this.hideItem('forceStart');
|
|
||||||
else if (!there_are_paused && !there_are_force_start)
|
|
||||||
this.hideItem('start');
|
|
||||||
|
|
||||||
if (!all_are_auto_tmm && there_are_auto_tmm) {
|
|
||||||
this.hideItem('autoTorrentManagement');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.showItem('autoTorrentManagement');
|
|
||||||
this.setItemChecked('autoTorrentManagement', all_are_auto_tmm);
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextTagList = $('contextTagList');
|
|
||||||
for (const tagHash in tagList) {
|
|
||||||
const checkbox = contextTagList.getElement('a[href=#Tag/' + tagHash + '] input[type=checkbox]');
|
|
||||||
const checkboxState = tagsSelectionState[tagHash];
|
|
||||||
checkbox.indeterminate = checkboxState.indeterminate;
|
|
||||||
checkbox.checked = checkboxState.checked;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateCategoriesSubMenu: function(category_list) {
|
|
||||||
const categoryList = $('contextCategoryList');
|
|
||||||
categoryList.empty();
|
|
||||||
categoryList.appendChild(new Element('li', {
|
|
||||||
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/qbt-theme/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
|
||||||
}));
|
|
||||||
categoryList.appendChild(new Element('li', {
|
|
||||||
html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
|
||||||
}));
|
|
||||||
|
|
||||||
const sortedCategories = [];
|
|
||||||
Object.each(category_list, function(category) {
|
|
||||||
sortedCategories.push(category.name);
|
|
||||||
});
|
|
||||||
sortedCategories.sort();
|
|
||||||
|
|
||||||
let first = true;
|
|
||||||
Object.each(sortedCategories, function(categoryName) {
|
|
||||||
const categoryHash = genHash(categoryName);
|
|
||||||
const el = new Element('li', {
|
|
||||||
html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="images/qbt-theme/inode-directory.svg"/> ' + escapeHtml(categoryName) + '</a>'
|
|
||||||
});
|
|
||||||
if (first) {
|
|
||||||
el.addClass('separator');
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
categoryList.appendChild(el);
|
else {
|
||||||
});
|
if (!show_seq_dl && show_f_l_piece_prio)
|
||||||
},
|
this.menu.getElement('a[href$=firstLastPiecePrio]').parentNode.addClass('separator');
|
||||||
|
else
|
||||||
|
this.menu.getElement('a[href$=firstLastPiecePrio]').parentNode.removeClass('separator');
|
||||||
|
|
||||||
updateTagsSubMenu: function(tagList) {
|
if (show_seq_dl)
|
||||||
const contextTagList = $('contextTagList');
|
this.showItem('sequentialDownload');
|
||||||
while (contextTagList.firstChild !== null)
|
else
|
||||||
contextTagList.removeChild(contextTagList.firstChild);
|
this.hideItem('sequentialDownload');
|
||||||
|
|
||||||
contextTagList.appendChild(new Element('li', {
|
if (show_f_l_piece_prio)
|
||||||
html: '<a href="javascript:torrentAddTagsFN();">'
|
this.showItem('firstLastPiecePrio');
|
||||||
+ '<img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
|
else
|
||||||
+ ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
|
this.hideItem('firstLastPiecePrio');
|
||||||
+ '</a>'
|
|
||||||
}));
|
|
||||||
contextTagList.appendChild(new Element('li', {
|
|
||||||
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
|
|
||||||
+ '<img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
|
|
||||||
+ ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
|
|
||||||
+ '</a>'
|
|
||||||
}));
|
|
||||||
|
|
||||||
const sortedTags = [];
|
this.setItemChecked('sequentialDownload', all_are_seq_dl);
|
||||||
for (const key in tagList)
|
this.setItemChecked('firstLastPiecePrio', all_are_f_l_piece_prio);
|
||||||
sortedTags.push(tagList[key].name);
|
|
||||||
sortedTags.sort();
|
|
||||||
|
|
||||||
for (let i = 0; i < sortedTags.length; ++i) {
|
this.showItem('downloadLimit');
|
||||||
const tagName = sortedTags[i];
|
this.menu.getElement('a[href$=uploadLimit]').parentNode.removeClass('separator');
|
||||||
const tagHash = genHash(tagName);
|
this.hideItem('superSeeding');
|
||||||
const el = new Element('li', {
|
}
|
||||||
html: '<a href="#Tag/' + tagHash + '" onclick="event.preventDefault(); torrentSetTagsFN(\'' + tagHash + '\', !event.currentTarget.getElement(\'input[type=checkbox]\').checked);">'
|
|
||||||
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + escapeHtml(tagName)
|
this.showItem('start');
|
||||||
+ '</a>'
|
this.showItem('pause');
|
||||||
|
this.showItem('forceStart');
|
||||||
|
if (all_are_paused)
|
||||||
|
this.hideItem('pause');
|
||||||
|
else if (all_are_force_start)
|
||||||
|
this.hideItem('forceStart');
|
||||||
|
else if (!there_are_paused && !there_are_force_start)
|
||||||
|
this.hideItem('start');
|
||||||
|
|
||||||
|
if (!all_are_auto_tmm && there_are_auto_tmm) {
|
||||||
|
this.hideItem('autoTorrentManagement');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.showItem('autoTorrentManagement');
|
||||||
|
this.setItemChecked('autoTorrentManagement', all_are_auto_tmm);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextTagList = $('contextTagList');
|
||||||
|
for (const tagHash in tagList) {
|
||||||
|
const checkbox = contextTagList.getElement('a[href=#Tag/' + tagHash + '] input[type=checkbox]');
|
||||||
|
const checkboxState = tagsSelectionState[tagHash];
|
||||||
|
checkbox.indeterminate = checkboxState.indeterminate;
|
||||||
|
checkbox.checked = checkboxState.checked;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateCategoriesSubMenu: function(category_list) {
|
||||||
|
const categoryList = $('contextCategoryList');
|
||||||
|
categoryList.empty();
|
||||||
|
categoryList.appendChild(new Element('li', {
|
||||||
|
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/qbt-theme/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
||||||
|
}));
|
||||||
|
categoryList.appendChild(new Element('li', {
|
||||||
|
html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
||||||
|
}));
|
||||||
|
|
||||||
|
const sortedCategories = [];
|
||||||
|
Object.each(category_list, function(category) {
|
||||||
|
sortedCategories.push(category.name);
|
||||||
});
|
});
|
||||||
if (i === 0)
|
sortedCategories.sort();
|
||||||
el.addClass('separator');
|
|
||||||
contextTagList.appendChild(el);
|
let first = true;
|
||||||
|
Object.each(sortedCategories, function(categoryName) {
|
||||||
|
const categoryHash = genHash(categoryName);
|
||||||
|
const el = new Element('li', {
|
||||||
|
html: '<a href="javascript:torrentSetCategoryFN(\'' + categoryHash + '\');"><img src="images/qbt-theme/inode-directory.svg"/> ' + window.qBittorrent.Misc.escapeHtml(categoryName) + '</a>'
|
||||||
|
});
|
||||||
|
if (first) {
|
||||||
|
el.addClass('separator');
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
categoryList.appendChild(el);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTagsSubMenu: function(tagList) {
|
||||||
|
const contextTagList = $('contextTagList');
|
||||||
|
while (contextTagList.firstChild !== null)
|
||||||
|
contextTagList.removeChild(contextTagList.firstChild);
|
||||||
|
|
||||||
|
contextTagList.appendChild(new Element('li', {
|
||||||
|
html: '<a href="javascript:torrentAddTagsFN();">'
|
||||||
|
+ '<img src="images/qbt-theme/list-add.svg" alt="QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]"/>'
|
||||||
|
+ ' QBT_TR(Add...)QBT_TR[CONTEXT=TransferListWidget]'
|
||||||
|
+ '</a>'
|
||||||
|
}));
|
||||||
|
contextTagList.appendChild(new Element('li', {
|
||||||
|
html: '<a href="javascript:torrentRemoveAllTagsFN();">'
|
||||||
|
+ '<img src="images/qbt-theme/edit-clear.svg" alt="QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]"/>'
|
||||||
|
+ ' QBT_TR(Remove All)QBT_TR[CONTEXT=TransferListWidget]'
|
||||||
|
+ '</a>'
|
||||||
|
}));
|
||||||
|
|
||||||
|
const sortedTags = [];
|
||||||
|
for (const key in tagList)
|
||||||
|
sortedTags.push(tagList[key].name);
|
||||||
|
sortedTags.sort();
|
||||||
|
|
||||||
|
for (let i = 0; i < sortedTags.length; ++i) {
|
||||||
|
const tagName = sortedTags[i];
|
||||||
|
const tagHash = genHash(tagName);
|
||||||
|
const el = new Element('li', {
|
||||||
|
html: '<a href="#Tag/' + tagHash + '" onclick="event.preventDefault(); torrentSetTagsFN(\'' + tagHash + '\', !event.currentTarget.getElement(\'input[type=checkbox]\').checked);">'
|
||||||
|
+ '<input type="checkbox" onclick="this.checked = !this.checked;"> ' + window.qBittorrent.Misc.escapeHtml(tagName)
|
||||||
|
+ '</a>'
|
||||||
|
});
|
||||||
|
if (i === 0)
|
||||||
|
el.addClass('separator');
|
||||||
|
contextTagList.appendChild(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const CategoriesFilterContextMenu = new Class({
|
const CategoriesFilterContextMenu = new Class({
|
||||||
Extends: ContextMenu,
|
Extends: ContextMenu,
|
||||||
updateMenuItems: function() {
|
updateMenuItems: function() {
|
||||||
const id = this.options.element.id;
|
const id = this.options.element.id;
|
||||||
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
|
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
|
||||||
this.showItem('editCategory');
|
this.showItem('editCategory');
|
||||||
this.showItem('deleteCategory');
|
this.showItem('deleteCategory');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.hideItem('editCategory');
|
||||||
|
this.hideItem('deleteCategory');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
});
|
||||||
this.hideItem('editCategory');
|
|
||||||
this.hideItem('deleteCategory');
|
const TagsFilterContextMenu = new Class({
|
||||||
|
Extends: ContextMenu,
|
||||||
|
updateMenuItems: function() {
|
||||||
|
const id = this.options.element.id;
|
||||||
|
if ((id !== TAGS_ALL.toString()) && (id !== TAGS_UNTAGGED.toString()))
|
||||||
|
this.showItem('deleteTag');
|
||||||
|
else
|
||||||
|
this.hideItem('deleteTag');
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
const TagsFilterContextMenu = new Class({
|
const SearchPluginsTableContextMenu = new Class({
|
||||||
Extends: ContextMenu,
|
Extends: ContextMenu,
|
||||||
updateMenuItems: function() {
|
|
||||||
const id = this.options.element.id;
|
|
||||||
if ((id !== TAGS_ALL.toString()) && (id !== TAGS_UNTAGGED.toString()))
|
|
||||||
this.showItem('deleteTag');
|
|
||||||
else
|
|
||||||
this.hideItem('deleteTag');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const SearchPluginsTableContextMenu = new Class({
|
updateMenuItems: function() {
|
||||||
Extends: ContextMenu,
|
const enabledColumnIndex = function(text) {
|
||||||
|
const columns = $("searchPluginsTableFixedHeaderRow").getChildren("th");
|
||||||
|
for (let i = 0; i < columns.length; ++i)
|
||||||
|
if (columns[i].get("html") === "Enabled")
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
updateMenuItems: function() {
|
this.showItem('Enabled');
|
||||||
const enabledColumnIndex = function(text) {
|
this.setItemChecked('Enabled', this.options.element.getChildren("td")[enabledColumnIndex()].get("html") === "Yes");
|
||||||
const columns = $("searchPluginsTableFixedHeaderRow").getChildren("th");
|
|
||||||
for (let i = 0; i < columns.length; ++i)
|
|
||||||
if (columns[i].get("html") === "Enabled")
|
|
||||||
return i;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.showItem('Enabled');
|
this.showItem('Uninstall');
|
||||||
this.setItemChecked('Enabled', this.options.element.getChildren("td")[enabledColumnIndex()].get("html") === "Yes");
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.showItem('Uninstall');
|
return exports();
|
||||||
}
|
})();
|
||||||
});
|
|
||||||
|
|
|
@ -23,98 +23,113 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let categories = {};
|
if (window.qBittorrent === undefined) {
|
||||||
let defaultSavePath = "";
|
window.qBittorrent = {};
|
||||||
|
}
|
||||||
|
|
||||||
const getCategories = function() {
|
window.qBittorrent.Download = (function() {
|
||||||
new Request.JSON({
|
const exports = function() {
|
||||||
url: 'api/v2/torrents/categories',
|
return {
|
||||||
noCache: true,
|
changeCategorySelect: changeCategorySelect,
|
||||||
method: 'get',
|
changeTMM: changeTMM
|
||||||
onSuccess: function(data) {
|
};
|
||||||
if (data) {
|
};
|
||||||
categories = data;
|
|
||||||
for (const i in data) {
|
let categories = {};
|
||||||
const category = data[i];
|
let defaultSavePath = "";
|
||||||
const option = new Element("option");
|
|
||||||
option.set('value', category.name);
|
const getCategories = function() {
|
||||||
option.set('html', category.name);
|
new Request.JSON({
|
||||||
$('categorySelect').appendChild(option);
|
url: 'api/v2/torrents/categories',
|
||||||
|
noCache: true,
|
||||||
|
method: 'get',
|
||||||
|
onSuccess: function(data) {
|
||||||
|
if (data) {
|
||||||
|
categories = data;
|
||||||
|
for (const i in data) {
|
||||||
|
const category = data[i];
|
||||||
|
const option = new Element("option");
|
||||||
|
option.set('value', category.name);
|
||||||
|
option.set('html', category.name);
|
||||||
|
$('categorySelect').appendChild(option);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}).send();
|
||||||
}).send();
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const getPreferences = function() {
|
const getPreferences = function() {
|
||||||
new Request.JSON({
|
new Request.JSON({
|
||||||
url: 'api/v2/app/preferences',
|
url: 'api/v2/app/preferences',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
noCache: true,
|
noCache: true,
|
||||||
onFailure: function() {
|
onFailure: function() {
|
||||||
alert("Could not contact qBittorrent");
|
alert("Could not contact qBittorrent");
|
||||||
},
|
},
|
||||||
onSuccess: function(pref) {
|
onSuccess: function(pref) {
|
||||||
if (!pref)
|
if (!pref)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
defaultSavePath = pref.save_path;
|
defaultSavePath = pref.save_path;
|
||||||
$('savepath').setProperty('value', defaultSavePath);
|
$('savepath').setProperty('value', defaultSavePath);
|
||||||
$('rootFolder').checked = pref.create_subfolder_enabled;
|
$('rootFolder').checked = pref.create_subfolder_enabled;
|
||||||
$('startTorrent').checked = !pref.start_paused_enabled;
|
$('startTorrent').checked = !pref.start_paused_enabled;
|
||||||
|
|
||||||
if (pref.auto_tmm_enabled == 1) {
|
if (pref.auto_tmm_enabled == 1) {
|
||||||
$('autoTMM').selectedIndex = 1;
|
$('autoTMM').selectedIndex = 1;
|
||||||
$('savepath').disabled = true;
|
$('savepath').disabled = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('autoTMM').selectedIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
}).send();
|
||||||
$('autoTMM').selectedIndex = 0;
|
};
|
||||||
|
|
||||||
|
const changeCategorySelect = function(item) {
|
||||||
|
if (item.value == "\\other") {
|
||||||
|
item.nextElementSibling.hidden = false;
|
||||||
|
item.nextElementSibling.value = "";
|
||||||
|
item.nextElementSibling.select();
|
||||||
|
|
||||||
|
if ($('autoTMM').selectedIndex == 1)
|
||||||
|
$('savepath').value = defaultSavePath;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item.nextElementSibling.hidden = true;
|
||||||
|
const text = item.options[item.selectedIndex].innerHTML;
|
||||||
|
item.nextElementSibling.value = text;
|
||||||
|
|
||||||
|
if ($('autoTMM').selectedIndex == 1) {
|
||||||
|
const categoryName = item.value;
|
||||||
|
const category = categories[categoryName];
|
||||||
|
let savePath = defaultSavePath;
|
||||||
|
if (category !== undefined)
|
||||||
|
savePath = (category['savePath'] !== "") ? category['savePath'] : (defaultSavePath + categoryName);
|
||||||
|
$('savepath').value = savePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).send();
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const changeCategorySelect = function(item) {
|
const changeTMM = function(item) {
|
||||||
if (item.value == "\\other") {
|
if (item.selectedIndex == 1) {
|
||||||
item.nextElementSibling.hidden = false;
|
$('savepath').disabled = true;
|
||||||
item.nextElementSibling.value = "";
|
|
||||||
item.nextElementSibling.select();
|
|
||||||
|
|
||||||
if ($('autoTMM').selectedIndex == 1)
|
const categorySelect = $('categorySelect');
|
||||||
$('savepath').value = defaultSavePath;
|
const categoryName = categorySelect.options[categorySelect.selectedIndex].value;
|
||||||
}
|
|
||||||
else {
|
|
||||||
item.nextElementSibling.hidden = true;
|
|
||||||
const text = item.options[item.selectedIndex].innerHTML;
|
|
||||||
item.nextElementSibling.value = text;
|
|
||||||
|
|
||||||
if ($('autoTMM').selectedIndex == 1) {
|
|
||||||
const categoryName = item.value;
|
|
||||||
const category = categories[categoryName];
|
const category = categories[categoryName];
|
||||||
let savePath = defaultSavePath;
|
$('savepath').value = (category === undefined) ? "" : category['savePath'];
|
||||||
if (category !== undefined)
|
|
||||||
savePath = (category['savePath'] !== "") ? category['savePath'] : (defaultSavePath + categoryName);
|
|
||||||
$('savepath').value = savePath;
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
};
|
$('savepath').disabled = false;
|
||||||
|
$('savepath').value = defaultSavePath;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const changeTMM = function(item) {
|
$(window).addEventListener("load", function() {
|
||||||
if (item.selectedIndex == 1) {
|
getPreferences();
|
||||||
$('savepath').disabled = true;
|
getCategories();
|
||||||
|
});
|
||||||
|
|
||||||
const categorySelect = $('categorySelect');
|
return exports();
|
||||||
const categoryName = categorySelect.options[categorySelect.selectedIndex].value;
|
})();
|
||||||
const category = categories[categoryName];
|
|
||||||
$('savepath').value = (category === undefined) ? "" : category['savePath'];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('savepath').disabled = false;
|
|
||||||
$('savepath').value = defaultSavePath;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$(window).addEventListener("load", function() {
|
|
||||||
getPreferences();
|
|
||||||
getCategories();
|
|
||||||
});
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,149 +28,167 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const FilePriority = {
|
if (window.qBittorrent === undefined) {
|
||||||
"Ignored": 0,
|
window.qBittorrent = {};
|
||||||
"Normal": 1,
|
}
|
||||||
"High": 6,
|
|
||||||
"Maximum": 7,
|
|
||||||
"Mixed": -1
|
|
||||||
};
|
|
||||||
Object.freeze(FilePriority);
|
|
||||||
|
|
||||||
const TriState = {
|
window.qBittorrent.FileTree = (function() {
|
||||||
"Unchecked": 0,
|
const exports = function() {
|
||||||
"Checked": 1,
|
return {
|
||||||
"Partial": 2
|
FilePriority: FilePriority,
|
||||||
};
|
TriState: TriState,
|
||||||
Object.freeze(TriState);
|
FileTree: FileTree,
|
||||||
|
FileNode: FileNode,
|
||||||
|
FolderNode: FolderNode,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const FileTree = new Class({
|
const FilePriority = {
|
||||||
root: null,
|
"Ignored": 0,
|
||||||
nodeMap: {},
|
"Normal": 1,
|
||||||
|
"High": 6,
|
||||||
|
"Maximum": 7,
|
||||||
|
"Mixed": -1
|
||||||
|
};
|
||||||
|
Object.freeze(FilePriority);
|
||||||
|
|
||||||
setRoot: function(root) {
|
const TriState = {
|
||||||
this.root = root;
|
"Unchecked": 0,
|
||||||
this.generateNodeMap(root);
|
"Checked": 1,
|
||||||
|
"Partial": 2
|
||||||
|
};
|
||||||
|
Object.freeze(TriState);
|
||||||
|
|
||||||
if (this.root.isFolder)
|
const FileTree = new Class({
|
||||||
this.root.calculateSize();
|
root: null,
|
||||||
},
|
nodeMap: {},
|
||||||
|
|
||||||
getRoot: function() {
|
setRoot: function(root) {
|
||||||
return this.root;
|
this.root = root;
|
||||||
},
|
this.generateNodeMap(root);
|
||||||
|
|
||||||
generateNodeMap: function(node) {
|
if (this.root.isFolder)
|
||||||
// don't store root node in map
|
this.root.calculateSize();
|
||||||
if (node.root !== null) {
|
},
|
||||||
this.nodeMap[node.rowId] = node;
|
|
||||||
|
getRoot: function() {
|
||||||
|
return this.root;
|
||||||
|
},
|
||||||
|
|
||||||
|
generateNodeMap: function(node) {
|
||||||
|
// don't store root node in map
|
||||||
|
if (node.root !== null) {
|
||||||
|
this.nodeMap[node.rowId] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.children.each(function(child) {
|
||||||
|
this.generateNodeMap(child);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
getNode: function(rowId) {
|
||||||
|
return (this.nodeMap[rowId] === undefined)
|
||||||
|
? null
|
||||||
|
: this.nodeMap[rowId];
|
||||||
|
},
|
||||||
|
|
||||||
|
getRowId: function(node) {
|
||||||
|
return node.rowId;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nodes in dfs order
|
||||||
|
*/
|
||||||
|
toArray: function() {
|
||||||
|
const nodes = [];
|
||||||
|
this.root.children.each(function(node) {
|
||||||
|
this._getArrayOfNodes(node, nodes);
|
||||||
|
}.bind(this));
|
||||||
|
return nodes;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getArrayOfNodes: function(node, array) {
|
||||||
|
array.push(node);
|
||||||
|
node.children.each(function(child) {
|
||||||
|
this._getArrayOfNodes(child, array);
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
node.children.each(function(child) {
|
const FileNode = new Class({
|
||||||
this.generateNodeMap(child);
|
name: "",
|
||||||
}.bind(this));
|
rowId: null,
|
||||||
},
|
size: 0,
|
||||||
|
checked: TriState.Unchecked,
|
||||||
|
remaining: 0,
|
||||||
|
progress: 0,
|
||||||
|
priority: FilePriority.Normal,
|
||||||
|
availability: 0,
|
||||||
|
depth: 0,
|
||||||
|
root: null,
|
||||||
|
data: null,
|
||||||
|
isFolder: false,
|
||||||
|
children: [],
|
||||||
|
});
|
||||||
|
|
||||||
getNode: function(rowId) {
|
const FolderNode = new Class({
|
||||||
return (this.nodeMap[rowId] === undefined)
|
Extends: FileNode,
|
||||||
? null
|
|
||||||
: this.nodeMap[rowId];
|
|
||||||
},
|
|
||||||
|
|
||||||
getRowId: function(node) {
|
initialize: function() {
|
||||||
return node.rowId;
|
this.isFolder = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
addChild(node) {
|
||||||
* Returns the nodes in dfs order
|
this.children.push(node);
|
||||||
*/
|
},
|
||||||
toArray: function() {
|
|
||||||
const nodes = [];
|
|
||||||
this.root.children.each(function(node) {
|
|
||||||
this._getArrayOfNodes(node, nodes);
|
|
||||||
}.bind(this));
|
|
||||||
return nodes;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getArrayOfNodes: function(node, array) {
|
/**
|
||||||
array.push(node);
|
* Recursively calculate size of node and its children
|
||||||
node.children.each(function(child) {
|
*/
|
||||||
this._getArrayOfNodes(child, array);
|
calculateSize: function() {
|
||||||
}.bind(this));
|
let size = 0;
|
||||||
}
|
let remaining = 0;
|
||||||
});
|
let progress = 0;
|
||||||
|
let availability = 0;
|
||||||
|
let checked = TriState.Unchecked;
|
||||||
|
let priority = FilePriority.Normal;
|
||||||
|
|
||||||
const FileNode = new Class({
|
let isFirstFile = true;
|
||||||
name: "",
|
|
||||||
rowId: null,
|
|
||||||
size: 0,
|
|
||||||
checked: TriState.Unchecked,
|
|
||||||
remaining: 0,
|
|
||||||
progress: 0,
|
|
||||||
priority: FilePriority.Normal,
|
|
||||||
availability: 0,
|
|
||||||
depth: 0,
|
|
||||||
root: null,
|
|
||||||
data: null,
|
|
||||||
isFolder: false,
|
|
||||||
children: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const FolderNode = new Class({
|
this.children.each(function(node) {
|
||||||
Extends: FileNode,
|
if (node.isFolder)
|
||||||
|
node.calculateSize();
|
||||||
|
|
||||||
initialize: function() {
|
size += node.size;
|
||||||
this.isFolder = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
addChild(node) {
|
if (isFirstFile) {
|
||||||
this.children.push(node);
|
priority = node.priority;
|
||||||
},
|
checked = node.checked;
|
||||||
|
isFirstFile = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (priority !== node.priority)
|
||||||
|
priority = FilePriority.Mixed;
|
||||||
|
if (checked !== node.checked)
|
||||||
|
checked = TriState.Partial;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
const isIgnored = (node.priority === FilePriority.Ignored);
|
||||||
* Recursively calculate size of node and its children
|
if (!isIgnored) {
|
||||||
*/
|
remaining += node.remaining;
|
||||||
calculateSize: function() {
|
progress += (node.progress * node.size);
|
||||||
let size = 0;
|
availability += (node.availability * node.size);
|
||||||
let remaining = 0;
|
}
|
||||||
let progress = 0;
|
}.bind(this));
|
||||||
let availability = 0;
|
|
||||||
let checked = TriState.Unchecked;
|
|
||||||
let priority = FilePriority.Normal;
|
|
||||||
|
|
||||||
let isFirstFile = true;
|
this.size = size;
|
||||||
|
this.remaining = remaining;
|
||||||
|
this.checked = checked;
|
||||||
|
this.progress = (progress / size);
|
||||||
|
this.priority = priority;
|
||||||
|
this.availability = (availability / size);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.children.each(function(node) {
|
return exports();
|
||||||
if (node.isFolder)
|
})();
|
||||||
node.calculateSize();
|
|
||||||
|
|
||||||
size += node.size;
|
|
||||||
|
|
||||||
if (isFirstFile) {
|
|
||||||
priority = node.priority;
|
|
||||||
checked = node.checked;
|
|
||||||
isFirstFile = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (priority !== node.priority)
|
|
||||||
priority = FilePriority.Mixed;
|
|
||||||
if (checked !== node.checked)
|
|
||||||
checked = TriState.Partial;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isIgnored = (node.priority === FilePriority.Ignored);
|
|
||||||
if (!isIgnored) {
|
|
||||||
remaining += node.remaining;
|
|
||||||
progress += (node.progress * node.size);
|
|
||||||
availability += (node.availability * node.size);
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
this.size = size;
|
|
||||||
this.remaining = remaining;
|
|
||||||
this.checked = checked;
|
|
||||||
this.progress = (progress / size);
|
|
||||||
this.priority = priority;
|
|
||||||
this.availability = (availability / size);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -30,32 +30,49 @@
|
||||||
|
|
||||||
// This file is the JavaScript implementation of base/utils/fs.cpp
|
// This file is the JavaScript implementation of base/utils/fs.cpp
|
||||||
|
|
||||||
const QB_EXT = '.!qB';
|
if (window.qBittorrent === undefined) {
|
||||||
const PathSeparator = '/';
|
window.qBittorrent = {};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the file extension part of a file name.
|
|
||||||
*/
|
|
||||||
function fileExtension(filename) {
|
|
||||||
const name = filename.endsWith(QB_EXT)
|
|
||||||
? filename.substring(0, filename.length - QB_EXT.length)
|
|
||||||
: filename;
|
|
||||||
const pointIndex = name.lastIndexOf('.');
|
|
||||||
if (pointIndex === -1)
|
|
||||||
return '';
|
|
||||||
return name.substring(pointIndex + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileName(filepath) {
|
window.qBittorrent.Filesystem = (function() {
|
||||||
const slashIndex = filepath.lastIndexOf(PathSeparator);
|
const exports = function() {
|
||||||
if (slashIndex === -1)
|
return {
|
||||||
return filepath;
|
PathSeparator: PathSeparator,
|
||||||
return filepath.substring(slashIndex + 1);
|
fileExtension: fileExtension,
|
||||||
}
|
fileName: fileName,
|
||||||
|
folderName: folderName
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function folderName(filepath) {
|
const QB_EXT = '.!qB';
|
||||||
const slashIndex = filepath.lastIndexOf(PathSeparator);
|
const PathSeparator = '/';
|
||||||
if (slashIndex === -1)
|
|
||||||
return filepath;
|
/**
|
||||||
return filepath.substring(0, slashIndex);
|
* Returns the file extension part of a file name.
|
||||||
}
|
*/
|
||||||
|
const fileExtension = function(filename) {
|
||||||
|
const name = filename.endsWith(QB_EXT)
|
||||||
|
? filename.substring(0, filename.length - QB_EXT.length)
|
||||||
|
: filename;
|
||||||
|
const pointIndex = name.lastIndexOf('.');
|
||||||
|
if (pointIndex === -1)
|
||||||
|
return '';
|
||||||
|
return name.substring(pointIndex + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fileName = function(filepath) {
|
||||||
|
const slashIndex = filepath.lastIndexOf(PathSeparator);
|
||||||
|
if (slashIndex === -1)
|
||||||
|
return filepath;
|
||||||
|
return filepath.substring(slashIndex + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const folderName = function(filepath) {
|
||||||
|
const slashIndex = filepath.lastIndexOf(PathSeparator);
|
||||||
|
if (slashIndex === -1)
|
||||||
|
return filepath;
|
||||||
|
return filepath.substring(0, slashIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
|
|
|
@ -28,166 +28,188 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/*
|
if (window.qBittorrent === undefined) {
|
||||||
* JS counterpart of the function in src/misc.cpp
|
window.qBittorrent = {};
|
||||||
*/
|
|
||||||
function friendlyUnit(value, isSpeed) {
|
|
||||||
const units = [
|
|
||||||
"QBT_TR(B)QBT_TR[CONTEXT=misc]",
|
|
||||||
"QBT_TR(KiB)QBT_TR[CONTEXT=misc]",
|
|
||||||
"QBT_TR(MiB)QBT_TR[CONTEXT=misc]",
|
|
||||||
"QBT_TR(GiB)QBT_TR[CONTEXT=misc]",
|
|
||||||
"QBT_TR(TiB)QBT_TR[CONTEXT=misc]",
|
|
||||||
"QBT_TR(PiB)QBT_TR[CONTEXT=misc]",
|
|
||||||
"QBT_TR(EiB)QBT_TR[CONTEXT=misc]"
|
|
||||||
];
|
|
||||||
|
|
||||||
if ((value === undefined) || (value === null) || (value < 0))
|
|
||||||
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
|
|
||||||
|
|
||||||
let i = 0;
|
|
||||||
while (value >= 1024.0 && i < 6) {
|
|
||||||
value /= 1024.0;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
function friendlyUnitPrecision(sizeUnit) {
|
|
||||||
if (sizeUnit <= 2) return 1; // KiB, MiB
|
|
||||||
else if (sizeUnit === 3) return 2; // GiB
|
|
||||||
else return 3; // TiB, PiB, EiB
|
|
||||||
}
|
|
||||||
|
|
||||||
let ret;
|
|
||||||
if (i === 0)
|
|
||||||
ret = value + " " + units[i];
|
|
||||||
else {
|
|
||||||
const precision = friendlyUnitPrecision(i);
|
|
||||||
const offset = Math.pow(10, precision);
|
|
||||||
// Don't round up
|
|
||||||
ret = (Math.floor(offset * value) / offset).toFixed(precision) + " " + units[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSpeed)
|
|
||||||
ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
window.qBittorrent.Misc = (function() {
|
||||||
* JS counterpart of the function in src/misc.cpp
|
const exports = function() {
|
||||||
*/
|
return {
|
||||||
function friendlyDuration(seconds) {
|
friendlyUnit: friendlyUnit,
|
||||||
const MAX_ETA = 8640000;
|
friendlyDuration: friendlyDuration,
|
||||||
if (seconds < 0 || seconds >= MAX_ETA)
|
friendlyPercentage: friendlyPercentage,
|
||||||
return "∞";
|
friendlyFloat: friendlyFloat,
|
||||||
if (seconds === 0)
|
parseHtmlLinks: parseHtmlLinks,
|
||||||
return "0";
|
escapeHtml: escapeHtml,
|
||||||
if (seconds < 60)
|
safeTrim: safeTrim,
|
||||||
return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]";
|
toFixedPointString: toFixedPointString,
|
||||||
let minutes = seconds / 60;
|
containsAllTerms: containsAllTerms
|
||||||
if (minutes < 60)
|
|
||||||
return "QBT_TR(%1m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(minutes));
|
|
||||||
let hours = minutes / 60;
|
|
||||||
minutes = minutes % 60;
|
|
||||||
if (hours < 24)
|
|
||||||
return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes));
|
|
||||||
const days = hours / 24;
|
|
||||||
hours = hours % 24;
|
|
||||||
if (days < 100)
|
|
||||||
return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours));
|
|
||||||
return "∞";
|
|
||||||
}
|
|
||||||
|
|
||||||
function friendlyPercentage(value) {
|
|
||||||
let percentage = (value * 100).round(1);
|
|
||||||
if (isNaN(percentage) || (percentage < 0))
|
|
||||||
percentage = 0;
|
|
||||||
if (percentage > 100)
|
|
||||||
percentage = 100;
|
|
||||||
return percentage.toFixed(1) + "%";
|
|
||||||
}
|
|
||||||
|
|
||||||
function friendlyFloat(value, precision) {
|
|
||||||
return parseFloat(value).toFixed(precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
|
|
||||||
*/
|
|
||||||
if (!Date.prototype.toISOString) {
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
function pad(number) {
|
|
||||||
if (number < 10) {
|
|
||||||
return '0' + number;
|
|
||||||
}
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
Date.prototype.toISOString = function() {
|
|
||||||
return this.getUTCFullYear()
|
|
||||||
+ '-' + pad(this.getUTCMonth() + 1)
|
|
||||||
+ '-' + pad(this.getUTCDate())
|
|
||||||
+ 'T' + pad(this.getUTCHours())
|
|
||||||
+ ':' + pad(this.getUTCMinutes())
|
|
||||||
+ ':' + pad(this.getUTCSeconds())
|
|
||||||
+ '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5)
|
|
||||||
+ 'Z';
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
}());
|
/*
|
||||||
}
|
* JS counterpart of the function in src/misc.cpp
|
||||||
|
*/
|
||||||
|
const friendlyUnit = function(value, isSpeed) {
|
||||||
|
const units = [
|
||||||
|
"QBT_TR(B)QBT_TR[CONTEXT=misc]",
|
||||||
|
"QBT_TR(KiB)QBT_TR[CONTEXT=misc]",
|
||||||
|
"QBT_TR(MiB)QBT_TR[CONTEXT=misc]",
|
||||||
|
"QBT_TR(GiB)QBT_TR[CONTEXT=misc]",
|
||||||
|
"QBT_TR(TiB)QBT_TR[CONTEXT=misc]",
|
||||||
|
"QBT_TR(PiB)QBT_TR[CONTEXT=misc]",
|
||||||
|
"QBT_TR(EiB)QBT_TR[CONTEXT=misc]"
|
||||||
|
];
|
||||||
|
|
||||||
/*
|
if ((value === undefined) || (value === null) || (value < 0))
|
||||||
* JS counterpart of the function in src/misc.cpp
|
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
|
||||||
*/
|
|
||||||
function parseHtmlLinks(text) {
|
|
||||||
const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
|
||||||
return text.replace(exp, "<a target='_blank' href='$1'>$1</a>");
|
|
||||||
}
|
|
||||||
|
|
||||||
function escapeHtml(str) {
|
let i = 0;
|
||||||
const div = document.createElement('div');
|
while (value >= 1024.0 && i < 6) {
|
||||||
div.appendChild(document.createTextNode(str));
|
value /= 1024.0;
|
||||||
return div.innerHTML;
|
++i;
|
||||||
}
|
|
||||||
|
|
||||||
function safeTrim(value) {
|
|
||||||
try {
|
|
||||||
return value.trim();
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
if (e instanceof TypeError)
|
|
||||||
return "";
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function toFixedPointString(number, digits) {
|
|
||||||
// Do not round up number
|
|
||||||
const power = Math.pow(10, digits);
|
|
||||||
return (Math.floor(power * number) / power).toFixed(digits);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {String} text the text to search
|
|
||||||
* @param {Array<String>} terms terms to search for within the text
|
|
||||||
* @returns {Boolean} true if all terms match the text, false otherwise
|
|
||||||
*/
|
|
||||||
function containsAllTerms(text, terms) {
|
|
||||||
const textToSearch = text.toLowerCase();
|
|
||||||
return terms.every((function(term) {
|
|
||||||
const isTermRequired = (term[0] === '+');
|
|
||||||
const isTermExcluded = (term[0] === '-');
|
|
||||||
if (isTermRequired || isTermExcluded) {
|
|
||||||
// ignore lonely +/-
|
|
||||||
if (term.length === 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
term = term.substring(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const textContainsTerm = (textToSearch.indexOf(term) !== -1);
|
function friendlyUnitPrecision(sizeUnit) {
|
||||||
return isTermExcluded ? !textContainsTerm : textContainsTerm;
|
if (sizeUnit <= 2) return 1; // KiB, MiB
|
||||||
}));
|
else if (sizeUnit === 3) return 2; // GiB
|
||||||
}
|
else return 3; // TiB, PiB, EiB
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret;
|
||||||
|
if (i === 0)
|
||||||
|
ret = value + " " + units[i];
|
||||||
|
else {
|
||||||
|
const precision = friendlyUnitPrecision(i);
|
||||||
|
const offset = Math.pow(10, precision);
|
||||||
|
// Don't round up
|
||||||
|
ret = (Math.floor(offset * value) / offset).toFixed(precision) + " " + units[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSpeed)
|
||||||
|
ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JS counterpart of the function in src/misc.cpp
|
||||||
|
*/
|
||||||
|
const friendlyDuration = function(seconds) {
|
||||||
|
const MAX_ETA = 8640000;
|
||||||
|
if (seconds < 0 || seconds >= MAX_ETA)
|
||||||
|
return "∞";
|
||||||
|
if (seconds === 0)
|
||||||
|
return "0";
|
||||||
|
if (seconds < 60)
|
||||||
|
return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]";
|
||||||
|
let minutes = seconds / 60;
|
||||||
|
if (minutes < 60)
|
||||||
|
return "QBT_TR(%1m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(minutes));
|
||||||
|
let hours = minutes / 60;
|
||||||
|
minutes = minutes % 60;
|
||||||
|
if (hours < 24)
|
||||||
|
return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes));
|
||||||
|
const days = hours / 24;
|
||||||
|
hours = hours % 24;
|
||||||
|
if (days < 100)
|
||||||
|
return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours));
|
||||||
|
return "∞";
|
||||||
|
}
|
||||||
|
|
||||||
|
const friendlyPercentage = function(value) {
|
||||||
|
let percentage = (value * 100).round(1);
|
||||||
|
if (isNaN(percentage) || (percentage < 0))
|
||||||
|
percentage = 0;
|
||||||
|
if (percentage > 100)
|
||||||
|
percentage = 100;
|
||||||
|
return percentage.toFixed(1) + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
const friendlyFloat = function(value, precision) {
|
||||||
|
return parseFloat(value).toFixed(precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
|
||||||
|
*/
|
||||||
|
if (!Date.prototype.toISOString) {
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
function pad(number) {
|
||||||
|
if (number < 10) {
|
||||||
|
return '0' + number;
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date.prototype.toISOString = function() {
|
||||||
|
return this.getUTCFullYear()
|
||||||
|
+ '-' + pad(this.getUTCMonth() + 1)
|
||||||
|
+ '-' + pad(this.getUTCDate())
|
||||||
|
+ 'T' + pad(this.getUTCHours())
|
||||||
|
+ ':' + pad(this.getUTCMinutes())
|
||||||
|
+ ':' + pad(this.getUTCSeconds())
|
||||||
|
+ '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5)
|
||||||
|
+ 'Z';
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JS counterpart of the function in src/misc.cpp
|
||||||
|
*/
|
||||||
|
const parseHtmlLinks = function(text) {
|
||||||
|
const exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
||||||
|
return text.replace(exp, "<a target='_blank' href='$1'>$1</a>");
|
||||||
|
}
|
||||||
|
|
||||||
|
const escapeHtml = function(str) {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.appendChild(document.createTextNode(str));
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
const safeTrim = function(value) {
|
||||||
|
try {
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (e instanceof TypeError)
|
||||||
|
return "";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const toFixedPointString = function(number, digits) {
|
||||||
|
// Do not round up number
|
||||||
|
const power = Math.pow(10, digits);
|
||||||
|
return (Math.floor(power * number) / power).toFixed(digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {String} text the text to search
|
||||||
|
* @param {Array<String>} terms terms to search for within the text
|
||||||
|
* @returns {Boolean} true if all terms match the text, false otherwise
|
||||||
|
*/
|
||||||
|
const containsAllTerms = function(text, terms) {
|
||||||
|
const textToSearch = text.toLowerCase();
|
||||||
|
return terms.every((function(term) {
|
||||||
|
const isTermRequired = (term[0] === '+');
|
||||||
|
const isTermExcluded = (term[0] === '-');
|
||||||
|
if (isTermRequired || isTermExcluded) {
|
||||||
|
// ignore lonely +/-
|
||||||
|
if (term.length === 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
term = term.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const textContainsTerm = (textToSearch.indexOf(term) !== -1);
|
||||||
|
return isTermExcluded ? !textContainsTerm : textContainsTerm;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
----------------------------------------------------------------- */
|
----------------------------------------------------------------- */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const LocalPreferences = new LocalPreferencesClass();
|
const LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferencesClass();
|
||||||
|
|
||||||
let saveWindowSize = function() {};
|
let saveWindowSize = function() {};
|
||||||
let loadWindowWidth = function() {};
|
let loadWindowWidth = function() {};
|
||||||
|
|
|
@ -28,20 +28,34 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const LocalPreferencesClass = new Class({
|
if (window.qBittorrent === undefined) {
|
||||||
get: function(key, defaultValue) {
|
window.qBittorrent = {};
|
||||||
const value = localStorage.getItem(key);
|
}
|
||||||
return ((value === null) && (defaultValue !== undefined))
|
|
||||||
? defaultValue
|
|
||||||
: value;
|
|
||||||
},
|
|
||||||
|
|
||||||
set: function(key, value) {
|
window.qBittorrent.LocalPreferences = (function() {
|
||||||
try {
|
const exports = function() {
|
||||||
localStorage.setItem(key, value);
|
return {
|
||||||
|
LocalPreferencesClass: LocalPreferencesClass
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const LocalPreferencesClass = new Class({
|
||||||
|
get: function(key, defaultValue) {
|
||||||
|
const value = localStorage.getItem(key);
|
||||||
|
return ((value === null) && (defaultValue !== undefined))
|
||||||
|
? defaultValue
|
||||||
|
: value;
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(key, value) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(key, value);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
})
|
||||||
console.error(err);
|
|
||||||
}
|
return exports();
|
||||||
}
|
})();
|
||||||
})
|
|
||||||
|
|
|
@ -28,113 +28,126 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ProgressBar = new Class({
|
if (window.qBittorrent === undefined) {
|
||||||
initialize: function(value, parameters) {
|
window.qBittorrent = {};
|
||||||
const vals = {
|
}
|
||||||
'id': 'progressbar_' + (ProgressBars++),
|
|
||||||
'value': $pick(value, 0),
|
window.qBittorrent.ProgressBar = (function() {
|
||||||
'width': 0,
|
const exports = function() {
|
||||||
'height': 0,
|
return {
|
||||||
'darkbg': '#006',
|
ProgressBar: ProgressBar
|
||||||
'darkfg': '#fff',
|
|
||||||
'lightbg': '#fff',
|
|
||||||
'lightfg': '#000'
|
|
||||||
};
|
};
|
||||||
if (parameters && $type(parameters) == 'object') $extend(vals, parameters);
|
};
|
||||||
if (vals.height < 12) vals.height = 12;
|
|
||||||
const obj = new Element('div', {
|
let ProgressBars = 0;
|
||||||
'id': vals.id,
|
const ProgressBar = new Class({
|
||||||
'class': 'progressbar_wrapper',
|
initialize: function(value, parameters) {
|
||||||
'styles': {
|
const vals = {
|
||||||
'border': '1px solid #000',
|
'id': 'progressbar_' + (ProgressBars++),
|
||||||
'width': vals.width,
|
'value': $pick(value, 0),
|
||||||
'height': vals.height,
|
'width': 0,
|
||||||
'position': 'relative',
|
'height': 0,
|
||||||
'margin': '0 auto'
|
'darkbg': '#006',
|
||||||
}
|
'darkfg': '#fff',
|
||||||
});
|
'lightbg': '#fff',
|
||||||
obj.vals = vals;
|
'lightfg': '#000'
|
||||||
obj.vals.value = $pick(value, 0); // Fix by Chris
|
};
|
||||||
obj.vals.dark = new Element('div', {
|
if (parameters && $type(parameters) == 'object') $extend(vals, parameters);
|
||||||
'id': vals.id + '_dark',
|
if (vals.height < 12) vals.height = 12;
|
||||||
'class': 'progressbar_dark',
|
const obj = new Element('div', {
|
||||||
'styles': {
|
'id': vals.id,
|
||||||
'width': vals.width,
|
'class': 'progressbar_wrapper',
|
||||||
'height': vals.height,
|
'styles': {
|
||||||
'background': vals.darkbg,
|
'border': '1px solid #000',
|
||||||
'color': vals.darkfg,
|
'width': vals.width,
|
||||||
'position': 'absolute',
|
'height': vals.height,
|
||||||
'text-align': 'center',
|
'position': 'relative',
|
||||||
'left': 0,
|
'margin': '0 auto'
|
||||||
'top': 0,
|
}
|
||||||
'line-height': vals.height
|
});
|
||||||
}
|
obj.vals = vals;
|
||||||
});
|
obj.vals.value = $pick(value, 0); // Fix by Chris
|
||||||
obj.vals.light = new Element('div', {
|
obj.vals.dark = new Element('div', {
|
||||||
'id': vals.id + '_light',
|
'id': vals.id + '_dark',
|
||||||
'class': 'progressbar_light',
|
'class': 'progressbar_dark',
|
||||||
'styles': {
|
'styles': {
|
||||||
'width': vals.width,
|
'width': vals.width,
|
||||||
'height': vals.height,
|
'height': vals.height,
|
||||||
'background': vals.lightbg,
|
'background': vals.darkbg,
|
||||||
'color': vals.lightfg,
|
'color': vals.darkfg,
|
||||||
'position': 'absolute',
|
'position': 'absolute',
|
||||||
'text-align': 'center',
|
'text-align': 'center',
|
||||||
'left': 0,
|
'left': 0,
|
||||||
'top': 0,
|
'top': 0,
|
||||||
'line-height': vals.height
|
'line-height': vals.height
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
obj.appendChild(obj.vals.dark);
|
obj.vals.light = new Element('div', {
|
||||||
obj.appendChild(obj.vals.light);
|
'id': vals.id + '_light',
|
||||||
obj.getValue = ProgressBar_getValue;
|
'class': 'progressbar_light',
|
||||||
obj.setValue = ProgressBar_setValue;
|
'styles': {
|
||||||
obj.setWidth = ProgressBar_setWidth;
|
'width': vals.width,
|
||||||
if (vals.width) obj.setValue(vals.value);
|
'height': vals.height,
|
||||||
else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1);
|
'background': vals.lightbg,
|
||||||
return obj;
|
'color': vals.lightfg,
|
||||||
|
'position': 'absolute',
|
||||||
|
'text-align': 'center',
|
||||||
|
'left': 0,
|
||||||
|
'top': 0,
|
||||||
|
'line-height': vals.height
|
||||||
|
}
|
||||||
|
});
|
||||||
|
obj.appendChild(obj.vals.dark);
|
||||||
|
obj.appendChild(obj.vals.light);
|
||||||
|
obj.getValue = ProgressBar_getValue;
|
||||||
|
obj.setValue = ProgressBar_setValue;
|
||||||
|
obj.setWidth = ProgressBar_setWidth;
|
||||||
|
if (vals.width) obj.setValue(vals.value);
|
||||||
|
else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function ProgressBar_getValue() {
|
||||||
|
return this.vals.value;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
function ProgressBar_getValue() {
|
function ProgressBar_setValue(value) {
|
||||||
return this.vals.value;
|
value = parseFloat(value);
|
||||||
}
|
if (isNaN(value)) value = 0;
|
||||||
|
if (value > 100) value = 100;
|
||||||
function ProgressBar_setValue(value) {
|
if (value < 0) value = 0;
|
||||||
value = parseFloat(value);
|
this.vals.value = value;
|
||||||
if (isNaN(value)) value = 0;
|
this.vals.dark.empty();
|
||||||
if (value > 100) value = 100;
|
this.vals.light.empty();
|
||||||
if (value < 0) value = 0;
|
this.vals.dark.appendText(value.round(1).toFixed(1) + '%');
|
||||||
this.vals.value = value;
|
this.vals.light.appendText(value.round(1).toFixed(1) + '%');
|
||||||
this.vals.dark.empty();
|
const r = parseInt(this.vals.width * (value / 100));
|
||||||
this.vals.light.empty();
|
this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)');
|
||||||
this.vals.dark.appendText(value.round(1).toFixed(1) + '%');
|
this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)');
|
||||||
this.vals.light.appendText(value.round(1).toFixed(1) + '%');
|
|
||||||
const r = parseInt(this.vals.width * (value / 100));
|
|
||||||
this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)');
|
|
||||||
this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)');
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProgressBar_setWidth(value) {
|
|
||||||
if (this.vals.width !== value) {
|
|
||||||
this.vals.width = value;
|
|
||||||
this.setStyle('width', value);
|
|
||||||
this.vals.dark.setStyle('width', value);
|
|
||||||
this.vals.light.setStyle('width', value);
|
|
||||||
this.setValue(this.vals.value);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function ProgressBar_checkForParent(id) {
|
function ProgressBar_setWidth(value) {
|
||||||
const obj = $(id);
|
if (this.vals.width !== value) {
|
||||||
if (!obj) return;
|
this.vals.width = value;
|
||||||
if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1);
|
this.setStyle('width', value);
|
||||||
obj.setStyle('width', '100%');
|
this.vals.dark.setStyle('width', value);
|
||||||
const w = obj.offsetWidth;
|
this.vals.light.setStyle('width', value);
|
||||||
obj.vals.dark.setStyle('width', w);
|
this.setValue(this.vals.value);
|
||||||
obj.vals.light.setStyle('width', w);
|
}
|
||||||
obj.vals.width = w;
|
}
|
||||||
obj.setValue(obj.vals.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ProgressBars = 0;
|
function ProgressBar_checkForParent(id) {
|
||||||
|
const obj = $(id);
|
||||||
|
if (!obj) return;
|
||||||
|
if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1);
|
||||||
|
obj.setStyle('width', '100%');
|
||||||
|
const w = obj.offsetWidth;
|
||||||
|
obj.vals.dark.setStyle('width', w);
|
||||||
|
obj.vals.light.setStyle('width', w);
|
||||||
|
obj.vals.width = w;
|
||||||
|
obj.setValue(obj.vals.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,172 +28,186 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const clearData = function() {
|
if (window.qBittorrent === undefined) {
|
||||||
$('time_elapsed').set('html', '');
|
window.qBittorrent = {};
|
||||||
$('eta').set('html', '');
|
}
|
||||||
$('nb_connections').set('html', '');
|
|
||||||
$('total_downloaded').set('html', '');
|
|
||||||
$('total_uploaded').set('html', '');
|
|
||||||
$('dl_speed').set('html', '');
|
|
||||||
$('up_speed').set('html', '');
|
|
||||||
$('dl_limit').set('html', '');
|
|
||||||
$('up_limit').set('html', '');
|
|
||||||
$('total_wasted').set('html', '');
|
|
||||||
$('seeds').set('html', '');
|
|
||||||
$('peers').set('html', '');
|
|
||||||
$('share_ratio').set('html', '');
|
|
||||||
$('reannounce').set('html', '');
|
|
||||||
$('last_seen').set('html', '');
|
|
||||||
$('total_size').set('html', '');
|
|
||||||
$('pieces').set('html', '');
|
|
||||||
$('created_by').set('html', '');
|
|
||||||
$('addition_date').set('html', '');
|
|
||||||
$('completion_date').set('html', '');
|
|
||||||
$('creation_date').set('html', '');
|
|
||||||
$('torrent_hash').set('html', '');
|
|
||||||
$('save_path').set('html', '');
|
|
||||||
$('comment').set('html', '');
|
|
||||||
};
|
|
||||||
|
|
||||||
let loadTorrentDataTimer;
|
window.qBittorrent.PropGeneral = (function() {
|
||||||
const loadTorrentData = function() {
|
const exports = function() {
|
||||||
if ($('prop_general').hasClass('invisible')
|
return {
|
||||||
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
updateData: updateData
|
||||||
// Tab changed, don't do anything
|
};
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
const current_hash = torrentsTable.getCurrentTorrentHash();
|
|
||||||
if (current_hash === "") {
|
|
||||||
clearData();
|
|
||||||
clearTimeout(loadTorrentDataTimer);
|
|
||||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Display hash
|
|
||||||
$('torrent_hash').set('html', current_hash);
|
|
||||||
const url = new URI('api/v2/torrents/properties?hash=' + current_hash);
|
|
||||||
new Request.JSON({
|
|
||||||
url: url,
|
|
||||||
noCache: true,
|
|
||||||
method: 'get',
|
|
||||||
onFailure: function() {
|
|
||||||
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
|
|
||||||
clearTimeout(loadTorrentDataTimer);
|
|
||||||
loadTorrentDataTimer = loadTorrentData.delay(10000);
|
|
||||||
},
|
|
||||||
onSuccess: function(data) {
|
|
||||||
$('error_div').set('html', '');
|
|
||||||
if (data) {
|
|
||||||
let temp;
|
|
||||||
// Update Torrent data
|
|
||||||
if (data.seeding_time > 0)
|
|
||||||
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", friendlyDuration(data.time_elapsed))
|
|
||||||
.replace("%2", friendlyDuration(data.seeding_time));
|
|
||||||
else
|
|
||||||
temp = friendlyDuration(data.time_elapsed);
|
|
||||||
$('time_elapsed').set('html', temp);
|
|
||||||
|
|
||||||
$('eta').set('html', friendlyDuration(data.eta));
|
const clearData = function() {
|
||||||
|
$('time_elapsed').set('html', '');
|
||||||
|
$('eta').set('html', '');
|
||||||
|
$('nb_connections').set('html', '');
|
||||||
|
$('total_downloaded').set('html', '');
|
||||||
|
$('total_uploaded').set('html', '');
|
||||||
|
$('dl_speed').set('html', '');
|
||||||
|
$('up_speed').set('html', '');
|
||||||
|
$('dl_limit').set('html', '');
|
||||||
|
$('up_limit').set('html', '');
|
||||||
|
$('total_wasted').set('html', '');
|
||||||
|
$('seeds').set('html', '');
|
||||||
|
$('peers').set('html', '');
|
||||||
|
$('share_ratio').set('html', '');
|
||||||
|
$('reannounce').set('html', '');
|
||||||
|
$('last_seen').set('html', '');
|
||||||
|
$('total_size').set('html', '');
|
||||||
|
$('pieces').set('html', '');
|
||||||
|
$('created_by').set('html', '');
|
||||||
|
$('addition_date').set('html', '');
|
||||||
|
$('completion_date').set('html', '');
|
||||||
|
$('creation_date').set('html', '');
|
||||||
|
$('torrent_hash').set('html', '');
|
||||||
|
$('save_path').set('html', '');
|
||||||
|
$('comment').set('html', '');
|
||||||
|
};
|
||||||
|
|
||||||
temp = "QBT_TR(%1 (%2 max))QBT_TR[CONTEXT=PropertiesWidget]"
|
let loadTorrentDataTimer;
|
||||||
.replace("%1", data.nb_connections)
|
const loadTorrentData = function() {
|
||||||
.replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit);
|
if ($('prop_general').hasClass('invisible')
|
||||||
$('nb_connections').set('html', temp);
|
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
||||||
|
// Tab changed, don't do anything
|
||||||
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
return;
|
||||||
.replace("%1", friendlyUnit(data.total_downloaded))
|
}
|
||||||
.replace("%2", friendlyUnit(data.total_downloaded_session));
|
const current_hash = torrentsTable.getCurrentTorrentHash();
|
||||||
$('total_downloaded').set('html', temp);
|
if (current_hash === "") {
|
||||||
|
clearData();
|
||||||
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", friendlyUnit(data.total_uploaded))
|
|
||||||
.replace("%2", friendlyUnit(data.total_uploaded_session));
|
|
||||||
$('total_uploaded').set('html', temp);
|
|
||||||
|
|
||||||
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", friendlyUnit(data.dl_speed, true))
|
|
||||||
.replace("%2", friendlyUnit(data.dl_speed_avg, true));
|
|
||||||
$('dl_speed').set('html', temp);
|
|
||||||
|
|
||||||
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", friendlyUnit(data.up_speed, true))
|
|
||||||
.replace("%2", friendlyUnit(data.up_speed_avg, true));
|
|
||||||
$('up_speed').set('html', temp);
|
|
||||||
|
|
||||||
temp = (data.dl_limit == -1 ? "∞" : friendlyUnit(data.dl_limit, true));
|
|
||||||
$('dl_limit').set('html', temp);
|
|
||||||
|
|
||||||
temp = (data.up_limit == -1 ? "∞" : friendlyUnit(data.up_limit, true));
|
|
||||||
$('up_limit').set('html', temp);
|
|
||||||
|
|
||||||
$('total_wasted').set('html', friendlyUnit(data.total_wasted));
|
|
||||||
|
|
||||||
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", data.seeds)
|
|
||||||
.replace("%2", data.seeds_total);
|
|
||||||
$('seeds').set('html', temp);
|
|
||||||
|
|
||||||
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", data.peers)
|
|
||||||
.replace("%2", data.peers_total);
|
|
||||||
$('peers').set('html', temp);
|
|
||||||
|
|
||||||
$('share_ratio').set('html', data.share_ratio.toFixed(2));
|
|
||||||
|
|
||||||
$('reannounce').set('html', friendlyDuration(data.reannounce));
|
|
||||||
|
|
||||||
if (data.last_seen != -1)
|
|
||||||
temp = new Date(data.last_seen * 1000).toLocaleString();
|
|
||||||
else
|
|
||||||
temp = "QBT_TR(Never)QBT_TR[CONTEXT=PropertiesWidget]";
|
|
||||||
$('last_seen').set('html', temp);
|
|
||||||
|
|
||||||
$('total_size').set('html', friendlyUnit(data.total_size));
|
|
||||||
|
|
||||||
if (data.pieces_num != -1)
|
|
||||||
temp = "QBT_TR(%1 x %2 (have %3))QBT_TR[CONTEXT=PropertiesWidget]"
|
|
||||||
.replace("%1", data.pieces_num)
|
|
||||||
.replace("%2", friendlyUnit(data.piece_size))
|
|
||||||
.replace("%3", data.pieces_have);
|
|
||||||
else
|
|
||||||
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
|
||||||
$('pieces').set('html', temp);
|
|
||||||
|
|
||||||
$('created_by').set('html', escapeHtml(data.created_by));
|
|
||||||
if (data.addition_date != -1)
|
|
||||||
temp = new Date(data.addition_date * 1000).toLocaleString();
|
|
||||||
else
|
|
||||||
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
|
||||||
|
|
||||||
$('addition_date').set('html', temp);
|
|
||||||
if (data.completion_date != -1)
|
|
||||||
temp = new Date(data.completion_date * 1000).toLocaleString();
|
|
||||||
else
|
|
||||||
temp = "";
|
|
||||||
|
|
||||||
$('completion_date').set('html', temp);
|
|
||||||
|
|
||||||
if (data.creation_date != -1)
|
|
||||||
temp = new Date(data.creation_date * 1000).toLocaleString();
|
|
||||||
else
|
|
||||||
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
|
||||||
$('creation_date').set('html', temp);
|
|
||||||
|
|
||||||
$('save_path').set('html', data.save_path);
|
|
||||||
|
|
||||||
$('comment').set('html', parseHtmlLinks(escapeHtml(data.comment)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearData();
|
|
||||||
}
|
|
||||||
clearTimeout(loadTorrentDataTimer);
|
clearTimeout(loadTorrentDataTimer);
|
||||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}).send();
|
// Display hash
|
||||||
};
|
$('torrent_hash').set('html', current_hash);
|
||||||
|
const url = new URI('api/v2/torrents/properties?hash=' + current_hash);
|
||||||
|
new Request.JSON({
|
||||||
|
url: url,
|
||||||
|
noCache: true,
|
||||||
|
method: 'get',
|
||||||
|
onFailure: function() {
|
||||||
|
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
|
||||||
|
clearTimeout(loadTorrentDataTimer);
|
||||||
|
loadTorrentDataTimer = loadTorrentData.delay(10000);
|
||||||
|
},
|
||||||
|
onSuccess: function(data) {
|
||||||
|
$('error_div').set('html', '');
|
||||||
|
if (data) {
|
||||||
|
let temp;
|
||||||
|
// Update Torrent data
|
||||||
|
if (data.seeding_time > 0)
|
||||||
|
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", window.qBittorrent.Misc.friendlyDuration(data.time_elapsed))
|
||||||
|
.replace("%2", window.qBittorrent.Misc.friendlyDuration(data.seeding_time));
|
||||||
|
else
|
||||||
|
temp = window.qBittorrent.Misc.friendlyDuration(data.time_elapsed);
|
||||||
|
$('time_elapsed').set('html', temp);
|
||||||
|
|
||||||
updateTorrentData = function() {
|
$('eta').set('html', window.qBittorrent.Misc.friendlyDuration(data.eta));
|
||||||
clearTimeout(loadTorrentDataTimer);
|
|
||||||
loadTorrentData();
|
temp = "QBT_TR(%1 (%2 max))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
};
|
.replace("%1", data.nb_connections)
|
||||||
|
.replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit);
|
||||||
|
$('nb_connections').set('html', temp);
|
||||||
|
|
||||||
|
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.total_downloaded))
|
||||||
|
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.total_downloaded_session));
|
||||||
|
$('total_downloaded').set('html', temp);
|
||||||
|
|
||||||
|
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.total_uploaded))
|
||||||
|
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.total_uploaded_session));
|
||||||
|
$('total_uploaded').set('html', temp);
|
||||||
|
|
||||||
|
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.dl_speed, true))
|
||||||
|
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.dl_speed_avg, true));
|
||||||
|
$('dl_speed').set('html', temp);
|
||||||
|
|
||||||
|
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", window.qBittorrent.Misc.friendlyUnit(data.up_speed, true))
|
||||||
|
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.up_speed_avg, true));
|
||||||
|
$('up_speed').set('html', temp);
|
||||||
|
|
||||||
|
temp = (data.dl_limit == -1 ? "∞" : window.qBittorrent.Misc.friendlyUnit(data.dl_limit, true));
|
||||||
|
$('dl_limit').set('html', temp);
|
||||||
|
|
||||||
|
temp = (data.up_limit == -1 ? "∞" : window.qBittorrent.Misc.friendlyUnit(data.up_limit, true));
|
||||||
|
$('up_limit').set('html', temp);
|
||||||
|
|
||||||
|
$('total_wasted').set('html', window.qBittorrent.Misc.friendlyUnit(data.total_wasted));
|
||||||
|
|
||||||
|
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", data.seeds)
|
||||||
|
.replace("%2", data.seeds_total);
|
||||||
|
$('seeds').set('html', temp);
|
||||||
|
|
||||||
|
temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", data.peers)
|
||||||
|
.replace("%2", data.peers_total);
|
||||||
|
$('peers').set('html', temp);
|
||||||
|
|
||||||
|
$('share_ratio').set('html', data.share_ratio.toFixed(2));
|
||||||
|
|
||||||
|
$('reannounce').set('html', window.qBittorrent.Misc.friendlyDuration(data.reannounce));
|
||||||
|
|
||||||
|
if (data.last_seen != -1)
|
||||||
|
temp = new Date(data.last_seen * 1000).toLocaleString();
|
||||||
|
else
|
||||||
|
temp = "QBT_TR(Never)QBT_TR[CONTEXT=PropertiesWidget]";
|
||||||
|
$('last_seen').set('html', temp);
|
||||||
|
|
||||||
|
$('total_size').set('html', window.qBittorrent.Misc.friendlyUnit(data.total_size));
|
||||||
|
|
||||||
|
if (data.pieces_num != -1)
|
||||||
|
temp = "QBT_TR(%1 x %2 (have %3))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||||
|
.replace("%1", data.pieces_num)
|
||||||
|
.replace("%2", window.qBittorrent.Misc.friendlyUnit(data.piece_size))
|
||||||
|
.replace("%3", data.pieces_have);
|
||||||
|
else
|
||||||
|
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
||||||
|
$('pieces').set('html', temp);
|
||||||
|
|
||||||
|
$('created_by').set('html', window.qBittorrent.Misc.escapeHtml(data.created_by));
|
||||||
|
if (data.addition_date != -1)
|
||||||
|
temp = new Date(data.addition_date * 1000).toLocaleString();
|
||||||
|
else
|
||||||
|
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
||||||
|
|
||||||
|
$('addition_date').set('html', temp);
|
||||||
|
if (data.completion_date != -1)
|
||||||
|
temp = new Date(data.completion_date * 1000).toLocaleString();
|
||||||
|
else
|
||||||
|
temp = "";
|
||||||
|
|
||||||
|
$('completion_date').set('html', temp);
|
||||||
|
|
||||||
|
if (data.creation_date != -1)
|
||||||
|
temp = new Date(data.creation_date * 1000).toLocaleString();
|
||||||
|
else
|
||||||
|
temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]";
|
||||||
|
$('creation_date').set('html', temp);
|
||||||
|
|
||||||
|
$('save_path').set('html', data.save_path);
|
||||||
|
|
||||||
|
$('comment').set('html', window.qBittorrent.Misc.parseHtmlLinks(window.qBittorrent.Misc.escapeHtml(data.comment)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clearData();
|
||||||
|
}
|
||||||
|
clearTimeout(loadTorrentDataTimer);
|
||||||
|
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateData = function() {
|
||||||
|
clearTimeout(loadTorrentDataTimer);
|
||||||
|
loadTorrentData();
|
||||||
|
};
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
|
|
|
@ -28,144 +28,160 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let loadTorrentPeersTimer;
|
if (window.qBittorrent === undefined) {
|
||||||
let syncTorrentPeersLastResponseId = 0;
|
window.qBittorrent = {};
|
||||||
let show_flags = true;
|
}
|
||||||
const loadTorrentPeersData = function() {
|
|
||||||
if ($('prop_peers').hasClass('invisible')
|
window.qBittorrent.PropPeers = (function() {
|
||||||
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
const exports = function() {
|
||||||
syncTorrentPeersLastResponseId = 0;
|
return {
|
||||||
torrentPeersTable.clear();
|
updateData: updateData
|
||||||
return;
|
}
|
||||||
}
|
};
|
||||||
const current_hash = torrentsTable.getCurrentTorrentHash();
|
|
||||||
if (current_hash === "") {
|
const torrentPeersTable = new window.qBittorrent.DynamicTable.TorrentPeersTable();
|
||||||
syncTorrentPeersLastResponseId = 0;
|
let loadTorrentPeersTimer;
|
||||||
torrentPeersTable.clear();
|
let syncTorrentPeersLastResponseId = 0;
|
||||||
clearTimeout(loadTorrentPeersTimer);
|
let show_flags = true;
|
||||||
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
|
|
||||||
return;
|
const loadTorrentPeersData = function() {
|
||||||
}
|
if ($('prop_peers').hasClass('invisible')
|
||||||
const url = new URI('api/v2/sync/torrentPeers');
|
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
||||||
url.setData('rid', syncTorrentPeersLastResponseId);
|
syncTorrentPeersLastResponseId = 0;
|
||||||
url.setData('hash', current_hash);
|
torrentPeersTable.clear();
|
||||||
new Request.JSON({
|
return;
|
||||||
url: url,
|
}
|
||||||
noCache: true,
|
const current_hash = torrentsTable.getCurrentTorrentHash();
|
||||||
method: 'get',
|
if (current_hash === "") {
|
||||||
onComplete: function() {
|
syncTorrentPeersLastResponseId = 0;
|
||||||
|
torrentPeersTable.clear();
|
||||||
clearTimeout(loadTorrentPeersTimer);
|
clearTimeout(loadTorrentPeersTimer);
|
||||||
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
|
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
|
||||||
},
|
return;
|
||||||
onSuccess: function(response) {
|
}
|
||||||
$('error_div').set('html', '');
|
const url = new URI('api/v2/sync/torrentPeers');
|
||||||
if (response) {
|
url.setData('rid', syncTorrentPeersLastResponseId);
|
||||||
const full_update = (response['full_update'] === true);
|
url.setData('hash', current_hash);
|
||||||
if (full_update)
|
new Request.JSON({
|
||||||
|
url: url,
|
||||||
|
noCache: true,
|
||||||
|
method: 'get',
|
||||||
|
onComplete: function() {
|
||||||
|
clearTimeout(loadTorrentPeersTimer);
|
||||||
|
loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval());
|
||||||
|
},
|
||||||
|
onSuccess: function(response) {
|
||||||
|
$('error_div').set('html', '');
|
||||||
|
if (response) {
|
||||||
|
const full_update = (response['full_update'] === true);
|
||||||
|
if (full_update)
|
||||||
|
torrentPeersTable.clear();
|
||||||
|
if (response['rid'])
|
||||||
|
syncTorrentPeersLastResponseId = response['rid'];
|
||||||
|
if (response['peers']) {
|
||||||
|
for (const key in response['peers']) {
|
||||||
|
response['peers'][key]['rowId'] = key;
|
||||||
|
|
||||||
|
if (response['peers'][key]['client'])
|
||||||
|
response['peers'][key]['client'] = window.qBittorrent.Misc.escapeHtml(response['peers'][key]['client']);
|
||||||
|
|
||||||
|
torrentPeersTable.updateRowData(response['peers'][key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (response['peers_removed']) {
|
||||||
|
response['peers_removed'].each(function(hash) {
|
||||||
|
torrentPeersTable.removeRow(hash);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
torrentPeersTable.updateTable(full_update);
|
||||||
|
torrentPeersTable.altRow();
|
||||||
|
|
||||||
|
if (response['show_flags']) {
|
||||||
|
if (show_flags != response['show_flags']) {
|
||||||
|
show_flags = response['show_flags'];
|
||||||
|
torrentPeersTable.columns['country'].force_hide = !show_flags;
|
||||||
|
torrentPeersTable.updateColumn('country');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
torrentPeersTable.clear();
|
torrentPeersTable.clear();
|
||||||
if (response['rid'])
|
|
||||||
syncTorrentPeersLastResponseId = response['rid'];
|
|
||||||
if (response['peers']) {
|
|
||||||
for (const key in response['peers']) {
|
|
||||||
response['peers'][key]['rowId'] = key;
|
|
||||||
|
|
||||||
if (response['peers'][key]['client'])
|
|
||||||
response['peers'][key]['client'] = escapeHtml(response['peers'][key]['client']);
|
|
||||||
|
|
||||||
torrentPeersTable.updateRowData(response['peers'][key]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (response['peers_removed']) {
|
}
|
||||||
response['peers_removed'].each(function(hash) {
|
}).send();
|
||||||
torrentPeersTable.removeRow(hash);
|
};
|
||||||
});
|
|
||||||
}
|
|
||||||
torrentPeersTable.updateTable(full_update);
|
|
||||||
torrentPeersTable.altRow();
|
|
||||||
|
|
||||||
if (response['show_flags']) {
|
const updateData = function() {
|
||||||
if (show_flags != response['show_flags']) {
|
clearTimeout(loadTorrentPeersTimer);
|
||||||
show_flags = response['show_flags'];
|
loadTorrentPeersData();
|
||||||
torrentPeersTable.columns['country'].force_hide = !show_flags;
|
};
|
||||||
torrentPeersTable.updateColumn('country');
|
|
||||||
}
|
const torrentPeersContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
|
||||||
|
targets: '#torrentPeersTableDiv',
|
||||||
|
menu: 'torrentPeersMenu',
|
||||||
|
actions: {
|
||||||
|
addPeer: function(element, ref) {
|
||||||
|
const hash = torrentsTable.getCurrentTorrentHash();
|
||||||
|
if (!hash)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new MochaUI.Window({
|
||||||
|
id: 'addPeersPage',
|
||||||
|
title: "QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]",
|
||||||
|
loadMethod: 'iframe',
|
||||||
|
contentURL: 'addpeers.html?hash=' + hash,
|
||||||
|
scrollbars: false,
|
||||||
|
resizable: false,
|
||||||
|
maximizable: false,
|
||||||
|
paddingVertical: 0,
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
width: 350,
|
||||||
|
height: 240
|
||||||
|
});
|
||||||
|
},
|
||||||
|
banPeer: function(element, ref) {
|
||||||
|
const selectedPeers = torrentPeersTable.selectedRowsIds();
|
||||||
|
if (selectedPeers.length === 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (confirm('QBT_TR(Are you sure you want to permanently ban the selected peers?)QBT_TR[CONTEXT=PeerListWidget]')) {
|
||||||
|
new Request({
|
||||||
|
url: 'api/v2/torrents/banPeers',
|
||||||
|
noCache: true,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
hash: torrentsTable.getCurrentTorrentHash(),
|
||||||
|
peers: selectedPeers.join('|')
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
offsets: {
|
||||||
|
x: -15,
|
||||||
|
y: 2
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
const selectedPeers = torrentPeersTable.selectedRowsIds();
|
||||||
|
|
||||||
|
if (selectedPeers.length >= 1) {
|
||||||
|
this.showItem('copyPeer');
|
||||||
|
this.showItem('banPeer');
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
torrentPeersTable.clear();
|
this.hideItem('copyPeer');
|
||||||
|
this.hideItem('banPeer');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).send();
|
});
|
||||||
};
|
|
||||||
|
|
||||||
updateTorrentPeersData = function() {
|
new ClipboardJS('#CopyPeerInfo', {
|
||||||
clearTimeout(loadTorrentPeersTimer);
|
text: function(trigger) {
|
||||||
loadTorrentPeersData();
|
return torrentPeersTable.selectedRowsIds().join("\n");
|
||||||
};
|
|
||||||
|
|
||||||
const torrentPeersContextMenu = new ContextMenu({
|
|
||||||
targets: '#torrentPeersTableDiv',
|
|
||||||
menu: 'torrentPeersMenu',
|
|
||||||
actions: {
|
|
||||||
addPeer: function(element, ref) {
|
|
||||||
const hash = torrentsTable.getCurrentTorrentHash();
|
|
||||||
if (!hash)
|
|
||||||
return;
|
|
||||||
|
|
||||||
new MochaUI.Window({
|
|
||||||
id: 'addPeersPage',
|
|
||||||
title: "QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog]",
|
|
||||||
loadMethod: 'iframe',
|
|
||||||
contentURL: 'addpeers.html?hash=' + hash,
|
|
||||||
scrollbars: false,
|
|
||||||
resizable: false,
|
|
||||||
maximizable: false,
|
|
||||||
paddingVertical: 0,
|
|
||||||
paddingHorizontal: 0,
|
|
||||||
width: 350,
|
|
||||||
height: 240
|
|
||||||
});
|
|
||||||
},
|
|
||||||
banPeer: function(element, ref) {
|
|
||||||
const selectedPeers = torrentPeersTable.selectedRowsIds();
|
|
||||||
if (selectedPeers.length === 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (confirm('QBT_TR(Are you sure you want to permanently ban the selected peers?)QBT_TR[CONTEXT=PeerListWidget]')) {
|
|
||||||
new Request({
|
|
||||||
url: 'api/v2/torrents/banPeers',
|
|
||||||
noCache: true,
|
|
||||||
method: 'post',
|
|
||||||
data: {
|
|
||||||
hash: torrentsTable.getCurrentTorrentHash(),
|
|
||||||
peers: selectedPeers.join('|')
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
offsets: {
|
|
||||||
x: -15,
|
|
||||||
y: 2
|
|
||||||
},
|
|
||||||
onShow: function() {
|
|
||||||
const selectedPeers = torrentPeersTable.selectedRowsIds();
|
|
||||||
|
|
||||||
if (selectedPeers.length >= 1) {
|
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
|
||||||
this.showItem('copyPeer');
|
|
||||||
this.showItem('banPeer');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.hideItem('copyPeer');
|
|
||||||
this.hideItem('banPeer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
new ClipboardJS('#CopyPeerInfo', {
|
return exports();
|
||||||
text: function(trigger) {
|
})();
|
||||||
return torrentPeersTable.selectedRowsIds().join("\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
torrentPeersTable.setup('torrentPeersTableDiv', 'torrentPeersTableFixedHeaderDiv', torrentPeersContextMenu);
|
|
||||||
|
|
|
@ -28,195 +28,211 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
this.current_hash = "";
|
if (window.qBittorrent === undefined) {
|
||||||
|
window.qBittorrent = {};
|
||||||
|
}
|
||||||
|
|
||||||
let loadTrackersDataTimer;
|
window.qBittorrent.PropTrackers = (function() {
|
||||||
const loadTrackersData = function() {
|
const exports = function() {
|
||||||
if ($('prop_trackers').hasClass('invisible')
|
return {
|
||||||
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
updateData: updateData
|
||||||
// Tab changed, don't do anything
|
};
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
const new_hash = torrentsTable.getCurrentTorrentHash();
|
let current_hash = "";
|
||||||
if (new_hash === "") {
|
|
||||||
torrentTrackersTable.clear();
|
const torrentTrackersTable = new window.qBittorrent.DynamicTable.TorrentTrackersTable();
|
||||||
clearTimeout(loadTrackersDataTimer);
|
let loadTrackersDataTimer;
|
||||||
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
|
||||||
return;
|
const loadTrackersData = function() {
|
||||||
}
|
if ($('prop_trackers').hasClass('invisible')
|
||||||
if (new_hash != current_hash) {
|
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
||||||
torrentTrackersTable.clear();
|
// Tab changed, don't do anything
|
||||||
current_hash = new_hash;
|
return;
|
||||||
}
|
}
|
||||||
const url = new URI('api/v2/torrents/trackers?hash=' + current_hash);
|
const new_hash = torrentsTable.getCurrentTorrentHash();
|
||||||
new Request.JSON({
|
if (new_hash === "") {
|
||||||
url: url,
|
torrentTrackersTable.clear();
|
||||||
noCache: true,
|
|
||||||
method: 'get',
|
|
||||||
onComplete: function() {
|
|
||||||
clearTimeout(loadTrackersDataTimer);
|
clearTimeout(loadTrackersDataTimer);
|
||||||
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
||||||
},
|
return;
|
||||||
onSuccess: function(trackers) {
|
}
|
||||||
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
if (new_hash != current_hash) {
|
||||||
torrentTrackersTable.clear();
|
torrentTrackersTable.clear();
|
||||||
|
current_hash = new_hash;
|
||||||
|
}
|
||||||
|
const url = new URI('api/v2/torrents/trackers?hash=' + current_hash);
|
||||||
|
new Request.JSON({
|
||||||
|
url: url,
|
||||||
|
noCache: true,
|
||||||
|
method: 'get',
|
||||||
|
onComplete: function() {
|
||||||
|
clearTimeout(loadTrackersDataTimer);
|
||||||
|
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
||||||
|
},
|
||||||
|
onSuccess: function(trackers) {
|
||||||
|
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
||||||
|
torrentTrackersTable.clear();
|
||||||
|
|
||||||
if (trackers) {
|
if (trackers) {
|
||||||
trackers.each(function(tracker) {
|
trackers.each(function(tracker) {
|
||||||
const url = escapeHtml(tracker.url);
|
const url = window.qBittorrent.Misc.escapeHtml(tracker.url);
|
||||||
let status;
|
let status;
|
||||||
switch (tracker.status) {
|
switch (tracker.status) {
|
||||||
case 0:
|
case 0:
|
||||||
status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
|
status = "QBT_TR(Disabled)QBT_TR[CONTEXT=TrackerListWidget]";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
status = "QBT_TR(Not contacted yet)QBT_TR[CONTEXT=TrackerListWidget]";
|
status = "QBT_TR(Not contacted yet)QBT_TR[CONTEXT=TrackerListWidget]";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
|
status = "QBT_TR(Working)QBT_TR[CONTEXT=TrackerListWidget]";
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
status = "QBT_TR(Updating...)QBT_TR[CONTEXT=TrackerListWidget]";
|
status = "QBT_TR(Updating...)QBT_TR[CONTEXT=TrackerListWidget]";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
status = "QBT_TR(Not working)QBT_TR[CONTEXT=TrackerListWidget]";
|
status = "QBT_TR(Not working)QBT_TR[CONTEXT=TrackerListWidget]";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const row = {
|
const row = {
|
||||||
rowId: url,
|
rowId: url,
|
||||||
tier: tracker.tier,
|
tier: tracker.tier,
|
||||||
url: url,
|
url: url,
|
||||||
status: status,
|
status: status,
|
||||||
peers: tracker.num_peers,
|
peers: tracker.num_peers,
|
||||||
seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
seeds: (tracker.num_seeds >= 0) ? tracker.num_seeds : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
leeches: (tracker.num_leeches >= 0) ? tracker.num_leeches : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
downloaded: (tracker.num_downloaded >= 0) ? tracker.num_downloaded : "QBT_TR(N/A)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
message: escapeHtml(tracker.msg)
|
message: window.qBittorrent.Misc.escapeHtml(tracker.msg)
|
||||||
};
|
};
|
||||||
|
|
||||||
torrentTrackersTable.updateRowData(row);
|
torrentTrackersTable.updateRowData(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
torrentTrackersTable.updateTable(false);
|
torrentTrackersTable.updateTable(false);
|
||||||
torrentTrackersTable.altRow();
|
torrentTrackersTable.altRow();
|
||||||
|
|
||||||
if (selectedTrackers.length > 0)
|
if (selectedTrackers.length > 0)
|
||||||
torrentTrackersTable.reselectRows(selectedTrackers);
|
torrentTrackersTable.reselectRows(selectedTrackers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateData = function() {
|
||||||
|
clearTimeout(loadTrackersDataTimer);
|
||||||
|
loadTrackersData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const torrentTrackersContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
|
||||||
|
targets: '#torrentTrackersTableDiv',
|
||||||
|
menu: 'torrentTrackersMenu',
|
||||||
|
actions: {
|
||||||
|
AddTracker: function(element, ref) {
|
||||||
|
addTrackerFN();
|
||||||
|
},
|
||||||
|
EditTracker: function(element, ref) {
|
||||||
|
// only allow editing of one row
|
||||||
|
element.firstChild.click();
|
||||||
|
editTrackerFN(element);
|
||||||
|
},
|
||||||
|
RemoveTracker: function(element, ref) {
|
||||||
|
removeTrackerFN(element);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
offsets: {
|
||||||
|
x: -15,
|
||||||
|
y: 2
|
||||||
|
},
|
||||||
|
onShow: function() {
|
||||||
|
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
||||||
|
const containsStaticTracker = selectedTrackers.some(function(tracker) {
|
||||||
|
return (tracker.indexOf("** [") === 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (containsStaticTracker || (selectedTrackers.length === 0)) {
|
||||||
|
this.hideItem('EditTracker');
|
||||||
|
this.hideItem('RemoveTracker');
|
||||||
|
this.hideItem('CopyTrackerUrl');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.showItem('EditTracker');
|
||||||
|
this.showItem('RemoveTracker');
|
||||||
|
this.showItem('CopyTrackerUrl');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).send();
|
});
|
||||||
};
|
|
||||||
|
|
||||||
updateTrackersData = function() {
|
const addTrackerFN = function() {
|
||||||
clearTimeout(loadTrackersDataTimer);
|
if (current_hash.length === 0) return;
|
||||||
loadTrackersData();
|
new MochaUI.Window({
|
||||||
};
|
id: 'trackersPage',
|
||||||
|
title: "QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDialog]",
|
||||||
const torrentTrackersContextMenu = new ContextMenu({
|
loadMethod: 'iframe',
|
||||||
targets: '#torrentTrackersTableDiv',
|
contentURL: 'addtrackers.html?hash=' + current_hash,
|
||||||
menu: 'torrentTrackersMenu',
|
scrollbars: true,
|
||||||
actions: {
|
resizable: false,
|
||||||
AddTracker: function(element, ref) {
|
maximizable: false,
|
||||||
addTrackerFN();
|
closable: true,
|
||||||
},
|
paddingVertical: 0,
|
||||||
EditTracker: function(element, ref) {
|
paddingHorizontal: 0,
|
||||||
// only allow editing of one row
|
width: 500,
|
||||||
element.firstChild.click();
|
height: 250,
|
||||||
editTrackerFN(element);
|
onCloseComplete: function() {
|
||||||
},
|
updateData();
|
||||||
RemoveTracker: function(element, ref) {
|
}
|
||||||
removeTrackerFN(element);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
offsets: {
|
|
||||||
x: -15,
|
|
||||||
y: 2
|
|
||||||
},
|
|
||||||
onShow: function() {
|
|
||||||
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
|
||||||
const containsStaticTracker = selectedTrackers.some(function(tracker) {
|
|
||||||
return (tracker.indexOf("** [") === 0);
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (containsStaticTracker || (selectedTrackers.length === 0)) {
|
const editTrackerFN = function(element) {
|
||||||
this.hideItem('EditTracker');
|
if (current_hash.length === 0) return;
|
||||||
this.hideItem('RemoveTracker');
|
|
||||||
this.hideItem('CopyTrackerUrl');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.showItem('EditTracker');
|
|
||||||
this.showItem('RemoveTracker');
|
|
||||||
this.showItem('CopyTrackerUrl');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const addTrackerFN = function() {
|
const trackerUrl = encodeURIComponent(element.childNodes[1].innerText);
|
||||||
if (current_hash.length === 0) return;
|
new MochaUI.Window({
|
||||||
new MochaUI.Window({
|
id: 'trackersPage',
|
||||||
id: 'trackersPage',
|
title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
|
||||||
title: "QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDialog]",
|
loadMethod: 'iframe',
|
||||||
loadMethod: 'iframe',
|
contentURL: 'edittracker.html?hash=' + current_hash + '&url=' + trackerUrl,
|
||||||
contentURL: 'addtrackers.html?hash=' + current_hash,
|
scrollbars: true,
|
||||||
scrollbars: true,
|
resizable: false,
|
||||||
resizable: false,
|
maximizable: false,
|
||||||
maximizable: false,
|
closable: true,
|
||||||
closable: true,
|
paddingVertical: 0,
|
||||||
paddingVertical: 0,
|
paddingHorizontal: 0,
|
||||||
paddingHorizontal: 0,
|
width: 500,
|
||||||
width: 500,
|
height: 150,
|
||||||
height: 250,
|
onCloseComplete: function() {
|
||||||
onCloseComplete: function() {
|
updateData();
|
||||||
updateTrackersData();
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeTrackerFN = function(element) {
|
||||||
|
if (current_hash.length === 0) return;
|
||||||
|
|
||||||
|
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
||||||
|
new Request({
|
||||||
|
url: 'api/v2/torrents/removeTrackers',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
hash: current_hash,
|
||||||
|
urls: selectedTrackers.join("|")
|
||||||
|
},
|
||||||
|
onSuccess: function() {
|
||||||
|
updateData();
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
new ClipboardJS('#CopyTrackerUrl', {
|
||||||
|
text: function(trigger) {
|
||||||
|
return torrentTrackersTable.selectedRowsIds().join("\n");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const editTrackerFN = function(element) {
|
torrentTrackersTable.setup('torrentTrackersTableDiv', 'torrentTrackersTableFixedHeaderDiv', torrentTrackersContextMenu);
|
||||||
if (current_hash.length === 0) return;
|
|
||||||
|
|
||||||
const trackerUrl = encodeURIComponent(element.childNodes[1].innerText);
|
return exports();
|
||||||
new MochaUI.Window({
|
})();
|
||||||
id: 'trackersPage',
|
|
||||||
title: "QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget]",
|
|
||||||
loadMethod: 'iframe',
|
|
||||||
contentURL: 'edittracker.html?hash=' + current_hash + '&url=' + trackerUrl,
|
|
||||||
scrollbars: true,
|
|
||||||
resizable: false,
|
|
||||||
maximizable: false,
|
|
||||||
closable: true,
|
|
||||||
paddingVertical: 0,
|
|
||||||
paddingHorizontal: 0,
|
|
||||||
width: 500,
|
|
||||||
height: 150,
|
|
||||||
onCloseComplete: function() {
|
|
||||||
updateTrackersData();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeTrackerFN = function(element) {
|
|
||||||
if (current_hash.length === 0) return;
|
|
||||||
|
|
||||||
const selectedTrackers = torrentTrackersTable.selectedRowsIds();
|
|
||||||
new Request({
|
|
||||||
url: 'api/v2/torrents/removeTrackers',
|
|
||||||
method: 'post',
|
|
||||||
data: {
|
|
||||||
hash: current_hash,
|
|
||||||
urls: selectedTrackers.join("|")
|
|
||||||
},
|
|
||||||
onSuccess: function() {
|
|
||||||
updateTrackersData();
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
};
|
|
||||||
|
|
||||||
new ClipboardJS('#CopyTrackerUrl', {
|
|
||||||
text: function(trigger) {
|
|
||||||
return torrentTrackersTable.selectedRowsIds().join("\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
torrentTrackersTable.setup('torrentTrackersTableDiv', 'torrentTrackersTableFixedHeaderDiv', torrentTrackersContextMenu);
|
|
||||||
|
|
|
@ -28,112 +28,126 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const webseedsDynTable = new Class({
|
if (window.qBittorrent === undefined) {
|
||||||
|
window.qBittorrent = {};
|
||||||
|
}
|
||||||
|
|
||||||
initialize: function() {},
|
window.qBittorrent.PropWebseeds = (function() {
|
||||||
|
const exports = function() {
|
||||||
|
return {
|
||||||
|
updateData: updateData
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
setup: function(table) {
|
const webseedsDynTable = new Class({
|
||||||
this.table = $(table);
|
|
||||||
this.rows = new Hash();
|
|
||||||
},
|
|
||||||
|
|
||||||
removeRow: function(url) {
|
initialize: function() {},
|
||||||
if (this.rows.has(url)) {
|
|
||||||
const tr = this.rows.get(url);
|
setup: function(table) {
|
||||||
tr.dispose();
|
this.table = $(table);
|
||||||
this.rows.erase(url);
|
this.rows = new Hash();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeRow: function(url) {
|
||||||
|
if (this.rows.has(url)) {
|
||||||
|
const tr = this.rows.get(url);
|
||||||
|
tr.dispose();
|
||||||
|
this.rows.erase(url);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
removeAllRows: function() {
|
||||||
|
this.rows.each(function(tr, url) {
|
||||||
|
this.removeRow(url);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
updateRow: function(tr, row) {
|
||||||
|
const tds = tr.getElements('td');
|
||||||
|
for (let i = 0; i < row.length; ++i) {
|
||||||
|
tds[i].set('html', row[i]);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
removeAllRows: function() {
|
insertRow: function(row) {
|
||||||
this.rows.each(function(tr, url) {
|
const url = row[0];
|
||||||
this.removeRow(url);
|
if (this.rows.has(url)) {
|
||||||
}.bind(this));
|
const tableRow = this.rows.get(url);
|
||||||
},
|
this.updateRow(tableRow, row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//this.removeRow(id);
|
||||||
|
const tr = new Element('tr');
|
||||||
|
this.rows.set(url, tr);
|
||||||
|
for (let i = 0; i < row.length; ++i) {
|
||||||
|
const td = new Element('td');
|
||||||
|
td.set('html', row[i]);
|
||||||
|
td.injectInside(tr);
|
||||||
|
}
|
||||||
|
tr.injectInside(this.table);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
updateRow: function(tr, row) {
|
let current_hash = "";
|
||||||
const tds = tr.getElements('td');
|
|
||||||
for (let i = 0; i < row.length; ++i) {
|
|
||||||
tds[i].set('html', row[i]);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
insertRow: function(row) {
|
let loadWebSeedsDataTimer;
|
||||||
const url = row[0];
|
const loadWebSeedsData = function() {
|
||||||
if (this.rows.has(url)) {
|
if ($('prop_webseeds').hasClass('invisible')
|
||||||
const tableRow = this.rows.get(url);
|
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
||||||
this.updateRow(tableRow, row);
|
// Tab changed, don't do anything
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//this.removeRow(id);
|
const new_hash = torrentsTable.getCurrentTorrentHash();
|
||||||
const tr = new Element('tr');
|
if (new_hash === "") {
|
||||||
this.rows.set(url, tr);
|
wsTable.removeAllRows();
|
||||||
for (let i = 0; i < row.length; ++i) {
|
|
||||||
const td = new Element('td');
|
|
||||||
td.set('html', row[i]);
|
|
||||||
td.injectInside(tr);
|
|
||||||
}
|
|
||||||
tr.injectInside(this.table);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.current_hash = "";
|
|
||||||
|
|
||||||
let loadWebSeedsDataTimer;
|
|
||||||
const loadWebSeedsData = function() {
|
|
||||||
if ($('prop_webseeds').hasClass('invisible')
|
|
||||||
|| $('propertiesPanel_collapseToggle').hasClass('panel-expand')) {
|
|
||||||
// Tab changed, don't do anything
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const new_hash = torrentsTable.getCurrentTorrentHash();
|
|
||||||
if (new_hash === "") {
|
|
||||||
wsTable.removeAllRows();
|
|
||||||
clearTimeout(loadWebSeedsDataTimer);
|
|
||||||
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (new_hash != current_hash) {
|
|
||||||
wsTable.removeAllRows();
|
|
||||||
current_hash = new_hash;
|
|
||||||
}
|
|
||||||
const url = new URI('api/v2/torrents/webseeds?hash=' + current_hash);
|
|
||||||
new Request.JSON({
|
|
||||||
url: url,
|
|
||||||
noCache: true,
|
|
||||||
method: 'get',
|
|
||||||
onFailure: function() {
|
|
||||||
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
|
|
||||||
clearTimeout(loadWebSeedsDataTimer);
|
|
||||||
loadWebSeedsDataTimer = loadWebSeedsData.delay(20000);
|
|
||||||
},
|
|
||||||
onSuccess: function(webseeds) {
|
|
||||||
$('error_div').set('html', '');
|
|
||||||
if (webseeds) {
|
|
||||||
// Update WebSeeds data
|
|
||||||
webseeds.each(function(webseed) {
|
|
||||||
const row = [];
|
|
||||||
row.length = 1;
|
|
||||||
row[0] = webseed.url;
|
|
||||||
wsTable.insertRow(row);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
wsTable.removeAllRows();
|
|
||||||
}
|
|
||||||
clearTimeout(loadWebSeedsDataTimer);
|
clearTimeout(loadWebSeedsDataTimer);
|
||||||
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
|
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}).send();
|
if (new_hash != current_hash) {
|
||||||
};
|
wsTable.removeAllRows();
|
||||||
|
current_hash = new_hash;
|
||||||
|
}
|
||||||
|
const url = new URI('api/v2/torrents/webseeds?hash=' + current_hash);
|
||||||
|
new Request.JSON({
|
||||||
|
url: url,
|
||||||
|
noCache: true,
|
||||||
|
method: 'get',
|
||||||
|
onFailure: function() {
|
||||||
|
$('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]');
|
||||||
|
clearTimeout(loadWebSeedsDataTimer);
|
||||||
|
loadWebSeedsDataTimer = loadWebSeedsData.delay(20000);
|
||||||
|
},
|
||||||
|
onSuccess: function(webseeds) {
|
||||||
|
$('error_div').set('html', '');
|
||||||
|
if (webseeds) {
|
||||||
|
// Update WebSeeds data
|
||||||
|
webseeds.each(function(webseed) {
|
||||||
|
const row = [];
|
||||||
|
row.length = 1;
|
||||||
|
row[0] = webseed.url;
|
||||||
|
wsTable.insertRow(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wsTable.removeAllRows();
|
||||||
|
}
|
||||||
|
clearTimeout(loadWebSeedsDataTimer);
|
||||||
|
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
updateWebSeedsData = function() {
|
const updateData = function() {
|
||||||
clearTimeout(loadWebSeedsDataTimer);
|
clearTimeout(loadWebSeedsDataTimer);
|
||||||
loadWebSeedsData();
|
loadWebSeedsData();
|
||||||
};
|
};
|
||||||
|
|
||||||
const wsTable = new webseedsDynTable();
|
const wsTable = new webseedsDynTable();
|
||||||
wsTable.setup($('webseedsTable'));
|
wsTable.setup($('webseedsTable'));
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
const path = new URI().getData('path');
|
const path = new URI().getData('path');
|
||||||
// set text field to current value
|
// set text field to current value
|
||||||
if (path)
|
if (path)
|
||||||
$('setLocation').value = escapeHtml(decodeURIComponent(path));
|
$('setLocation').value = window.qBittorrent.Misc.escapeHtml(decodeURIComponent(path));
|
||||||
|
|
||||||
$('setLocation').focus();
|
$('setLocation').focus();
|
||||||
$('setLocationButton').addEvent('click', function(e) {
|
$('setLocationButton').addEvent('click', function(e) {
|
||||||
|
|
|
@ -37,9 +37,9 @@
|
||||||
const origValues = new URI().getData('orig').split('|');
|
const origValues = new URI().getData('orig').split('|');
|
||||||
|
|
||||||
const values = {
|
const values = {
|
||||||
ratioLimit: friendlyFloat(origValues[0], 2),
|
ratioLimit: window.qBittorrent.Misc.friendlyFloat(origValues[0], 2),
|
||||||
seedingTimeLimit: parseInt(origValues[1]),
|
seedingTimeLimit: parseInt(origValues[1]),
|
||||||
maxRatio: friendlyFloat(origValues[2], 2),
|
maxRatio: window.qBittorrent.Misc.friendlyFloat(origValues[2], 2),
|
||||||
maxSeedingTime: parseInt(origValues[3])
|
maxSeedingTime: parseInt(origValues[3])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="autoTMM" name="autoTMM" onchange="changeTMM(this)">
|
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
|
||||||
<option selected value="false">Manual</option>
|
<option selected value="false">Manual</option>
|
||||||
<option value="true">Automatic</option>
|
<option value="true">Automatic</option>
|
||||||
</select>
|
</select>
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="select-watched-folder-editable">
|
<div class="select-watched-folder-editable">
|
||||||
<select id="categorySelect" onchange="changeCategorySelect(this)">
|
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
|
||||||
<option selected value="\other"></option>
|
<option selected value="\other"></option>
|
||||||
</select>
|
</select>
|
||||||
<input name="category" type="text" value="" />
|
<input name="category" type="text" value="" />
|
||||||
|
|
|
@ -681,22 +681,24 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
$('qbittorrentVersion').innerText = ("qBittorrent " + qbtVersion()
|
(function() {
|
||||||
|
$('qbittorrentVersion').innerText = ("qBittorrent " + qbtVersion()
|
||||||
+ " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]");
|
+ " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]");
|
||||||
|
|
||||||
new Request.JSON({
|
new Request.JSON({
|
||||||
url: 'api/v2/app/buildInfo',
|
url: 'api/v2/app/buildInfo',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
noCache: true,
|
noCache: true,
|
||||||
onSuccess: function(info) {
|
onSuccess: function(info) {
|
||||||
if (!info) return;
|
if (!info) return;
|
||||||
|
|
||||||
$('qtVersion').textContent = info.qt;
|
$('qtVersion').textContent = info.qt;
|
||||||
$('libtorrentVersion').textContent = info.libtorrent;
|
$('libtorrentVersion').textContent = info.libtorrent;
|
||||||
$('boostVersion').textContent = info.boost;
|
$('boostVersion').textContent = info.boost;
|
||||||
$('opensslVersion').textContent = info.openssl;
|
$('opensslVersion').textContent = info.openssl;
|
||||||
$('zlibVersion').textContent = info.zlib;
|
$('zlibVersion').textContent = info.zlib;
|
||||||
$('qbittorrentVersion').textContent += " (" + info.bitness + "-bit)";
|
$('qbittorrentVersion').textContent += " (" + info.bitness + "-bit)";
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -13,35 +13,37 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
MochaUI.initializeTabs('aboutTabs');
|
(function() {
|
||||||
|
MochaUI.initializeTabs('aboutTabs');
|
||||||
|
|
||||||
$('aboutAboutLink').addEvent('click', function() {
|
$('aboutAboutLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutAboutContent').removeClass('invisible');
|
$('aboutAboutContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('aboutAuthorLink').addEvent('click', function() {
|
$('aboutAuthorLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutAuthorContent').removeClass('invisible');
|
$('aboutAuthorContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('aboutSpecialThanksLink').addEvent('click', function() {
|
$('aboutSpecialThanksLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutSpecialThanksContent').removeClass('invisible');
|
$('aboutSpecialThanksContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('aboutTranslatorsLink').addEvent('click', function() {
|
$('aboutTranslatorsLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutTranslatorsContent').removeClass('invisible');
|
$('aboutTranslatorsContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('aboutLicenseLink').addEvent('click', function() {
|
$('aboutLicenseLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutLicenseContent').removeClass('invisible');
|
$('aboutLicenseContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('aboutLibrariesLink').addEvent('click', function() {
|
$('aboutLibrariesLink').addEvent('click', function() {
|
||||||
$$('.aboutTabContent').addClass('invisible');
|
$$('.aboutTabContent').addClass('invisible');
|
||||||
$('aboutLibrariesContent').removeClass('invisible');
|
$('aboutLibrariesContent').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -32,79 +32,94 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const categoriesFilterContextMenu = new CategoriesFilterContextMenu({
|
if (window.qBittorrent === undefined) {
|
||||||
targets: '.categoriesFilterContextMenuTarget',
|
window.qBittorrent = {};
|
||||||
menu: 'categoriesFilterMenu',
|
}
|
||||||
actions: {
|
|
||||||
createCategory: function(element, ref) {
|
window.qBittorrent.Filters = (function() {
|
||||||
createCategoryFN();
|
const exports = function() {
|
||||||
|
return {
|
||||||
|
categoriesFilterContextMenu: categoriesFilterContextMenu,
|
||||||
|
tagsFilterContextMenu: tagsFilterContextMenu
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const categoriesFilterContextMenu = new window.qBittorrent.ContextMenu.CategoriesFilterContextMenu({
|
||||||
|
targets: '.categoriesFilterContextMenuTarget',
|
||||||
|
menu: 'categoriesFilterMenu',
|
||||||
|
actions: {
|
||||||
|
createCategory: function(element, ref) {
|
||||||
|
createCategoryFN();
|
||||||
|
},
|
||||||
|
editCategory: function(element, ref) {
|
||||||
|
editCategoryFN(element.id);
|
||||||
|
},
|
||||||
|
deleteCategory: function(element, ref) {
|
||||||
|
removeCategoryFN(element.id);
|
||||||
|
},
|
||||||
|
deleteUnusedCategories: function(element, ref) {
|
||||||
|
deleteUnusedCategoriesFN();
|
||||||
|
},
|
||||||
|
startTorrentsByCategory: function(element, ref) {
|
||||||
|
startTorrentsByCategoryFN(element.id);
|
||||||
|
},
|
||||||
|
pauseTorrentsByCategory: function(element, ref) {
|
||||||
|
pauseTorrentsByCategoryFN(element.id);
|
||||||
|
},
|
||||||
|
deleteTorrentsByCategory: function(element, ref) {
|
||||||
|
deleteTorrentsByCategoryFN(element.id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
editCategory: function(element, ref) {
|
offsets: {
|
||||||
editCategoryFN(element.id);
|
x: -15,
|
||||||
|
y: 2
|
||||||
},
|
},
|
||||||
deleteCategory: function(element, ref) {
|
onShow: function() {
|
||||||
removeCategoryFN(element.id);
|
this.options.element.firstChild.click();
|
||||||
},
|
|
||||||
deleteUnusedCategories: function(element, ref) {
|
|
||||||
deleteUnusedCategoriesFN();
|
|
||||||
},
|
|
||||||
startTorrentsByCategory: function(element, ref) {
|
|
||||||
startTorrentsByCategoryFN(element.id);
|
|
||||||
},
|
|
||||||
pauseTorrentsByCategory: function(element, ref) {
|
|
||||||
pauseTorrentsByCategoryFN(element.id);
|
|
||||||
},
|
|
||||||
deleteTorrentsByCategory: function(element, ref) {
|
|
||||||
deleteTorrentsByCategoryFN(element.id);
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
offsets: {
|
|
||||||
x: -15,
|
|
||||||
y: 2
|
|
||||||
},
|
|
||||||
onShow: function() {
|
|
||||||
this.options.element.firstChild.click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const tagsFilterContextMenu = new TagsFilterContextMenu({
|
const tagsFilterContextMenu = new window.qBittorrent.ContextMenu.TagsFilterContextMenu({
|
||||||
targets: '.tagsFilterContextMenuTarget',
|
targets: '.tagsFilterContextMenuTarget',
|
||||||
menu: 'tagsFilterMenu',
|
menu: 'tagsFilterMenu',
|
||||||
actions: {
|
actions: {
|
||||||
createTag: function(element, ref) {
|
createTag: function(element, ref) {
|
||||||
createTagFN();
|
createTagFN();
|
||||||
|
},
|
||||||
|
deleteTag: function(element, ref) {
|
||||||
|
removeTagFN(element.id);
|
||||||
|
},
|
||||||
|
deleteUnusedTags: function(element, ref) {
|
||||||
|
deleteUnusedTagsFN();
|
||||||
|
},
|
||||||
|
startTorrentsByTag: function(element, ref) {
|
||||||
|
startTorrentsByTagFN(element.id);
|
||||||
|
},
|
||||||
|
pauseTorrentsByTag: function(element, ref) {
|
||||||
|
pauseTorrentsByTagFN(element.id);
|
||||||
|
},
|
||||||
|
deleteTorrentsByTag: function(element, ref) {
|
||||||
|
deleteTorrentsByTagFN(element.id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
deleteTag: function(element, ref) {
|
offsets: {
|
||||||
removeTagFN(element.id);
|
x: -15,
|
||||||
|
y: 2
|
||||||
},
|
},
|
||||||
deleteUnusedTags: function(element, ref) {
|
onShow: function() {
|
||||||
deleteUnusedTagsFN();
|
this.options.element.firstChild.click();
|
||||||
},
|
|
||||||
startTorrentsByTag: function(element, ref) {
|
|
||||||
startTorrentsByTagFN(element.id);
|
|
||||||
},
|
|
||||||
pauseTorrentsByTag: function(element, ref) {
|
|
||||||
pauseTorrentsByTagFN(element.id);
|
|
||||||
},
|
|
||||||
deleteTorrentsByTag: function(element, ref) {
|
|
||||||
deleteTorrentsByTagFN(element.id);
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
offsets: {
|
|
||||||
x: -15,
|
|
||||||
y: 2
|
|
||||||
},
|
|
||||||
onShow: function() {
|
|
||||||
this.options.element.firstChild.click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (LocalPreferences.get('filter_status_collapsed') === "true")
|
if (LocalPreferences.get('filter_status_collapsed') === "true")
|
||||||
toggleFilterDisplay('status');
|
toggleFilterDisplay('status');
|
||||||
|
|
||||||
if (LocalPreferences.get('filter_category_collapsed') === "true")
|
if (LocalPreferences.get('filter_category_collapsed') === "true")
|
||||||
toggleFilterDisplay('category');
|
toggleFilterDisplay('category');
|
||||||
|
|
||||||
if (LocalPreferences.get('filter_tag_collapsed') === "true")
|
if (LocalPreferences.get('filter_tag_collapsed') === "true")
|
||||||
toggleFilterDisplay('tag');
|
toggleFilterDisplay('tag');
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
<div>
|
<div>
|
||||||
<input type="text" id="newPluginPath" placeholder="QBT_TR(URL or local directory)QBT_TR[CONTEXT=PluginSourceDlg]" autocorrect="off" autocapitalize="none" />
|
<input type="text" id="newPluginPath" placeholder="QBT_TR(URL or local directory)QBT_TR[CONTEXT=PluginSourceDlg]" autocorrect="off" autocapitalize="none" />
|
||||||
<div style="margin-top: 10px; text-align: center;">
|
<div style="margin-top: 10px; text-align: center;">
|
||||||
<button id="newPluginCancel" onclick="closeSearchWindow('installSearchPlugin');">QBT_TR(Cancel)QBT_TR[CONTEXT=PluginSourceDlg]</button>
|
<button id="newPluginCancel" onclick="qBittorrent.SearchPlugins.closeSearchWindow('installSearchPlugin');">QBT_TR(Cancel)QBT_TR[CONTEXT=PluginSourceDlg]</button>
|
||||||
<button id="newPluginOk" onclick="newPluginOk();">QBT_TR(Ok)QBT_TR[CONTEXT=PluginSourceDlg]</button>
|
<button id="newPluginOk" onclick="qBittorrent.InstallSearchPlugin.newPluginOk();">QBT_TR(Ok)QBT_TR[CONTEXT=PluginSourceDlg]</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,41 +29,55 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
this.initInstallSearchPlugin = function() {
|
if (window.qBittorrent === undefined) {
|
||||||
new Keyboard({
|
window.qBittorrent = {};
|
||||||
defaultEventType: 'keydown',
|
}
|
||||||
events: {
|
|
||||||
'Enter': function(e) {
|
|
||||||
// accept enter key as a click
|
|
||||||
new Event(e).stop();
|
|
||||||
|
|
||||||
const elem = e.event.srcElement;
|
window.qBittorrent.InstallSearchPlugin = (function() {
|
||||||
if ((elem.id === "newPluginPath") || (elem.id === "newPluginOk"))
|
const exports = function() {
|
||||||
newPluginOk();
|
return {
|
||||||
else if (elem.id === "newPluginCancel")
|
newPluginOk: newPluginOk
|
||||||
closeSearchWindow('installSearchPlugin');
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const init = function() {
|
||||||
|
new Keyboard({
|
||||||
|
defaultEventType: 'keydown',
|
||||||
|
events: {
|
||||||
|
'Enter': function(e) {
|
||||||
|
// accept enter key as a click
|
||||||
|
new Event(e).stop();
|
||||||
|
|
||||||
|
const elem = e.event.srcElement;
|
||||||
|
if ((elem.id === "newPluginPath") || (elem.id === "newPluginOk"))
|
||||||
|
newPluginOk();
|
||||||
|
else if (elem.id === "newPluginCancel")
|
||||||
|
window.qBittorrent.SearchPlugins.closeSearchWindow('installSearchPlugin');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}).activate();
|
||||||
}).activate();
|
|
||||||
|
|
||||||
$('newPluginPath').select();
|
$('newPluginPath').select();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.newPluginOk = function() {
|
const newPluginOk = function() {
|
||||||
const path = $("newPluginPath").get("value").trim();
|
const path = $("newPluginPath").get("value").trim();
|
||||||
if (path)
|
if (path)
|
||||||
new Request({
|
new Request({
|
||||||
url: 'api/v2/search/installPlugin',
|
url: 'api/v2/search/installPlugin',
|
||||||
noCache: true,
|
noCache: true,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: {
|
data: {
|
||||||
sources: path,
|
sources: path,
|
||||||
},
|
},
|
||||||
onRequest: function() {
|
onRequest: function() {
|
||||||
closeSearchWindow('installSearchPlugin');
|
window.qBittorrent.SearchPlugins.closeSearchWindow('installSearchPlugin');
|
||||||
}
|
}
|
||||||
}).send();
|
}).send();
|
||||||
};
|
};
|
||||||
|
|
||||||
initInstallSearchPlugin();
|
init();
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,31 +14,33 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Tabs
|
(function() {
|
||||||
MochaUI.initializeTabs('preferencesTabs');
|
// Tabs
|
||||||
|
MochaUI.initializeTabs('preferencesTabs');
|
||||||
|
|
||||||
$('PrefDownloadsLink').addEvent('click', function(e) {
|
$('PrefDownloadsLink').addEvent('click', function(e) {
|
||||||
$$('.PrefTab').addClass('invisible');
|
$$('.PrefTab').addClass('invisible');
|
||||||
$('DownloadsTab').removeClass('invisible');
|
$('DownloadsTab').removeClass('invisible');
|
||||||
});
|
});
|
||||||
$('PrefConnectionLink').addEvent('click', function(e) {
|
$('PrefConnectionLink').addEvent('click', function(e) {
|
||||||
$$('.PrefTab').addClass('invisible');
|
$$('.PrefTab').addClass('invisible');
|
||||||
$('ConnectionTab').removeClass('invisible');
|
$('ConnectionTab').removeClass('invisible');
|
||||||
});
|
});
|
||||||
$('PrefSpeedLink').addEvent('click', function(e) {
|
$('PrefSpeedLink').addEvent('click', function(e) {
|
||||||
$$('.PrefTab').addClass('invisible');
|
$$('.PrefTab').addClass('invisible');
|
||||||
$('SpeedTab').removeClass('invisible');
|
$('SpeedTab').removeClass('invisible');
|
||||||
});
|
});
|
||||||
$('PrefBittorrentLink').addEvent('click', function(e) {
|
$('PrefBittorrentLink').addEvent('click', function(e) {
|
||||||
$$('.PrefTab').addClass('invisible');
|
$$('.PrefTab').addClass('invisible');
|
||||||
$('BittorrentTab').removeClass('invisible');
|
$('BittorrentTab').removeClass('invisible');
|
||||||
});
|
});
|
||||||
$('PrefWebUILink').addEvent('click', function(e) {
|
$('PrefWebUILink').addEvent('click', function(e) {
|
||||||
$$('.PrefTab').addClass('invisible');
|
$$('.PrefTab').addClass('invisible');
|
||||||
$('WebUITab').removeClass('invisible');
|
$('WebUITab').removeClass('invisible');
|
||||||
});
|
});
|
||||||
$('PrefAdvancedLink').addEvent('click', function(e) {
|
$('PrefAdvancedLink').addEvent('click', function(e) {
|
||||||
$$('.PrefTab').addClass('invisible');
|
$$('.PrefTab').addClass('invisible');
|
||||||
$('AdvancedTab').removeClass('invisible');
|
$('AdvancedTab').removeClass('invisible');
|
||||||
});
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -155,7 +155,9 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const selectedTab = $(LocalPreferences.get('selected_tab', 'PropGeneralLink'));
|
(function() {
|
||||||
if (selectedTab)
|
const selectedTab = $(LocalPreferences.get('selected_tab', 'PropGeneralLink'));
|
||||||
selectedTab.click();
|
if (selectedTab)
|
||||||
|
selectedTab.click();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -65,9 +65,9 @@
|
||||||
<span>QBT_TR(Warning: Be sure to comply with your country's copyright laws when downloading torrents from any of these search engines.)QBT_TR[CONTEXT=PluginSelectDlg]</span>
|
<span>QBT_TR(Warning: Be sure to comply with your country's copyright laws when downloading torrents from any of these search engines.)QBT_TR[CONTEXT=PluginSelectDlg]</span>
|
||||||
<span style="font-style: italic;">QBT_TR(You can get new search engine plugins here:)QBT_TR[CONTEXT=PluginSelectDlg] <a href="http://plugins.qbittorrent.org" target="_blank">http://plugins.qbittorrent.org</a></span>
|
<span style="font-style: italic;">QBT_TR(You can get new search engine plugins here:)QBT_TR[CONTEXT=PluginSelectDlg] <a href="http://plugins.qbittorrent.org" target="_blank">http://plugins.qbittorrent.org</a></span>
|
||||||
<div style="width: 100%; margin-top: 10px;">
|
<div style="width: 100%; margin-top: 10px;">
|
||||||
<button style="width: 33%; line-height: 1.4em;" onclick="installPlugin();">QBT_TR(Install new plugin)QBT_TR[CONTEXT=PluginSelectDlg]</button>
|
<button style="width: 33%; line-height: 1.4em;" onclick="qBittorrent.SearchPlugins.installPlugin();">QBT_TR(Install new plugin)QBT_TR[CONTEXT=PluginSelectDlg]</button>
|
||||||
<button style="width: 33%; line-height: 1.4em;" onclick="checkForUpdates();">QBT_TR(Check for updates)QBT_TR[CONTEXT=PluginSelectDlg]</button>
|
<button style="width: 33%; line-height: 1.4em;" onclick="qBittorrent.SearchPlugins.checkForUpdates();">QBT_TR(Check for updates)QBT_TR[CONTEXT=PluginSelectDlg]</button>
|
||||||
<button style="width: 32%; line-height: 1.4em;" onclick="closeSearchWindow('searchPlugins');">QBT_TR(Close)QBT_TR[CONTEXT=PluginSelectDlg]</button>
|
<button style="width: 32%; line-height: 1.4em;" onclick="qBittorrent.SearchPlugins.closeSearchWindow('searchPlugins');">QBT_TR(Close)QBT_TR[CONTEXT=PluginSelectDlg]</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -79,142 +79,161 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
this.searchPluginsTableContextMenu = undefined;
|
if (window.qBittorrent === undefined) {
|
||||||
this.prevOffsetLeft = undefined;
|
window.qBittorrent = {};
|
||||||
this.prevOffsetTop = undefined;
|
}
|
||||||
|
|
||||||
this.initSearchPlugins = function() {
|
window.qBittorrent.SearchPlugins = (function() {
|
||||||
searchPluginsTableContextMenu = new SearchPluginsTableContextMenu({
|
const exports = function() {
|
||||||
targets: '.searchPluginsTableRow',
|
return {
|
||||||
menu: 'searchPluginsTableMenu',
|
closeSearchWindow: closeSearchWindow,
|
||||||
actions: {
|
installPlugin: installPlugin,
|
||||||
Enabled: enablePlugin,
|
checkForUpdates: checkForUpdates,
|
||||||
Uninstall: uninstallPlugin
|
updateTable: updateTable
|
||||||
},
|
};
|
||||||
offsets: calculateContextMenuOffsets()
|
|
||||||
});
|
|
||||||
searchPluginsTable.setup('searchPluginsTableDiv', 'searchPluginsTableFixedHeaderDiv', searchPluginsTableContextMenu);
|
|
||||||
updateSearchPluginsTable();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.closeSearchWindow = function(id) {
|
|
||||||
window.parent.MochaUI.closeWindow(window.parent.$(id));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.installPlugin = function(path) {
|
|
||||||
new MochaUI.Window({
|
|
||||||
id: 'installSearchPlugin',
|
|
||||||
title: "QBT_TR(Install plugin)QBT_TR[CONTEXT=PluginSourceDlg]",
|
|
||||||
loadMethod: 'xhr',
|
|
||||||
contentURL: 'views/installsearchplugin.html',
|
|
||||||
scrollbars: false,
|
|
||||||
resizable: false,
|
|
||||||
maximizable: false,
|
|
||||||
paddingVertical: 0,
|
|
||||||
paddingHorizontal: 0,
|
|
||||||
width: 500,
|
|
||||||
height: 120
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.uninstallPlugin = function() {
|
|
||||||
const plugins = searchPluginsTable.selectedRowsIds().join('|');
|
|
||||||
const url = new URI('api/v2/search/uninstallPlugin');
|
|
||||||
new Request({
|
|
||||||
url: url,
|
|
||||||
noCache: true,
|
|
||||||
method: 'post',
|
|
||||||
data: {
|
|
||||||
names: plugins,
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.enablePlugin = function() {
|
|
||||||
const plugins = searchPluginsTable.selectedRowsIds();
|
|
||||||
let enable = true;
|
|
||||||
if (plugins && plugins.length)
|
|
||||||
enable = !getPlugin(plugins[0]).enabled;
|
|
||||||
|
|
||||||
const url = new URI('api/v2/search/enablePlugin');
|
|
||||||
new Request({
|
|
||||||
url: url,
|
|
||||||
noCache: true,
|
|
||||||
method: 'post',
|
|
||||||
data: {
|
|
||||||
names: plugins.join('|'),
|
|
||||||
enable: enable
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.checkForUpdates = function() {
|
|
||||||
const url = new URI('api/v2/search/updatePlugins');
|
|
||||||
new Request({
|
|
||||||
url: url,
|
|
||||||
noCache: true,
|
|
||||||
method: 'post'
|
|
||||||
}).send();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.calculateContextMenuOffsets = function() {
|
|
||||||
prevOffsetLeft = document.getElementById("searchPlugins").getBoundingClientRect().left;
|
|
||||||
prevOffsetTop = document.getElementById("searchPlugins").getBoundingClientRect().top;
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: -(prevOffsetLeft + 20),
|
|
||||||
y: -(prevOffsetTop + 2)
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
this.updateSearchPluginsTableContextMenuOffset = function() {
|
let searchPluginsTable;
|
||||||
// only re-calculate if window has moved
|
let searchPluginsTableContextMenu;
|
||||||
if ((prevOffsetLeft !== document.getElementById("searchPlugins").getBoundingClientRect().left) || (prevOffsetTop !== document.getElementById("searchPlugins").getBoundingClientRect().top))
|
let prevOffsetLeft;
|
||||||
searchPluginsTableContextMenu.options.offsets = calculateContextMenuOffsets();
|
let prevOffsetTop;
|
||||||
};
|
|
||||||
|
|
||||||
this.setupSearchPluginTableEvents = function(enable) {
|
const initSearchPlugins = function() {
|
||||||
if (enable)
|
searchPluginsTable = new window.qBittorrent.DynamicTable.SearchPluginsTable();
|
||||||
$$(".searchPluginsTableRow").each(function(target) {
|
searchPluginsTableContextMenu = new window.qBittorrent.ContextMenu.SearchPluginsTableContextMenu({
|
||||||
target.addEventListener('dblclick', enablePlugin, false);
|
targets: '.searchPluginsTableRow',
|
||||||
target.addEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
|
menu: 'searchPluginsTableMenu',
|
||||||
|
actions: {
|
||||||
|
Enabled: enablePlugin,
|
||||||
|
Uninstall: uninstallPlugin
|
||||||
|
},
|
||||||
|
offsets: calculateContextMenuOffsets()
|
||||||
});
|
});
|
||||||
else
|
searchPluginsTable.setup('searchPluginsTableDiv', 'searchPluginsTableFixedHeaderDiv', searchPluginsTableContextMenu);
|
||||||
$$(".searchPluginsTableRow").each(function(target) {
|
updateTable();
|
||||||
target.removeEventListener('dblclick', enablePlugin, false);
|
};
|
||||||
target.removeEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
|
|
||||||
|
const closeSearchWindow = function(id) {
|
||||||
|
window.parent.MochaUI.closeWindow(window.parent.$(id));
|
||||||
|
};
|
||||||
|
|
||||||
|
const installPlugin = function(path) {
|
||||||
|
new MochaUI.Window({
|
||||||
|
id: 'installSearchPlugin',
|
||||||
|
title: "QBT_TR(Install plugin)QBT_TR[CONTEXT=PluginSourceDlg]",
|
||||||
|
loadMethod: 'xhr',
|
||||||
|
contentURL: 'views/installsearchplugin.html',
|
||||||
|
scrollbars: false,
|
||||||
|
resizable: false,
|
||||||
|
maximizable: false,
|
||||||
|
paddingVertical: 0,
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
width: 500,
|
||||||
|
height: 120
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateSearchPluginsTable = function() {
|
const uninstallPlugin = function() {
|
||||||
// clear event listeners
|
const plugins = searchPluginsTable.selectedRowsIds().join('|');
|
||||||
setupSearchPluginTableEvents(false);
|
const url = new URI('api/v2/search/uninstallPlugin');
|
||||||
|
new Request({
|
||||||
const oldPlugins = Object.keys(searchPluginsTable.rows);
|
url: url,
|
||||||
// remove old rows from the table
|
noCache: true,
|
||||||
for (let i = 0; i < oldPlugins.length; ++i) {
|
method: 'post',
|
||||||
let found = false;
|
data: {
|
||||||
for (let j = 0; j < searchPlugins.length; ++j) {
|
names: plugins,
|
||||||
if (searchPlugins[j].name === oldPlugins[i]) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
const enablePlugin = function() {
|
||||||
|
const plugins = searchPluginsTable.selectedRowsIds();
|
||||||
|
let enable = true;
|
||||||
|
if (plugins && plugins.length)
|
||||||
|
enable = !window.qBittorrent.Search.getPlugin(plugins[0]).enabled;
|
||||||
|
|
||||||
|
const url = new URI('api/v2/search/enablePlugin');
|
||||||
|
new Request({
|
||||||
|
url: url,
|
||||||
|
noCache: true,
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
names: plugins.join('|'),
|
||||||
|
enable: enable
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkForUpdates = function() {
|
||||||
|
const url = new URI('api/v2/search/updatePlugins');
|
||||||
|
new Request({
|
||||||
|
url: url,
|
||||||
|
noCache: true,
|
||||||
|
method: 'post'
|
||||||
|
}).send();
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateContextMenuOffsets = function() {
|
||||||
|
prevOffsetLeft = document.getElementById("searchPlugins").getBoundingClientRect().left;
|
||||||
|
prevOffsetTop = document.getElementById("searchPlugins").getBoundingClientRect().top;
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: -(prevOffsetLeft + 20),
|
||||||
|
y: -(prevOffsetTop + 2)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateSearchPluginsTableContextMenuOffset = function() {
|
||||||
|
// only re-calculate if window has moved
|
||||||
|
if ((prevOffsetLeft !== document.getElementById("searchPlugins").getBoundingClientRect().left) || (prevOffsetTop !== document.getElementById("searchPlugins").getBoundingClientRect().top))
|
||||||
|
searchPluginsTableContextMenu.options.offsets = calculateContextMenuOffsets();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setupSearchPluginTableEvents = function(enable) {
|
||||||
|
if (enable)
|
||||||
|
$$(".searchPluginsTableRow").each(function(target) {
|
||||||
|
target.addEventListener('dblclick', enablePlugin, false);
|
||||||
|
target.addEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
|
||||||
|
});
|
||||||
|
else
|
||||||
|
$$(".searchPluginsTableRow").each(function(target) {
|
||||||
|
target.removeEventListener('dblclick', enablePlugin, false);
|
||||||
|
target.removeEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateTable = function() {
|
||||||
|
// clear event listeners
|
||||||
|
setupSearchPluginTableEvents(false);
|
||||||
|
|
||||||
|
const oldPlugins = Object.keys(searchPluginsTable.rows);
|
||||||
|
// remove old rows from the table
|
||||||
|
for (let i = 0; i < oldPlugins.length; ++i) {
|
||||||
|
let found = false;
|
||||||
|
for (let j = 0; j < window.qBittorrent.Search.searchPlugins.length; ++j) {
|
||||||
|
if (window.qBittorrent.Search.searchPlugins[j].name === oldPlugins[i]) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
searchPluginsTable.removeRow(oldPlugins[i]);
|
||||||
}
|
}
|
||||||
if (!found)
|
|
||||||
searchPluginsTable.removeRow(oldPlugins[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < searchPlugins.length; ++i) {
|
for (let i = 0; i < window.qBittorrent.Search.searchPlugins.length; ++i) {
|
||||||
searchPlugins[i].rowId = searchPlugins[i].name;
|
window.qBittorrent.Search.searchPlugins[i].rowId = window.qBittorrent.Search.searchPlugins[i].name;
|
||||||
searchPluginsTable.updateRowData(searchPlugins[i]);
|
searchPluginsTable.updateRowData(window.qBittorrent.Search.searchPlugins[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
searchPluginsTable.updateTable();
|
searchPluginsTable.updateTable();
|
||||||
searchPluginsTable.altRow();
|
searchPluginsTable.altRow();
|
||||||
|
|
||||||
// add event listeners
|
// add event listeners
|
||||||
setupSearchPluginTableEvents(true);
|
setupSearchPluginTableEvents(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
initSearchPlugins();
|
initSearchPlugins();
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -18,81 +18,95 @@
|
||||||
<script>
|
<script>
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
//create a context menu
|
if (window.qBittorrent === undefined) {
|
||||||
const torrentsTableContextMenu = new TorrentsTableContextMenu({
|
window.qBittorrent = {};
|
||||||
targets: '.torrentsTableContextMenuTarget',
|
}
|
||||||
menu: 'torrentsTableMenu',
|
|
||||||
actions: {
|
|
||||||
start: function(element, ref) {
|
|
||||||
startFN();
|
|
||||||
},
|
|
||||||
pause: function(element, ref) {
|
|
||||||
pauseFN();
|
|
||||||
},
|
|
||||||
forceStart: function(element, ref) {
|
|
||||||
setForceStartFN();
|
|
||||||
},
|
|
||||||
|
|
||||||
delete: function(element, ref) {
|
window.qBittorrent.TransferList = (function() {
|
||||||
deleteFN();
|
const exports = function() {
|
||||||
},
|
return {
|
||||||
|
contextMenu: contextMenu,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
setLocation: function(element, ref) {
|
//create a context menu
|
||||||
setLocationFN();
|
const contextMenu = new window.qBittorrent.ContextMenu.TorrentsTableContextMenu({
|
||||||
},
|
targets: '.torrentsTableContextMenuTarget',
|
||||||
|
menu: 'torrentsTableMenu',
|
||||||
|
actions: {
|
||||||
|
start: function(element, ref) {
|
||||||
|
startFN();
|
||||||
|
},
|
||||||
|
pause: function(element, ref) {
|
||||||
|
pauseFN();
|
||||||
|
},
|
||||||
|
forceStart: function(element, ref) {
|
||||||
|
setForceStartFN();
|
||||||
|
},
|
||||||
|
|
||||||
rename: function(element, ref) {
|
delete: function(element, ref) {
|
||||||
renameFN();
|
deleteFN();
|
||||||
},
|
},
|
||||||
queueTop: function(element, ref) {
|
|
||||||
setQueuePositionFN('topPrio');
|
|
||||||
},
|
|
||||||
queueUp: function(element, ref) {
|
|
||||||
setQueuePositionFN('increasePrio');
|
|
||||||
},
|
|
||||||
queueDown: function(element, ref) {
|
|
||||||
setQueuePositionFN('decreasePrio');
|
|
||||||
},
|
|
||||||
queueBottom: function(element, ref) {
|
|
||||||
setQueuePositionFN('bottomPrio');
|
|
||||||
},
|
|
||||||
|
|
||||||
downloadLimit: function(element, ref) {
|
setLocation: function(element, ref) {
|
||||||
downloadLimitFN();
|
setLocationFN();
|
||||||
},
|
},
|
||||||
uploadLimit: function(element, ref) {
|
|
||||||
uploadLimitFN();
|
|
||||||
},
|
|
||||||
shareRatio: function(element, ref) {
|
|
||||||
shareRatioFN();
|
|
||||||
},
|
|
||||||
|
|
||||||
sequentialDownload: function(element, ref) {
|
rename: function(element, ref) {
|
||||||
toggleSequentialDownloadFN();
|
renameFN();
|
||||||
},
|
},
|
||||||
firstLastPiecePrio: function(element, ref) {
|
queueTop: function(element, ref) {
|
||||||
toggleFirstLastPiecePrioFN();
|
setQueuePositionFN('topPrio');
|
||||||
},
|
},
|
||||||
|
queueUp: function(element, ref) {
|
||||||
|
setQueuePositionFN('increasePrio');
|
||||||
|
},
|
||||||
|
queueDown: function(element, ref) {
|
||||||
|
setQueuePositionFN('decreasePrio');
|
||||||
|
},
|
||||||
|
queueBottom: function(element, ref) {
|
||||||
|
setQueuePositionFN('bottomPrio');
|
||||||
|
},
|
||||||
|
|
||||||
autoTorrentManagement: function(element, ref) {
|
downloadLimit: function(element, ref) {
|
||||||
autoTorrentManagementFN();
|
downloadLimitFN();
|
||||||
},
|
},
|
||||||
forceRecheck: function(element, ref) {
|
uploadLimit: function(element, ref) {
|
||||||
recheckFN();
|
uploadLimitFN();
|
||||||
},
|
},
|
||||||
forceReannounce: function(element, ref) {
|
shareRatio: function(element, ref) {
|
||||||
reannounceFN();
|
shareRatioFN();
|
||||||
},
|
},
|
||||||
|
|
||||||
superSeeding: function(element, ref) {
|
sequentialDownload: function(element, ref) {
|
||||||
setSuperSeedingFN(!ref.getItemChecked('superSeeding'));
|
toggleSequentialDownloadFN();
|
||||||
|
},
|
||||||
|
firstLastPiecePrio: function(element, ref) {
|
||||||
|
toggleFirstLastPiecePrioFN();
|
||||||
|
},
|
||||||
|
|
||||||
|
autoTorrentManagement: function(element, ref) {
|
||||||
|
autoTorrentManagementFN();
|
||||||
|
},
|
||||||
|
forceRecheck: function(element, ref) {
|
||||||
|
recheckFN();
|
||||||
|
},
|
||||||
|
forceReannounce: function(element, ref) {
|
||||||
|
reannounceFN();
|
||||||
|
},
|
||||||
|
|
||||||
|
superSeeding: function(element, ref) {
|
||||||
|
setSuperSeedingFN(!ref.getItemChecked('superSeeding'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
offsets: {
|
||||||
|
x: -15,
|
||||||
|
y: 2
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
offsets: {
|
|
||||||
x: -15,
|
|
||||||
y: 2
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
torrentsTable.setup('torrentsTableDiv', 'torrentsTableFixedHeaderDiv', torrentsTableContextMenu);
|
torrentsTable.setup('torrentsTableDiv', 'torrentsTableFixedHeaderDiv', contextMenu);
|
||||||
|
|
||||||
|
return exports();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue