From 54d2c7382b2d51697f11b300ba885aeab586c849 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Wed, 28 Jun 2023 12:11:45 +0530 Subject: [PATCH 01/21] NMC 2341 - Theming changes --- iOSClient/NCGlobal.swift | 1 + iOSClient/Trash/Cell/NCTrashGridCell.swift | 136 ++++++++++--------- iOSClient/Trash/Cell/NCTrashListCell.swift | 9 +- iOSClient/Trash/NCTrash+CollectionView.swift | 53 +++++--- iOSClient/Trash/NCTrash.swift | 18 ++- 5 files changed, 134 insertions(+), 83 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 813c75d117..357a29d2fb 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -113,6 +113,7 @@ final class NCGlobal: Sendable { // let buttonMoreMore = "more" let buttonMoreLock = "moreLock" + let buttonMoreStop = "stop" // Rich Workspace // diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index cd68b288dc..8ad7352011 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,12 +11,15 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! + @IBOutlet weak var imageStatus: UIImageView! + @IBOutlet weak var imageFavorite: UIImageView! + @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! - @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! + @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -25,6 +28,52 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return nil } set { imageItem = newValue } } + var indexPath = IndexPath() + var account = "" + var user = "" + + var namedButtonMore = "" + + var fileObjectId: String? { + get { return objectId } + set { objectId = newValue ?? "" } + } + var filePreviewImageView: UIImageView? { + get { return imageItem } + set { imageItem = newValue } + } + var fileUser: String? { + get { return user } + set { user = newValue ?? "" } + } + var fileTitleLabel: UILabel? { + get { return labelTitle } + set { labelTitle = newValue } + } + var fileInfoLabel: UILabel? { + get { return labelInfo } + set { labelInfo = newValue } + } + var fileProgressView: UIProgressView? { + get { return progressView } + set { progressView = newValue } + } + var fileSelectImage: UIImageView? { + get { return imageSelect } + set { imageSelect = newValue } + } + var fileStatusImage: UIImageView? { + get { return imageStatus } + set { imageStatus = newValue } + } + var fileLocalImage: UIImageView? { + get { return imageLocal } + set { imageLocal = newValue } + } + var fileFavoriteImage: UIImageView? { + get { return imageFavorite } + set { imageFavorite = newValue } + } override func awakeFromNib() { super.awakeFromNib() @@ -77,6 +126,10 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { // adjustsFontForContentSizeCategory: // Enables live updates when accessibility settings change. // +// progressView.tintColor = NCBrandColor.shared.brandElement +// progressView.transform = CGAffineTransform(scaleX: 1.0, y: 0.5) +// progressView.trackTintColor = .clear + labelTitle.text = "" labelTitle.font = .callout() labelTitle.adjustsFontForContentSizeCategory = true @@ -90,9 +143,9 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { labelInfo.font = .footnote() labelInfo.adjustsFontForContentSizeCategory = true - labelSubinfo.text = "" - labelSubinfo.font = .footnote() - labelSubinfo.adjustsFontForContentSizeCategory = true +// labelSubinfo.text = "" +// labelSubinfo.font = .footnote() +// labelSubinfo.adjustsFontForContentSizeCategory = true if labelExtension.isHidden { labelTitle.numberOfLines = 2 @@ -101,6 +154,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { labelTitle.numberOfLines = 1 labelTitle.lineBreakMode = .byTruncatingTail } + labelTitle.textColor = .label + labelInfo.textColor = .systemGray } override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? { @@ -111,7 +166,10 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } + fileprivate func setA11yActions() { + let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" + self.accessibilityCustomActions = [ UIAccessibilityCustomAction( name: NSLocalizedString("_more_", comment: ""), @@ -120,7 +178,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { ] } - func setButtonMore(image: UIImage) { + func setButtonMore(named: String, image: UIImage) { + namedButtonMore = named buttonMore.setImage(image, for: .normal) setA11yActions() } @@ -137,6 +196,14 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { imageVisualEffect.alpha = status ? 1 : 0 imageSelect.alpha = status ? 1 : 0 imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) +// if status { +// imageSelect.image = NCImageCache.shared.getImageCheckedYes() +// imageSelect.isHidden = false +// imageVisualEffect.isHidden = false +// } else { +// imageSelect.image = NCImageCache.shared.getImageCheckedNo() +// imageVisualEffect.isHidden = true +// } } func writeInfoDateSize(date: NSDate, size: Int64) { @@ -145,8 +212,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) - labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -154,59 +220,3 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } - -// MARK: - Grid Layout - -class NCTrashGridLayout: UICollectionViewFlowLayout { - - var heightLabelPlusButton: CGFloat = 60 - var marginLeftRight: CGFloat = 10 - var itemForLine: CGFloat = 3 - var itemWidthDefault: CGFloat = 140 - - // MARK: - View Life Cycle - - override init() { - super.init() - - sectionHeadersPinToVisibleBounds = false - - minimumInteritemSpacing = 1 - minimumLineSpacing = marginLeftRight - - self.scrollDirection = .vertical - self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override var itemSize: CGSize { - get { - if let collectionView = collectionView { - - if collectionView.frame.width < 400 { - itemForLine = 3 - } else { - itemForLine = collectionView.frame.width / itemWidthDefault - } - - let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine - let itemHeight: CGFloat = itemWidth + heightLabelPlusButton - - return CGSize(width: itemWidth, height: itemHeight) - } - - // Default fallback - return CGSize(width: itemWidthDefault, height: itemWidthDefault) - } - set { - super.itemSize = newValue - } - } - - override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { - return proposedContentOffset - } -} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 69229e3672..19d96484b6 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -31,6 +31,9 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { get { return imageStatus } set { imageStatus = newValue } } + var account = "" + var indexPath = IndexPath() + let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() @@ -57,8 +60,10 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] - imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) - imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) + imageRestore.image = utility.loadImage(named: "restore", color: NCBrandColor.shared.iconColor) + imageMore.image = UIImage(systemName: "trash") + imageMore.tintColor = NCBrandColor.shared.iconColor + imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 258e430ac4..159f01070a 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,9 +4,11 @@ import UIKit import RealmSwift +import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { @@ -16,7 +18,7 @@ extension NCTrash: UICollectionViewDelegate { selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: selectOcId) + setNavigationRightItems() return } @@ -32,7 +34,9 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + setNavigationRightItems() return datasource?.count ?? 0 } @@ -46,7 +50,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -85,9 +89,11 @@ extension NCTrash: UICollectionViewDataSource { } } + cell.account = resultTableTrash.account cell.objectId = resultTableTrash.fileId cell.setupCellUI(tableTrash: resultTableTrash, image: image) - cell.selected(selectOcId.contains(resultTableTrash.fileId), isEditMode: isEditMode, color: NCBrandColor.shared.getElement(account: session.account)) + cell.selected(selectOcId.contains(resultTableTrash.fileId), isEditMode: isEditMode, account: resultTableTrash.account) +// cell.selected(selectOcId.contains(resultTableTrash.fileId), isEditMode: isEditMode, color: NCBrandColor.shared.getElement(account: session.account)) return cell } @@ -132,18 +138,34 @@ extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionHeader { - guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFirstHeaderEmptyData", for: indexPath) as? NCSectionFirstHeaderEmptyData - else { return NCSectionFirstHeaderEmptyData() } - header.emptyImage.image = utility.loadImage(named: "trash", colors: [NCBrandColor.shared.getElement(account: session.account)]) - header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") - header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") + + guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as? NCSectionHeaderMenu + else { return UICollectionReusableView() } + + if layoutForView?.layout == NCGlobal.shared.layoutGrid { + header.setImageSwitchList() + header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "") + } else { + header.setImageSwitchGrid() + header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "") + } + + header.delegate = self + header.setStatusButtonsView(enable: !(datasource?.isEmpty ?? false)) + header.setSortedTitle(layoutForView?.titleButtonHeader ?? "") + header.setButtonsView(height: NCGlobal.shared.heightButtonsView) + header.setRichWorkspaceHeight(0) + header.setSectionHeight(0) + header.setViewTransfer(isHidden: true) + return header + } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter - else { return NCSectionFooter() } - if let datasource { - footer.setTitleLabel(setTextFooter(datasource: datasource)) - } + else { return UICollectionReusableView() } + guard let datasource else { return footer } + footer.setTitleLabel(setTextFooter(datasource: datasource)) + footer.separatorIsHidden(true) return footer } } @@ -151,12 +173,9 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - var height: Double = 0 - if let datasource, datasource.isEmpty { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) - } - return CGSize(width: collectionView.frame.width, height: height) + return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index e5d92fe482..a2e072b0ec 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -58,6 +58,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") + collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true @@ -144,6 +145,21 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat collectionView(self.collectionView, didSelectItemAt: indexPath!) } } + func tapButtonSwitch(_ sender: Any) { + if layoutForView?.layout == NCGlobal.shared.layoutGrid { + onListSelected() + } else { + onGridSelected() + } + } + + func tapButtonOrder(_ sender: Any) { + + let sortMenu = NCSortMenu() + sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) + } + + func longPressGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { } func longPressMoreGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { } From eac1ba7109949c8f81e6b4e804844212ff89cc6c Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Mon, 14 Apr 2025 16:57:15 +0530 Subject: [PATCH 02/21] NMC 2341 - NCTrashView changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 20 ++++- iOSClient/Trash/Cell/NCTrashListCell.swift | 10 ++- iOSClient/Trash/NCTrash+CollectionView.swift | 24 ++++-- iOSClient/Trash/NCTrash.swift | 78 +++++++++++++++++--- 4 files changed, 107 insertions(+), 25 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 8ad7352011..7af025eb29 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -172,7 +172,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString("_more_", comment: ""), + name: NSLocalizedString(moreName, comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] @@ -186,16 +186,19 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { + imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { + imageSelect.isHidden = true buttonMore.isHidden = false + imageVisualEffect.isHidden = true setA11yActions() } - imageVisualEffect.alpha = status ? 1 : 0 - imageSelect.alpha = status ? 1 : 0 - imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) +// imageVisualEffect.alpha = status ? 1 : 0 +// imageSelect.alpha = status ? 1 : 0 +// imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) // if status { // imageSelect.image = NCImageCache.shared.getImageCheckedYes() // imageSelect.isHidden = false @@ -204,6 +207,15 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { // imageSelect.image = NCImageCache.shared.getImageCheckedNo() // imageVisualEffect.isHidden = true // } + if status { + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + imageVisualEffect.effect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + imageVisualEffect.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray + imageSelect.image = NCImageCache.shared.getImageCheckedYes() + imageVisualEffect.isHidden = false + } else { + imageSelect.image = NCImageCache.shared.getImageCheckedNo() + } } func writeInfoDateSize(date: NSDate, size: Int64) { diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 19d96484b6..0706385488 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -60,7 +60,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] - imageRestore.image = utility.loadImage(named: "restore", color: NCBrandColor.shared.iconColor) + imageRestore.image = utility.loadImage(named: "restore", colors: [NCBrandColor.shared.iconColor]) + imageMore.image = UIImage(systemName: "trash") imageMore.tintColor = NCBrandColor.shared.iconColor @@ -137,8 +138,11 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) - blurEffectView?.backgroundColor = .lightGray + var blurEffect: UIVisualEffect? + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 159f01070a..9d1466a840 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -10,14 +10,16 @@ import Foundation extension NCTrash: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } + let resultTableTrash = datasource[indexPath.item] + guard !isEditMode else { - if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { - selectOcId.remove(at: index) + if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { + fileSelect.remove(at: index) } else { - selectOcId.append(resultTableTrash.fileId) + fileSelect.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) + tabBarSelect.update(selectOcId: fileSelect) setNavigationRightItems() return } @@ -36,8 +38,10 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + let numberOfItems = datasource.count + emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) setNavigationRightItems() - return datasource?.count ?? 0 + return numberOfItems } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -71,7 +75,7 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) + image = UIImage(named: resultTableTrash.iconName) } if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, @@ -151,7 +155,7 @@ extension NCTrash: UICollectionViewDataSource { } header.delegate = self - header.setStatusButtonsView(enable: !(datasource?.isEmpty ?? false)) + header.setStatusButtonsView(enable: !datasource.isEmpty) header.setSortedTitle(layoutForView?.titleButtonHeader ?? "") header.setButtonsView(height: NCGlobal.shared.heightButtonsView) header.setRichWorkspaceHeight(0) @@ -163,7 +167,6 @@ extension NCTrash: UICollectionViewDataSource { } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return UICollectionReusableView() } - guard let datasource else { return footer } footer.setTitleLabel(setTextFooter(datasource: datasource)) footer.separatorIsHidden(true) return footer @@ -175,8 +178,13 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + if datasource.isEmpty { + let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) + return CGSize(width: collectionView.frame.width, height: height) + } return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index a2e072b0ec..ab8adbe5a1 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -16,13 +16,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var selectOcId: [String] = [] + var fileSelect: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash + var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? @@ -30,6 +31,11 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } + + var serverUrl = "" + var selectableDataSource: [RealmSwiftObject] { datasource } + private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! + var emptyDataSet: NCEmptyDataSet? @MainActor var controller: NCMainTabBarController? { @@ -50,14 +56,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat override func viewDidLoad() { super.viewDidLoad() - navigationController?.setNavigationBarAppearance() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) + serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") - collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -69,25 +75,29 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 refreshControl.action(for: .valueChanged) { _ in Task { await self.loadListingTrash() } } + // Empty + emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) + + NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if tabBarSelect == nil { - tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) - } + appDelegate.activeViewController = self navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") + gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -102,6 +112,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat await self.reloadDataSource() await loadListingTrash() } + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) } override func viewWillDisappear(_ animated: Bool) { @@ -113,6 +124,53 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() + dataSourceTask?.cancel() + isEditMode = false + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let frame = tabBarController?.tabBar.frame { + tabBarSelect.hostingController?.view.frame = frame + } + } + + // MARK: - Layout + + @objc func changeLayout(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, + account == session.account, + serverUrl == self.serverUrl + else { return } + + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + layoutForView.layout = layoutForView.layout + self.layoutType = layoutForView.layout +// self.reloadDataSource() + collectionView.reloadData() + + switch layoutForView.layout { + case NCGlobal.shared.layoutList: + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) + case NCGlobal.shared.layoutGrid: + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) + default: + break + } + + self.collectionView.collectionViewLayout.invalidateLayout() + } + + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") + view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") } // MARK: TAP EVENT @@ -156,7 +214,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat func tapButtonOrder(_ sender: Any) { let sortMenu = NCSortMenu() - sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) + sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) } func longPressGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { } @@ -165,7 +223,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - func reloadDataSource(withQueryDB: Bool = true) async { + @objc func reloadDataSource(withQueryDB: Bool = true) async { let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() From 745010271834db4a95fcdb794a90dc53b1036f3c Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 30 Sep 2025 19:13:16 +0530 Subject: [PATCH 03/21] NMC 2341 - NCTrashView updated changes --- .../Trash/Cell/NCTrashCellProtocol.swift | 5 +- iOSClient/Trash/NCTrash+CollectionView.swift | 28 +++---- .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 ++++++++++++------ iOSClient/Trash/NCTrash.swift | 83 ++++++++++--------- iOSClient/Trash/NCTrashSelectTabBar.swift | 55 +++++------- 5 files changed, 133 insertions(+), 118 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index aee200246b..78a1af4bf0 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,12 +36,13 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) + self.imageItem.image = NCImageCache.shared.getFolder() } else { self.imageItem.image = image - self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) +// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } + self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) self.accessibilityLabel = tableTrash.trashbinFileName + ", " + (self.labelInfo?.text ?? "") if self is NCTrashGridCell { diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 9d1466a840..f285ca6497 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -8,9 +8,10 @@ import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let resultTableTrash = datasource[indexPath.item] + + guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { @@ -38,10 +39,9 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - let numberOfItems = datasource.count - emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) + emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) setNavigationRightItems() - return numberOfItems + return datasource?.count ?? 0 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -78,17 +78,13 @@ extension NCTrash: UICollectionViewDataSource { image = UIImage(named: resultTableTrash.iconName) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, - etag: resultTableTrash.fileName, - ext: NCGlobal.shared.previewExt512, - userId: session.userId, - urlBase: session.urlBase) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) } } } @@ -155,7 +151,7 @@ extension NCTrash: UICollectionViewDataSource { } header.delegate = self - header.setStatusButtonsView(enable: !datasource.isEmpty) + header.setStatusButtonsView(enable: !(datasource?.isEmpty ?? false)) header.setSortedTitle(layoutForView?.titleButtonHeader ?? "") header.setButtonsView(height: NCGlobal.shared.heightButtonsView) header.setRichWorkspaceHeight(0) @@ -167,8 +163,10 @@ extension NCTrash: UICollectionViewDataSource { } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return UICollectionReusableView() } - footer.setTitleLabel(setTextFooter(datasource: datasource)) - footer.separatorIsHidden(true) + if let datasource { + footer.setTitleLabel(setTextFooter(datasource: datasource)) + footer.separatorIsHidden(true) + } return footer } } @@ -178,7 +176,7 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - if datasource.isEmpty { + if let datasource, datasource.isEmpty { let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) return CGSize(width: collectionView.frame.width, height: height) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 53191350f6..2809c953b3 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate { +extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,51 +27,81 @@ extension NCTrash: NCTrashSelectTabBarDelegate { } func selectAll() { - guard let datasource else { return } - if !selectOcId.isEmpty, datasource.count == selectOcId.count { - selectOcId = [] + if !fileSelect.isEmpty, datasource?.count == fileSelect.count { + fileSelect = [] } else { - selectOcId = datasource.compactMap({ $0.fileId }) + fileSelect = (datasource?.compactMap({ $0.fileId }))! } - tabBarSelect.update(selectOcId: selectOcId) + tabBarSelect.update(selectOcId: fileSelect) collectionView.reloadData() } func recover() { - let ids = selectOcId.map { $0 } + fileSelect.forEach(restoreItem) setEditMode(false) - - Task { - for id in ids { - await restoreItem(with: id) - } - } } func delete() { - let ids = selectOcId.map { $0 } + let ocIds = fileSelect.map { $0 } setEditMode(false) Task { - if ids.count > 0, ids.count == datasource?.count { + if ocIds.count > 0, ocIds.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ids) + await self.deleteItems(with: ocIds) } } } func setEditMode(_ editMode: Bool) { - Task { - isEditMode = editMode - selectOcId.removeAll() - - navigationItem.hidesBackButton = editMode - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + isEditMode = editMode + fileSelect.removeAll() - collectionView.reloadData() + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + navigationItem.hidesBackButton = editMode + DispatchQueue.main.async { + self.collectionView.reloadData() + self.setNavigationRightItems() } } + + func setNavigationRightItems(enableMenu: Bool = false) { + if isEditMode { + let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} + navigationItem.rightBarButtonItems = [more] + } else { + let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } + let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) + if layoutKey == NCGlobal.shared.layoutViewFiles { + navigationItem.rightBarButtonItems = [select, notification] + } else { + navigationItem.rightBarButtonItems = [select] + } + } + guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } + navigationItem.title = titleCurrentFolder + } + + func createMenuActions() -> [NCMenuAction] { +// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } +// +// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in +// self.setEditMode(true) +// } +// +// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in +// self.onListSelected() +//// self.setNavigationRightItems() +// } +// +// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in +// self.onGridSelected() +//// self.setNavigationRightItems() +// } +// +// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) +// + return []//[select, viewStyleSubmenu] + } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index ab8adbe5a1..8b253c6bff 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,6 +4,7 @@ import UIKit import NextcloudKit +import Realm import RealmSwift class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @@ -12,6 +13,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? + var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() @@ -26,8 +28,6 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? - - @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,18 +52,22 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground + self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") +// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -75,12 +79,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 - refreshControl.action(for: .valueChanged) { _ in - Task { - await self.loadListingTrash() - } - } + refreshControl.tintColor = .gray + refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) + // Empty emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) @@ -106,22 +107,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false + setNavigationRightItems() - Task { - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - await self.reloadDataSource() - await loadListingTrash() - } + reloadDataSource() + loadListingTrash(nil) + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") - } - // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() dataSourceTask?.cancel() @@ -175,11 +172,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: TAP EVENT - func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { if !isEditMode { - Task { - await restoreItem(with: id) - } + restoreItem(with: ocId) } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -214,6 +209,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat func tapButtonOrder(_ sender: Any) { let sortMenu = NCSortMenu() +// sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) } @@ -223,28 +219,33 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) async { - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + @objc func reloadDataSource(withQueryDB: Bool = true) { + Task { + // Await async DB call off the main thread + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() - - await MainActor.run { - self.datasource = results - self.collectionView.reloadData() - - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Mon, 15 Dec 2025 12:54:00 +0530 Subject: [PATCH 04/21] NMC 2341 - NCTrashView updated changes --- iOSClient/NCGlobal.swift | 54 +++++- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 83 +++++++-- iOSClient/Trash/Cell/NCTrashListCell.swift | 16 +- iOSClient/Trash/NCTrash+CollectionView.swift | 100 ++++------ .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 +++----- iOSClient/Trash/NCTrash.swift | 175 ++++++++---------- iOSClient/Trash/NCTrashSelectTabBar.swift | 48 +++-- 8 files changed, 286 insertions(+), 273 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 357a29d2fb..ee844cb45b 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -43,13 +43,14 @@ final class NCGlobal: Sendable { // Intro selector // let introLogin: Int = 0 + let introSignup: Int = 1 let introSignUpWithProvider: Int = 1 // Avatar // let avatarSize: Int = 128 * Int(UIScreen.main.scale) let avatarSizeRounded: Int = 128 - + // Preview size // let size1024: CGSize = CGSize(width: 1024, height: 1024) @@ -115,6 +116,33 @@ final class NCGlobal: Sendable { let buttonMoreLock = "moreLock" let buttonMoreStop = "stop" + // Standard height sections header/footer + // + let heightButtonsView: CGFloat = 50 + let heightHeaderTransfer: CGFloat = 50 + let heightSection: CGFloat = 30 + let heightFooter: CGFloat = 1 + let heightFooterButton: CGFloat = 30 + let endHeightFooter: CGFloat = 85 + + + // Text - OnlyOffice - Collabora - QuickLook + // + let editorText = "text" + let editorOnlyoffice = "onlyoffice" + let editorCollabora = "collabora" + let editorQuickLook = "quicklook" + + let onlyofficeDocx = "onlyoffice_docx" + let onlyofficeXlsx = "onlyoffice_xlsx" + let onlyofficePptx = "onlyoffice_pptx" + + // Template + // + let templateDocument = "document" + let templateSpreadsheet = "spreadsheet" + let templatePresentation = "presentation" + // Rich Workspace // let fileNameRichWorkspace = "Readme.md" @@ -199,6 +227,8 @@ final class NCGlobal: Sendable { let selectorSaveAsScan = "saveAsScan" let selectorOpenDetail = "openDetail" let selectorSynchronizationOffline = "synchronizationOffline" + let selectorPrint = "print" + let selectorDeleteFile = "deleteFile" // Metadata : Status // @@ -229,7 +259,6 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] - let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -247,6 +276,8 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" + let notificationCenterDidCreateShareLink = "didCreateShareLink" + let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -254,6 +285,8 @@ final class NCGlobal: Sendable { let notificationCenterServerDidUpdate = "serverDidUpdate" // userInfo: account let notificationCenterNetworkReachability = "networkReachability" + let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -271,6 +304,7 @@ final class NCGlobal: Sendable { let notificationCenterNetworkingProcess = "networkingProcess" let notificationCenterTransferCountChanged = "transferCountChanged" + let notificationCenterFavoriteStatusChanged = "favoriteStatusChanged" // Networking Status let networkingStatusCreateFolder = "statusCreateFolder" @@ -286,7 +320,9 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" + let networkingStatusReloadAvatar = "statusReloadAvatar" + let notificationCenterUpdateIcons = "updateIcons" // TIP // @@ -369,6 +405,20 @@ final class NCGlobal: Sendable { // let taskDescriptionRetrievesProperties = "retrievesProperties" let taskDescriptionSynchronization = "synchronization" + let taskDescriptionDeleteFileOrFolder = "deleteFileOrFolder" + + // MoEngage App Version + // + let moEngageAppVersion = 854 + + // Filename Mask and Type + // + let keyFileNameMask = "fileNameMask" + let keyFileNameType = "fileNameType" + let keyFileNameAutoUploadMask = "fileNameAutoUploadMask" + let keyFileNameAutoUploadType = "fileNameAutoUploadType" + let keyFileNameOriginal = "fileNameOriginal" + let keyFileNameOriginalAutoUpload = "fileNameOriginalAutoUpload" // LOG TAG // diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 78a1af4bf0..9a2f607730 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,10 +36,9 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder() + self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) } else { self.imageItem.image = image -// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 7af025eb29..109ba8718f 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,15 +11,12 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! - @IBOutlet weak var imageStatus: UIImageView! - @IBOutlet weak var imageFavorite: UIImageView! - @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! + @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! - @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -156,6 +153,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { } labelTitle.textColor = .label labelInfo.textColor = .systemGray + labelSubinfo.text = "" } override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? { @@ -166,33 +164,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } - fileprivate func setA11yActions() { - let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" - self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString(moreName, comment: ""), + name: NSLocalizedString("_more_", comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] } - func setButtonMore(named: String, image: UIImage) { - namedButtonMore = named + func setButtonMore(image: UIImage) { buttonMore.setImage(image, for: .normal) setA11yActions() } func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { - imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { - imageSelect.isHidden = true buttonMore.isHidden = false - imageVisualEffect.isHidden = true setA11yActions() } @@ -208,13 +199,12 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { // imageVisualEffect.isHidden = true // } if status { - let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark - imageVisualEffect.effect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) - imageVisualEffect.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray imageSelect.image = NCImageCache.shared.getImageCheckedYes() + imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { - imageSelect.image = NCImageCache.shared.getImageCheckedNo() + imageSelect.isHidden = true + imageVisualEffect.isHidden = true } } @@ -224,7 +214,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -232,3 +223,59 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } + +// MARK: - Grid Layout + +class NCTrashGridLayout: UICollectionViewFlowLayout { + + var heightLabelPlusButton: CGFloat = 60 + var marginLeftRight: CGFloat = 10 + var itemForLine: CGFloat = 3 + var itemWidthDefault: CGFloat = 140 + + // MARK: - View Life Cycle + + override init() { + super.init() + + sectionHeadersPinToVisibleBounds = false + + minimumInteritemSpacing = 1 + minimumLineSpacing = marginLeftRight + + self.scrollDirection = .vertical + self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var itemSize: CGSize { + get { + if let collectionView = collectionView { + + if collectionView.frame.width < 400 { + itemForLine = 3 + } else { + itemForLine = collectionView.frame.width / itemWidthDefault + } + + let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine + let itemHeight: CGFloat = itemWidth + heightLabelPlusButton + + return CGSize(width: itemWidth, height: itemHeight) + } + + // Default fallback + return CGSize(width: itemWidthDefault, height: itemWidthDefault) + } + set { + super.itemSize = newValue + } + } + + override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { + return proposedContentOffset + } +} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 0706385488..c3ea397cbe 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,8 +32,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" - var indexPath = IndexPath() - let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() @@ -60,11 +58,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] - imageRestore.image = utility.loadImage(named: "restore", colors: [NCBrandColor.shared.iconColor]) - - imageMore.image = UIImage(systemName: "trash") - imageMore.tintColor = NCBrandColor.shared.iconColor - + imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) + imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true @@ -138,11 +133,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - var blurEffect: UIVisualEffect? - let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark - blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) - blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray + blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) + blurEffectView?.backgroundColor = .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index f285ca6497..629127acef 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,24 +4,19 @@ import UIKit import RealmSwift -import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } - guard !isEditMode else { - if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { - fileSelect.remove(at: index) + if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { + selectOcId.remove(at: index) } else { - fileSelect.append(resultTableTrash.fileId) + selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: fileSelect) - setNavigationRightItems() + tabBarSelect.update(selectOcId: selectOcId) return } @@ -37,10 +32,7 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) - setNavigationRightItems() return datasource?.count ?? 0 } @@ -54,11 +46,10 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } - guard let resultTableTrash = datasource?[indexPath.item] else { return cell } let contextMenu = NCContextMenuTrash(objectId: resultTableTrash.fileId, trashController: self) @@ -75,16 +66,20 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = UIImage(named: resultTableTrash.iconName) + image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, + etag: resultTableTrash.fileName, + ext: NCGlobal.shared.previewExt512, + userId: session.userId, + urlBase: session.urlBase) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) } } } @@ -97,32 +92,22 @@ extension NCTrash: UICollectionViewDataSource { return cell } - - func setTextFooter(datasource: [tableTrash]) -> String { - var folders: Int = 0, foldersText = "" - var files: Int = 0, filesText = "" - var size: Int64 = 0 + + func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { + var foldersText = "" + var filesText = "" var text = "" - for record: tableTrash in datasource { - if record.directory { - folders += 1 - } else { - files += 1 - size += record.size - } - } - - if folders > 1 { - foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") - } else if folders == 1 { + if directories > 1 { + foldersText = "\(directories) " + NSLocalizedString("_folders_", comment: "") + } else if directories == 1 { foldersText = "1 " + NSLocalizedString("_folder_", comment: "") } if files > 1 { - filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } else if files == 1 { - filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } if foldersText.isEmpty { @@ -130,42 +115,25 @@ extension NCTrash: UICollectionViewDataSource { } else if filesText.isEmpty { text = foldersText } else { - text = foldersText + ", " + filesText + text = foldersText + " • " + filesText } - return text } func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if kind == UICollectionView.elementKindSectionHeader { - - guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as? NCSectionHeaderMenu - else { return UICollectionReusableView() } - - if layoutForView?.layout == NCGlobal.shared.layoutGrid { - header.setImageSwitchList() - header.buttonSwitch.accessibilityLabel = NSLocalizedString("_list_view_", comment: "") - } else { - header.setImageSwitchGrid() - header.buttonSwitch.accessibilityLabel = NSLocalizedString("_grid_view_", comment: "") - } - - header.delegate = self - header.setStatusButtonsView(enable: !(datasource?.isEmpty ?? false)) - header.setSortedTitle(layoutForView?.titleButtonHeader ?? "") - header.setButtonsView(height: NCGlobal.shared.heightButtonsView) - header.setRichWorkspaceHeight(0) - header.setSectionHeight(0) - header.setViewTransfer(isHidden: true) - + guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFirstHeaderEmptyData", for: indexPath) as? NCSectionFirstHeaderEmptyData + else { return NCSectionFirstHeaderEmptyData() } + header.emptyImage.image = utility.loadImage(named: "trashIcon", colors: [NCBrandColor.shared.getElement(account: session.account)]) + header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") + header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header - } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter - else { return UICollectionReusableView() } + else { return NCSectionFooter() } if let datasource { - footer.setTitleLabel(setTextFooter(datasource: datasource)) - footer.separatorIsHidden(true) + let info = self.getFooterInformation(datasource: datasource) + footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) } return footer } @@ -174,15 +142,13 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + var height: Double = 0 if let datasource, datasource.isEmpty { - let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) - return CGSize(width: collectionView.frame.width, height: height) + height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) } - return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) + return CGSize(width: collectionView.frame.width, height: height) } - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 2809c953b3..53191350f6 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { +extension NCTrash: NCTrashSelectTabBarDelegate { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,81 +27,51 @@ extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { } func selectAll() { - if !fileSelect.isEmpty, datasource?.count == fileSelect.count { - fileSelect = [] + guard let datasource else { return } + if !selectOcId.isEmpty, datasource.count == selectOcId.count { + selectOcId = [] } else { - fileSelect = (datasource?.compactMap({ $0.fileId }))! + selectOcId = datasource.compactMap({ $0.fileId }) } - tabBarSelect.update(selectOcId: fileSelect) + tabBarSelect.update(selectOcId: selectOcId) collectionView.reloadData() } func recover() { - fileSelect.forEach(restoreItem) + let ids = selectOcId.map { $0 } setEditMode(false) + + Task { + for id in ids { + await restoreItem(with: id) + } + } } func delete() { - let ocIds = fileSelect.map { $0 } + let ids = selectOcId.map { $0 } setEditMode(false) Task { - if ocIds.count > 0, ocIds.count == datasource?.count { + if ids.count > 0, ids.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ocIds) + await self.deleteItems(with: ids) } } } func setEditMode(_ editMode: Bool) { - isEditMode = editMode - fileSelect.removeAll() + Task { + isEditMode = editMode + selectOcId.removeAll() - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - navigationItem.hidesBackButton = editMode - DispatchQueue.main.async { - self.collectionView.reloadData() - self.setNavigationRightItems() - } - } - - func setNavigationRightItems(enableMenu: Bool = false) { - if isEditMode { - let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} - navigationItem.rightBarButtonItems = [more] - } else { - let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } - let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) - if layoutKey == NCGlobal.shared.layoutViewFiles { - navigationItem.rightBarButtonItems = [select, notification] - } else { - navigationItem.rightBarButtonItems = [select] - } + navigationItem.hidesBackButton = editMode + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + + collectionView.reloadData() } - guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } - navigationItem.title = titleCurrentFolder - } - - func createMenuActions() -> [NCMenuAction] { -// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } -// -// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in -// self.setEditMode(true) -// } -// -// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in -// self.onListSelected() -//// self.setNavigationRightItems() -// } -// -// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in -// self.onGridSelected() -//// self.setNavigationRightItems() -// } -// -// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) -// - return []//[select, viewStyleSubmenu] } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 8b253c6bff..81c7cf3271 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,30 +4,29 @@ import UIKit import NextcloudKit -import Realm import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? - var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var fileSelect: [String] = [] + var selectOcId: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash - var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? + + @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,23 +51,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } - // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - - tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) - serverUrl = utilityFileSystem.getHomeServer(session: session) + navigationController?.setNavigationBarAppearance() view.backgroundColor = .systemBackground - self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") -// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") - collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") + collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true @@ -79,26 +73,25 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray - refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) - - // Empty - emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) - - NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) + refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.action(for: .valueChanged) { _ in + Task { + await self.loadListingTrash() + } + } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - appDelegate.activeViewController = self + if tabBarSelect == nil { + tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) + } navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") - gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -107,74 +100,32 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false - setNavigationRightItems() - - reloadDataSource() - loadListingTrash(nil) - - AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + Task { + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + await self.reloadDataSource() + await loadListingTrash() + } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - // Cancel Queue & Retrieves Properties - NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() - dataSourceTask?.cancel() - isEditMode = false - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - if let frame = tabBarController?.tabBar.frame { - tabBarSelect.hostingController?.view.frame = frame - } - } - - // MARK: - Layout - - @objc func changeLayout(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, - account == session.account, - serverUrl == self.serverUrl - else { return } - - self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) - layoutForView.layout = layoutForView.layout - self.layoutType = layoutForView.layout -// self.reloadDataSource() - collectionView.reloadData() - - switch layoutForView.layout { - case NCGlobal.shared.layoutList: - self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) - case NCGlobal.shared.layoutGrid: - self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) - default: - break + Task { + await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") } - self.collectionView.collectionViewLayout.invalidateLayout() - } - - // MARK: - Empty - - func emptyDataSetView(_ view: NCEmptyView) { - view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) - view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") - view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") + // Cancel Queue & Retrieves Properties + NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() } // MARK: TAP EVENT - func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { if !isEditMode { - restoreItem(with: ocId) + Task { + await restoreItem(with: id) + } } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -219,33 +170,35 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) { - Task { - // Await async DB call off the main thread - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + func reloadDataSource(withQueryDB: Bool = true) async { + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() - // Switch back to main thread for UI updates - await MainActor.run { - self.datasource = results - self.collectionView.reloadData() - setNavigationRightItems() -// (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. (directories: Int, files: Int, size: Int64) { + let validMetadatas = datasource.filter { !$0.isInvalidated } + let directories = validMetadatas.filter({ $0.directory == true}) + let files = validMetadatas.filter({ $0.directory == false}) + + var size: Int64 = 0 + + directories.forEach { metadata in + size += metadata.size + } + + files.forEach { metadata in + size += metadata.size + } + + return (directories.count, files.count, size) + } } diff --git a/iOSClient/Trash/NCTrashSelectTabBar.swift b/iOSClient/Trash/NCTrashSelectTabBar.swift index 159f2bdbf8..f4bb726dc8 100644 --- a/iOSClient/Trash/NCTrashSelectTabBar.swift +++ b/iOSClient/Trash/NCTrashSelectTabBar.swift @@ -13,31 +13,46 @@ protocol NCTrashSelectTabBarDelegate: AnyObject { } class NCTrashSelectTabBar: ObservableObject { - var tabBarController: UITabBarController? + var controller: UITabBarController? var hostingController: UIViewController? open weak var delegate: NCTrashSelectTabBarDelegate? @Published var isSelectedEmpty = true - init(tabBarController: UITabBarController? = nil, delegate: NCTrashSelectTabBarDelegate? = nil) { + init(controller: UITabBarController? = nil, viewController: UIViewController, delegate: NCTrashSelectTabBarDelegate? = nil) { + guard let controller else { + return + } let rootView = NCTrashSelectTabBarView(tabBarSelect: self) + let bottomAreaInsets: CGFloat = controller.tabBar.safeAreaInsets.bottom == 0 ? 34 : 0 + let height = controller.tabBar.frame.height + bottomAreaInsets hostingController = UIHostingController(rootView: rootView) + guard let hostingController else { + return + } - self.tabBarController = tabBarController + self.controller = controller self.delegate = delegate - guard let tabBarController, let hostingController else { return } - - tabBarController.view.addSubview(hostingController.view) - - hostingController.view.frame = tabBarController.tabBar.frame - hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + hostingController.view.translatesAutoresizingMaskIntoConstraints = false hostingController.view.backgroundColor = .clear hostingController.view.isHidden = true + + viewController.view.addSubview(hostingController.view) + + NSLayoutConstraint.activate([ + hostingController.view.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor), + hostingController.view.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor), + hostingController.view.bottomAnchor.constraint(equalTo: viewController.view.bottomAnchor), + hostingController.view.heightAnchor.constraint(equalToConstant: height) + ]) } func show() { - guard let tabBarController, let hostingController else { return } + guard let controller, + let hostingController else { + return + } if #available(iOS 18.0, *) { controller.setTabBarHidden(true, animated: true) @@ -57,7 +72,10 @@ class NCTrashSelectTabBar: ObservableObject { } func hide() { - guard let tabBarController, let hostingController else { return } + guard let controller, + let hostingController else { + return + } hostingController.view.isHidden = true @@ -95,7 +113,7 @@ struct NCTrashSelectTabBarView: View { .font(Font.system(.body).weight(.light)) .imageScale(sizeClass == .compact ? .medium : .large) } -// .tint(Color(NCBrandColor.shared.iconImageColor)) + .tint(Color(NCBrandColor.shared.iconImageColor)) .frame(maxWidth: .infinity) .disabled(tabBarSelect.isSelectedEmpty) @@ -105,7 +123,7 @@ struct NCTrashSelectTabBarView: View { Image(systemName: "trash") .font(.icon()) } -// .tint(.red) + .tint(.red) .frame(maxWidth: .infinity) .disabled(tabBarSelect.isSelectedEmpty) @@ -115,7 +133,7 @@ struct NCTrashSelectTabBarView: View { Image(systemName: "checkmark") .font(.icon()) } -// .tint(Color(NCBrandColor.shared.iconImageColor)) + .tint(Color(NCBrandColor.shared.iconImageColor)) .frame(maxWidth: .infinity) } } @@ -126,5 +144,5 @@ struct NCTrashSelectTabBarView: View { } #Preview { - NCTrashSelectTabBarView(tabBarSelect: NCTrashSelectTabBar()) + NCTrashSelectTabBarView(tabBarSelect: NCTrashSelectTabBar(viewController: UIViewController())) } From 8d80fa89cfdacaa8f466825e7925b858e3330f52 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Thu, 9 Apr 2026 17:10:48 +0530 Subject: [PATCH 05/21] NMC 2341 - NCTrashView updated changes with 10.3.0 version --- iOSClient/NCGlobal.swift | 25 ++++++++--- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 20 --------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 43 ++++++++++++++++++- iOSClient/Trash/NCTrash.swift | 1 + 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index ee844cb45b..6d78016391 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -50,7 +50,7 @@ final class NCGlobal: Sendable { // let avatarSize: Int = 128 * Int(UIScreen.main.scale) let avatarSizeRounded: Int = 128 - + // Preview size // let size1024: CGSize = CGSize(width: 1024, height: 1024) @@ -104,6 +104,7 @@ final class NCGlobal: Sendable { let layoutViewOffline = "LayoutOffline" let layoutViewFavorite = "LayoutFavorite" let layoutViewFiles = "LayoutFiles" + let layoutViewTransfers = "LayoutTransfers" let layoutViewRecent = "LayoutRecent" let layoutViewShares = "LayoutShares" let layoutViewShareExtension = "LayoutShareExtension" @@ -125,7 +126,6 @@ final class NCGlobal: Sendable { let heightFooterButton: CGFloat = 30 let endHeightFooter: CGFloat = 85 - // Text - OnlyOffice - Collabora - QuickLook // let editorText = "text" @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,6 +259,7 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] + let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -276,16 +277,22 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" - let notificationCenterDidCreateShareLink = "didCreateShareLink" - let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" let notificationCenterCheckUserDelaultErrorDone = "checkUserDelaultErrorDone" // userInfo: account, controller let notificationCenterServerDidUpdate = "serverDidUpdate" // userInfo: account let notificationCenterNetworkReachability = "networkReachability" + let notificationCenterDidCreateShareLink = "didCreateShareLink" + let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error + let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) + let notificationCenterMoveFile = "moveFile" // userInfo: [ocId], [indexPath], error + let notificationCenterCopyFile = "copyFile" // userInfo: [ocId], [indexPath], error let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl + let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists + let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -293,6 +300,7 @@ final class NCGlobal: Sendable { let notificationCenterOpenMediaDetail = "openMediaDetail" // userInfo: ocId let notificationCenterDismissScanDocument = "dismissScanDocument" + let notificationCenterDismissUploadAssets = "dismissUploadAssets" let notificationCenterEnableSwipeGesture = "enableSwipeGesture" let notificationCenterDisableSwipeGesture = "disableSwipeGesture" @@ -320,7 +328,6 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" - let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" @@ -419,7 +426,7 @@ final class NCGlobal: Sendable { let keyFileNameAutoUploadType = "fileNameAutoUploadType" let keyFileNameOriginal = "fileNameOriginal" let keyFileNameOriginalAutoUpload = "fileNameOriginalAutoUpload" - + // LOG TAG // let logTagTask = "BGT" @@ -438,6 +445,10 @@ final class NCGlobal: Sendable { // let udMigrationMultiDomains = "migrationMultiDomains" let udLastVersion = "lastVersion" + + // Album + // + let selectedTabIndexAlbum: Int = 3 } /** diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 9a2f607730..78a1af4bf0 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,9 +36,10 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) + self.imageItem.image = NCImageCache.shared.getFolder() } else { self.imageItem.image = image +// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 109ba8718f..8d9988efab 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -51,26 +51,6 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } - var fileProgressView: UIProgressView? { - get { return progressView } - set { progressView = newValue } - } - var fileSelectImage: UIImageView? { - get { return imageSelect } - set { imageSelect = newValue } - } - var fileStatusImage: UIImageView? { - get { return imageStatus } - set { imageStatus = newValue } - } - var fileLocalImage: UIImageView? { - get { return imageLocal } - set { imageLocal = newValue } - } - var fileFavoriteImage: UIImageView? { - get { return imageFavorite } - set { imageFavorite = newValue } - } override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index c3ea397cbe..d8436da989 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -58,6 +58,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] +// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) +// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 629127acef..ca3d3467e8 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -92,6 +92,44 @@ extension NCTrash: UICollectionViewDataSource { return cell } + + func setTextFooter(datasource: [tableTrash]) -> String { + var folders: Int = 0, foldersText = "" + var files: Int = 0, filesText = "" + var size: Int64 = 0 + var text = "" + + for record: tableTrash in datasource { + if record.directory { + folders += 1 + } else { + files += 1 + size += record.size + } + } + + if folders > 1 { + foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") + } else if folders == 1 { + foldersText = "1 " + NSLocalizedString("_folder_", comment: "") + } + + if files > 1 { + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } else if files == 1 { + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } + + if foldersText.isEmpty { + text = filesText + } else if filesText.isEmpty { + text = foldersText + } else { + text = foldersText + ", " + filesText + } + + return text + } func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { var foldersText = "" @@ -132,8 +170,9 @@ extension NCTrash: UICollectionViewDataSource { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } if let datasource { - let info = self.getFooterInformation(datasource: datasource) - footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) + footer.setTitleLabel(setTextFooter(datasource: datasource)) +// let info = self.getFooterInformation(datasource: datasource) +// footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) } return footer } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 81c7cf3271..28c3ad9c26 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -106,6 +106,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat await self.reloadDataSource() await loadListingTrash() } + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) } override func viewWillDisappear(_ animated: Bool) { From 57b489c9943c5936d04823469869a8d08324ada3 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Wed, 28 Jun 2023 12:11:45 +0530 Subject: [PATCH 06/21] NMC 2341 - Theming changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 100 ++++++------------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 16 +-- iOSClient/Trash/NCTrash.swift | 3 +- 4 files changed, 44 insertions(+), 77 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 8d9988efab..f9f05065e7 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,12 +11,15 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! + @IBOutlet weak var imageStatus: UIImageView! + @IBOutlet weak var imageFavorite: UIImageView! + @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! - @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! + @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -51,6 +54,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } + var fileProgressView: UIProgressView? { + get { return progressView } + set { progressView = newValue } + } + var fileSelectImage: UIImageView? { + get { return imageSelect } + set { imageSelect = newValue } + } + var fileStatusImage: UIImageView? { + get { return imageStatus } + set { imageStatus = newValue } + } + var fileLocalImage: UIImageView? { + get { return imageLocal } + set { imageLocal = newValue } + } + var fileFavoriteImage: UIImageView? { + get { return imageFavorite } + set { imageFavorite = newValue } + } override func awakeFromNib() { super.awakeFromNib() @@ -144,7 +167,10 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } + fileprivate func setA11yActions() { + let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" + self.accessibilityCustomActions = [ UIAccessibilityCustomAction( name: NSLocalizedString("_more_", comment: ""), @@ -153,7 +179,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { ] } - func setButtonMore(image: UIImage) { + func setButtonMore(named: String, image: UIImage) { + namedButtonMore = named buttonMore.setImage(image, for: .normal) setA11yActions() } @@ -170,16 +197,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { // imageVisualEffect.alpha = status ? 1 : 0 // imageSelect.alpha = status ? 1 : 0 // imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) -// if status { -// imageSelect.image = NCImageCache.shared.getImageCheckedYes() -// imageSelect.isHidden = false -// imageVisualEffect.isHidden = false -// } else { -// imageSelect.image = NCImageCache.shared.getImageCheckedNo() -// imageVisualEffect.isHidden = true -// } if status { - imageSelect.image = NCImageCache.shared.getImageCheckedYes() + imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { @@ -194,8 +213,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) - labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -203,59 +221,3 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } - -// MARK: - Grid Layout - -class NCTrashGridLayout: UICollectionViewFlowLayout { - - var heightLabelPlusButton: CGFloat = 60 - var marginLeftRight: CGFloat = 10 - var itemForLine: CGFloat = 3 - var itemWidthDefault: CGFloat = 140 - - // MARK: - View Life Cycle - - override init() { - super.init() - - sectionHeadersPinToVisibleBounds = false - - minimumInteritemSpacing = 1 - minimumLineSpacing = marginLeftRight - - self.scrollDirection = .vertical - self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override var itemSize: CGSize { - get { - if let collectionView = collectionView { - - if collectionView.frame.width < 400 { - itemForLine = 3 - } else { - itemForLine = collectionView.frame.width / itemWidthDefault - } - - let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine - let itemHeight: CGFloat = itemWidth + heightLabelPlusButton - - return CGSize(width: itemWidth, height: itemHeight) - } - - // Default fallback - return CGSize(width: itemWidthDefault, height: itemWidthDefault) - } - set { - super.itemSize = newValue - } - } - - override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { - return proposedContentOffset - } -} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index d8436da989..ab5f23c1d7 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,6 +32,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" + var indexPath = IndexPath() + let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index ca3d3467e8..d2eee4a4da 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,9 +4,11 @@ import UIKit import RealmSwift +import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { @@ -16,7 +18,7 @@ extension NCTrash: UICollectionViewDelegate { selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: selectOcId) + setNavigationRightItems() return } @@ -32,7 +34,9 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + setNavigationRightItems() return datasource?.count ?? 0 } @@ -46,7 +50,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -166,6 +170,7 @@ extension NCTrash: UICollectionViewDataSource { header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header + } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } @@ -181,12 +186,9 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - var height: Double = 0 - if let datasource, datasource.isEmpty { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) - } - return CGSize(width: collectionView.frame.width, height: height) + return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 28c3ad9c26..2a7cb9399a 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -63,6 +63,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") + collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true From 4c7c0f6f0da2ca261e07e25d1ff7fad4b9439b48 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Mon, 14 Apr 2025 16:57:15 +0530 Subject: [PATCH 07/21] NMC 2341 - NCTrashView changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 5 +- iOSClient/Trash/Cell/NCTrashListCell.swift | 7 +- iOSClient/Trash/NCTrash+CollectionView.swift | 21 ++++-- iOSClient/Trash/NCTrash.swift | 70 +++++++++++++++++--- 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index f9f05065e7..e3fb5c5e76 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -173,7 +173,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString("_more_", comment: ""), + name: NSLocalizedString(moreName, comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] @@ -187,10 +187,13 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { + imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { + imageSelect.isHidden = true buttonMore.isHidden = false + imageVisualEffect.isHidden = true setA11yActions() } diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index ab5f23c1d7..741961a136 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -137,8 +137,11 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) - blurEffectView?.backgroundColor = .lightGray + var blurEffect: UIVisualEffect? + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index d2eee4a4da..e64e977dbf 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -10,14 +10,16 @@ import Foundation extension NCTrash: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } + let resultTableTrash = datasource[indexPath.item] + guard !isEditMode else { - if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { - selectOcId.remove(at: index) + if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { + fileSelect.remove(at: index) } else { - selectOcId.append(resultTableTrash.fileId) + fileSelect.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) + tabBarSelect.update(selectOcId: fileSelect) setNavigationRightItems() return } @@ -36,8 +38,10 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + let numberOfItems = datasource.count + emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) setNavigationRightItems() - return datasource?.count ?? 0 + return numberOfItems } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -70,7 +74,7 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) + image = UIImage(named: resultTableTrash.iconName) } if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, @@ -188,8 +192,13 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + if datasource.isEmpty { + let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) + return CGSize(width: collectionView.frame.width, height: height) + } return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 2a7cb9399a..fb6a3c8e5a 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -16,13 +16,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var selectOcId: [String] = [] + var fileSelect: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash + var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? @@ -55,14 +56,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat override func viewDidLoad() { super.viewDidLoad() - navigationController?.setNavigationBarAppearance() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) + serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") - collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -74,25 +75,29 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 refreshControl.action(for: .valueChanged) { _ in Task { await self.loadListingTrash() } } + // Empty + emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) + + NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if tabBarSelect == nil { - tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) - } + appDelegate.activeViewController = self navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") + gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -119,6 +124,53 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() + dataSourceTask?.cancel() + isEditMode = false + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let frame = tabBarController?.tabBar.frame { + tabBarSelect.hostingController?.view.frame = frame + } + } + + // MARK: - Layout + + @objc func changeLayout(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, + account == session.account, + serverUrl == self.serverUrl + else { return } + + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + layoutForView.layout = layoutForView.layout + self.layoutType = layoutForView.layout +// self.reloadDataSource() + collectionView.reloadData() + + switch layoutForView.layout { + case NCGlobal.shared.layoutList: + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) + case NCGlobal.shared.layoutGrid: + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) + default: + break + } + + self.collectionView.collectionViewLayout.invalidateLayout() + } + + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") + view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") } // MARK: TAP EVENT @@ -172,7 +224,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - func reloadDataSource(withQueryDB: Bool = true) async { + @objc func reloadDataSource(withQueryDB: Bool = true) async { let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() From ce96a2e80c04147102287bef5234f02810b0f4a7 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 30 Sep 2025 19:13:16 +0530 Subject: [PATCH 08/21] NMC 2341 - NCTrashView updated changes --- iOSClient/Trash/NCTrash+CollectionView.swift | 20 ++--- .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 +++++++++++++------ iOSClient/Trash/NCTrash.swift | 74 ++++++++--------- iOSClient/Trash/NCTrashSelectTabBar.swift | 48 ++++------- 4 files changed, 112 insertions(+), 110 deletions(-) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index e64e977dbf..8deffb9ba7 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -8,9 +8,10 @@ import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let resultTableTrash = datasource[indexPath.item] + + guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { @@ -38,10 +39,9 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - let numberOfItems = datasource.count - emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) + emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) setNavigationRightItems() - return numberOfItems + return datasource?.count ?? 0 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -77,17 +77,13 @@ extension NCTrash: UICollectionViewDataSource { image = UIImage(named: resultTableTrash.iconName) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, - etag: resultTableTrash.fileName, - ext: NCGlobal.shared.previewExt512, - userId: session.userId, - urlBase: session.urlBase) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) } } } @@ -192,7 +188,7 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - if datasource.isEmpty { + if let datasource, datasource.isEmpty { let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) return CGSize(width: collectionView.frame.width, height: height) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 53191350f6..2809c953b3 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate { +extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,51 +27,81 @@ extension NCTrash: NCTrashSelectTabBarDelegate { } func selectAll() { - guard let datasource else { return } - if !selectOcId.isEmpty, datasource.count == selectOcId.count { - selectOcId = [] + if !fileSelect.isEmpty, datasource?.count == fileSelect.count { + fileSelect = [] } else { - selectOcId = datasource.compactMap({ $0.fileId }) + fileSelect = (datasource?.compactMap({ $0.fileId }))! } - tabBarSelect.update(selectOcId: selectOcId) + tabBarSelect.update(selectOcId: fileSelect) collectionView.reloadData() } func recover() { - let ids = selectOcId.map { $0 } + fileSelect.forEach(restoreItem) setEditMode(false) - - Task { - for id in ids { - await restoreItem(with: id) - } - } } func delete() { - let ids = selectOcId.map { $0 } + let ocIds = fileSelect.map { $0 } setEditMode(false) Task { - if ids.count > 0, ids.count == datasource?.count { + if ocIds.count > 0, ocIds.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ids) + await self.deleteItems(with: ocIds) } } } func setEditMode(_ editMode: Bool) { - Task { - isEditMode = editMode - selectOcId.removeAll() - - navigationItem.hidesBackButton = editMode - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + isEditMode = editMode + fileSelect.removeAll() - collectionView.reloadData() + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + navigationItem.hidesBackButton = editMode + DispatchQueue.main.async { + self.collectionView.reloadData() + self.setNavigationRightItems() } } + + func setNavigationRightItems(enableMenu: Bool = false) { + if isEditMode { + let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} + navigationItem.rightBarButtonItems = [more] + } else { + let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } + let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) + if layoutKey == NCGlobal.shared.layoutViewFiles { + navigationItem.rightBarButtonItems = [select, notification] + } else { + navigationItem.rightBarButtonItems = [select] + } + } + guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } + navigationItem.title = titleCurrentFolder + } + + func createMenuActions() -> [NCMenuAction] { +// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } +// +// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in +// self.setEditMode(true) +// } +// +// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in +// self.onListSelected() +//// self.setNavigationRightItems() +// } +// +// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in +// self.onGridSelected() +//// self.setNavigationRightItems() +// } +// +// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) +// + return []//[select, viewStyleSubmenu] + } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index fb6a3c8e5a..050cae1606 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,6 +4,7 @@ import UIKit import NextcloudKit +import Realm import RealmSwift class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @@ -12,6 +13,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? + var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() @@ -26,8 +28,6 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? - - @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,18 +52,22 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground + self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") +// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -75,12 +79,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 - refreshControl.action(for: .valueChanged) { _ in - Task { - await self.loadListingTrash() - } - } + refreshControl.tintColor = .gray + refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) + // Empty emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) @@ -106,22 +107,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false + setNavigationRightItems() - Task { - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - await self.reloadDataSource() - await loadListingTrash() - } + reloadDataSource() + loadListingTrash(nil) + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") - } - // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() dataSourceTask?.cancel() @@ -175,11 +172,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: TAP EVENT - func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { if !isEditMode { - Task { - await restoreItem(with: id) - } + restoreItem(with: ocId) } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -224,8 +219,10 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) async { - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + @objc func reloadDataSource(withQueryDB: Bool = true) { + Task { + // Await async DB call off the main thread + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() // // Switch back to main thread for UI updates @@ -236,23 +233,20 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat //// (self.navigationController as? NCMainNavigationController)?.updateRightMenu() // await (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - await MainActor.run { - self.datasource = results - self.collectionView.reloadData() - - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Mon, 15 Dec 2025 12:54:00 +0530 Subject: [PATCH 09/21] NMC 2341 - NCTrashView updated changes --- iOSClient/NCGlobal.swift | 8 +- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 75 +++++++-- iOSClient/Trash/Cell/NCTrashListCell.swift | 11 +- iOSClient/Trash/NCTrash+CollectionView.swift | 68 +++------ .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 +++------- iOSClient/Trash/NCTrash.swift | 142 ++++++------------ iOSClient/Trash/NCTrashSelectTabBar.swift | 48 ++++-- 8 files changed, 200 insertions(+), 235 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 6d78016391..7cc4bc93b1 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,7 +259,6 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] - let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -277,6 +276,8 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" + let notificationCenterDidCreateShareLink = "didCreateShareLink" + let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -294,6 +295,8 @@ final class NCGlobal: Sendable { let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource + let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -328,6 +331,7 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" + let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 78a1af4bf0..9a2f607730 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,10 +36,9 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder() + self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) } else { self.imageItem.image = image -// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index e3fb5c5e76..16edfc5e43 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,15 +11,12 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! - @IBOutlet weak var imageStatus: UIImageView! - @IBOutlet weak var imageFavorite: UIImageView! - @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! + @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! - @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -167,33 +164,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } - fileprivate func setA11yActions() { - let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" - self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString(moreName, comment: ""), + name: NSLocalizedString("_more_", comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] } - func setButtonMore(named: String, image: UIImage) { - namedButtonMore = named + func setButtonMore(image: UIImage) { buttonMore.setImage(image, for: .normal) setA11yActions() } func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { - imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { - imageSelect.isHidden = true buttonMore.isHidden = false - imageVisualEffect.isHidden = true setA11yActions() } @@ -216,7 +206,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -224,3 +215,59 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } + +// MARK: - Grid Layout + +class NCTrashGridLayout: UICollectionViewFlowLayout { + + var heightLabelPlusButton: CGFloat = 60 + var marginLeftRight: CGFloat = 10 + var itemForLine: CGFloat = 3 + var itemWidthDefault: CGFloat = 140 + + // MARK: - View Life Cycle + + override init() { + super.init() + + sectionHeadersPinToVisibleBounds = false + + minimumInteritemSpacing = 1 + minimumLineSpacing = marginLeftRight + + self.scrollDirection = .vertical + self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var itemSize: CGSize { + get { + if let collectionView = collectionView { + + if collectionView.frame.width < 400 { + itemForLine = 3 + } else { + itemForLine = collectionView.frame.width / itemWidthDefault + } + + let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine + let itemHeight: CGFloat = itemWidth + heightLabelPlusButton + + return CGSize(width: itemWidth, height: itemHeight) + } + + // Default fallback + return CGSize(width: itemWidthDefault, height: itemWidthDefault) + } + set { + super.itemSize = newValue + } + } + + override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { + return proposedContentOffset + } +} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 741961a136..c3ea397cbe 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,8 +32,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" - var indexPath = IndexPath() - let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() @@ -60,8 +58,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] -// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) -// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 @@ -137,11 +133,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - var blurEffect: UIVisualEffect? - let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark - blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) - blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray + blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) + blurEffectView?.backgroundColor = .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 8deffb9ba7..e7edc695db 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,24 +4,19 @@ import UIKit import RealmSwift -import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } - guard !isEditMode else { - if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { - fileSelect.remove(at: index) + if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { + selectOcId.remove(at: index) } else { - fileSelect.append(resultTableTrash.fileId) + selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: fileSelect) - setNavigationRightItems() + tabBarSelect.update(selectOcId: selectOcId) return } @@ -37,10 +32,7 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) - setNavigationRightItems() return datasource?.count ?? 0 } @@ -54,7 +46,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -74,16 +66,20 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = UIImage(named: resultTableTrash.iconName) + image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, + etag: resultTableTrash.fileName, + ext: NCGlobal.shared.previewExt512, + userId: session.userId, + urlBase: session.urlBase) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) } } } @@ -96,32 +92,22 @@ extension NCTrash: UICollectionViewDataSource { return cell } - - func setTextFooter(datasource: [tableTrash]) -> String { - var folders: Int = 0, foldersText = "" - var files: Int = 0, filesText = "" - var size: Int64 = 0 + + func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { + var foldersText = "" + var filesText = "" var text = "" - for record: tableTrash in datasource { - if record.directory { - folders += 1 - } else { - files += 1 - size += record.size - } - } - - if folders > 1 { - foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") - } else if folders == 1 { + if directories > 1 { + foldersText = "\(directories) " + NSLocalizedString("_folders_", comment: "") + } else if directories == 1 { foldersText = "1 " + NSLocalizedString("_folder_", comment: "") } if files > 1 { - filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } else if files == 1 { - filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } if foldersText.isEmpty { @@ -129,9 +115,8 @@ extension NCTrash: UICollectionViewDataSource { } else if filesText.isEmpty { text = foldersText } else { - text = foldersText + ", " + filesText + text = foldersText + " • " + filesText } - return text } @@ -170,7 +155,6 @@ extension NCTrash: UICollectionViewDataSource { header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header - } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } @@ -186,15 +170,13 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + var height: Double = 0 if let datasource, datasource.isEmpty { - let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) - return CGSize(width: collectionView.frame.width, height: height) + height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) } - return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) + return CGSize(width: collectionView.frame.width, height: height) } - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 2809c953b3..53191350f6 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { +extension NCTrash: NCTrashSelectTabBarDelegate { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,81 +27,51 @@ extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { } func selectAll() { - if !fileSelect.isEmpty, datasource?.count == fileSelect.count { - fileSelect = [] + guard let datasource else { return } + if !selectOcId.isEmpty, datasource.count == selectOcId.count { + selectOcId = [] } else { - fileSelect = (datasource?.compactMap({ $0.fileId }))! + selectOcId = datasource.compactMap({ $0.fileId }) } - tabBarSelect.update(selectOcId: fileSelect) + tabBarSelect.update(selectOcId: selectOcId) collectionView.reloadData() } func recover() { - fileSelect.forEach(restoreItem) + let ids = selectOcId.map { $0 } setEditMode(false) + + Task { + for id in ids { + await restoreItem(with: id) + } + } } func delete() { - let ocIds = fileSelect.map { $0 } + let ids = selectOcId.map { $0 } setEditMode(false) Task { - if ocIds.count > 0, ocIds.count == datasource?.count { + if ids.count > 0, ids.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ocIds) + await self.deleteItems(with: ids) } } } func setEditMode(_ editMode: Bool) { - isEditMode = editMode - fileSelect.removeAll() + Task { + isEditMode = editMode + selectOcId.removeAll() - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - navigationItem.hidesBackButton = editMode - DispatchQueue.main.async { - self.collectionView.reloadData() - self.setNavigationRightItems() - } - } - - func setNavigationRightItems(enableMenu: Bool = false) { - if isEditMode { - let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} - navigationItem.rightBarButtonItems = [more] - } else { - let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } - let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) - if layoutKey == NCGlobal.shared.layoutViewFiles { - navigationItem.rightBarButtonItems = [select, notification] - } else { - navigationItem.rightBarButtonItems = [select] - } + navigationItem.hidesBackButton = editMode + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + + collectionView.reloadData() } - guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } - navigationItem.title = titleCurrentFolder - } - - func createMenuActions() -> [NCMenuAction] { -// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } -// -// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in -// self.setEditMode(true) -// } -// -// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in -// self.onListSelected() -//// self.setNavigationRightItems() -// } -// -// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in -// self.onGridSelected() -//// self.setNavigationRightItems() -// } -// -// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) -// - return []//[select, viewStyleSubmenu] } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 050cae1606..81c7cf3271 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,30 +4,29 @@ import UIKit import NextcloudKit -import Realm import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? - var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var fileSelect: [String] = [] + var selectOcId: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash - var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? + + @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,23 +51,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } - // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - - tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) - serverUrl = utilityFileSystem.getHomeServer(session: session) + navigationController?.setNavigationBarAppearance() view.backgroundColor = .systemBackground - self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") -// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") - collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") + collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true @@ -79,26 +73,25 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray - refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) - - // Empty - emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) - - NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) + refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.action(for: .valueChanged) { _ in + Task { + await self.loadListingTrash() + } + } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - appDelegate.activeViewController = self + if tabBarSelect == nil { + tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) + } navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") - gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -107,74 +100,32 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false - setNavigationRightItems() - - reloadDataSource() - loadListingTrash(nil) - - AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + Task { + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + await self.reloadDataSource() + await loadListingTrash() + } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - // Cancel Queue & Retrieves Properties - NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() - dataSourceTask?.cancel() - isEditMode = false - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - if let frame = tabBarController?.tabBar.frame { - tabBarSelect.hostingController?.view.frame = frame - } - } - - // MARK: - Layout - - @objc func changeLayout(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, - account == session.account, - serverUrl == self.serverUrl - else { return } - - self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) - layoutForView.layout = layoutForView.layout - self.layoutType = layoutForView.layout -// self.reloadDataSource() - collectionView.reloadData() - - switch layoutForView.layout { - case NCGlobal.shared.layoutList: - self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) - case NCGlobal.shared.layoutGrid: - self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) - default: - break + Task { + await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") } - self.collectionView.collectionViewLayout.invalidateLayout() - } - - // MARK: - Empty - - func emptyDataSetView(_ view: NCEmptyView) { - view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) - view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") - view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") + // Cancel Queue & Retrieves Properties + NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() } // MARK: TAP EVENT - func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { if !isEditMode { - restoreItem(with: ocId) + Task { + await restoreItem(with: id) + } } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -219,10 +170,8 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) { - Task { - // Await async DB call off the main thread - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + func reloadDataSource(withQueryDB: Bool = true) async { + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() // // Switch back to main thread for UI updates @@ -233,20 +182,23 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat //// (self.navigationController as? NCMainNavigationController)?.updateRightMenu() // await (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Thu, 9 Apr 2026 17:10:48 +0530 Subject: [PATCH 10/21] NMC 2341 - NCTrashView updated changes with 10.3.0 version --- iOSClient/NCGlobal.swift | 13 +++++-- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 20 ---------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 38 +++++++++++++++++++ iOSClient/Trash/NCTrash.swift | 1 + 6 files changed, 52 insertions(+), 25 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 7cc4bc93b1..4f456f09f0 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,6 +259,7 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] + let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -276,8 +277,6 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" - let notificationCenterDidCreateShareLink = "didCreateShareLink" - let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -295,7 +294,14 @@ final class NCGlobal: Sendable { let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource + let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error + let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) + let notificationCenterMoveFile = "moveFile" // userInfo: [ocId], [indexPath], error + let notificationCenterCopyFile = "copyFile" // userInfo: [ocId], [indexPath], error let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl + let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists + let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -331,7 +337,6 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" - let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 9a2f607730..78a1af4bf0 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,9 +36,10 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) + self.imageItem.image = NCImageCache.shared.getFolder() } else { self.imageItem.image = image +// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 16edfc5e43..2e9e324cb6 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -51,26 +51,6 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } - var fileProgressView: UIProgressView? { - get { return progressView } - set { progressView = newValue } - } - var fileSelectImage: UIImageView? { - get { return imageSelect } - set { imageSelect = newValue } - } - var fileStatusImage: UIImageView? { - get { return imageStatus } - set { imageStatus = newValue } - } - var fileLocalImage: UIImageView? { - get { return imageLocal } - set { imageLocal = newValue } - } - var fileFavoriteImage: UIImageView? { - get { return imageFavorite } - set { imageFavorite = newValue } - } override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index c3ea397cbe..d8436da989 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -58,6 +58,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] +// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) +// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index e7edc695db..e4162265c7 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -92,6 +92,44 @@ extension NCTrash: UICollectionViewDataSource { return cell } + + func setTextFooter(datasource: [tableTrash]) -> String { + var folders: Int = 0, foldersText = "" + var files: Int = 0, filesText = "" + var size: Int64 = 0 + var text = "" + + for record: tableTrash in datasource { + if record.directory { + folders += 1 + } else { + files += 1 + size += record.size + } + } + + if folders > 1 { + foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") + } else if folders == 1 { + foldersText = "1 " + NSLocalizedString("_folder_", comment: "") + } + + if files > 1 { + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } else if files == 1 { + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } + + if foldersText.isEmpty { + text = filesText + } else if filesText.isEmpty { + text = foldersText + } else { + text = foldersText + ", " + filesText + } + + return text + } func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { var foldersText = "" diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 81c7cf3271..28c3ad9c26 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -106,6 +106,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat await self.reloadDataSource() await loadListingTrash() } + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) } override func viewWillDisappear(_ animated: Bool) { From ec6aad6e89ab8d5a1bc12d7888bba0b22aadf8f7 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Wed, 28 Jun 2023 12:11:45 +0530 Subject: [PATCH 11/21] NMC 2341 - Theming changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 90 +++++++------------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 16 ++-- iOSClient/Trash/NCTrash.swift | 3 +- 4 files changed, 43 insertions(+), 68 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 2e9e324cb6..f9f05065e7 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,12 +11,15 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! + @IBOutlet weak var imageStatus: UIImageView! + @IBOutlet weak var imageFavorite: UIImageView! + @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! - @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! + @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -51,6 +54,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } + var fileProgressView: UIProgressView? { + get { return progressView } + set { progressView = newValue } + } + var fileSelectImage: UIImageView? { + get { return imageSelect } + set { imageSelect = newValue } + } + var fileStatusImage: UIImageView? { + get { return imageStatus } + set { imageStatus = newValue } + } + var fileLocalImage: UIImageView? { + get { return imageLocal } + set { imageLocal = newValue } + } + var fileFavoriteImage: UIImageView? { + get { return imageFavorite } + set { imageFavorite = newValue } + } override func awakeFromNib() { super.awakeFromNib() @@ -144,7 +167,10 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } + fileprivate func setA11yActions() { + let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" + self.accessibilityCustomActions = [ UIAccessibilityCustomAction( name: NSLocalizedString("_more_", comment: ""), @@ -153,7 +179,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { ] } - func setButtonMore(image: UIImage) { + func setButtonMore(named: String, image: UIImage) { + namedButtonMore = named buttonMore.setImage(image, for: .normal) setA11yActions() } @@ -186,8 +213,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) - labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -195,59 +221,3 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } - -// MARK: - Grid Layout - -class NCTrashGridLayout: UICollectionViewFlowLayout { - - var heightLabelPlusButton: CGFloat = 60 - var marginLeftRight: CGFloat = 10 - var itemForLine: CGFloat = 3 - var itemWidthDefault: CGFloat = 140 - - // MARK: - View Life Cycle - - override init() { - super.init() - - sectionHeadersPinToVisibleBounds = false - - minimumInteritemSpacing = 1 - minimumLineSpacing = marginLeftRight - - self.scrollDirection = .vertical - self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override var itemSize: CGSize { - get { - if let collectionView = collectionView { - - if collectionView.frame.width < 400 { - itemForLine = 3 - } else { - itemForLine = collectionView.frame.width / itemWidthDefault - } - - let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine - let itemHeight: CGFloat = itemWidth + heightLabelPlusButton - - return CGSize(width: itemWidth, height: itemHeight) - } - - // Default fallback - return CGSize(width: itemWidthDefault, height: itemWidthDefault) - } - set { - super.itemSize = newValue - } - } - - override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { - return proposedContentOffset - } -} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index d8436da989..ab5f23c1d7 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,6 +32,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" + var indexPath = IndexPath() + let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index e4162265c7..6854032463 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,9 +4,11 @@ import UIKit import RealmSwift +import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { @@ -16,7 +18,7 @@ extension NCTrash: UICollectionViewDelegate { selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: selectOcId) + setNavigationRightItems() return } @@ -32,7 +34,9 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + setNavigationRightItems() return datasource?.count ?? 0 } @@ -46,7 +50,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -193,6 +197,7 @@ extension NCTrash: UICollectionViewDataSource { header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header + } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } @@ -208,12 +213,9 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - var height: Double = 0 - if let datasource, datasource.isEmpty { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) - } - return CGSize(width: collectionView.frame.width, height: height) + return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 28c3ad9c26..2a7cb9399a 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -63,6 +63,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") + collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true From 83b19d1e0a16bfe2a53eb4396a2721d6d180e33b Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Mon, 14 Apr 2025 16:57:15 +0530 Subject: [PATCH 12/21] NMC 2341 - NCTrashView changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 5 +- iOSClient/Trash/Cell/NCTrashListCell.swift | 9 +-- iOSClient/Trash/NCTrash+CollectionView.swift | 21 ++++-- iOSClient/Trash/NCTrash.swift | 71 +++++++++++++++++--- 4 files changed, 85 insertions(+), 21 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index f9f05065e7..e3fb5c5e76 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -173,7 +173,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString("_more_", comment: ""), + name: NSLocalizedString(moreName, comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] @@ -187,10 +187,13 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { + imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { + imageSelect.isHidden = true buttonMore.isHidden = false + imageVisualEffect.isHidden = true setA11yActions() } diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index ab5f23c1d7..ee54201829 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -60,8 +60,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] -// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) -// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 @@ -137,8 +135,11 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) - blurEffectView?.backgroundColor = .lightGray + var blurEffect: UIVisualEffect? + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 6854032463..623d5c82ac 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -10,14 +10,16 @@ import Foundation extension NCTrash: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } + let resultTableTrash = datasource[indexPath.item] + guard !isEditMode else { - if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { - selectOcId.remove(at: index) + if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { + fileSelect.remove(at: index) } else { - selectOcId.append(resultTableTrash.fileId) + fileSelect.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) + tabBarSelect.update(selectOcId: fileSelect) setNavigationRightItems() return } @@ -36,8 +38,10 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + let numberOfItems = datasource.count + emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) setNavigationRightItems() - return datasource?.count ?? 0 + return numberOfItems } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -70,7 +74,7 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) + image = UIImage(named: resultTableTrash.iconName) } if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, @@ -215,8 +219,13 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + if datasource.isEmpty { + let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) + return CGSize(width: collectionView.frame.width, height: height) + } return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 2a7cb9399a..2e516de500 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -16,13 +16,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var selectOcId: [String] = [] + var fileSelect: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash + var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? @@ -55,14 +56,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat override func viewDidLoad() { super.viewDidLoad() - navigationController?.setNavigationBarAppearance() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) + serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") - collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -74,25 +75,29 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 refreshControl.action(for: .valueChanged) { _ in Task { await self.loadListingTrash() } } + // Empty + emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) + + NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if tabBarSelect == nil { - tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) - } + appDelegate.activeViewController = self navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") + gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -119,6 +124,53 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() + dataSourceTask?.cancel() + isEditMode = false + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let frame = tabBarController?.tabBar.frame { + tabBarSelect.hostingController?.view.frame = frame + } + } + + // MARK: - Layout + + @objc func changeLayout(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, + account == session.account, + serverUrl == self.serverUrl + else { return } + + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + layoutForView.layout = layoutForView.layout + self.layoutType = layoutForView.layout +// self.reloadDataSource() + collectionView.reloadData() + + switch layoutForView.layout { + case NCGlobal.shared.layoutList: + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) + case NCGlobal.shared.layoutGrid: + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) + default: + break + } + + self.collectionView.collectionViewLayout.invalidateLayout() + } + + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") + view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") } // MARK: TAP EVENT @@ -162,7 +214,6 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat func tapButtonOrder(_ sender: Any) { let sortMenu = NCSortMenu() -// sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) } @@ -172,7 +223,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - func reloadDataSource(withQueryDB: Bool = true) async { + @objc func reloadDataSource(withQueryDB: Bool = true) async { let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() From f8b695d9c0493ab71bc477b37833a122564daf44 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 30 Sep 2025 19:13:16 +0530 Subject: [PATCH 13/21] NMC 2341 - NCTrashView updated changes --- iOSClient/Trash/NCTrash+CollectionView.swift | 20 ++--- .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 ++++++++++++------ iOSClient/Trash/NCTrash.swift | 83 ++++++++----------- iOSClient/Trash/NCTrashSelectTabBar.swift | 48 ++++------- 4 files changed, 113 insertions(+), 118 deletions(-) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 623d5c82ac..f58f616bcb 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -8,9 +8,10 @@ import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let resultTableTrash = datasource[indexPath.item] + + guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { @@ -38,10 +39,9 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - let numberOfItems = datasource.count - emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) + emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) setNavigationRightItems() - return numberOfItems + return datasource?.count ?? 0 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -77,17 +77,13 @@ extension NCTrash: UICollectionViewDataSource { image = UIImage(named: resultTableTrash.iconName) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, - etag: resultTableTrash.fileName, - ext: NCGlobal.shared.previewExt512, - userId: session.userId, - urlBase: session.urlBase) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) } } } @@ -219,7 +215,7 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - if datasource.isEmpty { + if let datasource, datasource.isEmpty { let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) return CGSize(width: collectionView.frame.width, height: height) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 53191350f6..2809c953b3 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate { +extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,51 +27,81 @@ extension NCTrash: NCTrashSelectTabBarDelegate { } func selectAll() { - guard let datasource else { return } - if !selectOcId.isEmpty, datasource.count == selectOcId.count { - selectOcId = [] + if !fileSelect.isEmpty, datasource?.count == fileSelect.count { + fileSelect = [] } else { - selectOcId = datasource.compactMap({ $0.fileId }) + fileSelect = (datasource?.compactMap({ $0.fileId }))! } - tabBarSelect.update(selectOcId: selectOcId) + tabBarSelect.update(selectOcId: fileSelect) collectionView.reloadData() } func recover() { - let ids = selectOcId.map { $0 } + fileSelect.forEach(restoreItem) setEditMode(false) - - Task { - for id in ids { - await restoreItem(with: id) - } - } } func delete() { - let ids = selectOcId.map { $0 } + let ocIds = fileSelect.map { $0 } setEditMode(false) Task { - if ids.count > 0, ids.count == datasource?.count { + if ocIds.count > 0, ocIds.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ids) + await self.deleteItems(with: ocIds) } } } func setEditMode(_ editMode: Bool) { - Task { - isEditMode = editMode - selectOcId.removeAll() - - navigationItem.hidesBackButton = editMode - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + isEditMode = editMode + fileSelect.removeAll() - collectionView.reloadData() + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + navigationItem.hidesBackButton = editMode + DispatchQueue.main.async { + self.collectionView.reloadData() + self.setNavigationRightItems() } } + + func setNavigationRightItems(enableMenu: Bool = false) { + if isEditMode { + let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} + navigationItem.rightBarButtonItems = [more] + } else { + let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } + let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) + if layoutKey == NCGlobal.shared.layoutViewFiles { + navigationItem.rightBarButtonItems = [select, notification] + } else { + navigationItem.rightBarButtonItems = [select] + } + } + guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } + navigationItem.title = titleCurrentFolder + } + + func createMenuActions() -> [NCMenuAction] { +// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } +// +// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in +// self.setEditMode(true) +// } +// +// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in +// self.onListSelected() +//// self.setNavigationRightItems() +// } +// +// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in +// self.onGridSelected() +//// self.setNavigationRightItems() +// } +// +// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) +// + return []//[select, viewStyleSubmenu] + } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 2e516de500..dd797f22fa 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,6 +4,7 @@ import UIKit import NextcloudKit +import Realm import RealmSwift class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @@ -12,6 +13,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? + var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() @@ -26,8 +28,6 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? - - @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,18 +52,22 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground + self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") +// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -75,12 +79,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 - refreshControl.action(for: .valueChanged) { _ in - Task { - await self.loadListingTrash() - } - } + refreshControl.tintColor = .gray + refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) + // Empty emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) @@ -106,22 +107,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false + setNavigationRightItems() - Task { - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - await self.reloadDataSource() - await loadListingTrash() - } + reloadDataSource() + loadListingTrash(nil) + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") - } - // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() dataSourceTask?.cancel() @@ -175,11 +172,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: TAP EVENT - func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { if !isEditMode { - Task { - await restoreItem(with: id) - } + restoreItem(with: ocId) } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -214,6 +209,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat func tapButtonOrder(_ sender: Any) { let sortMenu = NCSortMenu() +// sortMenu.toggleMenu(viewController: self, account: appDelegate.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) sortMenu.toggleMenu(viewController: self, account: session.account, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) } @@ -223,35 +219,26 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) async { - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + @objc func reloadDataSource(withQueryDB: Bool = true) { + Task { + // Await async DB call off the main thread + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() -// // Switch back to main thread for UI updates -// await MainActor.run { -// self.datasource = results -// self.collectionView.reloadData() -// setNavigationRightItems() -//// (self.navigationController as? NCMainNavigationController)?.updateRightMenu() -// await (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - - await MainActor.run { - self.datasource = results - self.collectionView.reloadData() - - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Mon, 15 Dec 2025 12:54:00 +0530 Subject: [PATCH 14/21] NMC 2341 - NCTrashView updated changes --- iOSClient/NCGlobal.swift | 12 +- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 77 +++++++-- iOSClient/Trash/Cell/NCTrashListCell.swift | 9 +- iOSClient/Trash/NCTrash+CollectionView.swift | 73 ++++----- .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 +++------- iOSClient/Trash/NCTrash.swift | 150 +++++++----------- iOSClient/Trash/NCTrashSelectTabBar.swift | 48 ++++-- 8 files changed, 213 insertions(+), 239 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 4f456f09f0..8d2beaea12 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -50,7 +50,7 @@ final class NCGlobal: Sendable { // let avatarSize: Int = 128 * Int(UIScreen.main.scale) let avatarSizeRounded: Int = 128 - + // Preview size // let size1024: CGSize = CGSize(width: 1024, height: 1024) @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,7 +259,6 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] - let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -277,6 +276,8 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" + let notificationCenterDidCreateShareLink = "didCreateShareLink" + let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -303,6 +304,8 @@ final class NCGlobal: Sendable { let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource + let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -337,6 +340,7 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" + let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" @@ -435,7 +439,7 @@ final class NCGlobal: Sendable { let keyFileNameAutoUploadType = "fileNameAutoUploadType" let keyFileNameOriginal = "fileNameOriginal" let keyFileNameOriginalAutoUpload = "fileNameOriginalAutoUpload" - + // LOG TAG // let logTagTask = "BGT" diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 78a1af4bf0..9a2f607730 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,10 +36,9 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder() + self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) } else { self.imageItem.image = image -// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index e3fb5c5e76..2cc1f8fdbc 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,15 +11,12 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! - @IBOutlet weak var imageStatus: UIImageView! - @IBOutlet weak var imageFavorite: UIImageView! - @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! + @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! - @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -167,33 +164,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } - fileprivate func setA11yActions() { - let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" - self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString(moreName, comment: ""), + name: NSLocalizedString("_more_", comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] } - func setButtonMore(named: String, image: UIImage) { - namedButtonMore = named + func setButtonMore(image: UIImage) { buttonMore.setImage(image, for: .normal) setA11yActions() } func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { - imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { - imageSelect.isHidden = true buttonMore.isHidden = false - imageVisualEffect.isHidden = true setA11yActions() } @@ -201,7 +191,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { // imageSelect.alpha = status ? 1 : 0 // imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) if status { - imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) + imageSelect.image = NCImageCache.shared.getImageCheckedYes() imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { @@ -216,7 +206,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -224,3 +215,59 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } + +// MARK: - Grid Layout + +class NCTrashGridLayout: UICollectionViewFlowLayout { + + var heightLabelPlusButton: CGFloat = 60 + var marginLeftRight: CGFloat = 10 + var itemForLine: CGFloat = 3 + var itemWidthDefault: CGFloat = 140 + + // MARK: - View Life Cycle + + override init() { + super.init() + + sectionHeadersPinToVisibleBounds = false + + minimumInteritemSpacing = 1 + minimumLineSpacing = marginLeftRight + + self.scrollDirection = .vertical + self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var itemSize: CGSize { + get { + if let collectionView = collectionView { + + if collectionView.frame.width < 400 { + itemForLine = 3 + } else { + itemForLine = collectionView.frame.width / itemWidthDefault + } + + let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine + let itemHeight: CGFloat = itemWidth + heightLabelPlusButton + + return CGSize(width: itemWidth, height: itemHeight) + } + + // Default fallback + return CGSize(width: itemWidthDefault, height: itemWidthDefault) + } + set { + super.itemSize = newValue + } + } + + override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { + return proposedContentOffset + } +} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index ee54201829..c3ea397cbe 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,8 +32,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" - var indexPath = IndexPath() - let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() @@ -135,11 +133,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - var blurEffect: UIVisualEffect? - let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark - blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) - blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray + blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) + blurEffectView?.backgroundColor = .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index f58f616bcb..5c6f68dea9 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,24 +4,19 @@ import UIKit import RealmSwift -import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } - guard !isEditMode else { - if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { - fileSelect.remove(at: index) + if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { + selectOcId.remove(at: index) } else { - fileSelect.append(resultTableTrash.fileId) + selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: fileSelect) - setNavigationRightItems() + tabBarSelect.update(selectOcId: selectOcId) return } @@ -37,10 +32,7 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) - setNavigationRightItems() return datasource?.count ?? 0 } @@ -54,7 +46,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -74,16 +66,20 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = UIImage(named: resultTableTrash.iconName) + image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, + etag: resultTableTrash.fileName, + ext: NCGlobal.shared.previewExt512, + userId: session.userId, + urlBase: session.urlBase) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) } } } @@ -96,32 +92,22 @@ extension NCTrash: UICollectionViewDataSource { return cell } - - func setTextFooter(datasource: [tableTrash]) -> String { - var folders: Int = 0, foldersText = "" - var files: Int = 0, filesText = "" - var size: Int64 = 0 + + func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { + var foldersText = "" + var filesText = "" var text = "" - for record: tableTrash in datasource { - if record.directory { - folders += 1 - } else { - files += 1 - size += record.size - } - } - - if folders > 1 { - foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") - } else if folders == 1 { + if directories > 1 { + foldersText = "\(directories) " + NSLocalizedString("_folders_", comment: "") + } else if directories == 1 { foldersText = "1 " + NSLocalizedString("_folder_", comment: "") } if files > 1 { - filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } else if files == 1 { - filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } if foldersText.isEmpty { @@ -129,9 +115,8 @@ extension NCTrash: UICollectionViewDataSource { } else if filesText.isEmpty { text = foldersText } else { - text = foldersText + ", " + filesText + text = foldersText + " • " + filesText } - return text } @@ -197,14 +182,12 @@ extension NCTrash: UICollectionViewDataSource { header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header - } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } if let datasource { - footer.setTitleLabel(setTextFooter(datasource: datasource)) -// let info = self.getFooterInformation(datasource: datasource) -// footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) + let info = self.getFooterInformation(datasource: datasource) + footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) } return footer } @@ -213,15 +196,13 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + var height: Double = 0 if let datasource, datasource.isEmpty { - let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) - return CGSize(width: collectionView.frame.width, height: height) + height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) } - return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) + return CGSize(width: collectionView.frame.width, height: height) } - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 2809c953b3..53191350f6 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { +extension NCTrash: NCTrashSelectTabBarDelegate { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,81 +27,51 @@ extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { } func selectAll() { - if !fileSelect.isEmpty, datasource?.count == fileSelect.count { - fileSelect = [] + guard let datasource else { return } + if !selectOcId.isEmpty, datasource.count == selectOcId.count { + selectOcId = [] } else { - fileSelect = (datasource?.compactMap({ $0.fileId }))! + selectOcId = datasource.compactMap({ $0.fileId }) } - tabBarSelect.update(selectOcId: fileSelect) + tabBarSelect.update(selectOcId: selectOcId) collectionView.reloadData() } func recover() { - fileSelect.forEach(restoreItem) + let ids = selectOcId.map { $0 } setEditMode(false) + + Task { + for id in ids { + await restoreItem(with: id) + } + } } func delete() { - let ocIds = fileSelect.map { $0 } + let ids = selectOcId.map { $0 } setEditMode(false) Task { - if ocIds.count > 0, ocIds.count == datasource?.count { + if ids.count > 0, ids.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ocIds) + await self.deleteItems(with: ids) } } } func setEditMode(_ editMode: Bool) { - isEditMode = editMode - fileSelect.removeAll() + Task { + isEditMode = editMode + selectOcId.removeAll() - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - navigationItem.hidesBackButton = editMode - DispatchQueue.main.async { - self.collectionView.reloadData() - self.setNavigationRightItems() - } - } - - func setNavigationRightItems(enableMenu: Bool = false) { - if isEditMode { - let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} - navigationItem.rightBarButtonItems = [more] - } else { - let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } - let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) - if layoutKey == NCGlobal.shared.layoutViewFiles { - navigationItem.rightBarButtonItems = [select, notification] - } else { - navigationItem.rightBarButtonItems = [select] - } + navigationItem.hidesBackButton = editMode + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + + collectionView.reloadData() } - guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } - navigationItem.title = titleCurrentFolder - } - - func createMenuActions() -> [NCMenuAction] { -// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } -// -// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in -// self.setEditMode(true) -// } -// -// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in -// self.onListSelected() -//// self.setNavigationRightItems() -// } -// -// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in -// self.onGridSelected() -//// self.setNavigationRightItems() -// } -// -// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) -// - return []//[select, viewStyleSubmenu] } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index dd797f22fa..81c7cf3271 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,30 +4,29 @@ import UIKit import NextcloudKit -import Realm import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? - var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var fileSelect: [String] = [] + var selectOcId: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash - var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? + + @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,23 +51,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } - // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - - tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) - serverUrl = utilityFileSystem.getHomeServer(session: session) + navigationController?.setNavigationBarAppearance() view.backgroundColor = .systemBackground - self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") -// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") - collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") + collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true @@ -79,26 +73,25 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray - refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) - - // Empty - emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) - - NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) + refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.action(for: .valueChanged) { _ in + Task { + await self.loadListingTrash() + } + } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - appDelegate.activeViewController = self + if tabBarSelect == nil { + tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) + } navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") - gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -107,74 +100,32 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false - setNavigationRightItems() - - reloadDataSource() - loadListingTrash(nil) - - AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + Task { + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + await self.reloadDataSource() + await loadListingTrash() + } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - // Cancel Queue & Retrieves Properties - NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() - dataSourceTask?.cancel() - isEditMode = false - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - if let frame = tabBarController?.tabBar.frame { - tabBarSelect.hostingController?.view.frame = frame - } - } - - // MARK: - Layout - - @objc func changeLayout(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, - account == session.account, - serverUrl == self.serverUrl - else { return } - - self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) - layoutForView.layout = layoutForView.layout - self.layoutType = layoutForView.layout -// self.reloadDataSource() - collectionView.reloadData() - - switch layoutForView.layout { - case NCGlobal.shared.layoutList: - self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) - case NCGlobal.shared.layoutGrid: - self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) - default: - break + Task { + await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") } - self.collectionView.collectionViewLayout.invalidateLayout() - } - - // MARK: - Empty - - func emptyDataSetView(_ view: NCEmptyView) { - view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) - view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") - view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") + // Cancel Queue & Retrieves Properties + NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() } // MARK: TAP EVENT - func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { if !isEditMode { - restoreItem(with: ocId) + Task { + await restoreItem(with: id) + } } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -219,26 +170,35 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) { - Task { - // Await async DB call off the main thread - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + func reloadDataSource(withQueryDB: Bool = true) async { + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Thu, 9 Apr 2026 17:10:48 +0530 Subject: [PATCH 15/21] NMC 2341 - NCTrashView updated changes with 10.3.0 version --- iOSClient/NCGlobal.swift | 21 ++------- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 20 --------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 43 ++++++++++++++++++- iOSClient/Trash/NCTrash.swift | 1 + 6 files changed, 50 insertions(+), 40 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 8d2beaea12..6d78016391 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -50,7 +50,7 @@ final class NCGlobal: Sendable { // let avatarSize: Int = 128 * Int(UIScreen.main.scale) let avatarSizeRounded: Int = 128 - + // Preview size // let size1024: CGSize = CGSize(width: 1024, height: 1024) @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,6 +259,7 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] + let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -276,8 +277,6 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" - let notificationCenterDidCreateShareLink = "didCreateShareLink" - let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -295,17 +294,6 @@ final class NCGlobal: Sendable { let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource - let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error - let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) - let notificationCenterMoveFile = "moveFile" // userInfo: [ocId], [indexPath], error - let notificationCenterCopyFile = "copyFile" // userInfo: [ocId], [indexPath], error - let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error - let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl - let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists - let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource - - let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error - let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -340,7 +328,6 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" - let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" @@ -439,7 +426,7 @@ final class NCGlobal: Sendable { let keyFileNameAutoUploadType = "fileNameAutoUploadType" let keyFileNameOriginal = "fileNameOriginal" let keyFileNameOriginalAutoUpload = "fileNameOriginalAutoUpload" - + // LOG TAG // let logTagTask = "BGT" diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 9a2f607730..78a1af4bf0 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,9 +36,10 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) + self.imageItem.image = NCImageCache.shared.getFolder() } else { self.imageItem.image = image +// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 2cc1f8fdbc..9880516243 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -51,26 +51,6 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } - var fileProgressView: UIProgressView? { - get { return progressView } - set { progressView = newValue } - } - var fileSelectImage: UIImageView? { - get { return imageSelect } - set { imageSelect = newValue } - } - var fileStatusImage: UIImageView? { - get { return imageStatus } - set { imageStatus = newValue } - } - var fileLocalImage: UIImageView? { - get { return imageLocal } - set { imageLocal = newValue } - } - var fileFavoriteImage: UIImageView? { - get { return imageFavorite } - set { imageFavorite = newValue } - } override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index c3ea397cbe..d8436da989 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -58,6 +58,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] +// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) +// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 5c6f68dea9..f34ce34e04 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -92,6 +92,44 @@ extension NCTrash: UICollectionViewDataSource { return cell } + + func setTextFooter(datasource: [tableTrash]) -> String { + var folders: Int = 0, foldersText = "" + var files: Int = 0, filesText = "" + var size: Int64 = 0 + var text = "" + + for record: tableTrash in datasource { + if record.directory { + folders += 1 + } else { + files += 1 + size += record.size + } + } + + if folders > 1 { + foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") + } else if folders == 1 { + foldersText = "1 " + NSLocalizedString("_folder_", comment: "") + } + + if files > 1 { + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } else if files == 1 { + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } + + if foldersText.isEmpty { + text = filesText + } else if filesText.isEmpty { + text = foldersText + } else { + text = foldersText + ", " + filesText + } + + return text + } func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { var foldersText = "" @@ -186,8 +224,9 @@ extension NCTrash: UICollectionViewDataSource { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } if let datasource { - let info = self.getFooterInformation(datasource: datasource) - footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) + footer.setTitleLabel(setTextFooter(datasource: datasource)) +// let info = self.getFooterInformation(datasource: datasource) +// footer.setTitleLabel(directories: info.directories, files: info.files, size: info.size) } return footer } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 81c7cf3271..28c3ad9c26 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -106,6 +106,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat await self.reloadDataSource() await loadListingTrash() } + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) } override func viewWillDisappear(_ animated: Bool) { From a53174d33f48f1ec433ed94e472685c4392a9452 Mon Sep 17 00:00:00 2001 From: Shweta Waikar Date: Wed, 28 Jun 2023 12:11:45 +0530 Subject: [PATCH 16/21] NMC 2341 - Theming changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 92 +++++++------------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 16 ++-- iOSClient/Trash/NCTrash.swift | 3 +- 4 files changed, 44 insertions(+), 69 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 9880516243..f9f05065e7 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,12 +11,15 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! + @IBOutlet weak var imageStatus: UIImageView! + @IBOutlet weak var imageFavorite: UIImageView! + @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! - @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! + @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -51,6 +54,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } + var fileProgressView: UIProgressView? { + get { return progressView } + set { progressView = newValue } + } + var fileSelectImage: UIImageView? { + get { return imageSelect } + set { imageSelect = newValue } + } + var fileStatusImage: UIImageView? { + get { return imageStatus } + set { imageStatus = newValue } + } + var fileLocalImage: UIImageView? { + get { return imageLocal } + set { imageLocal = newValue } + } + var fileFavoriteImage: UIImageView? { + get { return imageFavorite } + set { imageFavorite = newValue } + } override func awakeFromNib() { super.awakeFromNib() @@ -144,7 +167,10 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } + fileprivate func setA11yActions() { + let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" + self.accessibilityCustomActions = [ UIAccessibilityCustomAction( name: NSLocalizedString("_more_", comment: ""), @@ -153,7 +179,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { ] } - func setButtonMore(image: UIImage) { + func setButtonMore(named: String, image: UIImage) { + namedButtonMore = named buttonMore.setImage(image, for: .normal) setA11yActions() } @@ -171,7 +198,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { // imageSelect.alpha = status ? 1 : 0 // imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) if status { - imageSelect.image = NCImageCache.shared.getImageCheckedYes() + imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { @@ -186,8 +213,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) - labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -195,59 +221,3 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } - -// MARK: - Grid Layout - -class NCTrashGridLayout: UICollectionViewFlowLayout { - - var heightLabelPlusButton: CGFloat = 60 - var marginLeftRight: CGFloat = 10 - var itemForLine: CGFloat = 3 - var itemWidthDefault: CGFloat = 140 - - // MARK: - View Life Cycle - - override init() { - super.init() - - sectionHeadersPinToVisibleBounds = false - - minimumInteritemSpacing = 1 - minimumLineSpacing = marginLeftRight - - self.scrollDirection = .vertical - self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override var itemSize: CGSize { - get { - if let collectionView = collectionView { - - if collectionView.frame.width < 400 { - itemForLine = 3 - } else { - itemForLine = collectionView.frame.width / itemWidthDefault - } - - let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine - let itemHeight: CGFloat = itemWidth + heightLabelPlusButton - - return CGSize(width: itemWidth, height: itemHeight) - } - - // Default fallback - return CGSize(width: itemWidthDefault, height: itemWidthDefault) - } - set { - super.itemSize = newValue - } - } - - override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { - return proposedContentOffset - } -} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index d8436da989..ab5f23c1d7 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,6 +32,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" + var indexPath = IndexPath() + let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index f34ce34e04..bdedce7144 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,9 +4,11 @@ import UIKit import RealmSwift +import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { @@ -16,7 +18,7 @@ extension NCTrash: UICollectionViewDelegate { selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: selectOcId) + setNavigationRightItems() return } @@ -32,7 +34,9 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + setNavigationRightItems() return datasource?.count ?? 0 } @@ -46,7 +50,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -220,6 +224,7 @@ extension NCTrash: UICollectionViewDataSource { header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header + } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } @@ -235,12 +240,9 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - var height: Double = 0 - if let datasource, datasource.isEmpty { - height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) - } - return CGSize(width: collectionView.frame.width, height: height) + return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 28c3ad9c26..2a7cb9399a 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -63,6 +63,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") + collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true From 8f6d508d8a0755ad4863008db55ec59e37e26660 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Mon, 14 Apr 2025 16:57:15 +0530 Subject: [PATCH 17/21] NMC 2341 - NCTrashView changes --- iOSClient/Trash/Cell/NCTrashGridCell.swift | 5 +- iOSClient/Trash/Cell/NCTrashListCell.swift | 7 +- iOSClient/Trash/NCTrash+CollectionView.swift | 21 ++++-- iOSClient/Trash/NCTrash.swift | 70 +++++++++++++++++--- 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index f9f05065e7..e3fb5c5e76 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -173,7 +173,7 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString("_more_", comment: ""), + name: NSLocalizedString(moreName, comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] @@ -187,10 +187,13 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { + imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { + imageSelect.isHidden = true buttonMore.isHidden = false + imageVisualEffect.isHidden = true setA11yActions() } diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index ab5f23c1d7..741961a136 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -137,8 +137,11 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) - blurEffectView?.backgroundColor = .lightGray + var blurEffect: UIVisualEffect? + let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark + blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) + blurEffectView = UIVisualEffectView(effect: blurEffect) + blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index bdedce7144..e82945bfbc 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -10,14 +10,16 @@ import Foundation extension NCTrash: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } + let resultTableTrash = datasource[indexPath.item] + guard !isEditMode else { - if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { - selectOcId.remove(at: index) + if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { + fileSelect.remove(at: index) } else { - selectOcId.append(resultTableTrash.fileId) + fileSelect.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) + tabBarSelect.update(selectOcId: fileSelect) setNavigationRightItems() return } @@ -36,8 +38,10 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + let numberOfItems = datasource.count + emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) setNavigationRightItems() - return datasource?.count ?? 0 + return numberOfItems } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -70,7 +74,7 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) + image = UIImage(named: resultTableTrash.iconName) } if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, @@ -242,8 +246,13 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + if datasource.isEmpty { + let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) + return CGSize(width: collectionView.frame.width, height: height) + } return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 2a7cb9399a..fb6a3c8e5a 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -6,7 +6,7 @@ import UIKit import NextcloudKit import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" @@ -16,13 +16,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var selectOcId: [String] = [] + var fileSelect: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash + var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? @@ -55,14 +56,14 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat override func viewDidLoad() { super.viewDidLoad() - navigationController?.setNavigationBarAppearance() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) + serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") - collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -74,25 +75,29 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 refreshControl.action(for: .valueChanged) { _ in Task { await self.loadListingTrash() } } + // Empty + emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) + + NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if tabBarSelect == nil { - tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) - } + appDelegate.activeViewController = self navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") + gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -119,6 +124,53 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() + dataSourceTask?.cancel() + isEditMode = false + } + + override func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + if let frame = tabBarController?.tabBar.frame { + tabBarSelect.hostingController?.view.frame = frame + } + } + + // MARK: - Layout + + @objc func changeLayout(_ notification: NSNotification) { + guard let userInfo = notification.userInfo as NSDictionary?, + let account = userInfo["account"] as? String, + let serverUrl = userInfo["serverUrl"] as? String, + let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, + account == session.account, + serverUrl == self.serverUrl + else { return } + + self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) + layoutForView.layout = layoutForView.layout + self.layoutType = layoutForView.layout +// self.reloadDataSource() + collectionView.reloadData() + + switch layoutForView.layout { + case NCGlobal.shared.layoutList: + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) + case NCGlobal.shared.layoutGrid: + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) + default: + break + } + + self.collectionView.collectionViewLayout.invalidateLayout() + } + + // MARK: - Empty + + func emptyDataSetView(_ view: NCEmptyView) { + view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) + view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") + view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") } // MARK: TAP EVENT @@ -172,7 +224,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - func reloadDataSource(withQueryDB: Bool = true) async { + @objc func reloadDataSource(withQueryDB: Bool = true) async { let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() From 28cb4499dfe655c530b894cab735d1c125a6aa5a Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Tue, 30 Sep 2025 19:13:16 +0530 Subject: [PATCH 18/21] NMC 2341 - NCTrashView updated changes --- iOSClient/Trash/NCTrash+CollectionView.swift | 20 ++--- .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 +++++++++++++------ iOSClient/Trash/NCTrash.swift | 74 ++++++++--------- iOSClient/Trash/NCTrashSelectTabBar.swift | 48 ++++------- 4 files changed, 112 insertions(+), 110 deletions(-) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index e82945bfbc..38832963e9 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -8,9 +8,10 @@ import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - let resultTableTrash = datasource[indexPath.item] + + guard let resultTableTrash = datasource?[indexPath.item] else { return } guard !isEditMode else { if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { @@ -38,10 +39,9 @@ extension NCTrash: UICollectionViewDelegate { extension NCTrash: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - let numberOfItems = datasource.count - emptyDataSet?.numberOfItemsInSection(numberOfItems, section: section) + emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) setNavigationRightItems() - return numberOfItems + return datasource?.count ?? 0 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { @@ -77,17 +77,13 @@ extension NCTrash: UICollectionViewDataSource { image = UIImage(named: resultTableTrash.iconName) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, - etag: resultTableTrash.fileName, - ext: NCGlobal.shared.previewExt512, - userId: session.userId, - urlBase: session.urlBase) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) } } } @@ -246,7 +242,7 @@ extension NCTrash: UICollectionViewDataSource { extension NCTrash: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { - if datasource.isEmpty { + if let datasource, datasource.isEmpty { let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) return CGSize(width: collectionView.frame.width, height: height) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 53191350f6..2809c953b3 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate { +extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,51 +27,81 @@ extension NCTrash: NCTrashSelectTabBarDelegate { } func selectAll() { - guard let datasource else { return } - if !selectOcId.isEmpty, datasource.count == selectOcId.count { - selectOcId = [] + if !fileSelect.isEmpty, datasource?.count == fileSelect.count { + fileSelect = [] } else { - selectOcId = datasource.compactMap({ $0.fileId }) + fileSelect = (datasource?.compactMap({ $0.fileId }))! } - tabBarSelect.update(selectOcId: selectOcId) + tabBarSelect.update(selectOcId: fileSelect) collectionView.reloadData() } func recover() { - let ids = selectOcId.map { $0 } + fileSelect.forEach(restoreItem) setEditMode(false) - - Task { - for id in ids { - await restoreItem(with: id) - } - } } func delete() { - let ids = selectOcId.map { $0 } + let ocIds = fileSelect.map { $0 } setEditMode(false) Task { - if ids.count > 0, ids.count == datasource?.count { + if ocIds.count > 0, ocIds.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ids) + await self.deleteItems(with: ocIds) } } } func setEditMode(_ editMode: Bool) { - Task { - isEditMode = editMode - selectOcId.removeAll() - - navigationItem.hidesBackButton = editMode - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + isEditMode = editMode + fileSelect.removeAll() - collectionView.reloadData() + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + navigationItem.hidesBackButton = editMode + DispatchQueue.main.async { + self.collectionView.reloadData() + self.setNavigationRightItems() } } + + func setNavigationRightItems(enableMenu: Bool = false) { + if isEditMode { + let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} + navigationItem.rightBarButtonItems = [more] + } else { + let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } + let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) + if layoutKey == NCGlobal.shared.layoutViewFiles { + navigationItem.rightBarButtonItems = [select, notification] + } else { + navigationItem.rightBarButtonItems = [select] + } + } + guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } + navigationItem.title = titleCurrentFolder + } + + func createMenuActions() -> [NCMenuAction] { +// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } +// +// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in +// self.setEditMode(true) +// } +// +// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in +// self.onListSelected() +//// self.setNavigationRightItems() +// } +// +// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in +// self.onGridSelected() +//// self.setNavigationRightItems() +// } +// +// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) +// + return []//[select, viewStyleSubmenu] + } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index fb6a3c8e5a..050cae1606 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,6 +4,7 @@ import UIKit import NextcloudKit +import Realm import RealmSwift class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { @@ -12,6 +13,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? + var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() @@ -26,8 +28,6 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? - - @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,18 +52,22 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } + // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() + tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) serverUrl = utilityFileSystem.getHomeServer(session: session) view.backgroundColor = .systemBackground + self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") +// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") @@ -75,12 +79,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray //NCBrandColor.shared.textColor2 - refreshControl.action(for: .valueChanged) { _ in - Task { - await self.loadListingTrash() - } - } + refreshControl.tintColor = .gray + refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) + // Empty emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) @@ -106,22 +107,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false + setNavigationRightItems() - Task { - await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() - await self.reloadDataSource() - await loadListingTrash() - } + reloadDataSource() + loadListingTrash(nil) + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - Task { - await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") - } - // Cancel Queue & Retrieves Properties NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() dataSourceTask?.cancel() @@ -175,11 +172,9 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: TAP EVENT - func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { if !isEditMode { - Task { - await restoreItem(with: id) - } + restoreItem(with: ocId) } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -224,8 +219,10 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) async { - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + @objc func reloadDataSource(withQueryDB: Bool = true) { + Task { + // Await async DB call off the main thread + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() // // Switch back to main thread for UI updates @@ -236,23 +233,20 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat //// (self.navigationController as? NCMainNavigationController)?.updateRightMenu() // await (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - await MainActor.run { - self.datasource = results - self.collectionView.reloadData() - - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Mon, 15 Dec 2025 12:54:00 +0530 Subject: [PATCH 19/21] NMC 2341 - NCTrashView updated changes --- iOSClient/NCGlobal.swift | 8 +- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 75 +++++++-- iOSClient/Trash/Cell/NCTrashListCell.swift | 11 +- iOSClient/Trash/NCTrash+CollectionView.swift | 68 +++------ .../Trash/NCTrash+SelectTabBarDelegate.swift | 80 +++------- iOSClient/Trash/NCTrash.swift | 142 ++++++------------ iOSClient/Trash/NCTrashSelectTabBar.swift | 48 ++++-- 8 files changed, 200 insertions(+), 235 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 6d78016391..7cc4bc93b1 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,7 +259,6 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] - let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -277,6 +276,8 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" + let notificationCenterDidCreateShareLink = "didCreateShareLink" + let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -294,6 +295,8 @@ final class NCGlobal: Sendable { let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource + let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -328,6 +331,7 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" + let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 78a1af4bf0..9a2f607730 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,10 +36,9 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder() + self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) } else { self.imageItem.image = image -// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index e3fb5c5e76..16edfc5e43 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -11,15 +11,12 @@ protocol NCTrashGridCellDelegate: AnyObject { class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! - @IBOutlet weak var imageStatus: UIImageView! - @IBOutlet weak var imageFavorite: UIImageView! - @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! + @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @IBOutlet weak var imageVisualEffect: UIVisualEffectView! - @IBOutlet weak var progressView: UIProgressView! weak var delegate: NCTrashGridCellDelegate? var objectId = "" @@ -167,33 +164,26 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapMoreGridItem(with: objectId, image: imageItem.image, sender: sender) } - fileprivate func setA11yActions() { - let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_" - self.accessibilityCustomActions = [ UIAccessibilityCustomAction( - name: NSLocalizedString(moreName, comment: ""), + name: NSLocalizedString("_more_", comment: ""), target: self, selector: #selector(touchUpInsideMore(_:))) ] } - func setButtonMore(named: String, image: UIImage) { - namedButtonMore = named + func setButtonMore(image: UIImage) { buttonMore.setImage(image, for: .normal) setA11yActions() } func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { if isEditMode { - imageSelect.isHidden = false buttonMore.isHidden = true accessibilityCustomActions = nil } else { - imageSelect.isHidden = true buttonMore.isHidden = false - imageVisualEffect.isHidden = true setA11yActions() } @@ -216,7 +206,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { dateFormatter.timeStyle = .none dateFormatter.locale = Locale.current - labelInfo.text = dateFormatter.string(from: date as Date) + " · " + NCUtilityFileSystem().transformedSize(size) + labelInfo.text = dateFormatter.string(from: date as Date) + labelSubinfo.text = NCUtilityFileSystem().transformedSize(size) } func setAccessibility(label: String, value: String) { @@ -224,3 +215,59 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { accessibilityValue = value } } + +// MARK: - Grid Layout + +class NCTrashGridLayout: UICollectionViewFlowLayout { + + var heightLabelPlusButton: CGFloat = 60 + var marginLeftRight: CGFloat = 10 + var itemForLine: CGFloat = 3 + var itemWidthDefault: CGFloat = 140 + + // MARK: - View Life Cycle + + override init() { + super.init() + + sectionHeadersPinToVisibleBounds = false + + minimumInteritemSpacing = 1 + minimumLineSpacing = marginLeftRight + + self.scrollDirection = .vertical + self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 0, right: marginLeftRight) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var itemSize: CGSize { + get { + if let collectionView = collectionView { + + if collectionView.frame.width < 400 { + itemForLine = 3 + } else { + itemForLine = collectionView.frame.width / itemWidthDefault + } + + let itemWidth: CGFloat = (collectionView.frame.width - marginLeftRight * 2 - marginLeftRight * (itemForLine - 1)) / itemForLine + let itemHeight: CGFloat = itemWidth + heightLabelPlusButton + + return CGSize(width: itemWidth, height: itemHeight) + } + + // Default fallback + return CGSize(width: itemWidthDefault, height: itemWidthDefault) + } + set { + super.itemSize = newValue + } + } + + override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint { + return proposedContentOffset + } +} diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 741961a136..c3ea397cbe 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -32,8 +32,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { set { imageStatus = newValue } } var account = "" - var indexPath = IndexPath() - let utility = NCUtility() override func awakeFromNib() { super.awakeFromNib() @@ -60,8 +58,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] -// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) -// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 @@ -137,11 +133,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { } if status { var blurEffectView: UIView? - var blurEffect: UIVisualEffect? - let traitCollectionUserInterfaceStyleDark = traitCollection.userInterfaceStyle == .dark - blurEffect = UIBlurEffect(style: traitCollectionUserInterfaceStyleDark ? .dark : .extraLight) - blurEffectView = UIVisualEffectView(effect: blurEffect) - blurEffectView?.backgroundColor = traitCollectionUserInterfaceStyleDark ? .black : .lightGray + blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterial)) + blurEffectView?.backgroundColor = .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index 38832963e9..a95e766e06 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -4,24 +4,19 @@ import UIKit import RealmSwift -import Foundation // MARK: UICollectionViewDelegate extension NCTrash: UICollectionViewDelegate { - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - guard let resultTableTrash = datasource?[indexPath.item] else { return } - guard !isEditMode else { - if let index = fileSelect.firstIndex(of: resultTableTrash.fileId) { - fileSelect.remove(at: index) + if let index = selectOcId.firstIndex(of: resultTableTrash.fileId) { + selectOcId.remove(at: index) } else { - fileSelect.append(resultTableTrash.fileId) + selectOcId.append(resultTableTrash.fileId) } collectionView.reloadItems(at: [indexPath]) - tabBarSelect.update(selectOcId: fileSelect) - setNavigationRightItems() + tabBarSelect.update(selectOcId: selectOcId) return } @@ -37,10 +32,7 @@ extension NCTrash: UICollectionViewDelegate { // MARK: UICollectionViewDataSource extension NCTrash: UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - emptyDataSet?.numberOfItemsInSection(datasource?.count ?? 0, section: section) - setNavigationRightItems() return datasource?.count ?? 0 } @@ -54,7 +46,7 @@ extension NCTrash: UICollectionViewDataSource { cell = listCell } else { let gridCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCTrashGridCell)! - gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCImageCache.shared.getImageButtonMore()) + gridCell.setButtonMore(image: NCImageCache.shared.getImageButtonMore()) gridCell.delegate = self cell = gridCell } @@ -74,16 +66,20 @@ extension NCTrash: UICollectionViewDataSource { if resultTableTrash.iconName.isEmpty { image = NCImageCache.shared.getImageFile() } else { - image = UIImage(named: resultTableTrash.iconName) + image = NCUtility().loadImage(named: resultTableTrash.iconName, useTypeIconFile: true, account: resultTableTrash.account) } - if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, etag: resultTableTrash.fileName, ext: NCGlobal.shared.previewExt512) { + if let imageIcon = utility.getImage(ocId: resultTableTrash.fileId, + etag: resultTableTrash.fileName, + ext: NCGlobal.shared.previewExt512, + userId: session.userId, + urlBase: session.urlBase) { image = imageIcon cell.imageItem.contentMode = .scaleAspectFill } else { if resultTableTrash.hasPreview { if NCNetworking.shared.downloadThumbnailTrashQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailTrash)?.fileId == resultTableTrash.fileId }).isEmpty { - NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, account: session.account, collectionView: collectionView)) + NCNetworking.shared.downloadThumbnailTrashQueue.addOperation(NCOperationDownloadThumbnailTrash(fileId: resultTableTrash.fileId, fileName: resultTableTrash.fileName, session: session, collectionView: collectionView)) } } } @@ -96,32 +92,22 @@ extension NCTrash: UICollectionViewDataSource { return cell } - - func setTextFooter(datasource: [tableTrash]) -> String { - var folders: Int = 0, foldersText = "" - var files: Int = 0, filesText = "" - var size: Int64 = 0 + + func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { + var foldersText = "" + var filesText = "" var text = "" - for record: tableTrash in datasource { - if record.directory { - folders += 1 - } else { - files += 1 - size += record.size - } - } - - if folders > 1 { - foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") - } else if folders == 1 { + if directories > 1 { + foldersText = "\(directories) " + NSLocalizedString("_folders_", comment: "") + } else if directories == 1 { foldersText = "1 " + NSLocalizedString("_folder_", comment: "") } if files > 1 { - filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } else if files == 1 { - filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " • " + utilityFileSystem.transformedSize(size) } if foldersText.isEmpty { @@ -129,9 +115,8 @@ extension NCTrash: UICollectionViewDataSource { } else if filesText.isEmpty { text = foldersText } else { - text = foldersText + ", " + filesText + text = foldersText + " • " + filesText } - return text } @@ -224,7 +209,6 @@ extension NCTrash: UICollectionViewDataSource { header.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") header.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") return header - } else { guard let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCSectionFooter else { return NCSectionFooter() } @@ -240,15 +224,13 @@ extension NCTrash: UICollectionViewDataSource { // MARK: UICollectionViewDelegateFlowLayout extension NCTrash: UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + var height: Double = 0 if let datasource, datasource.isEmpty { - let height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -20) - return CGSize(width: collectionView.frame.width, height: height) + height = utility.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: 0) } - return CGSize(width: collectionView.frame.width, height: NCGlobal.shared.heightButtonsView) + return CGSize(width: collectionView.frame.width, height: height) } - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: 85) } diff --git a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift index 2809c953b3..53191350f6 100644 --- a/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift +++ b/iOSClient/Trash/NCTrash+SelectTabBarDelegate.swift @@ -5,7 +5,7 @@ import Foundation import UIKit -extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { +extension NCTrash: NCTrashSelectTabBarDelegate { func onListSelected() { if layoutForView?.layout == NCGlobal.shared.layoutGrid { layoutForView?.layout = NCGlobal.shared.layoutList @@ -27,81 +27,51 @@ extension NCTrash: NCTrashSelectTabBarDelegate, NCSelectableNavigationView { } func selectAll() { - if !fileSelect.isEmpty, datasource?.count == fileSelect.count { - fileSelect = [] + guard let datasource else { return } + if !selectOcId.isEmpty, datasource.count == selectOcId.count { + selectOcId = [] } else { - fileSelect = (datasource?.compactMap({ $0.fileId }))! + selectOcId = datasource.compactMap({ $0.fileId }) } - tabBarSelect.update(selectOcId: fileSelect) + tabBarSelect.update(selectOcId: selectOcId) collectionView.reloadData() } func recover() { - fileSelect.forEach(restoreItem) + let ids = selectOcId.map { $0 } setEditMode(false) + + Task { + for id in ids { + await restoreItem(with: id) + } + } } func delete() { - let ocIds = fileSelect.map { $0 } + let ids = selectOcId.map { $0 } setEditMode(false) Task { - if ocIds.count > 0, ocIds.count == datasource?.count { + if ids.count > 0, ids.count == datasource?.count { await emptyTrash() } else { - await self.deleteItems(with: ocIds) + await self.deleteItems(with: ids) } } } func setEditMode(_ editMode: Bool) { - isEditMode = editMode - fileSelect.removeAll() + Task { + isEditMode = editMode + selectOcId.removeAll() - navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode - navigationItem.hidesBackButton = editMode - DispatchQueue.main.async { - self.collectionView.reloadData() - self.setNavigationRightItems() - } - } - - func setNavigationRightItems(enableMenu: Bool = false) { - if isEditMode { - let more = UIBarButtonItem(image: UIImage(systemName: "ellipsis"), style: .plain) { self.presentMenu(with: self.selectActions)} - navigationItem.rightBarButtonItems = [more] - } else { - let select = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain) { self.toggleSelect() } - let notification = UIBarButtonItem(image: UIImage(systemName: "bell"), style: .plain, action: tapNotification) - if layoutKey == NCGlobal.shared.layoutViewFiles { - navigationItem.rightBarButtonItems = [select, notification] - } else { - navigationItem.rightBarButtonItems = [select] - } + navigationItem.hidesBackButton = editMode + navigationController?.interactivePopGestureRecognizer?.isEnabled = !editMode + + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + + collectionView.reloadData() } - guard layoutKey == NCGlobal.shared.layoutViewFiles else { return } - navigationItem.title = titleCurrentFolder - } - - func createMenuActions() -> [NCMenuAction] { -// guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: session.account, key: layoutKey, serverUrl: "") else { return [] } -// -// let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: datasource.isEmpty ? .disabled : []) { _ in -// self.setEditMode(true) -// } -// -// let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in -// self.onListSelected() -//// self.setNavigationRightItems() -// } -// -// let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in -// self.onGridSelected() -//// self.setNavigationRightItems() -// } -// -// let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) -// - return []//[select, viewStyleSubmenu] } } diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 050cae1606..81c7cf3271 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,30 +4,29 @@ import UIKit import NextcloudKit -import Realm import RealmSwift -class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCSectionHeaderMenuDelegate, NCEmptyDataSetDelegate { +class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegate { @IBOutlet weak var collectionView: UICollectionView! var filePath = "" var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "") var blinkFileId: String? - var dataSourceTask: URLSessionTask? let utilityFileSystem = NCUtilityFileSystem() let database = NCManageDatabase.shared let utility = NCUtility() var isEditMode = false - var fileSelect: [String] = [] + var selectOcId: [String] = [] var tabBarSelect: NCTrashSelectTabBar! var datasource: [tableTrash]? var layoutForView: NCDBLayoutForView? var listLayout: NCListLayout! var gridLayout: NCGridLayout! var layoutKey = NCGlobal.shared.layoutViewTrash - var layoutType = NCGlobal.shared.layoutList let refreshControl = UIRefreshControl() var filename: String? + + @MainActor var session: NCSession.Session { NCSession.shared.getSession(controller: tabBarController) } @@ -52,23 +51,18 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat self.navigationController as? NCMainNavigationController } - // MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() - - tabBarSelect = NCTrashSelectTabBar(tabBarController: tabBarController, delegate: self) - serverUrl = utilityFileSystem.getHomeServer(session: session) + navigationController?.setNavigationBarAppearance() view.backgroundColor = .systemBackground - self.navigationController?.navigationBar.prefersLargeTitles = true collectionView.register(UINib(nibName: "NCTrashListCell", bundle: nil), forCellWithReuseIdentifier: "listCell") collectionView.register(UINib(nibName: "NCTrashGridCell", bundle: nil), forCellWithReuseIdentifier: "gridCell") -// collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") - collectionView.register(UINib(nibName: "NCSectionHeaderMenu", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionHeaderMenu") + collectionView.register(UINib(nibName: "NCSectionFirstHeaderEmptyData", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "sectionFirstHeaderEmptyData") collectionView.register(UINib(nibName: "NCSectionFooter", bundle: nil), forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "sectionFooter") collectionView.alwaysBounceVertical = true @@ -79,26 +73,25 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // Add Refresh Control collectionView.refreshControl = refreshControl - refreshControl.tintColor = .gray - refreshControl.addTarget(self, action: #selector(loadListingTrash), for: .valueChanged) - - // Empty - emptyDataSet = NCEmptyDataSet(view: collectionView, offset: NCGlobal.shared.heightButtonsView, delegate: self) - - NotificationCenter.default.addObserver(self, selector: #selector(reloadDataSource), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterReloadDataSource), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(changeLayout(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeLayout), object: nil) + refreshControl.tintColor = NCBrandColor.shared.textColor2 + refreshControl.action(for: .valueChanged) { _ in + Task { + await self.loadListingTrash() + } + } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - appDelegate.activeViewController = self + if tabBarSelect == nil { + tabBarSelect = NCTrashSelectTabBar(controller: tabBarController, viewController: self, delegate: self) + } navigationController?.setNavigationBarAppearance() navigationItem.title = titleCurrentFolder layoutForView = self.database.getLayoutForView(account: session.account, key: NCGlobal.shared.layoutViewTrash, serverUrl: "") - gridLayout.column = CGFloat(layoutForView?.columnGrid ?? 3) if layoutForView?.layout == NCGlobal.shared.layoutList { collectionView.collectionViewLayout = listLayout @@ -107,74 +100,32 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat } isEditMode = false - setNavigationRightItems() - - reloadDataSource() - loadListingTrash(nil) - - AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) + Task { + await (self.navigationController as? NCMainNavigationController)?.setNavigationRightItems() + await self.reloadDataSource() + await loadListingTrash() + } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - // Cancel Queue & Retrieves Properties - NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() - dataSourceTask?.cancel() - isEditMode = false - } - - override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - if let frame = tabBarController?.tabBar.frame { - tabBarSelect.hostingController?.view.frame = frame - } - } - - // MARK: - Layout - - @objc func changeLayout(_ notification: NSNotification) { - guard let userInfo = notification.userInfo as NSDictionary?, - let account = userInfo["account"] as? String, - let serverUrl = userInfo["serverUrl"] as? String, - let layoutForView = userInfo["layoutForView"] as? NCDBLayoutForView, - account == session.account, - serverUrl == self.serverUrl - else { return } - - self.layoutForView = self.database.setLayoutForView(layoutForView: layoutForView) - layoutForView.layout = layoutForView.layout - self.layoutType = layoutForView.layout -// self.reloadDataSource() - collectionView.reloadData() - - switch layoutForView.layout { - case NCGlobal.shared.layoutList: - self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) - case NCGlobal.shared.layoutGrid: - self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) - default: - break + Task { + await NCNetworking.shared.networkingTasks.cancel(identifier: "NCTrash") } - self.collectionView.collectionViewLayout.invalidateLayout() - } - - // MARK: - Empty - - func emptyDataSetView(_ view: NCEmptyView) { - view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) - view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") - view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") + // Cancel Queue & Retrieves Properties + NCNetworking.shared.downloadThumbnailTrashQueue.cancelAll() } // MARK: TAP EVENT - func tapRestoreListItem(with ocId: String, image: UIImage?, sender: Any) { + func tapRestoreListItem(with id: String, image: UIImage?, sender: Any) { if !isEditMode { - restoreItem(with: ocId) + Task { + await restoreItem(with: id) + } } else if let button = sender as? UIView { let buttonPosition = button.convert(CGPoint.zero, to: collectionView) let indexPath = collectionView.indexPathForItem(at: buttonPosition) @@ -219,10 +170,8 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat // MARK: - DataSource - @objc func reloadDataSource(withQueryDB: Bool = true) { - Task { - // Await async DB call off the main thread - let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) + func reloadDataSource(withQueryDB: Bool = true) async { + let results = await self.database.getTableTrashAsync(filePath: getFilePath(), account: session.account) await mainNavigationController?.updateMenuOption() // // Switch back to main thread for UI updates @@ -233,20 +182,23 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat //// (self.navigationController as? NCMainNavigationController)?.updateRightMenu() // await (self.navigationController as? NCMainNavigationController)?.updateRightMenu() - guard let blinkFileId = self.blinkFileId else { return } - - for itemIx in 0.. Date: Thu, 9 Apr 2026 17:10:48 +0530 Subject: [PATCH 20/21] NMC 2341 - NCTrashView updated changes with 10.3.0 version --- iOSClient/NCGlobal.swift | 13 +++++-- .../Trash/Cell/NCTrashCellProtocol.swift | 3 +- iOSClient/Trash/Cell/NCTrashGridCell.swift | 20 ---------- iOSClient/Trash/Cell/NCTrashListCell.swift | 2 + iOSClient/Trash/NCTrash+CollectionView.swift | 38 +++++++++++++++++++ iOSClient/Trash/NCTrash.swift | 1 + 6 files changed, 52 insertions(+), 25 deletions(-) diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 7cc4bc93b1..4f456f09f0 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -229,7 +229,7 @@ final class NCGlobal: Sendable { let selectorSynchronizationOffline = "synchronizationOffline" let selectorPrint = "print" let selectorDeleteFile = "deleteFile" - + // Metadata : Status // // 0 normal @@ -259,6 +259,7 @@ final class NCGlobal: Sendable { let metadataStatusForScreenAwake = [-1, -2, 1, 2] let metadataStatusHideInView = [1, 2, 3, 11] let metadataStatusWaitWebDav = [10, 11, 12, 13, 14, 15] + let metadataStatusTransfers = [-2, -3, 2, 3, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaiting = [-1, 1, 10, 11, 12, 13, 14, 15] let metadatasStatusInWaitingDownloadUpload = [-1, 1] @@ -276,8 +277,6 @@ final class NCGlobal: Sendable { let notificationCenterChangeTheming = "changeTheming" // userInfo: account let notificationCenterRichdocumentGrabFocus = "richdocumentGrabFocus" let notificationCenterReloadDataNCShare = "reloadDataNCShare" - let notificationCenterDidCreateShareLink = "didCreateShareLink" - let notificationCenterCloseRichWorkspaceWebView = "closeRichWorkspaceWebView" let notificationCenterReloadAvatar = "reloadAvatar" let notificationCenterClearCache = "clearCache" @@ -295,7 +294,14 @@ final class NCGlobal: Sendable { let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource + let notificationCenterDeleteFile = "deleteFile" // userInfo: [ocId], error + let notificationCenterCopyMoveFile = "copyMoveFile" // userInfo: [ocId] serverUrl, account, dragdrop, type (copy, move) + let notificationCenterMoveFile = "moveFile" // userInfo: [ocId], [indexPath], error + let notificationCenterCopyFile = "copyFile" // userInfo: [ocId], [indexPath], error let notificationCenterRenameFile = "renameFile" // userInfo: serverUrl, account, error + let notificationCenterFavoriteFile = "favoriteFile" // userInfo: ocId, serverUrl + let notificationCenterFileExists = "fileExists" // userInfo: ocId, fileExists + let notificationCenterReloadDataSource = "reloadDataSource" // userInfo: serverUrl?, clearDataSource let notificationCenterMenuSearchTextPDF = "menuSearchTextPDF" let notificationCenterMenuGotToPageInPDF = "menuGotToPageInPDF" @@ -331,7 +337,6 @@ final class NCGlobal: Sendable { let networkingStatusUploading = "statusUploading" let networkingStatusUploaded = "statusUploaded" - let networkingStatusReloadAvatar = "statusReloadAvatar" let notificationCenterUpdateIcons = "updateIcons" diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 9a2f607730..78a1af4bf0 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -36,9 +36,10 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.labelInfo?.text = dateFormatter.string(from: tableTrash.trashbinDeletionTime as Date) } if tableTrash.directory { - self.imageItem.image = NCImageCache.shared.getFolder(account: tableTrash.account) + self.imageItem.image = NCImageCache.shared.getFolder() } else { self.imageItem.image = image +// self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 16edfc5e43..2e9e324cb6 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -51,26 +51,6 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { get { return labelInfo } set { labelInfo = newValue } } - var fileProgressView: UIProgressView? { - get { return progressView } - set { progressView = newValue } - } - var fileSelectImage: UIImageView? { - get { return imageSelect } - set { imageSelect = newValue } - } - var fileStatusImage: UIImageView? { - get { return imageStatus } - set { imageStatus = newValue } - } - var fileLocalImage: UIImageView? { - get { return imageLocal } - set { imageLocal = newValue } - } - var fileFavoriteImage: UIImageView? { - get { return imageFavorite } - set { imageFavorite = newValue } - } override func awakeFromNib() { super.awakeFromNib() diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index c3ea397cbe..d8436da989 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -58,6 +58,8 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { ] +// imageRestore.image = NCUtility().loadImage(named: "arrow.counterclockwise", colors: [NCBrandColor.shared.iconImageColor]) +// imageMore.image = NCUtility().loadImage(named: "trash", colors: [.red]) imageRestore.image = NCUtility().loadImage(named: "restore", colors: [NCBrandColor.shared.iconImageColor]) imageMore.image = NCUtility().loadImage(named: "trashIcon", colors: [NCBrandColor.shared.iconImageColor]) //NCUtility().loadImage(named: "trashIcon", colors: [.red]) imageItem.layer.cornerRadius = 6 diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift index a95e766e06..a66e2b0c80 100644 --- a/iOSClient/Trash/NCTrash+CollectionView.swift +++ b/iOSClient/Trash/NCTrash+CollectionView.swift @@ -92,6 +92,44 @@ extension NCTrash: UICollectionViewDataSource { return cell } + + func setTextFooter(datasource: [tableTrash]) -> String { + var folders: Int = 0, foldersText = "" + var files: Int = 0, filesText = "" + var size: Int64 = 0 + var text = "" + + for record: tableTrash in datasource { + if record.directory { + folders += 1 + } else { + files += 1 + size += record.size + } + } + + if folders > 1 { + foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "") + } else if folders == 1 { + foldersText = "1 " + NSLocalizedString("_folder_", comment: "") + } + + if files > 1 { + filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } else if files == 1 { + filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + utilityFileSystem.transformedSize(size) + } + + if foldersText.isEmpty { + text = filesText + } else if filesText.isEmpty { + text = foldersText + } else { + text = foldersText + ", " + filesText + } + + return text + } func setTitleLabel(directories: Int, files: Int, size: Int64) -> String { var foldersText = "" diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 81c7cf3271..28c3ad9c26 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -106,6 +106,7 @@ class NCTrash: UIViewController, NCTrashListCellDelegate, NCTrashGridCellDelegat await self.reloadDataSource() await loadListingTrash() } + AnalyticsHelper.shared.trackEvent(eventName: .SCREEN_EVENT__DELETED_FILES) } override func viewWillDisappear(_ animated: Bool) { From 4f461366d4e6f748bf2ac6145590974e38378a15 Mon Sep 17 00:00:00 2001 From: harshada-15-tsys Date: Wed, 17 Jun 2026 13:40:38 +0530 Subject: [PATCH 21/21] NMC 2341 - NCTrashView updated changes --- .../Trash/Cell/NCTrashCellProtocol.swift | 32 +---- iOSClient/Trash/Cell/NCTrashGridCell.swift | 129 +++++------------- iOSClient/Trash/Cell/NCTrashGridCell.xib | 111 ++++++++------- iOSClient/Trash/Cell/NCTrashListCell.swift | 80 ++++------- iOSClient/Trash/Cell/NCTrashListCell.xib | 102 +++++--------- iOSClient/Trash/NCTrash+CollectionView.swift | 64 --------- iOSClient/Trash/NCTrash+Networking.swift | 36 +++-- .../Trash/NCTrash+SelectTabBarDelegate.swift | 23 +++- iOSClient/Trash/NCTrash.swift | 76 +++++------ iOSClient/Trash/NCTrashSelectTabBar.swift | 33 +++-- 10 files changed, 270 insertions(+), 416 deletions(-) diff --git a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift index 78a1af4bf0..b4fec5617e 100644 --- a/iOSClient/Trash/Cell/NCTrashCellProtocol.swift +++ b/iOSClient/Trash/Cell/NCTrashCellProtocol.swift @@ -7,27 +7,20 @@ import UIKit protocol NCTrashCellProtocol { var objectId: String { get set } var labelTitle: UILabel! { get set } - var labelExtension: UILabel! { get set } var labelInfo: UILabel! { get set } var imageItem: UIImageView! { get set } - var statusImg: UIImageView? { get set } + var account: String { get set } - func selected(_ status: Bool, isEditMode: Bool, color: UIColor) + func selected(_ status: Bool, isEditMode: Bool, account: String) } extension NCTrashCellProtocol where Self: UICollectionViewCell { mutating func setupCellUI(tableTrash: tableTrash, image: UIImage?) { self.objectId = tableTrash.fileId - - setBidiSafeFilename(tableTrash.trashbinFileName, isDirectory: tableTrash.directory, titleLabel: labelTitle, extensionLabel: labelExtension) - + self.labelTitle.text = tableTrash.trashbinFileName self.labelTitle.textColor = NCBrandColor.shared.textColor - self.labelExtension?.textColor = NCBrandColor.shared.textColor if self is NCTrashListCell { self.labelInfo?.text = NCUtility().getRelativeDateTitle(tableTrash.trashbinDeletionTime as Date) - if tableTrash.livePhoto { - statusImg?.image = NCUtility().loadImage(named: "livephoto", colors: [NCBrandColor.shared.iconImageColor]) - } } else { let dateFormatter = DateFormatter() dateFormatter.dateStyle = .short @@ -41,26 +34,7 @@ extension NCTrashCellProtocol where Self: UICollectionViewCell { self.imageItem.image = image // self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) } - self.labelInfo?.text = (self.labelInfo?.text ?? "") + " · " + NCUtilityFileSystem().transformedSize(tableTrash.size) self.accessibilityLabel = tableTrash.trashbinFileName + ", " + (self.labelInfo?.text ?? "") - - if self is NCTrashGridCell { - if labelExtension?.isHidden ?? true { - labelTitle.numberOfLines = 2 - labelTitle.lineBreakMode = .byWordWrapping - } else { - labelTitle.numberOfLines = 1 - labelTitle.lineBreakMode = .byTruncatingTail - } - } - - self.setIconOutlines() - } - - func setIconOutlines() { - statusImg?.makeCircularBackground( - withColor: statusImg?.image != nil ? .systemBackground : .clear - ) } } diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.swift b/iOSClient/Trash/Cell/NCTrashGridCell.swift index 2e9e324cb6..0fae0620f7 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.swift +++ b/iOSClient/Trash/Cell/NCTrashGridCell.swift @@ -1,6 +1,25 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2024 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCTrashGridCell.swift +// Nextcloud +// +// Created by Marino Faggiana on 19/03/2024. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// import UIKit @@ -9,10 +28,10 @@ protocol NCTrashGridCellDelegate: AnyObject { } class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { + @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! @IBOutlet weak var labelTitle: UILabel! - @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! @IBOutlet weak var labelSubinfo: UILabel! @IBOutlet weak var buttonMore: UIButton! @@ -20,38 +39,10 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { weak var delegate: NCTrashGridCellDelegate? var objectId = "" - - var statusImg: UIImageView? { - get { return nil } - set { imageItem = newValue } - } var indexPath = IndexPath() var account = "" var user = "" - var namedButtonMore = "" - - var fileObjectId: String? { - get { return objectId } - set { objectId = newValue ?? "" } - } - var filePreviewImageView: UIImageView? { - get { return imageItem } - set { imageItem = newValue } - } - var fileUser: String? { - get { return user } - set { user = newValue ?? "" } - } - var fileTitleLabel: UILabel? { - get { return labelTitle } - set { labelTitle = newValue } - } - var fileInfoLabel: UILabel? { - get { return labelInfo } - set { labelInfo = newValue } - } - override func awakeFromNib() { super.awakeFromNib() initCell() @@ -71,68 +62,12 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true - imageVisualEffect.isHidden = false - imageVisualEffect.effect = nil - imageVisualEffect.alpha = 0 - imageVisualEffect.isUserInteractionEnabled = false - imageVisualEffect.backgroundColor = UIColor.white.withAlphaComponent(0.2) - - // Dynamic Type Font Configuration - // - // These labels use fonts generated by the custom UIFont helpers defined in - // the UIFont extension (e.g. `.callout()`, `.caption1()`). - // - // Those helpers wrap `UIFontMetrics` to provide Dynamic Type scaling while - // applying an upper bound to the maximum font size. This ensures: - // - // - The text respects the user's preferred accessibility size. - // - The UI layout remains stable and does not grow indefinitely. - // - // `adjustsFontForContentSizeCategory` is enabled to allow UIKit to - // automatically update the font when the user changes the Dynamic Type - // setting while the application is running. - // - // Without this flag, the label would keep the initially computed font size - // and would not react to content size category changes. - // - // In summary: - // - // UIFont helper: - // Defines how the font scales and its maximum size. - // - // adjustsFontForContentSizeCategory: - // Enables live updates when accessibility settings change. - // -// progressView.tintColor = NCBrandColor.shared.brandElement -// progressView.transform = CGAffineTransform(scaleX: 1.0, y: 0.5) -// progressView.trackTintColor = .clear + imageVisualEffect.layer.cornerRadius = 6 + imageVisualEffect.clipsToBounds = true + imageVisualEffect.alpha = 0.5 labelTitle.text = "" - labelTitle.font = .callout() - labelTitle.adjustsFontForContentSizeCategory = true - - labelExtension.text = "" - labelExtension.isHidden = true - labelExtension.font = .callout() - labelExtension.adjustsFontForContentSizeCategory = true - labelInfo.text = "" - labelInfo.font = .footnote() - labelInfo.adjustsFontForContentSizeCategory = true - -// labelSubinfo.text = "" -// labelSubinfo.font = .footnote() -// labelSubinfo.adjustsFontForContentSizeCategory = true - - if labelExtension.isHidden { - labelTitle.numberOfLines = 2 - labelTitle.lineBreakMode = .byWordWrapping - } else { - labelTitle.numberOfLines = 1 - labelTitle.lineBreakMode = .byTruncatingTail - } - labelTitle.textColor = .label - labelInfo.textColor = .systemGray labelSubinfo.text = "" } @@ -158,7 +93,11 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { setA11yActions() } - func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { + func hideButtonMore(_ status: Bool) { + buttonMore.isHidden = status + } + + func selected(_ status: Bool, isEditMode: Bool, account: String) { if isEditMode { buttonMore.isHidden = true accessibilityCustomActions = nil @@ -166,12 +105,8 @@ class NCTrashGridCell: UICollectionViewCell, NCTrashCellProtocol { buttonMore.isHidden = false setA11yActions() } - -// imageVisualEffect.alpha = status ? 1 : 0 -// imageSelect.alpha = status ? 1 : 0 -// imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) if status { - imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) + imageSelect.image = NCImageCache.shared.getImageCheckedYes() imageSelect.isHidden = false imageVisualEffect.isHidden = false } else { diff --git a/iOSClient/Trash/Cell/NCTrashGridCell.xib b/iOSClient/Trash/Cell/NCTrashGridCell.xib index 065039029b..607f2744c6 100644 --- a/iOSClient/Trash/Cell/NCTrashGridCell.xib +++ b/iOSClient/Trash/Cell/NCTrashGridCell.xib @@ -1,15 +1,17 @@ - + - + + + - + @@ -17,20 +19,31 @@ - + - - + + + + + + + + + + + - - - + - + + - - + + - + - + - - + + - + + - + + + + + + + + + - @@ -121,11 +136,15 @@ + + + + diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index d8436da989..4af5d836c9 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -1,6 +1,27 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2024 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later +// +// NCTrashListCell.swift +// Nextcloud +// +// Created by Marino Faggiana on 08/10/2018. +// Copyright © 2018 Marino Faggiana. All rights reserved. +// Copyright © 2022 Henrik Storch. All rights reserved. +// +// Author Henrik Storch +// Author Marino Faggiana +// +// 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 . +// import UIKit @@ -11,11 +32,9 @@ protocol NCTrashListCellDelegate: AnyObject { class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { @IBOutlet weak var imageItem: UIImageView! - @IBOutlet weak var imageStatus: UIImageView! @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint! @IBOutlet weak var imageSelect: UIImageView! @IBOutlet weak var labelTitle: UILabel! - @IBOutlet weak var labelExtension: UILabel! @IBOutlet weak var labelInfo: UILabel! @IBOutlet weak var imageRestore: UIImageView! @IBOutlet weak var imageMore: UIImageView! @@ -26,11 +45,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { weak var delegate: NCTrashListCellDelegate? var objectId = "" - - var statusImg: UIImageView? { - get { return imageStatus } - set { imageStatus = newValue } - } var account = "" override func awakeFromNib() { @@ -65,45 +79,6 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true - imageStatus.image = nil - - // These labels use fonts generated by the custom UIFont helpers defined in - // the UIFont extension (e.g. `.callout()`, `.caption1()`). - // - // Those helpers wrap `UIFontMetrics` to provide Dynamic Type scaling while - // applying an upper bound to the maximum font size. This ensures: - // - // - The text respects the user's preferred accessibility size. - // - The UI layout remains stable and does not grow indefinitely. - // - // `adjustsFontForContentSizeCategory` is enabled to allow UIKit to - // automatically update the font when the user changes the Dynamic Type - // setting while the application is running. - // - // Without this flag, the label would keep the initially computed font size - // and would not react to content size category changes. - // - // In summary: - // - // UIFont helper: - // Defines how the font scales and its maximum size. - // - // adjustsFontForContentSizeCategory: - // Enables live updates when accessibility settings change. - // - labelTitle.text = "" - labelTitle.font = .callout() - labelTitle.adjustsFontForContentSizeCategory = true - - labelExtension.text = "" - labelExtension.isHidden = true - labelExtension.font = .callout() - labelExtension.adjustsFontForContentSizeCategory = true - - labelInfo.text = "" - labelInfo.font = .footnote() - labelInfo.adjustsFontForContentSizeCategory = true - separator.backgroundColor = .separator separatorHeightConstraint.constant = 0.5 } @@ -116,7 +91,7 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { delegate?.tapRestoreListItem(with: objectId, image: imageItem.image, sender: sender) } - func selected(_ status: Bool, isEditMode: Bool, color: UIColor) { + func selected(_ status: Bool, isEditMode: Bool, account: String) { if isEditMode { imageItemLeftConstraint.constant = 45 imageSelect.isHidden = false @@ -139,13 +114,14 @@ class NCTrashListCell: UICollectionViewCell, NCTrashCellProtocol { blurEffectView?.backgroundColor = .lightGray blurEffectView?.frame = self.bounds blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] - imageSelect.image = NCImageCache.shared.getImageCheckedYes(color: color) + imageSelect.image = NCImageCache.shared.getImageCheckedYes() backgroundView = blurEffectView separator.isHidden = true } else { - imageSelect.image = NCImageCache.shared.getImageCheckedNo(color: color) + imageSelect.image = NCImageCache.shared.getImageCheckedNo() backgroundView = nil separator.isHidden = false } + } } diff --git a/iOSClient/Trash/Cell/NCTrashListCell.xib b/iOSClient/Trash/Cell/NCTrashListCell.xib index b38073e32c..15946f2a5b 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.xib +++ b/iOSClient/Trash/Cell/NCTrashListCell.xib @@ -1,8 +1,10 @@ - + - + + + @@ -16,51 +18,26 @@ - + - - - - - - - - - - - - - - - - - - - - - - - + + - + - +