NCMediaCache.swift 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //
  2. // NCMediaCache.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 18/10/23.
  6. // Copyright © 2021 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 LRUCache
  25. import NextcloudKit
  26. @objc class NCMediaCache: NSObject {
  27. @objc public static let shared: NCMediaCache = {
  28. let instance = NCMediaCache()
  29. return instance
  30. }()
  31. private let limit: Int = 1500
  32. private typealias ThumbnailLRUCache = LRUCache<String, UIImage>
  33. private lazy var cache: ThumbnailLRUCache = {
  34. return ThumbnailLRUCache(countLimit: limit)
  35. }()
  36. private var ocIdEtag: [String: String] = [:]
  37. public var metadatas: [tableMetadata] = []
  38. public var predicateDefault: NSPredicate?
  39. public var predicate: NSPredicate?
  40. public var livePhoto: Bool = false
  41. func createCache(account: String) {
  42. metadatas.removeAll()
  43. getMetadatasMedia(account: account)
  44. guard !metadatas.isEmpty, let directory = CCUtility.getDirectoryProviderStorage() else { return }
  45. let ext = ".preview.ico"
  46. let manager = FileManager.default
  47. let resourceKeys = Set<URLResourceKey>([.nameKey, .pathKey, .fileSizeKey, .creationDateKey])
  48. struct FileInfo {
  49. var path: URL
  50. var ocId: String
  51. var date: Date
  52. }
  53. var files: [FileInfo] = []
  54. let startDate = Date()
  55. for metadata in metadatas {
  56. ocIdEtag[metadata.ocId] = metadata.etag
  57. }
  58. if let enumerator = manager.enumerator(at: URL(fileURLWithPath: directory), includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles]) {
  59. for case let fileURL as URL in enumerator where fileURL.lastPathComponent.hasSuffix(ext) {
  60. let fileName = fileURL.lastPathComponent
  61. let ocId = fileURL.deletingLastPathComponent().lastPathComponent
  62. guard let resourceValues = try? fileURL.resourceValues(forKeys: resourceKeys),
  63. let size = resourceValues.fileSize,
  64. size > 0,
  65. let date = resourceValues.creationDate,
  66. let etag = ocIdEtag[ocId],
  67. fileName == etag + ext else { continue }
  68. files.append(FileInfo(path: fileURL, ocId: ocId, date: date))
  69. }
  70. }
  71. files.sort(by: { $0.date > $1.date })
  72. if let firstDate = files.first?.date, let lastDate = files.last?.date {
  73. print("First date: \(firstDate)")
  74. print("Last date: \(lastDate)")
  75. }
  76. cache.removeAllValues()
  77. var counter: Int = 0
  78. for file in files {
  79. counter += 1
  80. if counter > limit { break }
  81. autoreleasepool {
  82. if let image = UIImage(contentsOfFile: file.path.path) {
  83. cache.setValue(image, forKey: file.ocId)
  84. }
  85. }
  86. }
  87. let endDate = Date()
  88. let diffDate = endDate.timeIntervalSinceReferenceDate - startDate.timeIntervalSinceReferenceDate
  89. NextcloudKit.shared.nkCommonInstance.writeLog("--------- ThumbnailLRUCache image process ---------")
  90. NextcloudKit.shared.nkCommonInstance.writeLog("Counter process: \(cache.count)")
  91. NextcloudKit.shared.nkCommonInstance.writeLog("Time process: \(diffDate)")
  92. NextcloudKit.shared.nkCommonInstance.writeLog("--------- ThumbnailLRUCache image process ---------")
  93. }
  94. func getImage(ocId: String) -> UIImage? {
  95. return cache.value(forKey: ocId)
  96. }
  97. func setImage(ocId: String, image: UIImage) {
  98. cache.setValue(image, forKey: ocId)
  99. }
  100. @objc func clearCache() {
  101. cache.removeAllValues()
  102. }
  103. func getMetadatasMedia(account: String, filterClassTypeImage: Bool = false, filterClassTypeVideo: Bool = false) {
  104. guard let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) else { return }
  105. let startServerUrl = NCUtilityFileSystem.shared.getHomeServer(urlBase: account.urlBase, userId: account.userId) + account.mediaPath
  106. predicateDefault = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND (classFile == %@ OR classFile == %@) AND NOT (session CONTAINS[c] 'upload')", account.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, NKCommon.TypeClassFile.video.rawValue)
  107. if filterClassTypeImage {
  108. predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", account.account, startServerUrl, NKCommon.TypeClassFile.video.rawValue)
  109. } else if filterClassTypeVideo {
  110. predicate = NSPredicate(format: "account == %@ AND serverUrl BEGINSWITH %@ AND classFile == %@ AND NOT (session CONTAINS[c] 'upload')", account.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue)
  111. } else {
  112. predicate = predicateDefault
  113. }
  114. guard let predicate = predicate else { return }
  115. livePhoto = CCUtility.getLivePhoto()
  116. metadatas = NCManageDatabase.shared.getMetadatasMedia(predicate: predicate, livePhoto: livePhoto)
  117. switch CCUtility.getMediaSortDate() {
  118. case "date":
  119. metadatas = self.metadatas.sorted(by: {($0.date as Date) > ($1.date as Date)})
  120. case "creationDate":
  121. metadatas = self.metadatas.sorted(by: {($0.creationDate as Date) > ($1.creationDate as Date)})
  122. case "uploadDate":
  123. metadatas = self.metadatas.sorted(by: {($0.uploadDate as Date) > ($1.uploadDate as Date)})
  124. default:
  125. break
  126. }
  127. }
  128. }