support display block status
This commit is contained in:
parent
e874477e94
commit
feb79aca2c
|
@ -286,6 +286,8 @@
|
|||
<script src="scripts/controllers/settings-ariang.js"></script>
|
||||
<script src="scripts/controllers/settings-aria2.js"></script>
|
||||
<script src="scripts/controllers/status.js"></script>
|
||||
<script src="scripts/directives/pieceBar.js"></script>
|
||||
<script src="scripts/directives/pieceMap.js"></script>
|
||||
<script src="scripts/directives/chart.js"></script>
|
||||
<script src="scripts/directives/placeholder.js"></script>
|
||||
<script src="scripts/directives/setting.js"></script>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
"Error Occurred": "发生错误",
|
||||
"Removed": "已删除",
|
||||
"Downloaded / Stopped": "已完成 / 已停止",
|
||||
"Uncompleted": "未完成",
|
||||
"Settings": "系统设置",
|
||||
"AriaNg Settings": "AriaNg 设置",
|
||||
"Aria2 Settings": "Aria2 设置",
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
'Error Occurred': 'Error Occurred',
|
||||
'Removed': 'Removed',
|
||||
'Downloaded / Stopped': 'Downloaded / Stopped',
|
||||
'Uncompleted': 'Uncompleted',
|
||||
'Settings': 'Settings',
|
||||
'AriaNg Settings': 'AriaNg Settings',
|
||||
'Aria2 Settings': 'Aria2 Settings',
|
||||
|
|
48
app/scripts/directives/pieceBar.js
Normal file
48
app/scripts/directives/pieceBar.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular.module('ariaNg').directive('ngPieceBar', ['aria2TaskService', function (aria2TaskService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: '<canvas class="piece-bar progress"></canvas>',
|
||||
replace: true,
|
||||
scope: {
|
||||
bitField: '=',
|
||||
pieceCount: '=',
|
||||
color: '@'
|
||||
},
|
||||
link: function (scope, element) {
|
||||
var redraw = function () {
|
||||
var canvas = element[0];
|
||||
var combinedPieces = aria2TaskService.getCombinedPieces(scope.bitField, scope.pieceCount);
|
||||
var context = canvas.getContext('2d');
|
||||
context.fillStyle = scope.color || '#000';
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
var posX = 0;
|
||||
var width = canvas.width;
|
||||
var height = canvas.height;
|
||||
|
||||
for (var i = 0; i < combinedPieces.length; i++) {
|
||||
var piece = combinedPieces[i];
|
||||
var pieceWidth = piece.count / scope.pieceCount * width;
|
||||
|
||||
if (piece.isCompleted) {
|
||||
context.fillRect(posX, 0, pieceWidth, height);
|
||||
}
|
||||
|
||||
posX += pieceWidth;
|
||||
}
|
||||
};
|
||||
|
||||
scope.$watch('bitField', function () {
|
||||
redraw();
|
||||
});
|
||||
|
||||
scope.$watch('pieceNumber', function () {
|
||||
redraw();
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
})();
|
33
app/scripts/directives/pieceMap.js
Normal file
33
app/scripts/directives/pieceMap.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular.module('ariaNg').directive('ngPieceMap', ['aria2TaskService', function (aria2TaskService) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: '<div class="piece-map"></div>',
|
||||
replace: true,
|
||||
scope: {
|
||||
bitField: '=',
|
||||
pieceCount: '='
|
||||
},
|
||||
link: function (scope, element) {
|
||||
var redraw = function () {
|
||||
var pieces = aria2TaskService.getPieceStatus(scope.bitField, scope.pieceCount);
|
||||
element.empty();
|
||||
|
||||
for (var i = 0; i < pieces.length; i++) {
|
||||
element.append('<div class="piece' + (pieces[i] ? ' piece-completed' : '') + '"></div>');
|
||||
}
|
||||
};
|
||||
|
||||
scope.$watch('bitField', function () {
|
||||
redraw();
|
||||
});
|
||||
|
||||
scope.$watch('pieceNumber', function () {
|
||||
redraw();
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
})();
|
|
@ -283,56 +283,78 @@
|
|||
processDownloadTask(tasks[i]);
|
||||
}
|
||||
},
|
||||
getPieceStatus: function (bitField, pieceCount) {
|
||||
var pieces = [];
|
||||
|
||||
if (!bitField) {
|
||||
return pieces;
|
||||
}
|
||||
|
||||
var pieceIndex = 0;
|
||||
|
||||
for (var i = 0; i < bitField.length; i++) {
|
||||
var bitSet = parseInt(bitField[i], 16);
|
||||
|
||||
for (var j = 1; j <= 4; j++) {
|
||||
var bit = (1 << (4 - j));
|
||||
var isCompleted = (bitSet & bit) == bit;
|
||||
|
||||
pieces.push(isCompleted ? 1 : 0);
|
||||
pieceIndex++;
|
||||
|
||||
if (pieceIndex >= pieceCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pieces;
|
||||
},
|
||||
getCombinedPieces: function (bitField, pieceCount) {
|
||||
var pieces = this.getPieceStatus(bitField, pieceCount);
|
||||
var combinedPieces = [];
|
||||
|
||||
for (var i = 0; i < pieces.length; i++) {
|
||||
var isCompleted = (pieces[i] == 1);
|
||||
|
||||
if (combinedPieces.length > 0 && combinedPieces[combinedPieces.length - 1].isCompleted == isCompleted) {
|
||||
combinedPieces[combinedPieces.length - 1].count++;
|
||||
} else {
|
||||
combinedPieces.push({
|
||||
isCompleted: isCompleted,
|
||||
count: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return combinedPieces;
|
||||
},
|
||||
estimateHealthPercentFromPeers: function (task, peers) {
|
||||
if (peers.length < 1) {
|
||||
return task.completePercent;
|
||||
}
|
||||
|
||||
var bitfieldCompletedArr = new Array(task.bitfield.length);
|
||||
var bitfieldPieceArr = new Array(task.bitfield.length);
|
||||
var totalLength = task.bitfield.length * 0xf;
|
||||
var healthBitCount = 0;
|
||||
|
||||
for (var i = 0; i < task.bitfield.length; i++) {
|
||||
var num = parseInt(task.bitfield[i], 16);
|
||||
bitfieldCompletedArr[i] = 0;
|
||||
bitfieldPieceArr[i] = 0;
|
||||
|
||||
if (num == 0xf) {
|
||||
bitfieldCompletedArr[i] = num;
|
||||
} else {
|
||||
bitfieldPieceArr[i] = num;
|
||||
}
|
||||
}
|
||||
var pieces = this.getPieceStatus(task.bitfield, task.numPieces);
|
||||
|
||||
for (var i = 0; i < peers.length; i++) {
|
||||
var peer = peers[i];
|
||||
var bitfield = peer.bitfield;
|
||||
var peerPieces = this.getPieceStatus(peer.bitfield, task.numPieces);
|
||||
|
||||
for (var j = 0; j < bitfield.length; j++) {
|
||||
var num = parseInt(bitfield[j], 16);
|
||||
|
||||
if (num == 0xf) {
|
||||
bitfieldCompletedArr[j] += num;
|
||||
} else {
|
||||
bitfieldPieceArr[j] = Math.max(bitfieldPieceArr[j], num);
|
||||
}
|
||||
for (var j = 0; j < peerPieces.length; j++) {
|
||||
pieces[j] += peerPieces[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < bitfieldCompletedArr.length; i++) {
|
||||
bitfieldCompletedArr[i] += bitfieldPieceArr[i];
|
||||
}
|
||||
var competedPieceCount = 0;
|
||||
|
||||
while (true) {
|
||||
var completed = true;
|
||||
|
||||
for (var i = 0; i < bitfieldCompletedArr.length; i++) {
|
||||
var bitCount = Math.min(bitfieldCompletedArr[i], 0xf);
|
||||
healthBitCount += bitCount;
|
||||
bitfieldCompletedArr[i] -= bitCount;
|
||||
|
||||
if (bitCount < 0xf) {
|
||||
for (var i = 0; i < pieces.length; i++) {
|
||||
if (pieces[i] > 0) {
|
||||
competedPieceCount++;
|
||||
pieces[i]--;
|
||||
} else {
|
||||
completed = false;
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +364,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
var healthPercent = healthBitCount / totalLength * 100;
|
||||
var healthPercent = competedPieceCount / task.numPieces * 100;
|
||||
|
||||
if (healthPercent < task.completePercent) {
|
||||
healthPercent = task.completePercent;
|
||||
|
|
|
@ -623,6 +623,46 @@ td {
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* piece-bar / piece-map */
|
||||
.piece-bar-wrapper {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.piece-bar {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.piece-map {
|
||||
padding-left: 6px;
|
||||
padding-right: 2px;
|
||||
line-height: 11px;
|
||||
}
|
||||
|
||||
.piece-legends {
|
||||
text-align: center;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.piece-legend {
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.piece-map .piece, .piece-legend .piece {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: #eef2f4;
|
||||
border: #dee2e5 solid 1px;
|
||||
display: inline-block;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.piece-map .piece.piece-completed, .piece-legend .piece.piece-completed {
|
||||
background-color: #b8dd69;
|
||||
border-color: #b8dd69;
|
||||
}
|
||||
|
||||
/* task-table */
|
||||
.task-table {
|
||||
margin-left: 15px;
|
||||
|
@ -831,3 +871,4 @@ td {
|
|||
}
|
||||
}
|
||||
|
||||
/* miscellaneous */
|
||||
|
|
|
@ -130,7 +130,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" ng-class="{'active': context.currentTab == 'blocks'}">
|
||||
|
||||
<div class="piece-legends">
|
||||
<div class="piece-legend">
|
||||
<div class="piece piece-completed"></div>
|
||||
<span translate>Completed</span>
|
||||
</div>
|
||||
<div class="piece-legend">
|
||||
<div class="piece"></div>
|
||||
<span translate>Uncompleted</span>
|
||||
</div>
|
||||
</div>
|
||||
<ng-piece-map bit-field="task.bitfield" piece-count="task.numPieces"></ng-piece-map>
|
||||
</div>
|
||||
<div class="tab-pane" ng-class="{'active': context.currentTab == 'filelist'}">
|
||||
<div class="task-table task-table-firstrow-noborder">
|
||||
|
@ -200,7 +210,9 @@
|
|||
<span ng-bind="peer.ip + ':' + peer.port"></span>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
|
||||
<div class="piece-bar-wrapper">
|
||||
<ng-piece-bar bit-field="peer.bitfield" piece-count="task.numPieces" color="#149BDF"></ng-piece-bar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-2 col-xs-4">
|
||||
<span ng-bind="(peer.completePercent | percent: 2) + '%'"></span>
|
||||
|
|
Reference in a new issue