Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements #3084

Merged
merged 15 commits into from
Oct 1, 2024
4 changes: 2 additions & 2 deletions Share/NCShareExtension+Files.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import NextcloudKit
extension NCShareExtension {
@objc func reloadDatasource(withLoadFolder: Bool) {
let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", session.account, serverUrl)
let metadatas = self.database.getResultsMetadatasPredicate(predicate, layoutForView: NCDBLayoutForView())
let results = self.database.getResultsMetadatasPredicate(predicate, layoutForView: NCDBLayoutForView())

self.dataSource = NCCollectionViewDataSource(metadatas: metadatas)
self.dataSource = NCCollectionViewDataSource(results: results)

if withLoadFolder {
loadFolder()
Expand Down
21 changes: 13 additions & 8 deletions iOSClient/Data/NCManageDatabase+Metadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ extension NCManageDatabase {

// MARK: - GetResult(s)Metadata

func getResultsMetadatasPredicate(_ predicate: NSPredicate, layoutForView: NCDBLayoutForView?) -> [tableMetadata] {
func getResultsMetadatasPredicate(_ predicate: NSPredicate, layoutForView: NCDBLayoutForView?) -> Results<tableMetadata>? {
do {
let realm = try Realm()
var results = realm.objects(tableMetadata.self).filter(predicate)
Expand All @@ -901,11 +901,11 @@ extension NCManageDatabase {
results = results.sorted(byKeyPath: layoutForView.sort, ascending: layoutForView.ascending).sorted(byKeyPath: "favorite", ascending: false)
}
}
return Array(results)
return results
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}
return []
return nil
}

func getResultsMetadatas(predicate: NSPredicate, sortedByKeyPath: String, ascending: Bool, arraySlice: Int) -> [tableMetadata] {
Expand Down Expand Up @@ -939,25 +939,30 @@ extension NCManageDatabase {
return nil
}

func getResultsMetadatasFromGroupfolders(session: NCSession.Session) -> [tableMetadata] {
var metadatas: [tableMetadata] = []
func getResultsMetadatasFromGroupfolders(session: NCSession.Session) -> Results<tableMetadata>? {
var ocId: [String] = []
let homeServerUrl = utilityFileSystem.getHomeServer(session: session)

do {
let realm = try Realm()
let groupfolders = realm.objects(TableGroupfolders.self).filter("account == %@", session.account).sorted(byKeyPath: "mountPoint", ascending: true)

for groupfolder in groupfolders {
let mountPoint = groupfolder.mountPoint.hasPrefix("/") ? groupfolder.mountPoint : "/" + groupfolder.mountPoint
let serverUrlFileName = homeServerUrl + mountPoint

if let directory = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", session.account, serverUrlFileName).first,
let metadata = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first {
metadatas.append(metadata)
let result = realm.objects(tableMetadata.self).filter("ocId == %@", directory.ocId).first {
ocId.append(result.ocId)
}
}

return realm.objects(tableMetadata.self).filter("ocId IN %@", ocId)
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}
return metadatas

return nil
}

func getResultsImageCacheMetadatas(predicate: NSPredicate) -> Results<tableMetadata>? {
Expand Down
4 changes: 2 additions & 2 deletions iOSClient/Favorites/NCFavorite.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class NCFavorite: NCCollectionViewCommon {
predicate = NSPredicate(format: "account == %@ AND favorite == true", session.account)
}

let metadatas = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, layoutForView: layoutForView)
let results = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: layoutForView)

super.reloadDataSource()
}
Expand Down
4 changes: 2 additions & 2 deletions iOSClient/Files/NCFiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ class NCFiles: NCCollectionViewCommon {
self.metadataFolder = database.getMetadataFolder(session: session, serverUrl: self.serverUrl)
self.richWorkspaceText = database.getTableDirectory(predicate: predicateDirectory)?.richWorkspace

let metadatas = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, layoutForView: layoutForView)
let results = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: layoutForView)

super.reloadDataSource()
}
Expand Down
8 changes: 4 additions & 4 deletions iOSClient/Groupfolders/NCGroupfolders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ class NCGroupfolders: NCCollectionViewCommon {
// MARK: - DataSource

override func reloadDataSource() {
var metadatas: [tableMetadata] = []
var results: Results<tableMetadata>?

if self.serverUrl.isEmpty {
metadatas = database.getResultsMetadatasFromGroupfolders(session: session)
results = database.getResultsMetadatasFromGroupfolders(session: session)
} else {
metadatas = self.database.getResultsMetadatasPredicate(self.defaultPredicate, layoutForView: layoutForView)
results = self.database.getResultsMetadatasPredicate(self.defaultPredicate, layoutForView: layoutForView)
}

self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: layoutForView)

super.reloadDataSource()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import Foundation
import UIKit
import NextcloudKit
import RealmSwift

extension NCCollectionViewCommon: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
Expand All @@ -40,27 +41,89 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
return self.dataSource.numberOfItemsInSection(section)
}

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let metadata = dataSource.getMetadata(indexPath: indexPath) else { return }
let existsImagePreview = utilityFileSystem.fileProviderStorageImageExists(metadata.ocId, etag: metadata.etag)
let ext = global.getSizeExtension(column: self.numberOfColumns)
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if !collectionView.indexPathsForVisibleItems.contains(indexPath), let results = self.dataSource.getResults() {
let threadSafeResults = ThreadSafeReference(to: results)

DispatchQueue.global().async {
guard let metadata = self.dataSource.getMetadata(threadSafeResults: threadSafeResults, indexPaths: [indexPath]).first else { return }

if metadata.hasPreview,
!existsImagePreview,
NCNetworking.shared.downloadThumbnailQueue.operations.filter({ ($0 as? NCMediaDownloadThumbnail)?.metadata.ocId == metadata.ocId }).isEmpty {
NCNetworking.shared.downloadThumbnailQueue.addOperation(NCCollectionViewDownloadThumbnail(metadata: metadata, collectionView: collectionView, ext: ext))
for case let operation as NCCollectionViewDownloadThumbnail in NCNetworking.shared.downloadThumbnailQueue.operations where operation.metadata.ocId == metadata.ocId {
operation.cancel()
}
}
}
}

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if !collectionView.indexPathsForVisibleItems.contains(indexPath) {
guard let metadata = self.dataSource.getMetadata(indexPath: indexPath) else { return }
for case let operation as NCCollectionViewDownloadThumbnail in NCNetworking.shared.downloadThumbnailQueue.operations where operation.metadata.ocId == metadata.ocId {
operation.cancel()
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard let results = self.dataSource.getResults() else { return }
let threadSafeResults = ThreadSafeReference(to: results)

DispatchQueue.global().async {
guard let metadata = self.dataSource.getMetadata(threadSafeResults: threadSafeResults, indexPaths: [indexPath]).first else { return }
let existsImagePreview = self.utilityFileSystem.fileProviderStorageImageExists(metadata.ocId, etag: metadata.etag)
let ext = self.global.getSizeExtension(column: self.numberOfColumns)

if metadata.hasPreview,
!existsImagePreview,
NCNetworking.shared.downloadThumbnailQueue.operations.filter({ ($0 as? NCMediaDownloadThumbnail)?.metadata.ocId == metadata.ocId }).isEmpty {
NCNetworking.shared.downloadThumbnailQueue.addOperation(NCCollectionViewDownloadThumbnail(metadata: metadata, collectionView: collectionView, ext: ext))
}
}
}

private func photoCell(cell: NCPhotoCell, indexPath: IndexPath, metadata: tableMetadata, ext: String) -> NCPhotoCell {
let width = UIScreen.main.bounds.width / CGFloat(self.numberOfColumns)

cell.ocId = metadata.ocId
cell.ocIdTransfer = metadata.ocIdTransfer

/// Image
///
if let image = NCImageCache.shared.getImageCache(ocId: metadata.ocId, etag: metadata.etag, ext: ext) {
cell.filePreviewImageView?.image = image
cell.filePreviewImageView?.contentMode = .scaleAspectFill
} else {
DispatchQueue.global(qos: .userInteractive).async {
let image = self.utility.getImage(ocId: metadata.ocId, etag: metadata.etag, ext: ext)
if let image {
self.imageCache.addImageCache(ocId: metadata.ocId, etag: metadata.etag, image: image, ext: ext, cost: indexPath.row)
DispatchQueue.main.async {
cell.filePreviewImageView?.image = image
cell.filePreviewImageView?.contentMode = .scaleAspectFill
}
} else {
DispatchQueue.main.async {
cell.filePreviewImageView?.contentMode = .scaleAspectFit
if metadata.iconName.isEmpty {
cell.filePreviewImageView?.image = NCImageCache.shared.getImageFile()
} else {
cell.filePreviewImageView?.image = self.utility.loadImage(named: metadata.iconName, useTypeIconFile: true, account: metadata.account)
}
}
}
}
}

/// Status
///
if metadata.isLivePhoto {
cell.fileStatusImage?.image = utility.loadImage(named: "livephoto", colors: isLayoutPhoto ? [.white] : [NCBrandColor.shared.iconImageColor2])
} else if metadata.isVideo {
cell.fileStatusImage?.image = utility.loadImage(named: "play.circle", colors: NCBrandColor.shared.iconImageMultiColors)
}

if width < 100 {
cell.hideButtonMore(true)
cell.hideImageStatus(true)
} else {
cell.hideButtonMore(false)
cell.hideImageStatus(false)
}

return cell
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell: NCCellProtocol & UICollectionViewCell
let permissions = NCPermissions()
Expand All @@ -83,6 +146,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
let photoCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as? NCPhotoCell)!
photoCell.photoCellDelegate = self
cell = photoCell
return self.photoCell(cell: photoCell, indexPath: indexPath, metadata: metadata, ext: ext)
} else {
let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridCell)!
gridCell.gridCellDelegate = self
Expand All @@ -108,7 +172,6 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
cell.filePreviewImageView?.contentMode = .scaleAspectFill
} else {
cell.filePreviewImageView?.contentMode = .scaleAspectFit

}

guard let metadata = self.dataSource.getMetadata(indexPath: indexPath) else { return cell }
Expand Down Expand Up @@ -176,6 +239,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {

// color folder
cell.filePreviewImageView?.image = cell.filePreviewImageView?.image?.colorizeFolder(metadata: metadata, tableDirectory: tableDirectory)

} else {

if metadata.hasPreviewBorder {
Expand Down Expand Up @@ -263,12 +327,6 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
cell.fileSharedImage?.image = imageCache.getImageCanShare()
}

/*
if appDelegate.account != metadata.account {
cell.fileSharedImage?.image = NCImageCache.images.shared
}
*/

// Button More
if metadata.lock == true {
cell.setButtonMore(image: imageCache.getImageButtonMoreLock())
Expand Down Expand Up @@ -369,6 +427,16 @@ extension NCCollectionViewCommon: UICollectionViewDataSource {
// Layout photo
if isLayoutPhoto {
let width = UIScreen.main.bounds.width / CGFloat(self.numberOfColumns)

cell.hideImageFavorite(false)
cell.hideImageLocal(false)
cell.hideImageItem(false)
cell.hideButtonMore(false)
cell.hideLabelInfo(false)
cell.hideLabelSubinfo(false)
cell.hideImageStatus(false)
cell.fileTitleLabel?.font = UIFont.systemFont(ofSize: 15)

if width < 120 {
cell.hideImageFavorite(true)
cell.hideImageLocal(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,20 @@

import Foundation
import UIKit
import RealmSwift

extension NCCollectionViewCommon: UICollectionViewDataSourcePrefetching {
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
guard !isSearchingMode, !imageCache.isLoadingCache else { return }

let ext = global.getSizeExtension(column: self.numberOfColumns)
let metadatas = self.dataSource.getMetadatas(indexPaths: indexPaths)
guard !isSearchingMode,
imageCache.allowExtensions(ext: ext),
let results = self.dataSource.getResults()
else { return }
let threadSafeResults = ThreadSafeReference(to: results)
let cost = indexPaths.first?.row ?? 0

DispatchQueue.global(qos: .userInteractive).async {
DispatchQueue.global().async {
let metadatas = self.dataSource.getMetadata(threadSafeResults: threadSafeResults, indexPaths: indexPaths)
for metadata in metadatas where metadata.isImageOrVideo {
if self.imageCache.getImageCache(ocId: metadata.ocId, etag: metadata.etag, ext: ext) == nil,
let image = self.utility.getImage(ocId: metadata.ocId, etag: metadata.etag, ext: ext) {
Expand Down
7 changes: 5 additions & 2 deletions iOSClient/Main/Collection Common/NCCollectionViewCommon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
} providers: { _, searchProviders in
self.providers = searchProviders
self.searchResults = []
self.dataSource = NCCollectionViewDataSource(metadatas: [], layoutForView: self.layoutForView, providers: self.providers, searchResults: self.searchResults)
self.dataSource = NCCollectionViewDataSource(results: nil, layoutForView: self.layoutForView, providers: self.providers, searchResults: self.searchResults)
} update: { _, _, searchResult, metadatas in
guard let metadatas, !metadatas.isEmpty, self.isSearchingMode, let searchResult else { return }
NCNetworking.shared.unifiedSearchQueue.addOperation(NCCollectionViewUnifiedSearch(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult))
Expand All @@ -1021,7 +1021,10 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
self.collectionView.reloadData()
}
guard let metadatas, error == .success, self.isSearchingMode else { return }
self.dataSource = NCCollectionViewDataSource(metadatas: metadatas, layoutForView: self.layoutForView, providers: self.providers, searchResults: self.searchResults)
let ocId = metadatas.map { $0.ocId }
let results = self.database.getResultsMetadatasPredicate(NSPredicate(format: "ocId IN %@", ocId), layoutForView: self.layoutForView)

self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: self.layoutForView, providers: self.providers, searchResults: self.searchResults)
}
}
}
Expand Down
35 changes: 33 additions & 2 deletions iOSClient/Main/Collection Common/NCCollectionViewDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,34 @@

import UIKit
import NextcloudKit
import RealmSwift

class NCCollectionViewDataSource: NSObject {
private let utilityFileSystem = NCUtilityFileSystem()
private let global = NCGlobal.shared
private var sectionsValue: [String] = []
private var providers: [NKSearchProvider]?
private var searchResults: [NKSearchResult]?
private var results: Results<tableMetadata>?
private var metadatas: [tableMetadata] = []
private var metadatasForSection: [NCMetadataForSection] = []
private var layoutForView: NCDBLayoutForView?

override init() { super.init() }

init(metadatas: [tableMetadata],
init(results: Results<tableMetadata>?,
layoutForView: NCDBLayoutForView? = nil,
providers: [NKSearchProvider]? = nil,
searchResults: [NKSearchResult]? = nil) {
super.init()

self.metadatas = metadatas
self.results = results
if let results {
self.metadatas = Array(results)
} else {
self.metadatas = []
}

self.layoutForView = layoutForView
/// unified search
self.providers = providers
Expand Down Expand Up @@ -165,6 +173,29 @@ class NCCollectionViewDataSource: NSObject {

// MARK: -

func getResults() -> Results<tableMetadata>? {
return results
}

func getMetadata(threadSafeResults: ThreadSafeReference<Results<tableMetadata>>, indexPaths: [IndexPath]) -> [tableMetadata] {
autoreleasepool {
var metadatas: [tableMetadata] = []
do {
let realm = try Realm()
if let resolvedResults = realm.resolve(threadSafeResults) {
let validMetadatas = resolvedResults.filter { !$0.isInvalidated }
for indexPath in indexPaths where indexPath.row < validMetadatas.count {
metadatas.append(tableMetadata(value: validMetadatas[indexPath.row]))
}
return metadatas
}
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}
return metadatas
}
}

func isMetadatasValid() -> Bool {
let validMetadatas = metadatas.filter { !$0.isInvalidated }

Expand Down
Loading
Loading