diff --git a/gui/default/index.html b/gui/default/index.html
index 655a46fc..9fa5466e 100644
--- a/gui/default/index.html
+++ b/gui/default/index.html
@@ -323,6 +323,10 @@
Up to Date
+
+ Preparing to Sync
+
+
Syncing
({{syncPercentage(folder.id) | percent}}, {{model[folder.id].needBytes | binary}}B)
diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js
index 611b3d93..1479a1da 100755
--- a/gui/default/syncthing/core/syncthingController.js
+++ b/gui/default/syncthing/core/syncthingController.js
@@ -803,7 +803,7 @@ angular.module('syncthing.core')
if (status == 'paused') {
return 'default';
}
- if (status === 'syncing' || status === 'scanning') {
+ if (status === 'syncing' || status === 'sync-preparing' || status === 'scanning') {
return 'primary';
}
if (status === 'unknown') {
@@ -968,6 +968,7 @@ angular.module('syncthing.core')
for (var i = 0; i < folderListCache.length; i++) {
var status = $scope.folderStatus(folderListCache[i]);
switch (status) {
+ case 'sync-preparing':
case 'syncing':
syncCount++;
break;
diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go
index bbf381a9..a2da02c4 100644
--- a/lib/model/folder_sendrecv.go
+++ b/lib/model/folder_sendrecv.go
@@ -176,7 +176,6 @@ func (f *sendReceiveFolder) pull() bool {
l.Debugf("%v pulling", f)
- f.setState(FolderSyncing)
f.clearPullErrors()
scanChan := make(chan string)
@@ -194,6 +193,10 @@ func (f *sendReceiveFolder) pull() bool {
default:
}
+ // Needs to be set on every loop, as the puller might have set
+ // it to FolderSyncing during the last iteration.
+ f.setState(FolderSyncPreparing)
+
changed := f.pullerIteration(scanChan)
l.Debugln(f, "changed", changed, "on try", tries+1)
@@ -1396,6 +1399,8 @@ func (f *sendReceiveFolder) pullerRoutine(in <-chan pullBlockState, out chan<- *
continue
}
+ f.setState(FolderSyncing) // Does nothing if already FolderSyncing
+
// The requestLimiter limits how many pending block requests we have
// ongoing at any given time, based on the size of the blocks
// themselves.
diff --git a/lib/model/folderstate.go b/lib/model/folderstate.go
index d11a72ea..d1a4c54c 100644
--- a/lib/model/folderstate.go
+++ b/lib/model/folderstate.go
@@ -19,6 +19,7 @@ const (
FolderIdle folderState = iota
FolderScanning
FolderScanWaiting
+ FolderSyncPreparing
FolderSyncing
FolderError
)
@@ -31,6 +32,8 @@ func (s folderState) String() string {
return "scanning"
case FolderScanWaiting:
return "scan-waiting"
+ case FolderSyncPreparing:
+ return "sync-preparing"
case FolderSyncing:
return "syncing"
case FolderError:
@@ -65,29 +68,32 @@ func (s *stateTracker) setState(newState folderState) {
}
s.mut.Lock()
- if newState != s.current {
- /* This should hold later...
- if s.current != FolderIdle && (newState == FolderScanning || newState == FolderSyncing) {
- panic("illegal state transition " + s.current.String() + " -> " + newState.String())
- }
- */
+ defer s.mut.Unlock()
- eventData := map[string]interface{}{
- "folder": s.folderID,
- "to": newState.String(),
- "from": s.current.String(),
- }
-
- if !s.changed.IsZero() {
- eventData["duration"] = time.Since(s.changed).Seconds()
- }
-
- s.current = newState
- s.changed = time.Now()
-
- s.evLogger.Log(events.StateChanged, eventData)
+ if newState == s.current {
+ return
}
- s.mut.Unlock()
+
+ /* This should hold later...
+ if s.current != FolderIdle && (newState == FolderScanning || newState == FolderSyncing) {
+ panic("illegal state transition " + s.current.String() + " -> " + newState.String())
+ }
+ */
+
+ eventData := map[string]interface{}{
+ "folder": s.folderID,
+ "to": newState.String(),
+ "from": s.current.String(),
+ }
+
+ if !s.changed.IsZero() {
+ eventData["duration"] = time.Since(s.changed).Seconds()
+ }
+
+ s.current = newState
+ s.changed = time.Now()
+
+ s.evLogger.Log(events.StateChanged, eventData)
}
// getState returns the current state, the time when it last changed, and the