From 1b3c0d45c7b6e618c531f087c518a712c0df706f Mon Sep 17 00:00:00 2001 From: Mustafa Merza <mustafa.merza95@gmail.com> Date: Wed, 14 Aug 2024 10:23:37 +0300 Subject: [PATCH] - Added displaying scanned items as a grid in documents preview screen. --- MiniScanner.xcodeproj/project.pbxproj | 4 + MiniScanner/Extensions/UIImage+Images.swift | 1 + .../DocumentPreview.storyboard | 52 +++++-- .../DocumentPreviewViewController.swift | 128 +++++++++++++++++- .../DocumentPreview/PreviewCellLayout.swift | 32 +++++ .../layout-images-ic.imageset/Contents.json | 12 ++ .../layout-images-ic.svg | 3 + 7 files changed, 215 insertions(+), 17 deletions(-) create mode 100644 MiniScanner/Modules/DocumentPreview/PreviewCellLayout.swift create mode 100644 MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/Contents.json create mode 100644 MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/layout-images-ic.svg diff --git a/MiniScanner.xcodeproj/project.pbxproj b/MiniScanner.xcodeproj/project.pbxproj index 6645f8d..9f08366 100644 --- a/MiniScanner.xcodeproj/project.pbxproj +++ b/MiniScanner.xcodeproj/project.pbxproj @@ -266,6 +266,7 @@ 67A2AF8F2C6B9B5400039F30 /* View+CustomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A2AF8E2C6B9B5400039F30 /* View+CustomSheet.swift */; }; 67A2AF922C6B9B8700039F30 /* View+iOS15Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A2AF912C6B9B8700039F30 /* View+iOS15Sheet.swift */; }; 67A2AF962C6BADAA00039F30 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A2AF952C6BADAA00039F30 /* UserSettings.swift */; }; + 67A2AF982C6BC4AE00039F30 /* PreviewCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67A2AF972C6BC4AE00039F30 /* PreviewCellLayout.swift */; }; 67D714B52C5161A30065E6F4 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 67D714B42C5161A30065E6F4 /* Images.xcassets */; }; 67E6A1962C64DEB400A77F29 /* ScannedItemType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6A1952C64DEB400A77F29 /* ScannedItemType.swift */; }; 67E6A1982C65151F00A77F29 /* ImageCompressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6A1972C65151F00A77F29 /* ImageCompressView.swift */; }; @@ -580,6 +581,7 @@ 67A2AF8E2C6B9B5400039F30 /* View+CustomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+CustomSheet.swift"; sourceTree = "<group>"; }; 67A2AF912C6B9B8700039F30 /* View+iOS15Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+iOS15Sheet.swift"; sourceTree = "<group>"; }; 67A2AF952C6BADAA00039F30 /* UserSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettings.swift; sourceTree = "<group>"; }; + 67A2AF972C6BC4AE00039F30 /* PreviewCellLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewCellLayout.swift; sourceTree = "<group>"; }; 67D714B42C5161A30065E6F4 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; 67E6A1952C64DEB400A77F29 /* ScannedItemType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannedItemType.swift; sourceTree = "<group>"; }; 67E6A1972C65151F00A77F29 /* ImageCompressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCompressView.swift; sourceTree = "<group>"; }; @@ -1640,6 +1642,7 @@ EC8A9B26254DE91B00F9AF99 /* DocumentPreviewViewController.swift */, EC702521254DF13200BE1958 /* PencilKitViewController.swift */, 677E65F52C5F9E6E0039E2C5 /* ScannedItemPagerViewCell.swift */, + 67A2AF972C6BC4AE00039F30 /* PreviewCellLayout.swift */, ); path = DocumentPreview; sourceTree = "<group>"; @@ -2025,6 +2028,7 @@ 677E65C12C5A15F40039E2C5 /* ScanSessionEntity+CoreDataProperties.swift in Sources */, 677E65C22C5A15F40039E2C5 /* FolderEntity+CoreDataClass.swift in Sources */, 677E65C32C5A15F40039E2C5 /* FolderEntity+CoreDataProperties.swift in Sources */, + 67A2AF982C6BC4AE00039F30 /* PreviewCellLayout.swift in Sources */, 672C464A2C47BD8800497EF0 /* String+StringKeys.swift in Sources */, 677E65EB2C5A36AE0039E2C5 /* UpdateFolderUseCase.swift in Sources */, 53014F962C11A8E80071CE39 /* ScannerViewController.swift in Sources */, diff --git a/MiniScanner/Extensions/UIImage+Images.swift b/MiniScanner/Extensions/UIImage+Images.swift index d05180e..20b0fd7 100644 --- a/MiniScanner/Extensions/UIImage+Images.swift +++ b/MiniScanner/Extensions/UIImage+Images.swift @@ -27,6 +27,7 @@ extension UIImage { static let search = UIImage(resource: .searchIc) static let layoutGrid = UIImage(resource: .layoutGridIc) static let layoutList = UIImage(resource: .layoutListIc) + static let layoutImages = UIImage(resource: .layoutImagesIc) static let folderOpen = UIImage(resource: .folderOpenIc) static let gallery = UIImage(resource: .galleryIc) diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard b/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard index c38382f..e94452b 100644 --- a/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard +++ b/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard @@ -27,8 +27,27 @@ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YIu-mV-Xt3" userLabel="Top Section"> <rect key="frame" x="16" y="104" width="382" height="34"/> <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="g4H-6z-yTr" userLabel="Layout Button"> + <rect key="frame" x="31.5" y="4.5" width="25" height="25"/> + <constraints> + <constraint firstAttribute="width" secondItem="g4H-6z-yTr" secondAttribute="height" multiplier="1:1" id="w1c-RR-goA"/> + </constraints> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="layout-grid-ic"/> + <connections> + <action selector="layoutTapped:" destination="lAb-mo-IO6" eventType="touchUpInside" id="0Kj-dY-bkQ"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="R2E-Ce-wdD"> + <rect key="frame" x="0.0" y="5.5" width="23.5" height="23.5"/> + <constraints> + <constraint firstAttribute="width" secondItem="R2E-Ce-wdD" secondAttribute="height" id="4FN-TU-J5g"/> + </constraints> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="ellipsis" catalog="system"/> + </button> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TqR-ZS-2Pv"> - <rect key="frame" x="0.0" y="0.0" width="99.5" height="34"/> + <rect key="frame" x="220.5" y="0.0" width="99.5" height="34"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aMM-Hs-if2"> <rect key="frame" x="4" y="0.0" width="41.5" height="34"/> @@ -56,15 +75,6 @@ <constraint firstItem="aMM-Hs-if2" firstAttribute="leading" secondItem="TqR-ZS-2Pv" secondAttribute="leading" constant="4" id="xfJ-nL-Idd"/> </constraints> </view> - <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="R2E-Ce-wdD"> - <rect key="frame" x="0.0" y="-6.5" width="47.5" height="47.5"/> - <constraints> - <constraint firstAttribute="width" secondItem="R2E-Ce-wdD" secondAttribute="height" id="4FN-TU-J5g"/> - </constraints> - <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> - <state key="normal" image="ellipsis" catalog="system"/> - <buttonConfiguration key="configuration" style="plain" image="ellipsis" catalog="system"/> - </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yWg-kQ-A5X"> <rect key="frame" x="336" y="0.0" width="46" height="34"/> <state key="normal" title="Button"/> @@ -84,21 +94,34 @@ <constraints> <constraint firstItem="Jpc-O0-8Id" firstAttribute="top" secondItem="YIu-mV-Xt3" secondAttribute="top" id="1mG-M0-gNq"/> <constraint firstItem="R2E-Ce-wdD" firstAttribute="leading" secondItem="YIu-mV-Xt3" secondAttribute="leading" id="9we-Pv-599"/> + <constraint firstItem="g4H-6z-yTr" firstAttribute="leading" secondItem="R2E-Ce-wdD" secondAttribute="trailing" constant="8" id="GtU-Pb-Hxs"/> <constraint firstAttribute="bottom" secondItem="TqR-ZS-2Pv" secondAttribute="bottom" id="ZUQ-Ag-eOW"/> <constraint firstItem="Jpc-O0-8Id" firstAttribute="centerX" secondItem="YIu-mV-Xt3" secondAttribute="centerX" id="att-Ib-oBi"/> <constraint firstItem="yWg-kQ-A5X" firstAttribute="centerY" secondItem="YIu-mV-Xt3" secondAttribute="centerY" id="cPj-8z-trd"/> + <constraint firstItem="g4H-6z-yTr" firstAttribute="centerY" secondItem="YIu-mV-Xt3" secondAttribute="centerY" id="cVc-Gu-Hzk"/> <constraint firstItem="R2E-Ce-wdD" firstAttribute="centerY" secondItem="YIu-mV-Xt3" secondAttribute="centerY" id="eQy-LQ-RwM"/> <constraint firstItem="TqR-ZS-2Pv" firstAttribute="top" secondItem="YIu-mV-Xt3" secondAttribute="top" id="g8Q-cU-fNM"/> <constraint firstItem="yWg-kQ-A5X" firstAttribute="trailing" secondItem="YIu-mV-Xt3" secondAttribute="trailing" id="h3Q-dw-S3L"/> - <constraint firstItem="TqR-ZS-2Pv" firstAttribute="leading" secondItem="YIu-mV-Xt3" secondAttribute="leading" id="ioq-C9-2iC"/> <constraint firstItem="yWg-kQ-A5X" firstAttribute="top" secondItem="YIu-mV-Xt3" secondAttribute="top" id="kyG-zt-er0"/> <constraint firstAttribute="bottom" secondItem="Jpc-O0-8Id" secondAttribute="bottom" id="kzj-Z3-1lw"/> + <constraint firstItem="yWg-kQ-A5X" firstAttribute="leading" secondItem="TqR-ZS-2Pv" secondAttribute="trailing" constant="16" id="szf-Uv-3UE"/> </constraints> </view> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HkK-Fc-Rgz" customClass="FSPagerView" customModule="MiniScanner" customModuleProvider="target"> <rect key="frame" x="0.0" y="138" width="414" height="543"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> </view> + <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="jFy-zp-lQZ"> + <rect key="frame" x="0.0" y="154" width="414" height="511"/> + <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <collectionViewFlowLayout key="collectionViewLayout" automaticEstimatedItemSize="YES" minimumLineSpacing="10" minimumInteritemSpacing="10" id="ofj-ZA-k7O"> + <size key="itemSize" width="128" height="128"/> + <size key="headerReferenceSize" width="0.0" height="0.0"/> + <size key="footerReferenceSize" width="0.0" height="0.0"/> + <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> + </collectionViewFlowLayout> + <cells/> + </collectionView> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YNN-5t-yKF" userLabel="Page Index View"> <rect key="frame" x="123.5" y="681" width="167" height="40"/> <subviews> @@ -330,13 +353,17 @@ <constraint firstItem="YIu-mV-Xt3" firstAttribute="top" secondItem="4bJ-Eb-Q72" secondAttribute="top" constant="12" id="M1U-Fa-vUM"/> <constraint firstItem="oyQ-Gx-pj4" firstAttribute="leading" secondItem="4bJ-Eb-Q72" secondAttribute="leading" id="Mwk-iJ-rhi"/> <constraint firstAttribute="trailing" secondItem="7cK-Hy-SJm" secondAttribute="trailing" id="OYo-8j-emp"/> + <constraint firstItem="jFy-zp-lQZ" firstAttribute="leading" secondItem="4bJ-Eb-Q72" secondAttribute="leading" id="Ugj-5f-hn5"/> <constraint firstItem="4bJ-Eb-Q72" firstAttribute="trailing" secondItem="HkK-Fc-Rgz" secondAttribute="trailing" id="d8m-yC-rcc"/> <constraint firstItem="RBy-RI-NPW" firstAttribute="bottom" secondItem="oyQ-Gx-pj4" secondAttribute="top" id="f17-ly-k6b"/> + <constraint firstItem="YNN-5t-yKF" firstAttribute="top" secondItem="jFy-zp-lQZ" secondAttribute="bottom" constant="16" id="g7o-EH-YzN"/> <constraint firstItem="HkK-Fc-Rgz" firstAttribute="leading" secondItem="4bJ-Eb-Q72" secondAttribute="leading" id="lmq-dV-1Xb"/> <constraint firstItem="HkK-Fc-Rgz" firstAttribute="top" secondItem="YIu-mV-Xt3" secondAttribute="bottom" id="r9f-lx-Udl"/> <constraint firstItem="4bJ-Eb-Q72" firstAttribute="trailing" secondItem="RBy-RI-NPW" secondAttribute="trailing" id="sxU-bk-A97"/> <constraint firstItem="4bJ-Eb-Q72" firstAttribute="trailing" secondItem="YIu-mV-Xt3" secondAttribute="trailing" constant="16" id="tDh-4W-Iol"/> + <constraint firstItem="4bJ-Eb-Q72" firstAttribute="trailing" secondItem="jFy-zp-lQZ" secondAttribute="trailing" id="xPk-Qg-p5S"/> <constraint firstItem="RBy-RI-NPW" firstAttribute="leading" secondItem="4bJ-Eb-Q72" secondAttribute="leading" id="ze4-pg-QcJ"/> + <constraint firstItem="jFy-zp-lQZ" firstAttribute="top" secondItem="YIu-mV-Xt3" secondAttribute="bottom" constant="16" id="zma-rp-RtQ"/> </constraints> </view> <navigationItem key="navigationItem" id="Nf0-zM-NqU"> @@ -345,9 +372,11 @@ <connections> <outlet property="clearSelectionButton" destination="SHr-Ym-2En" id="mOk-0b-t3s"/> <outlet property="closeButton" destination="yWg-kQ-A5X" id="2CJ-QC-mvV"/> + <outlet property="collectionView" destination="jFy-zp-lQZ" id="IoW-dj-fcR"/> <outlet property="currentPageLabel" destination="AEe-Tw-owM" id="iwi-YD-CJm"/> <outlet property="directShareLabel" destination="GR8-HI-C1V" id="586-VP-rx9"/> <outlet property="extraButton" destination="R2E-Ce-wdD" id="gCe-Dd-88D"/> + <outlet property="layoutButton" destination="g4H-6z-yTr" id="eR3-5s-JPn"/> <outlet property="nextPageButton" destination="cVY-eB-Oiw" id="anB-qz-F19"/> <outlet property="pagerView" destination="HkK-Fc-Rgz" id="FYA-r7-Pxm"/> <outlet property="previousPageButton" destination="zeo-0x-xpI" id="ef5-6G-8Bd"/> @@ -390,6 +419,7 @@ <image name="edit-ic" width="24" height="23"/> <image name="ellipsis" catalog="system" width="128" height="37"/> <image name="gmail" width="48" height="48"/> + <image name="layout-grid-ic" width="24" height="25"/> <image name="more-img" width="48" height="48"/> <image name="print-img" width="49" height="48"/> <image name="printer" catalog="system" width="128" height="111"/> diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift index f64676d..7fbffae 100644 --- a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift +++ b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift @@ -15,6 +15,9 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable struct Constants { static let reuseIdentifier = String(describing: DocumentPreviewViewController.self) + + static let cellIdentifier = String(describing: ScannedItemPagerViewCell.self) + static let storyboardName = "DocumentPreview" } @@ -26,9 +29,12 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable } @IBOutlet private weak var pagerView: FSPagerView! + @IBOutlet weak var collectionView: UICollectionView! + @IBOutlet weak var directShareLabel: UILabel! @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var closeButton: UIButton! + @IBOutlet weak var layoutButton: UIButton! @IBOutlet weak var currentPageLabel: UILabel! @IBOutlet weak var nextPageButton: UIButton! @@ -70,6 +76,17 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable private var renameAlertController: UIAlertController? private var renameFileName: String? + private var layoutType: PreviewCellLayout = .pager { + didSet { + switch layoutType { + case .pager: + displayPager() + case .grid: + displayGrid() + } + } + } + lazy var activityIndicator: UIActivityIndicatorView = { let activityIndicator = UIActivityIndicatorView(style: .large) activityIndicator.color = .gray @@ -129,18 +146,24 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable updateCurrentPageLabel() + layoutButton.tintColor = .mainText + shareType = userSettings.defaultFileType.shareType + layoutType = .pager + setupMenu() setupExtraButtonMenu() setupPagerView() + + setupCollectionView() } private func setupPagerView() { - pagerView.register(ScannedItemPagerViewCell.self, forCellWithReuseIdentifier: "cell") + pagerView.register(ScannedItemPagerViewCell.self, forCellWithReuseIdentifier: Constants.cellIdentifier) pagerView.transformer = FSPagerViewTransformer(type: .linear) @@ -156,6 +179,24 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable pagerView.backgroundColor = .clear } + private func setupCollectionView() { + + let layout = UICollectionViewFlowLayout() + + layout.scrollDirection = .vertical + layout.minimumLineSpacing = 10 + layout.minimumInteritemSpacing = 10 + + collectionView.collectionViewLayout = layout + + collectionView.register(ScannedItemPagerViewCell.self, forCellWithReuseIdentifier: Constants.cellIdentifier) + + collectionView.delegate = self + collectionView.dataSource = self + + collectionView.backgroundColor = .mainBackground + } + private func setupExtraButtonMenu() { let move = UIAction(title: .move.localized) { [self] _ in @@ -183,7 +224,7 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable updateSelectedImagesLabel() - pagerView.reloadData() + refreshContainer() } private func updateCurrentPageIndex(index: Int) { @@ -206,7 +247,6 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable private func updateSelectedImagesLabel() { selectedPagesView.isHidden = selectedPagesCount == 0 - extraButton.isHidden = selectedPagesCount != 0 selectedPagesLabel.set(text: String(selectedPagesCount)) } @@ -214,6 +254,40 @@ final class DocumentPreviewViewController: UIViewController, ScanSessionSharable private func handleShareTypeChanged() { shareTypeLabel.set(localized: shareType.displayName) } + + private func changeLayout(to layout: PreviewCellLayout) { + self.layoutType = layout + } + + private func displayPager() { + pagerView.isHidden = false + collectionView.isHidden = true + } + + private func displayGrid() { + pagerView.isHidden = true + collectionView.isHidden = false + } + + private func refreshContainer() { + + switch layoutType { + case .pager: + pagerView.reloadData() + case .grid: + collectionView.reloadData() + } + } + + private func refreshContainer(at index: Int) { + + switch layoutType { + case .pager: + pagerView.reloadData(at: index) + case .grid: + collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) + } + } } extension DocumentPreviewViewController: FSPagerViewDelegate, FSPagerViewDataSource { @@ -224,7 +298,7 @@ extension DocumentPreviewViewController: FSPagerViewDelegate, FSPagerViewDataSou func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell { - let cell = pagerView.dequeueReusableCell(withReuseIdentifier: "cell", at: index) as! ScannedItemPagerViewCell + let cell = pagerView.dequeueReusableCell(withReuseIdentifier: Constants.cellIdentifier, at: index) as! ScannedItemPagerViewCell let scannedItem = session.scannedItems[index] @@ -239,6 +313,41 @@ extension DocumentPreviewViewController: FSPagerViewDelegate, FSPagerViewDataSou } } +// MARK: - Collection view data source and delegate + +extension DocumentPreviewViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + + let itemHeight = 200.0 + + let itemWidth = collectionView.frame.width / 2 - (5 + 32) + + return CGSize(width: itemWidth, height: itemHeight) + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + UIEdgeInsets(top: 0, left: 32, bottom: 32, right: 32) + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + session.itemsCount + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.cellIdentifier, for: indexPath) as? ScannedItemPagerViewCell else { return UICollectionViewCell() } + + let index = indexPath.row + + let scannedItem = session.scannedItems[index] + + cell.configure(with: scannedItem, at: index, delegate: self) + + return cell + } +} + extension DocumentPreviewViewController: ScannedItemPagerViewCellDelegate { func select(at index: Int) { @@ -247,7 +356,7 @@ extension DocumentPreviewViewController: ScannedItemPagerViewCellDelegate { selectedPagesCount += session.scannedItems[index].isSelected ? 1 : -1 - pagerView.reloadData(at: index) + refreshContainer(at: index) updateSelectedImagesLabel() } @@ -427,6 +536,13 @@ extension DocumentPreviewViewController { clearSelection() } + @IBAction func layoutTapped(_ sender: Any) { + layoutType = layoutType.toggle() + layoutButton.setImage(layoutType.image, for: .normal) + + changeLayout(to: layoutType) + } + @IBAction func nextPageTapped(_ sender: UIButton) { if currentPageIndex < (session.itemsCount - 1) { @@ -616,7 +732,7 @@ extension DocumentPreviewViewController { updateScanSessionUseCase.execute(with: session) - pagerView.reloadData() + refreshContainer() delegate?.sessionUpdated(session: session) diff --git a/MiniScanner/Modules/DocumentPreview/PreviewCellLayout.swift b/MiniScanner/Modules/DocumentPreview/PreviewCellLayout.swift new file mode 100644 index 0000000..92f3e4b --- /dev/null +++ b/MiniScanner/Modules/DocumentPreview/PreviewCellLayout.swift @@ -0,0 +1,32 @@ +// +// PreviewCellLayout.swift +// MiniScanner +// +// Created by Mustafa Merza on 8/13/24. +// Copyright © 2024 AppsNectar. All rights reserved. +// + +import Foundation + +enum PreviewCellLayout { + case pager + case grid + + var image: UIImage { + switch self { + case .pager: + .layoutGrid + case .grid: + .layoutImages + } + } + + func toggle() -> Self { + switch self { + case .pager: + .grid + case .grid: + .pager + } + } +} diff --git a/MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/Contents.json b/MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/Contents.json new file mode 100644 index 0000000..52445b5 --- /dev/null +++ b/MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "layout-images-ic.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/layout-images-ic.svg b/MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/layout-images-ic.svg new file mode 100644 index 0000000..b0d8a94 --- /dev/null +++ b/MiniScanner/Supporting Files/Icons.xcassets/layout-images-ic.imageset/layout-images-ic.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M18 22H4C3.46957 22 2.96086 21.7893 2.58579 21.4142C2.21071 21.0391 2 20.5304 2 20V6M22 13L20.704 11.704C20.252 11.2522 19.6391 10.9983 19 10.9983C18.3609 10.9983 17.748 11.2522 17.296 11.704L11 18M14 8C14 9.10457 13.1046 10 12 10C10.8954 10 10 9.10457 10 8C10 6.89543 10.8954 6 12 6C13.1046 6 14 6.89543 14 8ZM8 2H20C21.1046 2 22 2.89543 22 4V16C22 17.1046 21.1046 18 20 18H8C6.89543 18 6 17.1046 6 16V4C6 2.89543 6.89543 2 8 2Z" stroke="#1C1C1E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +</svg> -- GitLab