123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- //
- // NCImageCache.swift
- // Nextcloud
- //
- // Created by Marino Faggiana on 18/10/23.
- // Copyright © 2021 Marino Faggiana. All rights reserved.
- //
- // Author Marino Faggiana <marino.faggiana@nextcloud.com>
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
- import Foundation
- import UIKit
- import LRUCache
- import NextcloudKit
- import RealmSwift
- class NCImageCache: NSObject {
- static let shared = NCImageCache()
- private let utility = NCUtility()
- private let global = NCGlobal.shared
- private let allowExtensions = [NCGlobal.shared.previewExt256]
- private var brandElementColor: UIColor?
- public var countLimit: Int = 0
- lazy var cache: LRUCache<String, UIImage> = {
- return LRUCache<String, UIImage>(countLimit: countLimit)
- }()
- public var isLoadingCache: Bool = false
- override init() {
- super.init()
- countLimit = calculateMaxImages(percentage: 5.0, imageSizeKB: 30.0) // 5% of cache = 20
- NextcloudKit.shared.nkCommonInstance.writeLog("Counter cache image: \(countLimit)")
- NotificationCenter.default.addObserver(forName: LRUCacheMemoryWarningNotification, object: nil, queue: nil) { _ in
- self.cache.removeAllValues()
- self.countLimit = self.countLimit - 500
- if self.countLimit <= 0 { self.countLimit = 100 }
- self.cache = LRUCache<String, UIImage>(countLimit: self.countLimit)
- #if DEBUG
- NCContentPresenter().messageNotification("Cache image memory warning \(self.countLimit)", error: .success, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
- #endif
- }
- NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: nil) { _ in
- autoreleasepool {
- self.cache.removeAllValues()
- }
- }
- NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: nil) { _ in
- #if !EXTENSION
- var files: [NCFiles] = []
- var cost: Int = 0
- if let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount(),
- NCImageCache.shared.cache.count == 0 {
- let session = NCSession.shared.getSession(account: activeTableAccount.account)
- for mainTabBarController in SceneManager.shared.getControllers() {
- if let currentVC = mainTabBarController.selectedViewController as? UINavigationController,
- let file = currentVC.visibleViewController as? NCFiles {
- files.append(file)
- }
- }
- /// MEDIA
- if let metadatas = NCManageDatabase.shared.getResultsMetadatas(predicate: self.getMediaPredicate(filterLivePhotoFile: true, session: session, showOnlyImages: false, showOnlyVideos: false), sortedByKeyPath: "date", freeze: true)?.prefix(self.countLimit) {
- self.cache.removeAllValues()
- self.isLoadingCache = true
- metadatas.forEach { metadata in
- if let image = self.utility.getImage(ocId: metadata.ocId, etag: metadata.etag, ext: NCGlobal.shared.previewExt256) {
- self.addImageCache(ocId: metadata.ocId, etag: metadata.etag, image: image, ext: NCGlobal.shared.previewExt256, cost: cost)
- cost += 1
- }
- }
- self.isLoadingCache = false
- }
- /// FILE
- for file in files where !file.serverUrl.isEmpty {
- NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": file.serverUrl])
- }
- }
- #endif
- }
- }
- deinit {
- NotificationCenter.default.removeObserver(self, name: LRUCacheMemoryWarningNotification, object: nil)
- }
- func calculateMaxImages(percentage: Double, imageSizeKB: Double) -> Int {
- let totalRamBytes = Double(ProcessInfo.processInfo.physicalMemory)
- let cacheSizeBytes = totalRamBytes * (percentage / 100.0)
- let imageSizeBytes = imageSizeKB * 1024
- let maxImages = Int(cacheSizeBytes / imageSizeBytes)
- return maxImages
- }
- func allowExtensions(ext: String) -> Bool {
- return allowExtensions.contains(ext)
- }
- func addImageCache(ocId: String, etag: String, data: Data, ext: String, cost: Int) {
- guard allowExtensions.contains(ext),
- let image = UIImage(data: data) else { return }
- cache.setValue(image, forKey: ocId + etag + ext, cost: cost)
- }
- func addImageCache(ocId: String, etag: String, image: UIImage, ext: String, cost: Int) {
- guard allowExtensions.contains(ext) else { return }
- cache.setValue(image, forKey: ocId + etag + ext, cost: cost)
- }
- func getImageCache(ocId: String, etag: String, ext: String) -> UIImage? {
- return cache.value(forKey: ocId + etag + ext)
- }
- func removeImageCache(ocIdPlusEtag: String) {
- for i in 0..<allowExtensions.count {
- cache.removeValue(forKey: ocIdPlusEtag + allowExtensions[i])
- }
- }
- func removeAll() {
- cache.removeAllValues()
- }
- // MARK: - MEDIA -
- func getMediaPredicate(filterLivePhotoFile: Bool, session: NCSession.Session, showOnlyImages: Bool, showOnlyVideos: Bool) -> NSPredicate {
- guard let tableAccount = NCManageDatabase.shared.getTableAccount(predicate: NSPredicate(format: "account == %@", session.account)) else { return NSPredicate() }
- var predicate = NSPredicate()
- let startServerUrl = NCUtilityFileSystem().getHomeServer(session: session) + tableAccount.mediaPath
- var showBothPredicateMediaString = "account == %@ AND serverUrl BEGINSWITH %@ AND hasPreview == true AND (classFile == '\(NKCommon.TypeClassFile.image.rawValue)' OR classFile == '\(NKCommon.TypeClassFile.video.rawValue)') AND NOT (status IN %@)"
- var showOnlyPredicateMediaString = "account == %@ AND serverUrl BEGINSWITH %@ AND hasPreview == true AND classFile == %@ AND NOT (status IN %@)"
- if filterLivePhotoFile {
- showBothPredicateMediaString = showBothPredicateMediaString + " AND NOT (livePhotoFile != '' AND classFile == '\(NKCommon.TypeClassFile.video.rawValue)')"
- showOnlyPredicateMediaString = showOnlyPredicateMediaString + " AND NOT (livePhotoFile != '' AND classFile == '\(NKCommon.TypeClassFile.video.rawValue)')"
- }
- if showOnlyImages {
- predicate = NSPredicate(format: showOnlyPredicateMediaString, session.account, startServerUrl, NKCommon.TypeClassFile.image.rawValue, global.metadataStatusHideInView)
- } else if showOnlyVideos {
- predicate = NSPredicate(format: showOnlyPredicateMediaString, session.account, startServerUrl, NKCommon.TypeClassFile.video.rawValue, global.metadataStatusHideInView)
- } else {
- predicate = NSPredicate(format: showBothPredicateMediaString, session.account, startServerUrl, global.metadataStatusHideInView)
- }
- return predicate
- }
- // MARK: -
- func getImageFile() -> UIImage {
- return utility.loadImage(named: "doc", colors: [NCBrandColor.shared.iconImageColor2])
- }
- func getImageShared() -> UIImage {
- return utility.loadImage(named: "person.fill.badge.plus", colors: NCBrandColor.shared.iconImageMultiColors)
- }
- func getImageCanShare() -> UIImage {
- return utility.loadImage(named: "person.fill.badge.plus", colors: NCBrandColor.shared.iconImageMultiColors)
- }
- func getImageShareByLink() -> UIImage {
- return utility.loadImage(named: "link", colors: [NCBrandColor.shared.iconImageColor])
- }
- func getImageFavorite() -> UIImage {
- return utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite])
- }
- func getImageOfflineFlag() -> UIImage {
- return utility.loadImage(named: "arrow.down.circle.fill", colors: [.systemGreen])
- }
- func getImageLocal() -> UIImage {
- return utility.loadImage(named: "checkmark.circle.fill", colors: [.systemGreen])
- }
- func getImageCheckedYes() -> UIImage {
- return utility.loadImage(named: "checkmark.circle.fill", colors: [NCBrandColor.shared.iconImageColor2])
- }
- func getImageCheckedNo() -> UIImage {
- return utility.loadImage(named: "circle", colors: [NCBrandColor.shared.iconImageColor])
- }
- func getImageButtonMore() -> UIImage {
- return utility.loadImage(named: "ellipsis", colors: [NCBrandColor.shared.iconImageColor])
- }
- func getImageButtonStop() -> UIImage {
- return utility.loadImage(named: "stop.circle", colors: [NCBrandColor.shared.iconImageColor])
- }
- func getImageButtonMoreLock() -> UIImage {
- return utility.loadImage(named: "lock.fill", colors: [NCBrandColor.shared.iconImageColor])
- }
- func getFolder(account: String) -> UIImage {
- return UIImage(named: "folder")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- func getFolderEncrypted(account: String) -> UIImage {
- return UIImage(named: "folderEncrypted")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- func getFolderSharedWithMe(account: String) -> UIImage {
- return UIImage(named: "folder_shared_with_me")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- func getFolderPublic(account: String) -> UIImage {
- return UIImage(named: "folder_public")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- func getFolderGroup(account: String) -> UIImage {
- return UIImage(named: "folder_group")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- func getFolderExternal(account: String) -> UIImage {
- return UIImage(named: "folder_external")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- func getFolderAutomaticUpload(account: String) -> UIImage {
- return UIImage(named: "folderAutomaticUpload")!.image(color: NCBrandColor.shared.getElement(account: account))
- }
- }
|