mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 03:18:59 +00:00
Implement identicon representation for devices.
The first fifteen characters of device IDs are now used to procedurally generate psuedo-unique avatars for their respective devices. The avatars are represented using SVG elements that replace the icons previously shown next to device names in the GUI.
This commit is contained in:
parent
e82e912151
commit
ac079f0f83
65
gui/app.js
65
gui/app.js
@ -1231,3 +1231,68 @@ syncthing.directive('modal', function () {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
syncthing.directive('identicon', ['$window', function ($window) {
|
||||||
|
var svgNS = 'http://www.w3.org/2000/svg';
|
||||||
|
|
||||||
|
function Identicon (value, size) {
|
||||||
|
var svg = document.createElementNS(svgNS, 'svg');
|
||||||
|
var shouldFillRectAt = function (row, col) {
|
||||||
|
return !($window.parseInt(value.charCodeAt(row + col * size), 10) % 2);
|
||||||
|
};
|
||||||
|
var shouldMirrorRectAt = function (row, col) {
|
||||||
|
return !(size % 2 && col === middleCol)
|
||||||
|
};
|
||||||
|
var mirrorColFor = function (col) {
|
||||||
|
return size - col - 1;
|
||||||
|
};
|
||||||
|
var fillRectAt = function (row, col) {
|
||||||
|
var rect = document.createElementNS(svgNS, 'rect');
|
||||||
|
|
||||||
|
rect.setAttribute('x', (col * rectSize) + '%');
|
||||||
|
rect.setAttribute('y', (row * rectSize) + '%');
|
||||||
|
rect.setAttribute('width', rectSize + '%');
|
||||||
|
rect.setAttribute('height', rectSize + '%');
|
||||||
|
|
||||||
|
svg.appendChild(rect);
|
||||||
|
};
|
||||||
|
var rect;
|
||||||
|
var row;
|
||||||
|
var col;
|
||||||
|
var middleCol;
|
||||||
|
var rectSize;
|
||||||
|
|
||||||
|
svg.setAttribute('class', 'identicon');
|
||||||
|
size = size || 5;
|
||||||
|
rectSize = 100 / size;
|
||||||
|
middleCol = Math.ceil(size / 2) - 1;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
value = value.toString().replace(/[\W_]/i, '');
|
||||||
|
|
||||||
|
for (row = 0; row < size; ++row) {
|
||||||
|
for (col = middleCol; col > -1; --col) {
|
||||||
|
if (shouldFillRectAt(row, col)) {
|
||||||
|
fillRectAt(row, col);
|
||||||
|
|
||||||
|
if (shouldMirrorRectAt(row, col)) {
|
||||||
|
fillRectAt(row, mirrorColFor(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return svg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
value: '='
|
||||||
|
},
|
||||||
|
link: function (scope, element, attributes) {
|
||||||
|
element.append(new Identicon(scope.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
@ -190,7 +190,7 @@
|
|||||||
<div class="panel panel-default" ng-repeat="deviceCfg in [thisDevice()]">
|
<div class="panel panel-default" ng-repeat="deviceCfg in [thisDevice()]">
|
||||||
<div class="panel-heading" data-toggle="collapse" href="#device-this" style="cursor: pointer">
|
<div class="panel-heading" data-toggle="collapse" href="#device-this" style="cursor: pointer">
|
||||||
<h3 class="panel-title">
|
<h3 class="panel-title">
|
||||||
<span class="glyphicon glyphicon-home"></span> {{deviceName(deviceCfg)}}
|
<identicon data-value="deviceCfg.DeviceID"></identicon> {{deviceName(deviceCfg)}}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div id="device-this" class="panel-collapse collapse in">
|
<div id="device-this" class="panel-collapse collapse in">
|
||||||
@ -236,7 +236,7 @@
|
|||||||
<div class="panel panel-{{deviceClass(deviceCfg)}}" ng-repeat="deviceCfg in otherDevices()">
|
<div class="panel panel-{{deviceClass(deviceCfg)}}" ng-repeat="deviceCfg in otherDevices()">
|
||||||
<div class="panel-heading" data-toggle="collapse" data-parent="#devices" href="#device-{{$index}}" style="cursor: pointer">
|
<div class="panel-heading" data-toggle="collapse" data-parent="#devices" href="#device-{{$index}}" style="cursor: pointer">
|
||||||
<h3 class="panel-title">
|
<h3 class="panel-title">
|
||||||
<span class="glyphicon glyphicon-retweet"></span> {{deviceName(deviceCfg)}}
|
<identicon data-value="deviceCfg.DeviceID"></identicon> {{deviceName(deviceCfg)}}
|
||||||
<span class="pull-right hidden-xs">
|
<span class="pull-right hidden-xs">
|
||||||
<span ng-if="connections[deviceCfg.DeviceID] && completion[deviceCfg.DeviceID]._total == 100">
|
<span ng-if="connections[deviceCfg.DeviceID] && completion[deviceCfg.DeviceID]._total == 100">
|
||||||
<span translate>Up to Date</span> (100%)
|
<span translate>Up to Date</span> (100%)
|
||||||
@ -822,7 +822,6 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</modal>
|
</modal>
|
||||||
|
|
||||||
|
|
||||||
<script src="angular/angular.min.js"></script>
|
<script src="angular/angular.min.js"></script>
|
||||||
<script src="angular/angular-translate.min.js"></script>
|
<script src="angular/angular-translate.min.js"></script>
|
||||||
<script src="angular/angular-translate-loader.min.js"></script>
|
<script src="angular/angular-translate-loader.min.js"></script>
|
||||||
|
@ -28,6 +28,43 @@ ul+h5 {
|
|||||||
margin-top: 1.5em;
|
margin-top: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
identicon {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
line-height: 1em;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.identicon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.identicon rect {
|
||||||
|
opacity: 0.5;
|
||||||
|
fill: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading .identicon {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: -4px;
|
||||||
|
left: -9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class*="-info"] .identicon rect,
|
||||||
|
[class*="-success"] .identicon rect,
|
||||||
|
[class*="-primary"] .identicon rect {
|
||||||
|
fill: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.text-monospace {
|
.text-monospace {
|
||||||
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user