diff --git a/gui/default/index.html b/gui/default/index.html
index ec673d89..655a46fc 100644
--- a/gui/default/index.html
+++ b/gui/default/index.html
@@ -325,7 +325,7 @@
Up to Date
Syncing
- ({{syncPercentage(folder.id) | percent}}, {{syncRemaining(folder.id) | binary}}B)
+ ({{syncPercentage(folder.id) | percent}}, {{model[folder.id].needBytes | binary}}B)
Out of Sync
Failed Items
diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js
index ea7a97f1..c19b9f43 100755
--- a/gui/default/syncthing/core/syncthingController.js
+++ b/gui/default/syncthing/core/syncthingController.js
@@ -816,22 +816,6 @@ angular.module('syncthing.core')
return Math.floor(pct);
};
- $scope.syncRemaining = function (folder) {
- // Remaining sync bytes
- if (typeof $scope.model[folder] === 'undefined') {
- return 0;
- }
- if ($scope.model[folder].globalBytes === 0) {
- return 0;
- }
-
- var bytes = $scope.model[folder].globalBytes - $scope.model[folder].inSyncBytes;
- if (isNaN(bytes) || bytes < 0) {
- return 0;
- }
- return bytes;
- };
-
$scope.scanPercentage = function (folder) {
if (!$scope.scanProgress[folder]) {
return undefined;
diff --git a/lib/model/folder_summary.go b/lib/model/folder_summary.go
index 195afb0d..4848de99 100644
--- a/lib/model/folder_summary.go
+++ b/lib/model/folder_summary.go
@@ -149,7 +149,7 @@ func (c *folderSummaryService) OnEventRequest() {
// listenForUpdates subscribes to the event bus and makes note of folders that
// need their data recalculated.
func (c *folderSummaryService) listenForUpdates() {
- sub := events.Default.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged | events.RemoteDownloadProgress | events.DeviceConnected | events.FolderWatchStateChanged)
+ sub := events.Default.Subscribe(events.LocalIndexUpdated | events.RemoteIndexUpdated | events.StateChanged | events.RemoteDownloadProgress | events.DeviceConnected | events.FolderWatchStateChanged | events.DownloadProgress)
defer events.Default.Unsubscribe(sub)
for {
@@ -157,68 +157,84 @@ func (c *folderSummaryService) listenForUpdates() {
select {
case ev := <-sub.C():
- if ev.Type == events.DeviceConnected {
- // When a device connects we schedule a refresh of all
- // folders shared with that device.
-
- data := ev.Data.(map[string]string)
- deviceID, _ := protocol.DeviceIDFromString(data["id"])
-
- c.foldersMut.Lock()
- nextFolder:
- for _, folder := range c.cfg.Folders() {
- for _, dev := range folder.Devices {
- if dev.DeviceID == deviceID {
- c.folders[folder.ID] = struct{}{}
- continue nextFolder
- }
- }
- }
- c.foldersMut.Unlock()
-
- continue
- }
-
- // The other events all have a "folder" attribute that they
- // affect. Whenever the local or remote index is updated for a
- // given folder we make a note of it.
-
- data := ev.Data.(map[string]interface{})
- folder := data["folder"].(string)
-
- switch ev.Type {
- case events.StateChanged:
- if data["to"].(string) == "idle" && data["from"].(string) == "syncing" {
- // The folder changed to idle from syncing. We should do an
- // immediate refresh to update the GUI. The send to
- // c.immediate must be nonblocking so that we can continue
- // handling events.
-
- c.foldersMut.Lock()
- select {
- case c.immediate <- folder:
- delete(c.folders, folder)
- default:
- c.folders[folder] = struct{}{}
- }
- c.foldersMut.Unlock()
- }
-
- default:
- // This folder needs to be refreshed whenever we do the next
- // refresh.
-
- c.foldersMut.Lock()
- c.folders[folder] = struct{}{}
- c.foldersMut.Unlock()
- }
-
+ c.processUpdate(ev)
case <-c.stop:
return
}
}
}
+func (c *folderSummaryService) processUpdate(ev events.Event) {
+ var folder string
+
+ switch ev.Type {
+ case events.DeviceConnected:
+ // When a device connects we schedule a refresh of all
+ // folders shared with that device.
+
+ data := ev.Data.(map[string]string)
+ deviceID, _ := protocol.DeviceIDFromString(data["id"])
+
+ c.foldersMut.Lock()
+ nextFolder:
+ for _, folder := range c.cfg.Folders() {
+ for _, dev := range folder.Devices {
+ if dev.DeviceID == deviceID {
+ c.folders[folder.ID] = struct{}{}
+ continue nextFolder
+ }
+ }
+ }
+ c.foldersMut.Unlock()
+
+ return
+
+ case events.DownloadProgress:
+ data := ev.Data.(map[string]map[string]*pullerProgress)
+ c.foldersMut.Lock()
+ for folder := range data {
+ c.folders[folder] = struct{}{}
+ }
+ c.foldersMut.Unlock()
+ return
+
+ case events.StateChanged:
+ data := ev.Data.(map[string]interface{})
+ if !(data["to"].(string) == "idle" && data["from"].(string) == "syncing") {
+ return
+ }
+
+ // The folder changed to idle from syncing. We should do an
+ // immediate refresh to update the GUI. The send to
+ // c.immediate must be nonblocking so that we can continue
+ // handling events.
+
+ folder = data["folder"].(string)
+ select {
+ case c.immediate <- folder:
+ c.foldersMut.Lock()
+ delete(c.folders, folder)
+ c.foldersMut.Unlock()
+ return
+ default:
+ // Refresh whenever we do the next summary.
+ }
+
+ default:
+ // The other events all have a "folder" attribute that they
+ // affect. Whenever the local or remote index is updated for a
+ // given folder we make a note of it.
+ // This folder needs to be refreshed whenever we do the next
+ // refresh.
+
+ folder = ev.Data.(map[string]interface{})["folder"].(string)
+ }
+
+ c.foldersMut.Lock()
+ c.folders[folder] = struct{}{}
+ c.foldersMut.Unlock()
+}
+
// calculateSummaries periodically recalculates folder summaries and
// completion percentage, and sends the results on the event bus.
func (c *folderSummaryService) calculateSummaries() {
diff --git a/lib/model/model.go b/lib/model/model.go
index 7e2e58d5..73917ddf 100644
--- a/lib/model/model.go
+++ b/lib/model/model.go
@@ -801,7 +801,8 @@ func (m *model) ReceiveOnlyChangedSize(folder string) db.Counts {
return db.Counts{}
}
-// NeedSize returns the number and total size of currently needed files.
+// NeedSize returns the number of currently needed files and their total size
+// minus the amount that has already been downloaded.
func (m *model) NeedSize(folder string) db.Counts {
m.fmut.RLock()
rf, ok := m.folderFiles[folder]