NCMediaDataSource.swift 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //
  2. // NCMediaDataSource.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 25/01/24.
  6. // Copyright © 2024 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import UIKit
  24. import NextcloudKit
  25. extension NCMedia {
  26. func reloadDataSource() {
  27. self.metadatas = imageCache.getMediaMetadatas(account: activeAccount.account, predicate: self.getPredicate())
  28. self.collectionViewReloadData()
  29. }
  30. func collectionViewReloadData() {
  31. DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
  32. self.collectionView.reloadData()
  33. self.setTitleDate()
  34. }
  35. }
  36. // MARK: - Search media
  37. @objc func searchMediaUI() {
  38. var lessDate: Date?
  39. var greaterDate: Date?
  40. let firstMetadataDate = metadatas?.first?.date as? Date
  41. let lastMetadataDate = metadatas?.last?.date as? Date
  42. let countMetadatas = self.metadatas?.count ?? 0
  43. guard loadingTask == nil,
  44. !isEditMode,
  45. self.viewIfLoaded?.window != nil,
  46. let visibleCells = self.collectionView?.indexPathsForVisibleItems.sorted(by: { $0.row < $1.row }).compactMap({ self.collectionView?.cellForItem(at: $0) })
  47. else {
  48. return
  49. }
  50. // first date
  51. let firstCellDate = (visibleCells.first as? NCGridMediaCell)?.fileDate
  52. if firstCellDate == firstMetadataDate {
  53. lessDate = Date.distantFuture
  54. } else {
  55. if let date = firstCellDate {
  56. lessDate = Calendar.current.date(byAdding: .second, value: 1, to: date)!
  57. } else {
  58. lessDate = Date.distantFuture
  59. }
  60. }
  61. // last date
  62. let lastCellDate = (visibleCells.last as? NCGridMediaCell)?.fileDate
  63. if lastCellDate == lastMetadataDate {
  64. greaterDate = Date.distantPast
  65. } else {
  66. if let date = lastCellDate {
  67. greaterDate = Calendar.current.date(byAdding: .second, value: -1, to: date)!
  68. } else {
  69. greaterDate = Date.distantPast
  70. }
  71. }
  72. if lessDate == Date.distantFuture,
  73. greaterDate == Date.distantPast,
  74. (self.metadatas?.count ?? 0) > visibleCells.count {
  75. NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Media search new media oops. something is bad (distantFuture, distantPast): \(self.activeAccount.account), \(self.appDelegate.account), \(self.metadatas?.count ?? 0)")
  76. return
  77. }
  78. if let lessDate, let greaterDate {
  79. activityIndicator.startAnimating()
  80. loadingTask = Task.detached {
  81. if countMetadatas == 0 {
  82. await self.collectionViewReloadData()
  83. }
  84. let results = await self.searchMedia(lessDate: lessDate, greaterDate: greaterDate)
  85. if results.error == .success {
  86. Task { @MainActor in
  87. if results.lessDate == Date.distantFuture, results.greaterDate == Date.distantPast, !results.isChanged, results.metadatasCount == 0 {
  88. self.metadatas = nil
  89. self.collectionViewReloadData()
  90. print("searchMediaUI: metadatacount 0")
  91. } else if results.isChanged {
  92. self.reloadDataSource()
  93. print("searchMediaUI: changed")
  94. } else {
  95. print("searchMediaUI: nothing")
  96. }
  97. }
  98. } else {
  99. NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Media search new media error code \(results.error.errorCode) " + results.error.errorDescription)
  100. }
  101. Task { @MainActor in
  102. self.loadingTask = nil
  103. self.activityIndicator.stopAnimating()
  104. }
  105. }
  106. }
  107. }
  108. private func searchMedia(lessDate: Date, greaterDate: Date, limit: Int = 300, timeout: TimeInterval = 120) async -> (lessDate: Date?, greaterDate: Date?, metadatasCount: Int, isChanged: Bool, error: NKError) {
  109. guard let mediaPath = NCManageDatabase.shared.getActiveAccount()?.mediaPath else {
  110. return(lessDate, greaterDate, 0, false, NKError())
  111. }
  112. NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start searchMedia with lessDate \(lessDate), greaterDate \(greaterDate)")
  113. let options = NKRequestOptions(timeout: timeout, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
  114. let results = await NextcloudKit.shared.searchMedia(path: mediaPath, lessDate: lessDate, greaterDate: greaterDate, elementDate: "d:getlastmodified/", limit: limit, showHiddenFiles: NCKeychain().showHiddenFiles, includeHiddenFiles: [], options: options)
  115. if results.account != self.activeAccount.account {
  116. let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "User changed")
  117. return(lessDate, greaterDate, 0, false, error)
  118. } else if results.error == .success {
  119. let metadatas = await NCManageDatabase.shared.convertFilesToMetadatas(results.files, useMetadataFolder: false).metadatas
  120. var predicate = NSPredicate(format: "date > %@ AND date < %@", greaterDate as NSDate, lessDate as NSDate)
  121. predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, getPredicate(showAll: true)])
  122. let resultsUpdate = NCManageDatabase.shared.updateMetadatas(metadatas, predicate: predicate)
  123. let isChaged: Bool = (resultsUpdate.metadatasDifferentCount != 0 || resultsUpdate.metadatasModified != 0)
  124. NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] End searchMedia UpdateMetadatas with differentCount \(resultsUpdate.metadatasDifferentCount), modified \(resultsUpdate.metadatasModified)")
  125. return(lessDate, greaterDate, metadatas.count, isChaged, results.error)
  126. } else {
  127. return(lessDate, greaterDate, 0, false, results.error)
  128. }
  129. }
  130. private func getPredicate(showAll: Bool = false) -> NSPredicate {
  131. let startServerUrl = NCUtilityFileSystem().getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId) + activeAccount.mediaPath
  132. if showAll {
  133. return NSPredicate(format: imageCache.showAllPredicateMediaString, activeAccount.account, startServerUrl)
  134. } else if showOnlyImages {
  135. return NSPredicate(format: imageCache.showOnlyPredicateMediaString, activeAccount.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue)
  136. } else if showOnlyVideos {
  137. return NSPredicate(format: imageCache.showOnlyPredicateMediaString, activeAccount.account, startServerUrl, NKCommon.TypeClassFile.video.rawValue)
  138. } else {
  139. return NSPredicate(format: imageCache.showBothPredicateMediaString, activeAccount.account, startServerUrl)
  140. }
  141. }
  142. }