diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 08f62fb9ad..b0c9548050 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -5576,7 +5576,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 6.2.1; + MARKETING_VERSION = 6.2.2; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-v"; OTHER_LDFLAGS = ""; @@ -5639,7 +5639,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 6.2.1; + MARKETING_VERSION = 6.2.2; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-v"; OTHER_LDFLAGS = ""; diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index dcd604cf8d..796178a128 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -31,7 +31,7 @@ class NCFiles: NCCollectionViewCommon { internal var fileNameBlink: String? internal var fileNameOpen: String? internal var matadatasHash: String = "" - internal var reloadDataSourceInProgress: Bool = false + internal var semaphoreReloadDataSource = DispatchSemaphore(value: 1) required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) @@ -122,12 +122,16 @@ class NCFiles: NCCollectionViewCommon { // MARK: - DataSource override func reloadDataSource() { - guard !isSearchingMode, - !reloadDataSourceInProgress + guard !isSearchingMode else { return super.reloadDataSource() } - reloadDataSourceInProgress = true + + // This is only a fail safe "dead lock", I don't think the timeout will ever be called but at least nothing gets stuck, if after 5 sec. (which is a long time in this routine), the semaphore is still locked + // + if self.semaphoreReloadDataSource.wait(timeout: .now() + 5) == .timedOut { + self.semaphoreReloadDataSource.signal() + } var predicate = self.defaultPredicate let predicateDirectory = NSPredicate(format: "account == %@ AND serverUrl == %@", session.account, self.serverUrl) @@ -145,14 +149,16 @@ class NCFiles: NCCollectionViewCommon { self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, layoutForView: layoutForView) if metadatas.isEmpty { - reloadDataSourceInProgress = false + self.semaphoreReloadDataSource.signal() return super.reloadDataSource() } self.dataSource.caching(metadatas: metadatas, dataSourceMetadatas: dataSourceMetadatas) { updated in - self.reloadDataSourceInProgress = false - if updated || self.isNumberOfItemsInAllSectionsNull || self.numberOfItemsInAllSections != metadatas.count { - super.reloadDataSource() + self.semaphoreReloadDataSource.signal() + DispatchQueue.main.async { + if updated || self.isNumberOfItemsInAllSectionsNull || self.numberOfItemsInAllSections != metadatas.count { + super.reloadDataSource() + } } } } diff --git a/iOSClient/Media/NCMedia.swift b/iOSClient/Media/NCMedia.swift index 222591a080..ea14552be2 100644 --- a/iOSClient/Media/NCMedia.swift +++ b/iOSClient/Media/NCMedia.swift @@ -36,6 +36,9 @@ class NCMedia: UIViewController { @IBOutlet weak var menuButton: UIButton! @IBOutlet weak var gradientView: UIView! + let semaphoreSearchMedia = DispatchSemaphore(value: 1) + let semaphoreNotificationCenter = DispatchSemaphore(value: 1) + let layout = NCMediaLayout() var layoutType = NCGlobal.shared.mediaLayoutRatio var documentPickerViewController: NCDocumentPickerViewController? @@ -257,13 +260,25 @@ class NCMedia: UIViewController { return } + // This is only a fail safe "dead lock", I don't think the timeout will ever be called but at least nothing gets stuck, if after 5 sec. (which is a long time in this routine), the semaphore is still locked + // + if self.semaphoreNotificationCenter.wait(timeout: .now() + 5) == .timedOut { + self.semaphoreNotificationCenter.signal() + } + if error.errorCode == self.global.errorResourceNotFound, let ocId = userInfo["ocId"] as? String { self.database.deleteMetadataOcId(ocId) - self.loadDataSource() + self.loadDataSource { + self.semaphoreNotificationCenter.signal() + } } else if error != .success { NCContentPresenter().showError(error: error) - self.loadDataSource() + self.loadDataSource { + self.semaphoreNotificationCenter.signal() + } + } else { + semaphoreNotificationCenter.signal() } } diff --git a/iOSClient/Media/NCMediaDataSource.swift b/iOSClient/Media/NCMediaDataSource.swift index 4a62a534c3..19740441f8 100644 --- a/iOSClient/Media/NCMediaDataSource.swift +++ b/iOSClient/Media/NCMediaDataSource.swift @@ -58,12 +58,13 @@ extension NCMedia { NCNetworking.shared.downloadThumbnailQueue.operationCount == 0, let tableAccount = database.getTableAccount(predicate: NSPredicate(format: "account == %@", session.account)) else { return } - self.searchMediaInProgress = true - let limit = max(self.collectionView.visibleCells.count * 3, 300) let visibleCells = self.collectionView?.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row }).compactMap({ self.collectionView?.cellForItem(at: $0) }) DispatchQueue.global(qos: .background).async { + self.semaphoreSearchMedia.wait() + self.searchMediaInProgress = true + var lessDate = Date.distantFuture var greaterDate = Date.distantPast let countMetadatas = self.dataSource.metadatas.count @@ -156,6 +157,8 @@ extension NCMedia { self.collectionViewReloadData() } + self.semaphoreSearchMedia.signal() + DispatchQueue.main.async { self.activityIndicator.stopAnimating() self.searchMediaInProgress = false