diff --git a/src/webui/www/private/css/style.css b/src/webui/www/private/css/style.css index 6a4f96bfc..5a9c04ce7 100644 --- a/src/webui/www/private/css/style.css +++ b/src/webui/www/private/css/style.css @@ -517,6 +517,21 @@ td.generalLabel { padding: 2px; } +#progress { + border: 1px solid #999; + padding: 0; + position: relative; + width: 100%; +} + +#progress canvas { + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; +} + #watched_folders_tab { border-collapse: collapse; } diff --git a/src/webui/www/private/scripts/prop-general.js b/src/webui/www/private/scripts/prop-general.js index 2c77cfab2..5e1d604fb 100644 --- a/src/webui/www/private/scripts/prop-general.js +++ b/src/webui/www/private/scripts/prop-general.js @@ -65,6 +65,9 @@ window.qBittorrent.PropGeneral = (function() { $('torrent_hash_v2').set('html', ''); $('save_path').set('html', ''); $('comment').set('html', ''); + + const canvas = $('progress').getFirst('canvas'); + canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); }; let loadTorrentDataTimer; @@ -213,6 +216,66 @@ window.qBittorrent.PropGeneral = (function() { loadTorrentDataTimer = loadTorrentData.delay(5000); } }).send(); + + const piecesUrl = new URI('api/v2/torrents/pieceStates?hash=' + current_id); + new Request.JSON({ + url: piecesUrl, + 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) { + const canvas = $('progress').getFirst('canvas'); + canvas.width = data.length; + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // Group contiguous colors together and draw as a single rectangle + let color = ''; + let rectWidth = 1; + + for (let i = 0; i < data.length; ++i) { + const status = data[i]; + let newColor = ''; + + if (status === 1) + newColor = 'green'; + else if (status === 2) + newColor = 'blue'; + + if (newColor === color) { + ++rectWidth; + continue; + } + + if (color !== '') { + ctx.fillStyle = color; + ctx.fillRect((i - rectWidth), 0, rectWidth, canvas.height); + } + + rectWidth = 1; + color = newColor; + } + + // Fill a rect at the end of the canvas if one is needed + if (color !== '') { + ctx.fillStyle = color; + ctx.fillRect((data.length - rectWidth), 0, rectWidth, canvas.height); + } + } + else { + clearData(); + } + clearTimeout(loadTorrentDataTimer); + loadTorrentDataTimer = loadTorrentData.delay(5000); + } + }).send(); }; const updateData = function() { diff --git a/src/webui/www/private/views/properties.html b/src/webui/www/private/views/properties.html index cc0b5a560..171e54196 100644 --- a/src/webui/www/private/views/properties.html +++ b/src/webui/www/private/views/properties.html @@ -1,4 +1,13 @@
QBT_TR(Progress:)QBT_TR[CONTEXT=PropertiesWidget] | ++ + | +