parent
1b59960ff9
commit
a09079ed25
@ -90,6 +90,7 @@ type modelIntf interface {
|
|||||||
Revert(folder string)
|
Revert(folder string)
|
||||||
NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated)
|
NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated)
|
||||||
RemoteNeedFolderFiles(device protocol.DeviceID, folder string, page, perpage int) ([]db.FileInfoTruncated, error)
|
RemoteNeedFolderFiles(device protocol.DeviceID, folder string, page, perpage int) ([]db.FileInfoTruncated, error)
|
||||||
|
LocalChangedFiles(folder string, page, perpage int) []db.FileInfoTruncated
|
||||||
NeedSize(folder string) db.Counts
|
NeedSize(folder string) db.Counts
|
||||||
ConnectionStats() map[string]interface{}
|
ConnectionStats() map[string]interface{}
|
||||||
DeviceStatistics() map[string]stats.DeviceStatistics
|
DeviceStatistics() map[string]stats.DeviceStatistics
|
||||||
@ -258,6 +259,7 @@ func (s *apiService) Serve() {
|
|||||||
getRestMux.HandleFunc("/rest/db/ignores", s.getDBIgnores) // folder
|
getRestMux.HandleFunc("/rest/db/ignores", s.getDBIgnores) // folder
|
||||||
getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page]
|
getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page]
|
||||||
getRestMux.HandleFunc("/rest/db/remoteneed", s.getDBRemoteNeed) // device folder [perpage] [page]
|
getRestMux.HandleFunc("/rest/db/remoteneed", s.getDBRemoteNeed) // device folder [perpage] [page]
|
||||||
|
getRestMux.HandleFunc("/rest/db/localchanged", s.getDBLocalChanged) // folder
|
||||||
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
|
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
|
||||||
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
|
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
|
||||||
getRestMux.HandleFunc("/rest/folder/versions", s.getFolderVersions) // folder
|
getRestMux.HandleFunc("/rest/folder/versions", s.getFolderVersions) // folder
|
||||||
@ -707,13 +709,13 @@ func folderSummary(cfg configIntf, m modelIntf, folder string) (map[string]inter
|
|||||||
res["invalid"] = "" // Deprecated, retains external API for now
|
res["invalid"] = "" // Deprecated, retains external API for now
|
||||||
|
|
||||||
global := m.GlobalSize(folder)
|
global := m.GlobalSize(folder)
|
||||||
res["globalFiles"], res["globalDirectories"], res["globalSymlinks"], res["globalDeleted"], res["globalBytes"] = global.Files, global.Directories, global.Symlinks, global.Deleted, global.Bytes
|
res["globalFiles"], res["globalDirectories"], res["globalSymlinks"], res["globalDeleted"], res["globalBytes"], res["globalTotalItems"] = global.Files, global.Directories, global.Symlinks, global.Deleted, global.Bytes, global.TotalItems()
|
||||||
|
|
||||||
local := m.LocalSize(folder)
|
local := m.LocalSize(folder)
|
||||||
res["localFiles"], res["localDirectories"], res["localSymlinks"], res["localDeleted"], res["localBytes"] = local.Files, local.Directories, local.Symlinks, local.Deleted, local.Bytes
|
res["localFiles"], res["localDirectories"], res["localSymlinks"], res["localDeleted"], res["localBytes"], res["localTotalItems"] = local.Files, local.Directories, local.Symlinks, local.Deleted, local.Bytes, local.TotalItems()
|
||||||
|
|
||||||
need := m.NeedSize(folder)
|
need := m.NeedSize(folder)
|
||||||
res["needFiles"], res["needDirectories"], res["needSymlinks"], res["needDeletes"], res["needBytes"] = need.Files, need.Directories, need.Symlinks, need.Deleted, need.Bytes
|
res["needFiles"], res["needDirectories"], res["needSymlinks"], res["needDeletes"], res["needBytes"], res["needTotalItems"] = need.Files, need.Directories, need.Symlinks, need.Deleted, need.Bytes, need.TotalItems()
|
||||||
|
|
||||||
if cfg.Folders()[folder].Type == config.FolderTypeReceiveOnly {
|
if cfg.Folders()[folder].Type == config.FolderTypeReceiveOnly {
|
||||||
// Add statistics for things that have changed locally in a receive
|
// Add statistics for things that have changed locally in a receive
|
||||||
@ -724,6 +726,7 @@ func folderSummary(cfg configIntf, m modelIntf, folder string) (map[string]inter
|
|||||||
res["receiveOnlyChangedSymlinks"] = ro.Symlinks
|
res["receiveOnlyChangedSymlinks"] = ro.Symlinks
|
||||||
res["receiveOnlyChangedDeletes"] = ro.Deleted
|
res["receiveOnlyChangedDeletes"] = ro.Deleted
|
||||||
res["receiveOnlyChangedBytes"] = ro.Bytes
|
res["receiveOnlyChangedBytes"] = ro.Bytes
|
||||||
|
res["receiveOnlyTotalItems"] = ro.TotalItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
res["inSyncFiles"], res["inSyncBytes"] = global.Files-need.Files, global.Bytes-need.Bytes
|
res["inSyncFiles"], res["inSyncBytes"] = global.Files-need.Files, global.Bytes-need.Bytes
|
||||||
@ -791,9 +794,9 @@ func (s *apiService) getDBNeed(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// Convert the struct to a more loose structure, and inject the size.
|
// Convert the struct to a more loose structure, and inject the size.
|
||||||
sendJSON(w, map[string]interface{}{
|
sendJSON(w, map[string]interface{}{
|
||||||
"progress": toNeedSlice(progress),
|
"progress": toJsonFileInfoSlice(progress),
|
||||||
"queued": toNeedSlice(queued),
|
"queued": toJsonFileInfoSlice(queued),
|
||||||
"rest": toNeedSlice(rest),
|
"rest": toJsonFileInfoSlice(rest),
|
||||||
"page": page,
|
"page": page,
|
||||||
"perpage": perpage,
|
"perpage": perpage,
|
||||||
})
|
})
|
||||||
@ -816,13 +819,29 @@ func (s *apiService) getDBRemoteNeed(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, err.Error(), http.StatusNotFound)
|
http.Error(w, err.Error(), http.StatusNotFound)
|
||||||
} else {
|
} else {
|
||||||
sendJSON(w, map[string]interface{}{
|
sendJSON(w, map[string]interface{}{
|
||||||
"files": toNeedSlice(files),
|
"files": toJsonFileInfoSlice(files),
|
||||||
"page": page,
|
"page": page,
|
||||||
"perpage": perpage,
|
"perpage": perpage,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *apiService) getDBLocalChanged(w http.ResponseWriter, r *http.Request) {
|
||||||
|
qs := r.URL.Query()
|
||||||
|
|
||||||
|
folder := qs.Get("folder")
|
||||||
|
|
||||||
|
page, perpage := getPagingParams(qs)
|
||||||
|
|
||||||
|
files := s.model.LocalChangedFiles(folder, page, perpage)
|
||||||
|
|
||||||
|
sendJSON(w, map[string]interface{}{
|
||||||
|
"files": toJsonFileInfoSlice(files),
|
||||||
|
"page": page,
|
||||||
|
"perpage": perpage,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *apiService) getSystemConnections(w http.ResponseWriter, r *http.Request) {
|
func (s *apiService) getSystemConnections(w http.ResponseWriter, r *http.Request) {
|
||||||
sendJSON(w, s.model.ConnectionStats())
|
sendJSON(w, s.model.ConnectionStats())
|
||||||
}
|
}
|
||||||
@ -1638,7 +1657,7 @@ func (s *apiService) getHeapProf(w http.ResponseWriter, r *http.Request) {
|
|||||||
pprof.WriteHeapProfile(w)
|
pprof.WriteHeapProfile(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toNeedSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo {
|
func toJsonFileInfoSlice(fs []db.FileInfoTruncated) []jsonDBFileInfo {
|
||||||
res := make([]jsonDBFileInfo, len(fs))
|
res := make([]jsonDBFileInfo, len(fs))
|
||||||
for i, f := range fs {
|
for i, f := range fs {
|
||||||
res[i] = jsonDBFileInfo(f)
|
res[i] = jsonDBFileInfo(f)
|
||||||
|
|||||||
@ -146,3 +146,7 @@ func (m *mockedModel) FolderErrors(folder string) ([]model.FileError, error) {
|
|||||||
func (m *mockedModel) WatchError(folder string) error {
|
func (m *mockedModel) WatchError(folder string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockedModel) LocalChangedFiles(folder string, page, perpage int) []db.FileInfoTruncated {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -373,10 +373,10 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="neededItems(folder.id) > 0">
|
<tr ng-if="model[folder.id].needTotalItems > 0">
|
||||||
<th><span class="fas fa-fw fa-cloud-download-alt"></span> <span translate>Out of Sync Items</span></th>
|
<th><span class="fas fa-fw fa-cloud-download-alt"></span> <span translate>Out of Sync Items</span></th>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<a href="" ng-click="showNeed(folder.id)">{{neededItems(folder.id) | alwaysNumber}} <span translate>items</span>, ~{{model[folder.id].needBytes | binary}}B</a>
|
<a href="" ng-click="showNeed(folder.id)">{{model[folder.id].needTotalItems | alwaysNumber}} <span translate>items</span>, ~{{model[folder.id].needBytes | binary}}B</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr ng-if="folderStatus(folder) === 'scanning' && scanRate(folder.id) > 0">
|
<tr ng-if="folderStatus(folder) === 'scanning' && scanRate(folder.id) > 0">
|
||||||
@ -392,6 +392,12 @@
|
|||||||
<a href="" ng-click="showFailed(folder.id)">{{model[folder.id].pullErrors | alwaysNumber | localeNumber}} <span translate>items</span></a>
|
<a href="" ng-click="showFailed(folder.id)">{{model[folder.id].pullErrors | alwaysNumber | localeNumber}} <span translate>items</span></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr ng-if="folder.type == 'receiveonly' && canRevert(folder.id)">
|
||||||
|
<th><span class="fas fa-fw fa-exclamation-circle"></span> <span translate>Locally Changed Items</span></th>
|
||||||
|
<td class="text-right">
|
||||||
|
<a href="" ng-click="showLocalChanged(folder.id)">{{model[folder.id].receiveOnlyTotalItems | alwaysNumber}} <span translate>items</span>, ~{{model[folder.id].receiveOnlyBytes | binary}}B</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr ng-if="folder.type != 'sendreceive'">
|
<tr ng-if="folder.type != 'sendreceive'">
|
||||||
<th><span class="fas fa-fw fa-folder"></span> <span translate>Folder Type</span></th>
|
<th><span class="fas fa-fw fa-folder"></span> <span translate>Folder Type</span></th>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
@ -822,6 +828,7 @@
|
|||||||
<ng-include src="'syncthing/transfer/neededFilesModalView.html'"></ng-include>
|
<ng-include src="'syncthing/transfer/neededFilesModalView.html'"></ng-include>
|
||||||
<ng-include src="'syncthing/transfer/failedFilesModalView.html'"></ng-include>
|
<ng-include src="'syncthing/transfer/failedFilesModalView.html'"></ng-include>
|
||||||
<ng-include src="'syncthing/transfer/remoteNeededFilesModalView.html'"></ng-include>
|
<ng-include src="'syncthing/transfer/remoteNeededFilesModalView.html'"></ng-include>
|
||||||
|
<ng-include src="'syncthing/transfer/localChangedFilesModalView.html'"></ng-include>
|
||||||
<ng-include src="'syncthing/core/majorUpgradeModalView.html'"></ng-include>
|
<ng-include src="'syncthing/core/majorUpgradeModalView.html'"></ng-include>
|
||||||
<ng-include src="'syncthing/core/aboutModalView.html'"></ng-include>
|
<ng-include src="'syncthing/core/aboutModalView.html'"></ng-include>
|
||||||
<ng-include src="'syncthing/core/discoveryFailuresModalView.html'"></ng-include>
|
<ng-include src="'syncthing/core/discoveryFailuresModalView.html'"></ng-include>
|
||||||
|
|||||||
@ -46,6 +46,7 @@ angular.module('syncthing.core')
|
|||||||
$scope.neededCurrentPage = 1;
|
$scope.neededCurrentPage = 1;
|
||||||
$scope.neededPageSize = 10;
|
$scope.neededPageSize = 10;
|
||||||
$scope.failed = {};
|
$scope.failed = {};
|
||||||
|
$scope.localChanged = {};
|
||||||
$scope.scanProgress = {};
|
$scope.scanProgress = {};
|
||||||
$scope.themes = [];
|
$scope.themes = [];
|
||||||
$scope.globalChangeEvents = {};
|
$scope.globalChangeEvents = {};
|
||||||
@ -672,6 +673,15 @@ angular.module('syncthing.core')
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.refreshLocalChanged = function (page, perpage) {
|
||||||
|
var url = urlbase + '/db/localchanged?folder=';
|
||||||
|
url += encodeURIComponent($scope.localChanged.folder);
|
||||||
|
url += "&page=" + page + "&perpage=" + perpage;
|
||||||
|
$http.get(url).success(function (data) {
|
||||||
|
$scope.localChanged = data;
|
||||||
|
}).error($scope.emitHTTPError);
|
||||||
|
};
|
||||||
|
|
||||||
var refreshDeviceStats = debounce(function () {
|
var refreshDeviceStats = debounce(function () {
|
||||||
$http.get(urlbase + "/stats/device").success(function (data) {
|
$http.get(urlbase + "/stats/device").success(function (data) {
|
||||||
$scope.deviceStats = data;
|
$scope.deviceStats = data;
|
||||||
@ -737,7 +747,7 @@ angular.module('syncthing.core')
|
|||||||
if (state === 'error') {
|
if (state === 'error') {
|
||||||
return 'stopped'; // legacy, the state is called "stopped" in the GUI
|
return 'stopped'; // legacy, the state is called "stopped" in the GUI
|
||||||
}
|
}
|
||||||
if (state === 'idle' && $scope.neededItems(folderCfg.id) > 0) {
|
if (state === 'idle' && $scope.model[folderCfg.id].needTotalItems > 0) {
|
||||||
return 'outofsync';
|
return 'outofsync';
|
||||||
}
|
}
|
||||||
if (state === 'scanning') {
|
if (state === 'scanning') {
|
||||||
@ -776,15 +786,6 @@ angular.module('syncthing.core')
|
|||||||
return 'info';
|
return 'info';
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.neededItems = function (folderID) {
|
|
||||||
if (!$scope.model[folderID]) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return $scope.model[folderID].needFiles + $scope.model[folderID].needDirectories +
|
|
||||||
$scope.model[folderID].needSymlinks + $scope.model[folderID].needDeletes;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.syncPercentage = function (folder) {
|
$scope.syncPercentage = function (folder) {
|
||||||
if (typeof $scope.model[folder] === 'undefined') {
|
if (typeof $scope.model[folder] === 'undefined') {
|
||||||
return 100;
|
return 100;
|
||||||
@ -2194,6 +2195,14 @@ angular.module('syncthing.core')
|
|||||||
$http.post(urlbase + "/db/override?folder=" + encodeURIComponent(folder));
|
$http.post(urlbase + "/db/override?folder=" + encodeURIComponent(folder));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.showLocalChanged = function (folder) {
|
||||||
|
$scope.localChanged.folder = folder;
|
||||||
|
$scope.localChanged = $scope.refreshLocalChanged(1, 10);
|
||||||
|
$('#localChanged').modal().one('hidden.bs.modal', function () {
|
||||||
|
$scope.localChanged = {};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$scope.revert = function (folder) {
|
$scope.revert = function (folder) {
|
||||||
$http.post(urlbase + "/db/revert?folder=" + encodeURIComponent(folder));
|
$http.post(urlbase + "/db/revert?folder=" + encodeURIComponent(folder));
|
||||||
};
|
};
|
||||||
@ -2203,11 +2212,7 @@ angular.module('syncthing.core')
|
|||||||
if (!f) {
|
if (!f) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return f.receiveOnlyChangedBytes > 0 ||
|
return $scope.model[folder].receiveOnlyTotalItems > 0;
|
||||||
f.receiveOnlyChangedDeletes > 0 ||
|
|
||||||
f.receiveOnlyChangedDirectories > 0 ||
|
|
||||||
f.receiveOnlyChangedFiles > 0 ||
|
|
||||||
f.receiveOnlyChangedSymlinks > 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.advanced = function () {
|
$scope.advanced = function () {
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
<modal id="localChanged" status="info" icon="fas fa-exclamation-circle" heading="{{'Locally Changed Items' | translate}}" large="yes" closeable="yes">
|
||||||
|
<div class="modal-body">
|
||||||
|
<p translate>
|
||||||
|
The following items were changed locally.
|
||||||
|
</p>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th translate>Path</th>
|
||||||
|
<th translate>Size</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tr dir-paginate="file in localChanged.files | itemsPerPage: localChanged.perpage" current-page="localChanged.page" total-items="model[localChanged.folder].receiveOnlyTotalItems" pagination-id="localChanged">
|
||||||
|
<td>{{file.name}}</td>
|
||||||
|
<td><span ng-hide="file.type == 'DIRECTORY'">{{file.size | binary}}B</span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<dir-pagination-controls on-page-change="refreshLocalChanged(newPageNumber, localChanged.perpage)" pagination-id="localChanged"></dir-pagination-controls>
|
||||||
|
<ul class="pagination pull-right">
|
||||||
|
<li ng-repeat="option in [10, 25, 50]" ng-class="{ active: localChanged.page == option }">
|
||||||
|
<a href="#" ng-click="refreshLocalChanged(localChanged.page, option)">{{option}}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||||
|
<span class="fas fa-times"></span> <span translate>Close</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</modal>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<table class="table table-striped table-condensed">
|
<table class="table table-striped table-condensed">
|
||||||
|
|
||||||
<tr dir-paginate="f in needed | itemsPerPage: neededPageSize" current-page="neededCurrentPage" total-items="neededItems(neededFolder)" pagination-id="needed">
|
<tr dir-paginate="f in needed | itemsPerPage: neededPageSize" current-page="neededCurrentPage" total-items="model[neededFolder].needTotalItems" pagination-id="needed">
|
||||||
|
|
||||||
<!-- Icon -->
|
<!-- Icon -->
|
||||||
<td class="small-data col-xs-2">
|
<td class="small-data col-xs-2">
|
||||||
|
|||||||
@ -45,6 +45,7 @@ type FileIntf interface {
|
|||||||
IsIgnored() bool
|
IsIgnored() bool
|
||||||
IsUnsupported() bool
|
IsUnsupported() bool
|
||||||
MustRescan() bool
|
MustRescan() bool
|
||||||
|
IsReceiveOnlyChanged() bool
|
||||||
IsDirectory() bool
|
IsDirectory() bool
|
||||||
IsSymlink() bool
|
IsSymlink() bool
|
||||||
ShouldConflict() bool
|
ShouldConflict() bool
|
||||||
|
|||||||
@ -142,6 +142,10 @@ func (c Counts) Add(other Counts) Counts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Counts) TotalItems() int32 {
|
||||||
|
return c.Files + c.Directories + c.Symlinks + c.Deleted
|
||||||
|
}
|
||||||
|
|
||||||
func (vl VersionList) String() string {
|
func (vl VersionList) String() string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
var id protocol.DeviceID
|
var id protocol.DeviceID
|
||||||
|
|||||||
@ -797,19 +797,58 @@ func (m *Model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfo
|
|||||||
skip--
|
skip--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if get > 0 {
|
|
||||||
ft := f.(db.FileInfoTruncated)
|
ft := f.(db.FileInfoTruncated)
|
||||||
if _, ok := seen[ft.Name]; !ok {
|
if _, ok := seen[ft.Name]; !ok {
|
||||||
rest = append(rest, ft)
|
rest = append(rest, ft)
|
||||||
get--
|
get--
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return get > 0
|
return get > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return progress, queued, rest
|
return progress, queued, rest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LocalChangedFiles returns a paginated list of currently needed files in
|
||||||
|
// progress, queued, and to be queued on next puller iteration, as well as the
|
||||||
|
// total number of files currently needed.
|
||||||
|
func (m *Model) LocalChangedFiles(folder string, page, perpage int) []db.FileInfoTruncated {
|
||||||
|
m.fmut.RLock()
|
||||||
|
defer m.fmut.RUnlock()
|
||||||
|
|
||||||
|
rf, ok := m.folderFiles[folder]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fcfg := m.folderCfgs[folder]
|
||||||
|
if fcfg.Type != config.FolderTypeReceiveOnly {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if rf.ReceiveOnlyChangedSize().TotalItems() == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
files := make([]db.FileInfoTruncated, 0, perpage)
|
||||||
|
|
||||||
|
skip := (page - 1) * perpage
|
||||||
|
get := perpage
|
||||||
|
|
||||||
|
rf.WithHaveTruncated(protocol.LocalDeviceID, func(f db.FileIntf) bool {
|
||||||
|
if !f.IsReceiveOnlyChanged() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if skip > 0 {
|
||||||
|
skip--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
ft := f.(db.FileInfoTruncated)
|
||||||
|
files = append(files, ft)
|
||||||
|
get--
|
||||||
|
return get > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// RemoteNeedFolderFiles returns paginated list of currently needed files in
|
// RemoteNeedFolderFiles returns paginated list of currently needed files in
|
||||||
// progress, queued, and to be queued on next puller iteration, as well as the
|
// progress, queued, and to be queued on next puller iteration, as well as the
|
||||||
// total number of files currently needed.
|
// total number of files currently needed.
|
||||||
@ -833,10 +872,8 @@ func (m *Model) RemoteNeedFolderFiles(device protocol.DeviceID, folder string, p
|
|||||||
skip--
|
skip--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if get > 0 {
|
|
||||||
files = append(files, f.(db.FileInfoTruncated))
|
files = append(files, f.(db.FileInfoTruncated))
|
||||||
get--
|
get--
|
||||||
}
|
|
||||||
return get > 0
|
return get > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user