mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-20 05:13:30 -07:00
Merge pull request #11103 from Piccirello/webui-explicit-export
Move JavaScript code into explicit namespaces
This commit is contained in:
commit
209831d3b0
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…
Add table
Add a link
Reference in a new issue