webgui: moved events controller to events service
This commit is contained in:
parent
6a6593c656
commit
2449f1e1b6
@ -23,8 +23,6 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div ng-controller="EventController"></div>
|
|
||||||
|
|
||||||
<!-- Top bar -->
|
<!-- Top bar -->
|
||||||
|
|
||||||
<nav class="navbar navbar-top navbar-default" role="navigation">
|
<nav class="navbar navbar-top navbar-default" role="navigation">
|
||||||
@ -1118,7 +1116,7 @@
|
|||||||
|
|
||||||
<!-- gui application code -->
|
<!-- gui application code -->
|
||||||
<script src="scripts/syncthing/core/module.js"></script>
|
<script src="scripts/syncthing/core/module.js"></script>
|
||||||
<script src="scripts/syncthing/core/controllers/eventController.js"></script>
|
<script src="scripts/syncthing/core/services/events.js"></script>
|
||||||
<script src="scripts/syncthing/core/controllers/syncthingController.js"></script>
|
<script src="scripts/syncthing/core/controllers/syncthingController.js"></script>
|
||||||
<script src="scripts/syncthing/core/directives/identiconDirective.js"></script>
|
<script src="scripts/syncthing/core/directives/identiconDirective.js"></script>
|
||||||
<script src="scripts/syncthing/core/directives/languageSelectDirective.js"></script>
|
<script src="scripts/syncthing/core/directives/languageSelectDirective.js"></script>
|
||||||
|
|||||||
@ -1,55 +0,0 @@
|
|||||||
var debugEvents = false;
|
|
||||||
|
|
||||||
angular.module('syncthing.core')
|
|
||||||
.controller('EventController', function ($scope, $http) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
$scope.lastEvent = null;
|
|
||||||
var lastID = 0;
|
|
||||||
|
|
||||||
var successFn = function (data) {
|
|
||||||
// When Syncthing restarts while the long polling connection is in
|
|
||||||
// progress the browser on some platforms returns a 200 (since the
|
|
||||||
// headers has been flushed with the return code 200), with no data.
|
|
||||||
// This basically means that the connection has been reset, and the call
|
|
||||||
// was not actually successful.
|
|
||||||
if (!data) {
|
|
||||||
errorFn(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.$emit('UIOnline');
|
|
||||||
|
|
||||||
if (lastID > 0) {
|
|
||||||
data.forEach(function (event) {
|
|
||||||
if (debugEvents) {
|
|
||||||
console.log("event", event.id, event.type, event.data);
|
|
||||||
}
|
|
||||||
$scope.$emit(event.type, event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.lastEvent = data[data.length - 1];
|
|
||||||
lastID = $scope.lastEvent.id;
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
$http.get(urlbase + '/events?since=' + lastID)
|
|
||||||
.success(successFn)
|
|
||||||
.error(errorFn);
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
var errorFn = function (data) {
|
|
||||||
$scope.$emit('UIOffline');
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
$http.get(urlbase + '/events?limit=1')
|
|
||||||
.success(successFn)
|
|
||||||
.error(errorFn);
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
$http.get(urlbase + '/events?limit=1')
|
|
||||||
.success(successFn)
|
|
||||||
.error(errorFn);
|
|
||||||
});
|
|
||||||
@ -2,7 +2,7 @@ angular.module('syncthing.core')
|
|||||||
.config(function($locationProvider) {
|
.config(function($locationProvider) {
|
||||||
$locationProvider.html5Mode(true).hashPrefix('!');
|
$locationProvider.html5Mode(true).hashPrefix('!');
|
||||||
})
|
})
|
||||||
.controller('SyncthingController', function ($scope, $http, $location, LocaleService) {
|
.controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// private/helper definitions
|
// private/helper definitions
|
||||||
@ -15,6 +15,7 @@ angular.module('syncthing.core')
|
|||||||
function initController() {
|
function initController() {
|
||||||
LocaleService.autoConfigLocale();
|
LocaleService.autoConfigLocale();
|
||||||
setInterval($scope.refresh, 10000);
|
setInterval($scope.refresh, 10000);
|
||||||
|
Events.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ angular.module('syncthing.core')
|
|||||||
'touch': 'asterisk'
|
'touch': 'asterisk'
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$on('UIOnline', function (event, arg) {
|
$scope.$on(Events.ONLINE, function () {
|
||||||
if (online && !restarting) {
|
if (online && !restarting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -100,7 +101,7 @@ angular.module('syncthing.core')
|
|||||||
$('#shutdown').modal('hide');
|
$('#shutdown').modal('hide');
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('UIOffline', function (event, arg) {
|
$scope.$on(Events.OFFLINE, function () {
|
||||||
if (navigatingAway || !online) {
|
if (navigatingAway || !online) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ angular.module('syncthing.core')
|
|||||||
if (!restarting) {
|
if (!restarting) {
|
||||||
if (arg.status === 0) {
|
if (arg.status === 0) {
|
||||||
// A network error, not an HTTP error
|
// A network error, not an HTTP error
|
||||||
$scope.$emit('UIOffline');
|
$scope.$emit(Events.OFFLINE);
|
||||||
} else if (arg.status >= 400 && arg.status <= 599) {
|
} else if (arg.status >= 400 && arg.status <= 599) {
|
||||||
// A genuine HTTP error
|
// A genuine HTTP error
|
||||||
$('#networkError').modal('hide');
|
$('#networkError').modal('hide');
|
||||||
@ -136,7 +137,7 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('StateChanged', function (event, arg) {
|
$scope.$on(Events.STATE_CHANGED, function (event, arg) {
|
||||||
var data = arg.data;
|
var data = arg.data;
|
||||||
if ($scope.model[data.folder]) {
|
if ($scope.model[data.folder]) {
|
||||||
$scope.model[data.folder].state = data.to;
|
$scope.model[data.folder].state = data.to;
|
||||||
@ -144,21 +145,24 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('LocalIndexUpdated', function (event, arg) {
|
$scope.$on(Events.LOCAL_INDEX_UPDATED, function (event, arg) {
|
||||||
var data = arg.data;
|
|
||||||
refreshFolderStats();
|
refreshFolderStats();
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('RemoteIndexUpdated', function (event, arg) {
|
/* currently not using
|
||||||
|
|
||||||
|
$scope.$on('Events.REMOTE_INDEX_UPDATED', function (event, arg) {
|
||||||
// Nothing
|
// Nothing
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('DeviceDisconnected', function (event, arg) {
|
*/
|
||||||
|
|
||||||
|
$scope.$on(Events.DEVICE_DISCONNECTED, function (event, arg) {
|
||||||
delete $scope.connections[arg.data.id];
|
delete $scope.connections[arg.data.id];
|
||||||
refreshDeviceStats();
|
refreshDeviceStats();
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('DeviceConnected', function (event, arg) {
|
$scope.$on(Events.DEVICE_CONNECTED, function (event, arg) {
|
||||||
if (!$scope.connections[arg.data.id]) {
|
if (!$scope.connections[arg.data.id]) {
|
||||||
$scope.connections[arg.data.id] = {
|
$scope.connections[arg.data.id] = {
|
||||||
inbps: 0,
|
inbps: 0,
|
||||||
@ -173,7 +177,7 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('ConfigLoaded', function (event) {
|
$scope.$on('ConfigLoaded', function () {
|
||||||
if ($scope.config.options.urAccepted === 0) {
|
if ($scope.config.options.urAccepted === 0) {
|
||||||
// If usage reporting has been neither accepted nor declined,
|
// If usage reporting has been neither accepted nor declined,
|
||||||
// we want to ask the user to make a choice. But we don't want
|
// we want to ask the user to make a choice. But we don't want
|
||||||
@ -193,15 +197,15 @@ angular.module('syncthing.core')
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('DeviceRejected', function (event, arg) {
|
$scope.$on(Events.DEVICE_REJECTED, function (event, arg) {
|
||||||
$scope.deviceRejections[arg.data.device] = arg;
|
$scope.deviceRejections[arg.data.device] = arg;
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('FolderRejected', function (event, arg) {
|
$scope.$on(Events.FOLDER_REJECTED, function (event, arg) {
|
||||||
$scope.folderRejections[arg.data.folder + "-" + arg.data.device] = arg;
|
$scope.folderRejections[arg.data.folder + "-" + arg.data.device] = arg;
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('ConfigSaved', function (event, arg) {
|
$scope.$on(Events.CONFIG_SAVED, function (event, arg) {
|
||||||
updateLocalConfig(arg.data);
|
updateLocalConfig(arg.data);
|
||||||
|
|
||||||
$http.get(urlbase + '/system/config/insync').success(function (data) {
|
$http.get(urlbase + '/system/config/insync').success(function (data) {
|
||||||
@ -209,7 +213,7 @@ angular.module('syncthing.core')
|
|||||||
}).error($scope.emitHTTPError);
|
}).error($scope.emitHTTPError);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('DownloadProgress', function (event, arg) {
|
$scope.$on(Events.DOWNLOAD_PROGRESS, function (event, arg) {
|
||||||
var stats = arg.data;
|
var stats = arg.data;
|
||||||
var progress = {};
|
var progress = {};
|
||||||
for (var folder in stats) {
|
for (var folder in stats) {
|
||||||
@ -254,12 +258,12 @@ angular.module('syncthing.core')
|
|||||||
console.log("DownloadProgress", $scope.progress);
|
console.log("DownloadProgress", $scope.progress);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('FolderSummary', function (event, arg) {
|
$scope.$on(Events.FOLDER_SUMMARY, function (event, arg) {
|
||||||
var data = arg.data;
|
var data = arg.data;
|
||||||
$scope.model[data.folder] = data.summary;
|
$scope.model[data.folder] = data.summary;
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('FolderCompletion', function (event, arg) {
|
$scope.$on(Events.FOLDER_COMPLETION, function (event, arg) {
|
||||||
var data = arg.data;
|
var data = arg.data;
|
||||||
if (!$scope.completion[data.device]) {
|
if (!$scope.completion[data.device]) {
|
||||||
$scope.completion[data.device] = {};
|
$scope.completion[data.device] = {};
|
||||||
@ -444,7 +448,7 @@ angular.module('syncthing.core')
|
|||||||
} else {
|
} else {
|
||||||
return 'sync';
|
return 'sync';
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function parseNeeded(data) {
|
function parseNeeded(data) {
|
||||||
var merged = [];
|
var merged = [];
|
||||||
@ -475,7 +479,7 @@ angular.module('syncthing.core')
|
|||||||
$scope.neededChangePageSize = function (perpage) {
|
$scope.neededChangePageSize = function (perpage) {
|
||||||
$scope.neededPageSize = perpage;
|
$scope.neededPageSize = perpage;
|
||||||
refreshNeed($scope.neededFolder);
|
refreshNeed($scope.neededFolder);
|
||||||
}
|
};
|
||||||
|
|
||||||
var refreshDeviceStats = debounce(function () {
|
var refreshDeviceStats = debounce(function () {
|
||||||
$http.get(urlbase + "/stats/device").success(function (data) {
|
$http.get(urlbase + "/stats/device").success(function (data) {
|
||||||
@ -973,7 +977,7 @@ angular.module('syncthing.core')
|
|||||||
|
|
||||||
$scope.$watch('currentFolder.path', function (newvalue) {
|
$scope.$watch('currentFolder.path', function (newvalue) {
|
||||||
if (newvalue && newvalue.trim().charAt(0) == '~') {
|
if (newvalue && newvalue.trim().charAt(0) == '~') {
|
||||||
$scope.currentFolder.path = $scope.system.tilde + newvalue.trim().substring(1)
|
$scope.currentFolder.path = $scope.system.tilde + newvalue.trim().substring(1);
|
||||||
}
|
}
|
||||||
$http.get(urlbase + '/system/browse', {
|
$http.get(urlbase + '/system/browse', {
|
||||||
params: { current: newvalue }
|
params: { current: newvalue }
|
||||||
@ -1052,19 +1056,19 @@ angular.module('syncthing.core')
|
|||||||
$scope.dismissFolderRejection(folder, device);
|
$scope.dismissFolderRejection(folder, device);
|
||||||
$scope.currentFolder = {
|
$scope.currentFolder = {
|
||||||
id: folder,
|
id: folder,
|
||||||
selectedDevices: {}
|
selectedDevices: {},
|
||||||
|
rescanIntervalS: 60,
|
||||||
|
fileVersioningSelector: "none",
|
||||||
|
trashcanClean: 0,
|
||||||
|
simpleKeep: 5,
|
||||||
|
staggeredMaxAge: 365,
|
||||||
|
staggeredCleanInterval: 3600,
|
||||||
|
staggeredVersionsPath: "",
|
||||||
|
externalCommand: "",
|
||||||
|
autoNormalize: true
|
||||||
};
|
};
|
||||||
$scope.currentFolder.selectedDevices[device] = true;
|
$scope.currentFolder.selectedDevices[device] = true;
|
||||||
|
|
||||||
$scope.currentFolder.rescanIntervalS = 60;
|
|
||||||
$scope.currentFolder.fileVersioningSelector = "none";
|
|
||||||
$scope.currentFolder.trashcanClean = 0;
|
|
||||||
$scope.currentFolder.simpleKeep = 5;
|
|
||||||
$scope.currentFolder.staggeredMaxAge = 365;
|
|
||||||
$scope.currentFolder.staggeredCleanInterval = 3600;
|
|
||||||
$scope.currentFolder.staggeredVersionsPath = "";
|
|
||||||
$scope.currentFolder.externalCommand = "";
|
|
||||||
$scope.currentFolder.autoNormalize = true;
|
|
||||||
$scope.editingExisting = false;
|
$scope.editingExisting = false;
|
||||||
$scope.folderEditor.$setPristine();
|
$scope.folderEditor.$setPristine();
|
||||||
$('#editFolder').modal();
|
$('#editFolder').modal();
|
||||||
@ -1159,12 +1163,12 @@ angular.module('syncthing.core')
|
|||||||
});
|
});
|
||||||
names.sort();
|
names.sort();
|
||||||
return names.join(", ");
|
return names.join(", ");
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.deviceFolders = function (deviceCfg) {
|
$scope.deviceFolders = function (deviceCfg) {
|
||||||
var folders = [];
|
var folders = [];
|
||||||
for (var folderID in $scope.folders) {
|
for (var folderID in $scope.folders) {
|
||||||
var devices = $scope.folders[folderID].devices
|
var devices = $scope.folders[folderID].devices;
|
||||||
for (var i = 0; i < devices.length; i++) {
|
for (var i = 0; i < devices.length; i++) {
|
||||||
if (devices[i].deviceID == deviceCfg.deviceID) {
|
if (devices[i].deviceID == deviceCfg.deviceID) {
|
||||||
folders.push(folderID);
|
folders.push(folderID);
|
||||||
|
|||||||
85
gui/scripts/syncthing/core/services/events.js
Normal file
85
gui/scripts/syncthing/core/services/events.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
var debugEvents = !true;
|
||||||
|
|
||||||
|
angular.module('syncthing.core')
|
||||||
|
.service('Events', ['$http', '$rootScope', '$timeout', function ($http, $rootScope, $timeout) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var lastID = 0;
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
function successFn (data) {
|
||||||
|
// When Syncthing restarts while the long polling connection is in
|
||||||
|
// progress the browser on some platforms returns a 200 (since the
|
||||||
|
// headers has been flushed with the return code 200), with no data.
|
||||||
|
// This basically means that the connection has been reset, and the call
|
||||||
|
// was not actually successful.
|
||||||
|
if (!data) {
|
||||||
|
errorFn(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$rootScope.$broadcast(self.ONLINE);
|
||||||
|
|
||||||
|
if (lastID > 0) { // not emit events from first response
|
||||||
|
data.forEach(function (event) {
|
||||||
|
if (debugEvents) {
|
||||||
|
console.log("event", event.id, event.type, event.data);
|
||||||
|
}
|
||||||
|
$rootScope.$broadcast(event.type, event);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastEvent = data.pop();
|
||||||
|
if (lastEvent) {
|
||||||
|
lastID = lastEvent.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$timeout(function () {
|
||||||
|
$http.get(urlbase + '/events?since=' + lastID)
|
||||||
|
.success(successFn)
|
||||||
|
.error(errorFn);
|
||||||
|
}, 500, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorFn (dummy) {
|
||||||
|
$rootScope.$broadcast(self.OFFLINE);
|
||||||
|
|
||||||
|
$timeout(function () {
|
||||||
|
$http.get(urlbase + '/events?limit=1')
|
||||||
|
.success(successFn)
|
||||||
|
.error(errorFn);
|
||||||
|
}, 1000, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
angular.extend(self, {
|
||||||
|
// emitted by this
|
||||||
|
|
||||||
|
ONLINE: 'UIOnline',
|
||||||
|
OFFLINE: 'UIOffline',
|
||||||
|
|
||||||
|
// emitted by syncthing process
|
||||||
|
|
||||||
|
CONFIG_SAVED: 'ConfigSaved', // Emitted after the config has been saved by the user or by Syncthing itself
|
||||||
|
DEVICE_CONNECTED: 'DeviceConnected', // Generated each time a connection to a device has been established
|
||||||
|
DEVICE_DISCONNECTED: 'DeviceDisconnected', // Generated each time a connection to a device has been terminated
|
||||||
|
DEVICE_DISCOVERED: 'DeviceDiscovered', // Emitted when a new device is discovered using local discovery
|
||||||
|
DEVICE_REJECTED: 'DeviceRejected', // Emitted when there is a connection from a device we are not configured to talk to
|
||||||
|
DOWNLOAD_PROGRESS: 'DownloadProgress', // Emitted during file downloads for each folder for each file
|
||||||
|
FOLDER_COMPLETION: 'FolderCompletion', //Emitted when the local or remote contents for a folder changes
|
||||||
|
FOLDER_REJECTED: 'FolderRejected', // Emitted when a device sends index information for a folder we do not have, or have but do not share with the device in question
|
||||||
|
FOLDER_SUMMARY: 'FolderSummary', // Emitted when folder contents have changed locally
|
||||||
|
ITEM_FINISHED: 'ItemFinished', // Generated when Syncthing ends synchronizing a file to a newer version
|
||||||
|
ITEM_STARTED: 'ItemStarted', // Generated when Syncthing begins synchronizing a file to a newer version
|
||||||
|
LOCAL_INDEX_UPDATED: 'LocalIndexUpdated', // Generated when the local index information has changed, due to synchronizing one or more items from the cluster or discovering local changes during a scan
|
||||||
|
PING: 'Ping', // Generated automatically every 60 seconds
|
||||||
|
REMOTE_INDEX_UPDATED: 'RemoteIndexUpdated', // Generated each time new index information is received from a device
|
||||||
|
STARTING: 'Starting', // Emitted exactly once, when Syncthing starts, before parsing configuration etc
|
||||||
|
STARTUP_COMPLETED: 'StartupCompleted', // Emitted exactly once, when initialization is complete and Syncthing is ready to start exchanging data with other devices
|
||||||
|
STATE_CHANGED: 'StateChanged', // Emitted when a folder changes state
|
||||||
|
|
||||||
|
start: function() {
|
||||||
|
$http.get(urlbase + '/events?limit=1')
|
||||||
|
.success(successFn)
|
||||||
|
.error(errorFn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}]);
|
||||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user