mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-12 16:26:37 +00:00
parent
e5c1948b94
commit
6864f7c9d0
@ -234,6 +234,7 @@
|
|||||||
"Release Notes": "Release Notes",
|
"Release Notes": "Release Notes",
|
||||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
||||||
"Remote Devices": "Remote Devices",
|
"Remote Devices": "Remote Devices",
|
||||||
|
"Remote GUI": "Remote GUI",
|
||||||
"Remove": "Remove",
|
"Remove": "Remove",
|
||||||
"Remove Device": "Remove Device",
|
"Remove Device": "Remove Device",
|
||||||
"Remove Folder": "Remove Folder",
|
"Remove Folder": "Remove Folder",
|
||||||
|
@ -806,8 +806,8 @@
|
|||||||
<th><span class="fas fa-fw fa-desktop"></span> <span translate>Remote GUI</span></th>
|
<th><span class="fas fa-fw fa-desktop"></span> <span translate>Remote GUI</span></th>
|
||||||
<td class="text-right" ng-attr-title="Port {{deviceCfg.remoteGUIPort}}">
|
<td class="text-right" ng-attr-title="Port {{deviceCfg.remoteGUIPort}}">
|
||||||
<!-- Apply RFC6874 encoding for IPv6 link-local zone identifier -->
|
<!-- Apply RFC6874 encoding for IPv6 link-local zone identifier -->
|
||||||
<a ng-if="idToRemoteGUI[deviceCfg.deviceID]" href="{{idToRemoteGUI[deviceCfg.deviceID].replace('%', '%25')}}">{{idToRemoteGUI[deviceCfg.deviceID]}}</a>
|
<a ng-if="hasRemoteGUIAddress(deviceCfg)" href="{{remoteGUIAddress(deviceCfg).replace('%', '%25')}}">{{remoteGUIAddress(deviceCfg)}}</a>
|
||||||
<span ng-if="!idToRemoteGUI[deviceCfg.deviceID]">Unreachable</span>
|
<span translate ng-if="!hasRemoteGUIAddress(deviceCfg)">Unknown</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -24,9 +24,6 @@ angular.module('syncthing.core')
|
|||||||
$scope.config = {};
|
$scope.config = {};
|
||||||
$scope.configInSync = true;
|
$scope.configInSync = true;
|
||||||
$scope.connections = {};
|
$scope.connections = {};
|
||||||
$scope.idToRemoteGUI = {};
|
|
||||||
$scope.remoteGUICache = {};
|
|
||||||
$scope.showRemoteGUI = true;
|
|
||||||
$scope.errors = [];
|
$scope.errors = [];
|
||||||
$scope.model = {};
|
$scope.model = {};
|
||||||
$scope.myID = '';
|
$scope.myID = '';
|
||||||
@ -64,10 +61,6 @@ angular.module('syncthing.core')
|
|||||||
$scope.metricRates = (window.localStorage["metricRates"] == "true");
|
$scope.metricRates = (window.localStorage["metricRates"] == "true");
|
||||||
} catch (exception) { }
|
} catch (exception) { }
|
||||||
|
|
||||||
if ("showRemoteGUI" in window.localStorage) {
|
|
||||||
$scope.showRemoteGUI = (window.localStorage["showRemoteGUI"] == "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.folderDefaults = {
|
$scope.folderDefaults = {
|
||||||
devices: [],
|
devices: [],
|
||||||
type: "sendreceive",
|
type: "sendreceive",
|
||||||
@ -382,7 +375,6 @@ angular.module('syncthing.core')
|
|||||||
$scope.config.options._globalAnnounceServersStr = $scope.config.options.globalAnnounceServers.join(', ');
|
$scope.config.options._globalAnnounceServersStr = $scope.config.options.globalAnnounceServers.join(', ');
|
||||||
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
||||||
|
|
||||||
$scope.config.gui["showRemoteGUI"] = $scope.showRemoteGUI;
|
|
||||||
$scope.devices = deviceMap($scope.config.devices);
|
$scope.devices = deviceMap($scope.config.devices);
|
||||||
for (var id in $scope.devices) {
|
for (var id in $scope.devices) {
|
||||||
$scope.completion[id] = {
|
$scope.completion[id] = {
|
||||||
@ -525,16 +517,6 @@ angular.module('syncthing.core')
|
|||||||
console.log("recalcCompletion", device, $scope.completion[device]);
|
console.log("recalcCompletion", device, $scope.completion[device]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceAddressPort(address, newPort) {
|
|
||||||
var lastColonIndex = address.length;
|
|
||||||
for (var index = 0; index < address.length; index++) {
|
|
||||||
if (address[index] === ":") {
|
|
||||||
lastColonIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return address.substr(0, lastColonIndex) + ":" + newPort.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshCompletion(device, folder) {
|
function refreshCompletion(device, folder) {
|
||||||
if (device === $scope.myID) {
|
if (device === $scope.myID) {
|
||||||
return;
|
return;
|
||||||
@ -581,50 +563,9 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
$scope.connections = data;
|
$scope.connections = data;
|
||||||
console.log("refreshConnections", data);
|
console.log("refreshConnections", data);
|
||||||
|
|
||||||
refreshRemoteGUI(data);
|
|
||||||
}).error($scope.emitHTTPError);
|
}).error($scope.emitHTTPError);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshRemoteGUI(connections) {
|
|
||||||
if (!$scope.showRemoteGUI) {
|
|
||||||
$scope.idToRemoteGUI = {}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var newCache = {};
|
|
||||||
for (var id in connections) {
|
|
||||||
if (!(id in $scope.devices)) {
|
|
||||||
// Avoid errors when called before first updateLocalConfig()
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var port = $scope.devices[id].remoteGUIPort;
|
|
||||||
if (port <= 0
|
|
||||||
|| !connections[id].address
|
|
||||||
|| connections[id].type.includes("relay")) {
|
|
||||||
// Relay connections never work as desired here, nor incomplete addresses
|
|
||||||
$scope.idToRemoteGUI[id] = "";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var newAddress = "http://" + replaceAddressPort(connections[id].address, port);
|
|
||||||
if (!(newAddress in $scope.remoteGUICache)) {
|
|
||||||
// No cached result, trigger a new port probing asynchronously
|
|
||||||
$scope.probeRemoteGUIAddress(id, newAddress);
|
|
||||||
} else {
|
|
||||||
newCache[newAddress] = $scope.remoteGUICache[newAddress];
|
|
||||||
// Copy cached probing result in the corner case of duplicate GUI
|
|
||||||
// addresses for different devices. Which is useless, but
|
|
||||||
// possible when behind the same NAT router.
|
|
||||||
if (newCache[newAddress]) {
|
|
||||||
$scope.idToRemoteGUI[id] = newAddress;
|
|
||||||
} else {
|
|
||||||
$scope.idToRemoteGUI[id] = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Replace the cache to discard stale addresses
|
|
||||||
$scope.remoteGUICache = newCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshErrors() {
|
function refreshErrors() {
|
||||||
$http.get(urlbase + '/system/error').success(function (data) {
|
$http.get(urlbase + '/system/error').success(function (data) {
|
||||||
$scope.errors = data.errors;
|
$scope.errors = data.errors;
|
||||||
@ -643,22 +584,6 @@ angular.module('syncthing.core')
|
|||||||
}).error($scope.emitHTTPError);
|
}).error($scope.emitHTTPError);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.probeRemoteGUIAddress = function (deviceId, address) {
|
|
||||||
// Strip off possible IPv6 link-local zone identifier, as Angular chokes on it
|
|
||||||
// with an (ugly, unjustified) console error message.
|
|
||||||
var urlAddress = address.replace(/%[a-zA-Z0-9_\.\-]*\]/, ']');
|
|
||||||
$http({
|
|
||||||
method: "OPTIONS",
|
|
||||||
url: urlAddress,
|
|
||||||
}).success(function (data) {
|
|
||||||
$scope.remoteGUICache[address] = true;
|
|
||||||
$scope.idToRemoteGUI[deviceId] = address;
|
|
||||||
}).error(function (err) {
|
|
||||||
$scope.remoteGUICache[address] = false;
|
|
||||||
$scope.idToRemoteGUI[deviceId] = "";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.refreshNeed = function (page, perpage) {
|
$scope.refreshNeed = function (page, perpage) {
|
||||||
if (!$scope.neededFolder) {
|
if (!$scope.neededFolder) {
|
||||||
return;
|
return;
|
||||||
@ -1140,6 +1065,28 @@ angular.module('syncthing.core')
|
|||||||
return '?';
|
return '?';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.hasRemoteGUIAddress = function (deviceCfg) {
|
||||||
|
if (!deviceCfg.remoteGUIPort)
|
||||||
|
return false;
|
||||||
|
var conn = $scope.connections[deviceCfg.deviceID];
|
||||||
|
return conn && conn.connected && conn.address && conn.type.indexOf('Relay') == -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.remoteGUIAddress = function (deviceCfg) {
|
||||||
|
// Assume hasRemoteGUIAddress is true or we would not be here
|
||||||
|
var conn = $scope.connections[deviceCfg.deviceID];
|
||||||
|
return 'http://' + replaceAddressPort(conn.address, deviceCfg.remoteGUIPort);
|
||||||
|
};
|
||||||
|
|
||||||
|
function replaceAddressPort(address, newPort) {
|
||||||
|
for (var index = address.length - 1; index >= 0; index--) {
|
||||||
|
if (address[index] === ":") {
|
||||||
|
return address.substr(0, index) + ":" + newPort.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.friendlyNameFromShort = function (shortID) {
|
$scope.friendlyNameFromShort = function (shortID) {
|
||||||
var matches = Object.keys($scope.devices).filter(function (id) {
|
var matches = Object.keys($scope.devices).filter(function (id) {
|
||||||
return id.substr(0, 7) === shortID;
|
return id.substr(0, 7) === shortID;
|
||||||
@ -1317,11 +1264,6 @@ angular.module('syncthing.core')
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.saveConfig = function (callback) {
|
$scope.saveConfig = function (callback) {
|
||||||
// set local storage feature and delete from post request
|
|
||||||
window.localStorage.setItem("showRemoteGUI", $scope.config.gui.showRemoteGUI ? "true" : "false");
|
|
||||||
$scope.showRemoteGUI = $scope.config.gui.showRemoteGUI;
|
|
||||||
delete $scope.config.gui.showRemoteGUI;
|
|
||||||
|
|
||||||
var cfg = JSON.stringify($scope.config);
|
var cfg = JSON.stringify($scope.config);
|
||||||
var opts = {
|
var opts = {
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -818,8 +818,8 @@
|
|||||||
<th><span class="fas fa-fw fa-desktop"></span> <span translate>Remote GUI</span></th>
|
<th><span class="fas fa-fw fa-desktop"></span> <span translate>Remote GUI</span></th>
|
||||||
<td class="text-right" ng-attr-title="Port {{deviceCfg.remoteGUIPort}}">
|
<td class="text-right" ng-attr-title="Port {{deviceCfg.remoteGUIPort}}">
|
||||||
<!-- Apply RFC6874 encoding for IPv6 link-local zone identifier -->
|
<!-- Apply RFC6874 encoding for IPv6 link-local zone identifier -->
|
||||||
<a ng-if="idToRemoteGUI[deviceCfg.deviceID]" href="{{idToRemoteGUI[deviceCfg.deviceID].replace('%', '%25')}}">{{idToRemoteGUI[deviceCfg.deviceID]}}</a>
|
<a ng-if="hasRemoteGUIAddress(deviceCfg)" href="{{remoteGUIAddress(deviceCfg).replace('%', '%25')}}">{{remoteGUIAddress(deviceCfg)}}</a>
|
||||||
<span ng-if="!idToRemoteGUI[deviceCfg.deviceID]">Unreachable</span>
|
<span translate ng-if="!hasRemoteGUIAddress(deviceCfg)">Unknown</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -24,9 +24,6 @@ angular.module('syncthing.core')
|
|||||||
$scope.config = {};
|
$scope.config = {};
|
||||||
$scope.configInSync = true;
|
$scope.configInSync = true;
|
||||||
$scope.connections = {};
|
$scope.connections = {};
|
||||||
$scope.idToRemoteGUI = {};
|
|
||||||
$scope.remoteGUICache = {};
|
|
||||||
$scope.showRemoteGUI = true;
|
|
||||||
$scope.errors = [];
|
$scope.errors = [];
|
||||||
$scope.model = {};
|
$scope.model = {};
|
||||||
$scope.myID = '';
|
$scope.myID = '';
|
||||||
@ -64,10 +61,6 @@ angular.module('syncthing.core')
|
|||||||
$scope.metricRates = (window.localStorage["metricRates"] == "true");
|
$scope.metricRates = (window.localStorage["metricRates"] == "true");
|
||||||
} catch (exception) { }
|
} catch (exception) { }
|
||||||
|
|
||||||
if ("showRemoteGUI" in window.localStorage) {
|
|
||||||
$scope.showRemoteGUI = (window.localStorage["showRemoteGUI"] == "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.folderDefaults = {
|
$scope.folderDefaults = {
|
||||||
devices: [],
|
devices: [],
|
||||||
type: "sendreceive",
|
type: "sendreceive",
|
||||||
@ -382,7 +375,6 @@ angular.module('syncthing.core')
|
|||||||
$scope.config.options._globalAnnounceServersStr = $scope.config.options.globalAnnounceServers.join(', ');
|
$scope.config.options._globalAnnounceServersStr = $scope.config.options.globalAnnounceServers.join(', ');
|
||||||
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
||||||
|
|
||||||
$scope.config.gui["showRemoteGUI"] = $scope.showRemoteGUI;
|
|
||||||
$scope.devices = deviceMap($scope.config.devices);
|
$scope.devices = deviceMap($scope.config.devices);
|
||||||
for (var id in $scope.devices) {
|
for (var id in $scope.devices) {
|
||||||
$scope.completion[id] = {
|
$scope.completion[id] = {
|
||||||
@ -525,16 +517,6 @@ angular.module('syncthing.core')
|
|||||||
console.log("recalcCompletion", device, $scope.completion[device]);
|
console.log("recalcCompletion", device, $scope.completion[device]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceAddressPort(address, newPort) {
|
|
||||||
var lastColonIndex = address.length;
|
|
||||||
for (var index = 0; index < address.length; index++) {
|
|
||||||
if (address[index] === ":") {
|
|
||||||
lastColonIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return address.substr(0, lastColonIndex) + ":" + newPort.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshCompletion(device, folder) {
|
function refreshCompletion(device, folder) {
|
||||||
if (device === $scope.myID) {
|
if (device === $scope.myID) {
|
||||||
return;
|
return;
|
||||||
@ -581,50 +563,9 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
$scope.connections = data;
|
$scope.connections = data;
|
||||||
console.log("refreshConnections", data);
|
console.log("refreshConnections", data);
|
||||||
|
|
||||||
refreshRemoteGUI(data);
|
|
||||||
}).error($scope.emitHTTPError);
|
}).error($scope.emitHTTPError);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshRemoteGUI(connections) {
|
|
||||||
if (!$scope.showRemoteGUI) {
|
|
||||||
$scope.idToRemoteGUI = {}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var newCache = {};
|
|
||||||
for (var id in connections) {
|
|
||||||
if (!(id in $scope.devices)) {
|
|
||||||
// Avoid errors when called before first updateLocalConfig()
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var port = $scope.devices[id].remoteGUIPort;
|
|
||||||
if (port <= 0
|
|
||||||
|| !connections[id].address
|
|
||||||
|| connections[id].type.includes("relay")) {
|
|
||||||
// Relay connections never work as desired here, nor incomplete addresses
|
|
||||||
$scope.idToRemoteGUI[id] = "";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var newAddress = "http://" + replaceAddressPort(connections[id].address, port);
|
|
||||||
if (!(newAddress in $scope.remoteGUICache)) {
|
|
||||||
// No cached result, trigger a new port probing asynchronously
|
|
||||||
$scope.probeRemoteGUIAddress(id, newAddress);
|
|
||||||
} else {
|
|
||||||
newCache[newAddress] = $scope.remoteGUICache[newAddress];
|
|
||||||
// Copy cached probing result in the corner case of duplicate GUI
|
|
||||||
// addresses for different devices. Which is useless, but
|
|
||||||
// possible when behind the same NAT router.
|
|
||||||
if (newCache[newAddress]) {
|
|
||||||
$scope.idToRemoteGUI[id] = newAddress;
|
|
||||||
} else {
|
|
||||||
$scope.idToRemoteGUI[id] = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Replace the cache to discard stale addresses
|
|
||||||
$scope.remoteGUICache = newCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshErrors() {
|
function refreshErrors() {
|
||||||
$http.get(urlbase + '/system/error').success(function (data) {
|
$http.get(urlbase + '/system/error').success(function (data) {
|
||||||
$scope.errors = data.errors;
|
$scope.errors = data.errors;
|
||||||
@ -643,23 +584,6 @@ angular.module('syncthing.core')
|
|||||||
}).error($scope.emitHTTPError);
|
}).error($scope.emitHTTPError);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.probeRemoteGUIAddress = function (deviceId, address) {
|
|
||||||
// Strip off possible IPv6 link-local zone identifier, as Angular chokes on it
|
|
||||||
// with an (ugly, unjustified) console error message.
|
|
||||||
var urlAddress = address.replace(/%[a-zA-Z0-9_\.\-]*\]/, ']');
|
|
||||||
console.log(urlAddress);
|
|
||||||
$http({
|
|
||||||
method: "OPTIONS",
|
|
||||||
url: urlAddress,
|
|
||||||
}).success(function (data) {
|
|
||||||
$scope.remoteGUICache[address] = true;
|
|
||||||
$scope.idToRemoteGUI[deviceId] = address;
|
|
||||||
}).error(function (err) {
|
|
||||||
$scope.remoteGUICache[address] = false;
|
|
||||||
$scope.idToRemoteGUI[deviceId] = "";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.refreshNeed = function (page, perpage) {
|
$scope.refreshNeed = function (page, perpage) {
|
||||||
if (!$scope.neededFolder) {
|
if (!$scope.neededFolder) {
|
||||||
return;
|
return;
|
||||||
@ -1145,6 +1069,28 @@ angular.module('syncthing.core')
|
|||||||
return '?';
|
return '?';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.hasRemoteGUIAddress = function (deviceCfg) {
|
||||||
|
if (!deviceCfg.remoteGUIPort)
|
||||||
|
return false;
|
||||||
|
var conn = $scope.connections[deviceCfg.deviceID];
|
||||||
|
return conn && conn.connected && conn.address && conn.type.indexOf('Relay') == -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.remoteGUIAddress = function (deviceCfg) {
|
||||||
|
// Assume hasRemoteGUIAddress is true or we would not be here
|
||||||
|
var conn = $scope.connections[deviceCfg.deviceID];
|
||||||
|
return 'http://' + replaceAddressPort(conn.address, deviceCfg.remoteGUIPort);
|
||||||
|
};
|
||||||
|
|
||||||
|
function replaceAddressPort(address, newPort) {
|
||||||
|
for (var index = address.length - 1; index >= 0; index--) {
|
||||||
|
if (address[index] === ":") {
|
||||||
|
return address.substr(0, index) + ":" + newPort.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.friendlyNameFromShort = function (shortID) {
|
$scope.friendlyNameFromShort = function (shortID) {
|
||||||
var matches = Object.keys($scope.devices).filter(function (id) {
|
var matches = Object.keys($scope.devices).filter(function (id) {
|
||||||
return id.substr(0, 7) === shortID;
|
return id.substr(0, 7) === shortID;
|
||||||
@ -1322,11 +1268,6 @@ angular.module('syncthing.core')
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.saveConfig = function (callback) {
|
$scope.saveConfig = function (callback) {
|
||||||
// set local storage feature and delete from post request
|
|
||||||
window.localStorage.setItem("showRemoteGUI", $scope.config.gui.showRemoteGUI ? "true" : "false");
|
|
||||||
$scope.showRemoteGUI = $scope.config.gui.showRemoteGUI;
|
|
||||||
delete $scope.config.gui.showRemoteGUI;
|
|
||||||
|
|
||||||
var cfg = JSON.stringify($scope.config);
|
var cfg = JSON.stringify($scope.config);
|
||||||
var opts = {
|
var opts = {
|
||||||
headers: {
|
headers: {
|
||||||
|
Loading…
Reference in New Issue
Block a user