Repository: syncthing/syncthing (language: go)

Issue:
Indicate folders / devices where the remote end is paused.
If a remote device has accepted a folder we share to them, but set it to paused state, the only indication right now is the device completion never reaching 100 percent. This should be marked on a more granular basis for each shared folder in the device details / each "Shared With" device in the folder details.

The info is already available by looking at missing folder entries from the protocol's ClusterConfig message and exposed through the interface added in #8283.  It should be indicated in the GUI just like for folders not shared back from the remote, with a footnote number.


Discussion / hints:

Fix patch:
diff --git a/gui/default/index.html b/gui/default/index.html
index 9f63c4ab931..6178f75aa9f 100644
--- a/gui/default/index.html
+++ b/gui/default/index.html
@@ -533,7 +533,7 @@ <h4 class="panel-title">
                       <tr>
                         <th><span class="fas fa-fw fa-share-alt"></span>&nbsp;<span translate>Shared With</span></th>
                         <td class="text-right">
-                          <span tooltip data-original-title="{{sharesFolder(folder)}} {{folderHasUnacceptedDevices(folder) ? '<br/>(<sup>1</sup>' + ('The remote device has not accepted sharing this folder.' | translate) + ')' : ''}}" ng-bind-html="sharesFolder(folder)"></span>
+                          <span tooltip data-original-title="{{sharesFolder(folder)}} {{folderHasUnacceptedDevices(folder) ? '<br/>(<sup>1</sup>' + ('The remote device has not accepted sharing this folder.' | translate) + ')' : ''}} {{folderHasPausedDevices(folder) ? '<br/>(<sup>2</sup>' + ('The remote device has paused this folder.' | translate) + ')' : ''}}" ng-bind-html="sharesFolder(folder)"></span>
                         </td>
                       </tr>
                       <tr ng-if="folderStats[folder.id].lastScan">
@@ -835,7 +835,7 @@ <h4 class="panel-title">
                       <tr ng-if="deviceFolders(deviceCfg).length > 0">
                         <th><span class="fas fa-fw fa-folder"></span>&nbsp;<span translate>Folders</span></th>
                         <td class="text-right">
-                          <span tooltip data-original-title="{{sharedFolders(deviceCfg)}} {{deviceHasUnacceptedFolders(deviceCfg) ? '<br/>(<sup>1</sup>' + ('The remote device has not accepted sharing this folder.' | translate) + ')' : '' }}" ng-bind-html="sharedFolders(deviceCfg)"></span>
+                          <span tooltip data-original-title="{{sharedFolders(deviceCfg)}} {{deviceHasUnacceptedFolders(deviceCfg) ? '<br/>(<sup>1</sup>' + ('The remote device has not accepted sharing this folder.' | translate) + ')' : '' }} {{deviceHasPausedFolders(deviceCfg) ? '<br/>(<sup>2</sup>' + ('The remote device has paused this folder.' | translate) + ')' : '' }}" ng-bind-html="sharedFolders(deviceCfg)"></span>
                         </td>
                       </tr>
                       <tr ng-if="deviceCfg.remoteGUIPort > 0">
diff --git a/gui/default/syncthing/core/syncthingController.js b/gui/default/syncthing/core/syncthingController.js
index 939ff585967..277f305ecdd 100755
--- a/gui/default/syncthing/core/syncthingController.js
+++ b/gui/default/syncthing/core/syncthingController.js
@@ -2365,11 +2365,15 @@ angular.module('syncthing.core')
                          + '&device=' + encodeURIComponent(deviceID));
         };
 
