support display peer client information
This commit is contained in:
parent
5f5fd7087b
commit
09e3abea3e
|
@ -45,6 +45,7 @@
|
||||||
"angular-utf8-base64": "^0.0.5",
|
"angular-utf8-base64": "^0.0.5",
|
||||||
"angular-local-storage": "^0.2.7",
|
"angular-local-storage": "^0.2.7",
|
||||||
"angular-notification": "775ee861c1737b284588bcb878ba1f4e43c70c97",
|
"angular-notification": "775ee861c1737b284588bcb878ba1f4e43c70c97",
|
||||||
|
"angular-bittorrent-peerid": "^1.0.2",
|
||||||
"angular-busy": "^4.1.3",
|
"angular-busy": "^4.1.3",
|
||||||
"angular-promise-buttons": "^0.1.14",
|
"angular-promise-buttons": "^0.1.14",
|
||||||
"angular-dragula": "^1.2.7",
|
"angular-dragula": "^1.2.7",
|
||||||
|
|
|
@ -276,6 +276,7 @@
|
||||||
<script src="../bower_components/angular-utf8-base64/angular-utf8-base64.min.js"></script>
|
<script src="../bower_components/angular-utf8-base64/angular-utf8-base64.min.js"></script>
|
||||||
<script src="../bower_components/angular-local-storage/dist/angular-local-storage.min.js"></script>
|
<script src="../bower_components/angular-local-storage/dist/angular-local-storage.min.js"></script>
|
||||||
<script src="../bower_components/angular-notification/angular-notification.js"></script>
|
<script src="../bower_components/angular-notification/angular-notification.js"></script>
|
||||||
|
<script src="../bower_components/angular-bittorrent-peerid/angular-bittorrent-peerid.min.js"></script>
|
||||||
<script src="../bower_components/angular-busy/dist/angular-busy.min.js"></script>
|
<script src="../bower_components/angular-busy/dist/angular-busy.min.js"></script>
|
||||||
<script src="../bower_components/angular-promise-buttons/dist/angular-promise-buttons.min.js"></script>
|
<script src="../bower_components/angular-promise-buttons/dist/angular-promise-buttons.min.js"></script>
|
||||||
<script src="../bower_components/angular-dragula/dist/angular-dragula.min.js"></script>
|
<script src="../bower_components/angular-dragula/dist/angular-dragula.min.js"></script>
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
"Applications": "应用程序",
|
"Applications": "应用程序",
|
||||||
"Archives": "存档文件",
|
"Archives": "存档文件",
|
||||||
"Address": "地址",
|
"Address": "地址",
|
||||||
|
"Client": "客户端",
|
||||||
"Status": "状态",
|
"Status": "状态",
|
||||||
"Speed": "速度",
|
"Speed": "速度",
|
||||||
"(local)": "(本机)",
|
"(local)": "(本机)",
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
'Applications': 'Applications',
|
'Applications': 'Applications',
|
||||||
'Archives': 'Archives',
|
'Archives': 'Archives',
|
||||||
'Address': 'Address',
|
'Address': 'Address',
|
||||||
|
'Client': 'Client',
|
||||||
'Status': 'Status',
|
'Status': 'Status',
|
||||||
'Speed': 'Speed',
|
'Speed': 'Speed',
|
||||||
'(local)': '(local)',
|
'(local)': '(local)',
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
'ab-base64',
|
'ab-base64',
|
||||||
'LocalStorageModule',
|
'LocalStorageModule',
|
||||||
'notification',
|
'notification',
|
||||||
|
'angularBittorrentPeerid',
|
||||||
'cgBusy',
|
'cgBusy',
|
||||||
'angularPromiseButtons',
|
'angularPromiseButtons',
|
||||||
'oitozero.ngSweetAlert',
|
'oitozero.ngSweetAlert',
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
},
|
},
|
||||||
link: function (scope, element, attrs) {
|
link: function (scope, element, attrs) {
|
||||||
var options = {
|
var options = {
|
||||||
|
ngTooltipIf: true,
|
||||||
ngTooltipPlacement: 'top',
|
ngTooltipPlacement: 'top',
|
||||||
ngTooltipContainer: null,
|
ngTooltipContainer: null,
|
||||||
ngTooltipTrigger: 'hover'
|
ngTooltipTrigger: 'hover'
|
||||||
|
@ -16,15 +17,53 @@
|
||||||
|
|
||||||
angular.extend(options, attrs);
|
angular.extend(options, attrs);
|
||||||
|
|
||||||
|
var showTooltip = options.ngTooltipIf === true || options.ngTooltipIf === 'true';
|
||||||
|
|
||||||
|
var addTooltip = function () {
|
||||||
angular.element(element).tooltip({
|
angular.element(element).tooltip({
|
||||||
title: scope.title,
|
title: scope.title,
|
||||||
placement: options.ngTooltipPlacement,
|
placement: options.ngTooltipPlacement,
|
||||||
container: options.ngTooltipContainer,
|
container: options.ngTooltipContainer,
|
||||||
trigger: options.ngTooltipTrigger
|
trigger: options.ngTooltipTrigger
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var refreshTooltip = function () {
|
||||||
|
angular.element(element).attr('title', scope.title).tooltip('fixTitle');
|
||||||
|
};
|
||||||
|
|
||||||
|
var removeTooltip = function () {
|
||||||
|
angular.element(element).tooltip('destroy');
|
||||||
|
};
|
||||||
|
|
||||||
|
if (showTooltip) {
|
||||||
|
addTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
scope.$watch('title', function () {
|
scope.$watch('title', function () {
|
||||||
angular.element(element).attr('title', scope.title).tooltip('fixTitle');
|
if (showTooltip) {
|
||||||
|
refreshTooltip();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.$watch('ngTooltipIf', function (value) {
|
||||||
|
if (angular.isUndefined(value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (value === true || value === 'true');
|
||||||
|
|
||||||
|
if (showTooltip == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
addTooltip();
|
||||||
|
} else {
|
||||||
|
removeTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
showTooltip = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
if (orderType.type == 'address') {
|
if (orderType.type == 'address') {
|
||||||
return $filter('orderBy')(array, ['ip', 'port'], orderType.reverse);
|
return $filter('orderBy')(array, ['ip', 'port'], orderType.reverse);
|
||||||
|
} else if (orderType.type == 'client') {
|
||||||
|
return $filter('orderBy')(array, ['client.name', 'client.version'], orderType.reverse);
|
||||||
} else if (orderType.type == 'percent') {
|
} else if (orderType.type == 'percent') {
|
||||||
return $filter('orderBy')(array, ['completePercent'], orderType.reverse);
|
return $filter('orderBy')(array, ['completePercent'], orderType.reverse);
|
||||||
} else if (orderType.type == 'dspeed') {
|
} else if (orderType.type == 'dspeed') {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('ariaNg').factory('aria2TaskService', ['$q', '$translate', 'aria2RpcService', 'ariaNgCommonService', function ($q, $translate, aria2RpcService, ariaNgCommonService) {
|
angular.module('ariaNg').factory('aria2TaskService', ['$q', '$translate', 'bittorrentPeeridService', 'aria2RpcService', 'ariaNgCommonService', function ($q, $translate, bittorrentPeeridService, aria2RpcService, ariaNgCommonService) {
|
||||||
var getFileName = function (file) {
|
var getFileName = function (file) {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -122,6 +122,18 @@
|
||||||
if (completedPieceCount == localTaskCompletedPieceCount && peer.completePercent != localTaskCompletedPercent) {
|
if (completedPieceCount == localTaskCompletedPieceCount && peer.completePercent != localTaskCompletedPercent) {
|
||||||
peer.completePercent = localTaskCompletedPercent;
|
peer.completePercent = localTaskCompletedPercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (peer.peerId) {
|
||||||
|
var peerId = ariaNgCommonService.decodePercentEncodedString(peer.peerId);
|
||||||
|
var client = (peerId ? bittorrentPeeridService.parseClient(peerId) : null);
|
||||||
|
|
||||||
|
if (client && client.client != 'unknown') {
|
||||||
|
peer.client = {
|
||||||
|
name: (client.client ? client.client.trim() : ''),
|
||||||
|
version: (client.version ? client.version.trim() : '')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeLocalPeer) {
|
if (includeLocalPeer) {
|
||||||
|
|
|
@ -58,6 +58,27 @@
|
||||||
|
|
||||||
return filePath.substring(filePath.lastIndexOf('.'));
|
return filePath.substring(filePath.lastIndexOf('.'));
|
||||||
},
|
},
|
||||||
|
decodePercentEncodedString: function (s) {
|
||||||
|
if (!s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = '';
|
||||||
|
|
||||||
|
for (var i = 0; i < s.length; i++) {
|
||||||
|
var ch = s.charAt(i);
|
||||||
|
|
||||||
|
if (ch == '%' && i < s.length - 2) {
|
||||||
|
var code = s.substring(i + 1, i + 3);
|
||||||
|
ret += String.fromCharCode(parseInt(code, 16));
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
|
ret += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
extendArray: function (sourceArray, targetArray, keyProperty) {
|
extendArray: function (sourceArray, targetArray, keyProperty) {
|
||||||
if (!targetArray || !sourceArray || sourceArray.length != targetArray.length) {
|
if (!targetArray || !sourceArray || sourceArray.length != targetArray.length) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -51,6 +51,14 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-table .peer-name-wrapper {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.task-table .task-files, .task-table .task-size {
|
.task-table .task-files, .task-table .task-size {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -413,6 +413,11 @@
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.skin-aria-ng .task-table .peer-client {
|
||||||
|
color: #888;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
/* settings-table */
|
/* settings-table */
|
||||||
.skin-aria-ng .settings-table {
|
.skin-aria-ng .settings-table {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
|
@ -221,7 +221,7 @@
|
||||||
<div class="checkbox checkbox-primary">
|
<div class="checkbox checkbox-primary">
|
||||||
<input id="{{'file_' + file.index}}" type="checkbox" ng-disabled="!task || !task.files || task.files.length < 2 || (task.status != 'waiting' && task.status != 'paused')"
|
<input id="{{'file_' + file.index}}" type="checkbox" ng-disabled="!task || !task.files || task.files.length < 2 || (task.status != 'waiting' && task.status != 'paused')"
|
||||||
ng-model="file.selected" ng-change="setSelectedFile()"/>
|
ng-model="file.selected" ng-change="setSelectedFile()"/>
|
||||||
<label for="{{'file_' + file.index}}" ng-bind="file.fileName"></label>
|
<label for="{{'file_' + file.index}}" ng-bind="file.fileName" ng-tooltip="{{file.fileName}}" ng-tooltip-container="body"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
@ -245,18 +245,25 @@
|
||||||
<div class="task-table">
|
<div class="task-table">
|
||||||
<div class="task-table-title">
|
<div class="task-table-title">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-3">
|
<div class="col-md-4 col-sm-4">
|
||||||
<a ng-click="changePeerListDisplayOrder('address:asc', true)" translate>Address</a>
|
<a ng-click="changePeerListDisplayOrder('address:asc', true)" translate>Address</a>
|
||||||
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('address:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('address:desc')}"></i>
|
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('address:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('address:desc')}"></i>
|
||||||
|
<span>/</span>
|
||||||
|
<a ng-click="changePeerListDisplayOrder('client:asc', true)" translate>Client</a>
|
||||||
|
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('client:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('client:desc')}"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-md-5 col-sm-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
<span translate>Status</span>
|
<span translate>Status</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-6 text-right">
|
||||||
<a ng-click="changePeerListDisplayOrder('percent:desc', true)" translate>Progress</a>
|
<a ng-click="changePeerListDisplayOrder('percent:desc', true)" translate>Progress</a>
|
||||||
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('percent:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('percent:desc')}"></i>
|
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('percent:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('percent:desc')}"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4">
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-sm-4">
|
||||||
<a ng-click="changePeerListDisplayOrder('dspeed:desc', true)" translate>Download</a>
|
<a ng-click="changePeerListDisplayOrder('dspeed:desc', true)" translate>Download</a>
|
||||||
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('dspeed:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('dspeed:desc')}"></i>
|
<i class="fa" ng-class="{'fa-sort-asc fa-order-asc': isSetPeerListDisplayOrder('dspeed:asc'), 'fa-sort-desc fa-order-desc': isSetPeerListDisplayOrder('dspeed:desc')}"></i>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
|
@ -268,18 +275,30 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="task-table-body">
|
<div class="task-table-body">
|
||||||
<div class="row" ng-repeat="peer in context.btPeers | peerOrderBy: getPeerListOrderType()">
|
<div class="row" ng-repeat="peer in context.btPeers | peerOrderBy: getPeerListOrderType()">
|
||||||
<div class="col-sm-3">
|
<div class="col-md-4 col-sm-4 col-xs-12">
|
||||||
<span ng-bind="peer.name | translate"></span><i class="icon-seeder fa fa-angle-double-up" title="{{'Seeding' | translate}}" ng-if="peer && peer.seeder"></i>
|
<div class="peer-name-wrapper" ng-tooltip-if="{{!!peer.client}}" ng-tooltip-container="body"
|
||||||
|
ng-tooltip="{{(peer.client ? (peer.client.name + (peer.client.version ? ' ' + peer.client.version : '')) : ('Unknown Client' | translate)) + (peer.seeder ? ', ' + ('Seeding' | translate) : '')}}">
|
||||||
|
<span ng-bind="peer.name | translate"></span><i class="icon-seeder fa fa-angle-double-up" ng-if="peer && peer.seeder"></i>
|
||||||
|
<span class="peer-client" ng-if="!!peer.client"
|
||||||
|
ng-bind="peer.client ? ('(' + peer.client.name + (peer.client.version ? ' ' + peer.client.version : '') + ')') : ''"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
</div>
|
||||||
|
<div class="col-md-5 col-sm-4 col-xs-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-9 col-sm-7 col-xs-12">
|
||||||
<div class="piece-bar-wrapper">
|
<div class="piece-bar-wrapper">
|
||||||
<ng-piece-bar bit-field="peer.bitfield" piece-count="task.numPieces" color="#208fe5"></ng-piece-bar>
|
<ng-piece-bar bit-field="peer.bitfield" piece-count="task.numPieces" color="#208fe5"></ng-piece-bar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 col-xs-4">
|
<div class="col-md-3 col-sm-5 hidden-xs text-right">
|
||||||
<span ng-bind="(peer.completePercent | percent: 2) + '%'"></span>
|
<span ng-bind="(peer.completePercent | percent: 2) + '%'"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 col-xs-8">
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="visible-xs col-xs-4">
|
||||||
|
<span ng-bind="(peer.completePercent | percent: 2) + '%'"></span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-sm-4 col-xs-8">
|
||||||
<div class="task-peer-download-speed">
|
<div class="task-peer-download-speed">
|
||||||
<i class="icon-download fa fa-arrow-down"></i>
|
<i class="icon-download fa fa-arrow-down"></i>
|
||||||
<span ng-bind="(peer.downloadSpeed | readableVolumn) + '/s'"></span>
|
<span ng-bind="(peer.downloadSpeed | readableVolumn) + '/s'"></span>
|
||||||
|
|
Reference in a new issue