-        $scope.deviceNameMarkUnaccepted = function (deviceID, folderID) {
+        $scope.deviceNameMarkRemoteState = function (deviceID, folderID) {
             var name = $scope.deviceName($scope.devices[deviceID]);
             // Add footnote if sharing was not accepted on the remote device
-            if (deviceID in $scope.completion && folderID in $scope.completion[deviceID] && $scope.completion[deviceID][folderID].remoteState == 'notSharing') {
-                name += '<sup>1</sup>';
+            if (deviceID in $scope.completion && folderID in $scope.completion[deviceID]) {
+                if ($scope.completion[deviceID][folderID].remoteState == 'notSharing') {
+                    name += '<sup>1</sup>';
+                } else if ($scope.completion[deviceID][folderID].remoteState == 'paused') {
+                    name += '<sup>2</sup>';
+                }
             }
             return name;
         };
@@ -2378,7 +2382,7 @@ angular.module('syncthing.core')
             var names = [];
             folderCfg.devices.forEach(function (device) {
                 if (device.deviceID !== $scope.myID) {
-                    names.push($scope.deviceNameMarkUnaccepted(device.deviceID, folderCfg.id));
+                    names.push($scope.deviceNameMarkRemoteState(device.deviceID, folderCfg.id));
                 }
             });
             names.sort();
@@ -2396,6 +2400,17 @@ angular.module('syncthing.core')
             return false;
         };
 
+        $scope.folderHasPausedDevices = function (folderCfg) {
+            for (var deviceID in $scope.completion) {
+                if (deviceID in $scope.devices
+                    && folderCfg.id in $scope.completion[deviceID]
+                    && $scope.completion[deviceID][folderCfg.id].remoteState == 'paused') {
+                    return true;
+                }
+            }
+            return false;
+        };
+
         $scope.deviceFolders = function (deviceCfg) {
             var folders = [];
             $scope.folderList().forEach(function (folder) {
@@ -2417,11 +2432,15 @@ angular.module('syncthing.core')
             return label && label.length > 0 ? label : folderID;
         };
 
-        $scope.folderLabelMarkUnaccepted = function (folderID, deviceID) {
+        $scope.folderLabelMarkRemoteState = function (folderID, deviceID) {
             var label = $scope.folderLabel(folderID);
             // Add footnote if sharing was not accepted on the remote device
-            if (deviceID in $scope.completion && folderID in $scope.completion[deviceID] && $scope.completion[deviceID][folderID].remoteState == 'notSharing') {
-                label += '<sup>1</sup>';
+            if (deviceID in $scope.completion && folderID in $scope.completion[deviceID]) {
+                if ($scope.completion[deviceID][folderID].remoteState == 'notSharing') {
+                    label += '<sup>1</sup>';
+                } else if ($scope.completion[deviceID][folderID].remoteState == 'paused') {
+                    label += '<sup>2</sup>';
+                }
             }
             return label;
         };
@@ -2429,7 +2448,7 @@ angular.module('syncthing.core')
         $scope.sharedFolders = function (deviceCfg) {
             var labels = [];
             $scope.deviceFolders(deviceCfg).forEach(function (folderID) {
-                labels.push($scope.folderLabelMarkUnaccepted(folderID, deviceCfg.deviceID));
+                labels.push($scope.folderLabelMarkRemoteState(folderID, deviceCfg.deviceID));
             });
             return labels.join(', ');
         };
@@ -2447,6 +2466,19 @@ angular.module('syncthing.core')
             return false;
         };
 
+        $scope.deviceHasPausedFolders = function (deviceCfg) {
+            if (!(deviceCfg.deviceID in $scope.completion)) {
+                return false;
+            }
+            for (var folderID in $scope.completion[deviceCfg.deviceID]) {
+                if (folderID in $scope.folders
+                    && $scope.completion[deviceCfg.deviceID][folderID].remoteState == 'paused') {
+                    return true;
+                }
+            }
+            return false;
+        };
+
         $scope.deleteFolder = function (id) {
             hideFolderModal();
             if ($scope.currentFolder._editing != "existing") {
diff --git a/gui/default/syncthing/device/editDeviceModalView.html b/gui/default/syncthing/device/editDeviceModalView.html
index ad7653dc9e3..6cef431ca00 100644
--- a/gui/default/syncthing/device/editDeviceModalView.html
+++ b/gui/default/syncthing/device/editDeviceModalView.html
@@ -88,6 +88,9 @@
               <p class="help-block" ng-if="deviceHasUnacceptedFolders(currentDevice)">
                 <sup>1</sup> <span translate>The remote device has not accepted sharing this folder.</span>
               </p>
+              <p class="help-block" ng-if="deviceHasPausedFolders(currentDevice)">
+                <sup>2</sup> <span translate>The remote device has paused this folder.</span>
+              </p>
             </div>
             <div class="form-horizontal" ng-if="currentSharing.unrelated.length">
               <label translate for="folders">Unshared Folders</label>
diff --git a/gui/default/syncthing/folder/editFolderModalView.html b/gui/default/syncthing/folder/editFolderModalView.html
index 183bd8b86d5..7e28c347111 100644
--- a/gui/default/syncthing/folder/editFolderModalView.html
+++ b/gui/default/syncthing/folder/editFolderModalView.html
@@ -61,6 +61,9 @@
             <p class="help-block" ng-if="folderHasUnacceptedDevices(currentFolder)">
               <sup>1</sup> <span translate>The remote device has not accepted sharing this folder.</span>
             </p>
+            <p class="help-block" ng-if="folderHasPausedDevices(currentFolder)">
+              <sup>2</sup> <span translate>The remote device has paused this folder.</span>
+            </p>
           </div>
           <div class="form-horizontal" ng-if="currentSharing.unrelated.length || otherDevices().length <= 0">
             <label translate>Unshared Devices</label>


Test patch: