diff --git a/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate b/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate index 0a920dad79f261fb88caad6d2749d7119facd989..2d1d43ef753c3ff1fb811355bc21d6c8fc1fb1a5 100644 Binary files a/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate and b/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index f08bae0b390dc324e22f80494372542f7b295a26..216ee44a169a423c337b1cc8c733a132117605a0 100644 --- a/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/MiniScanner.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -3,38 +3,4 @@ uuid = "270C854E-19C5-4254-A77F-7774BFB2FDA6" type = "0" version = "2.0"> - <Breakpoints> - <BreakpointProxy - BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> - <BreakpointContent - uuid = "95CD7D19-EA69-443B-B2CB-85BF78B4914E" - shouldBeEnabled = "No" - ignoreCount = "0" - continueAfterRunningActions = "No" - filePath = "MiniScanner/Modules/EditViewController/EditViewController.swift" - startingColumnNumber = "9223372036854775807" - endingColumnNumber = "9223372036854775807" - startingLineNumber = "329" - endingLineNumber = "329" - landmarkName = "updateImage(screenShot:at:)" - landmarkType = "7"> - </BreakpointContent> - </BreakpointProxy> - <BreakpointProxy - BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> - <BreakpointContent - uuid = "E0378F70-5CED-4217-A237-C2D061DC0AB8" - shouldBeEnabled = "No" - ignoreCount = "0" - continueAfterRunningActions = "No" - filePath = "MiniScanner/Modules/EditViewController/EditViewController.swift" - startingColumnNumber = "9223372036854775807" - endingColumnNumber = "9223372036854775807" - startingLineNumber = "330" - endingLineNumber = "330" - landmarkName = "updateImage(screenShot:at:)" - landmarkType = "7"> - </BreakpointContent> - </BreakpointProxy> - </Breakpoints> </Bucket> diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard b/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard index 58e91d199abf5e15b1a40950828addefb11825db..c66d3920b1925575ab2c25996a48bc481453b396 100644 --- a/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard +++ b/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard @@ -1,13 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="b1K-XK-mdX"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="b1K-XK-mdX"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> + <customFonts key="customFonts"> + <array key="Poppins-Medium.ttf"> + <string>Poppins-Medium</string> + </array> + </customFonts> <scenes> <!--Document Preview View Controller--> <scene sceneID="19p-no-z6i"> @@ -18,7 +23,7 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HkK-Fc-Rgz" customClass="CustomPDFView" customModule="MiniScanner" customModuleProvider="target"> - <rect key="frame" x="0.0" y="88" width="414" height="730"/> + <rect key="frame" x="0.0" y="92" width="414" height="614"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> </view> <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyQ-Gx-pj4"> @@ -32,12 +37,6 @@ <action selector="addPageTapped:" destination="lAb-mo-IO6" id="We1-uS-Ln6"/> </connections> </barButtonItem> - <barButtonItem style="plain" systemItem="flexibleSpace" id="mcP-tt-3bA"/> - <barButtonItem title="Item" image="square.and.arrow.up" catalog="system" id="ucN-Zr-CWB"> - <connections> - <action selector="shareTapped:" destination="lAb-mo-IO6" id="SsG-S8-qkx"/> - </connections> - </barButtonItem> <barButtonItem style="plain" systemItem="flexibleSpace" id="pCQ-bY-37s"/> <barButtonItem title="Item" image="pencil.tip.crop.circle" catalog="system" id="ity-9J-3Up"> <connections> @@ -52,25 +51,114 @@ </barButtonItem> </items> </toolbar> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7cK-Hy-SJm"> + <rect key="frame" x="0.0" y="706" width="414" height="112"/> + <subviews> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dOf-mQ-Tzg"> + <rect key="frame" x="0.0" y="0.0" width="414" height="1"/> + <color key="backgroundColor" red="0.3921568627" green="0.3921568627" blue="0.3921568627" alpha="1" colorSpace="calibratedRGB"/> + <constraints> + <constraint firstAttribute="height" constant="1" id="Ttm-tp-Zo6"/> + </constraints> + </view> + <label opaque="NO" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Direct Share" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GR8-HI-C1V"> + <rect key="frame" x="158" y="13" width="98.5" height="22"/> + <fontDescription key="fontDescription" name="Poppins-Medium" family="Poppins" pointSize="16"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="12.5" translatesAutoresizingMaskIntoConstraints="NO" id="seU-fd-Aqq"> + <rect key="frame" x="62" y="50" width="290" height="48"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Snt-pf-H3g"> + <rect key="frame" x="0.0" y="0.0" width="48" height="48"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="more"/> + <connections> + <action selector="moreTapped:" destination="lAb-mo-IO6" eventType="touchUpInside" id="zw9-d8-SWm"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zd1-3T-PwV"> + <rect key="frame" x="60.5" y="0.0" width="48" height="48"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="print"/> + <connections> + <action selector="printTapped:" destination="lAb-mo-IO6" eventType="touchUpInside" id="fim-ht-t0j"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="J0d-J4-wMP"> + <rect key="frame" x="121" y="0.0" width="48" height="48"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="gmail"/> + <connections> + <action selector="gmailTapped:" destination="lAb-mo-IO6" eventType="touchUpInside" id="u0l-Ec-SlW"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KMc-eH-hbo"> + <rect key="frame" x="181.5" y="0.0" width="48" height="48"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="telegram"/> + <connections> + <action selector="telegramTapped:" destination="lAb-mo-IO6" eventType="touchUpInside" id="dpg-dY-YZc"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xNG-Q7-5jF"> + <rect key="frame" x="242" y="0.0" width="48" height="48"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <state key="normal" image="whatsapp"/> + <connections> + <action selector="whatsappTapped:" destination="lAb-mo-IO6" eventType="touchUpInside" id="Vo8-nt-dMR"/> + </connections> + </button> + </subviews> + <constraints> + <constraint firstAttribute="height" constant="48" id="fry-jr-j4m"/> + <constraint firstAttribute="width" constant="290" id="wG4-iX-fXX"/> + </constraints> + </stackView> + <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RBy-RI-NPW"> + <rect key="frame" x="0.0" y="111" width="414" height="1"/> + <color key="backgroundColor" red="0.3921568627" green="0.3921568627" blue="0.3921568627" alpha="1" colorSpace="calibratedRGB"/> + <constraints> + <constraint firstAttribute="height" constant="1" id="mG9-7i-hAB"/> + </constraints> + </view> + </subviews> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <constraints> + <constraint firstItem="RBy-RI-NPW" firstAttribute="leading" secondItem="7cK-Hy-SJm" secondAttribute="leading" id="01q-F9-fZU"/> + <constraint firstItem="seU-fd-Aqq" firstAttribute="centerX" secondItem="7cK-Hy-SJm" secondAttribute="centerX" id="1a1-Su-8l5"/> + <constraint firstAttribute="bottom" secondItem="RBy-RI-NPW" secondAttribute="bottom" id="75K-oO-I23"/> + <constraint firstAttribute="height" constant="112" id="BxB-kE-esX"/> + <constraint firstItem="dOf-mQ-Tzg" firstAttribute="leading" secondItem="7cK-Hy-SJm" secondAttribute="leading" id="Mjs-LE-vow"/> + <constraint firstItem="dOf-mQ-Tzg" firstAttribute="top" secondItem="7cK-Hy-SJm" secondAttribute="top" id="OJt-KA-SAm"/> + <constraint firstItem="GR8-HI-C1V" firstAttribute="centerX" secondItem="7cK-Hy-SJm" secondAttribute="centerX" id="PeR-HM-sJV"/> + <constraint firstAttribute="bottom" secondItem="RBy-RI-NPW" secondAttribute="bottom" id="R1a-5D-S6r"/> + <constraint firstAttribute="trailing" secondItem="dOf-mQ-Tzg" secondAttribute="trailing" id="RXz-Zb-VIN"/> + <constraint firstItem="GR8-HI-C1V" firstAttribute="top" secondItem="dOf-mQ-Tzg" secondAttribute="bottom" constant="12" id="a9w-eE-GDu"/> + <constraint firstItem="seU-fd-Aqq" firstAttribute="top" secondItem="GR8-HI-C1V" secondAttribute="bottom" constant="15" id="b5C-MZ-1dY"/> + <constraint firstAttribute="trailing" secondItem="RBy-RI-NPW" secondAttribute="trailing" id="yDj-5v-ojX"/> + <constraint firstItem="RBy-RI-NPW" firstAttribute="top" secondItem="seU-fd-Aqq" secondAttribute="bottom" constant="13" id="ygU-KF-9wQ"/> + </constraints> + </view> </subviews> <viewLayoutGuide key="safeArea" id="4bJ-Eb-Q72"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> + <constraint firstItem="7cK-Hy-SJm" firstAttribute="top" secondItem="HkK-Fc-Rgz" secondAttribute="bottom" id="1Dx-rR-0cv"/> <constraint firstItem="oyQ-Gx-pj4" firstAttribute="bottom" secondItem="4bJ-Eb-Q72" secondAttribute="bottom" id="2IQ-zw-463"/> <constraint firstItem="oyQ-Gx-pj4" firstAttribute="trailing" secondItem="4bJ-Eb-Q72" secondAttribute="trailing" id="76k-FR-uDf"/> + <constraint firstItem="7cK-Hy-SJm" firstAttribute="leading" secondItem="yh9-W2-Nlc" secondAttribute="leading" id="CkG-TO-NfS"/> <constraint firstItem="oyQ-Gx-pj4" firstAttribute="leading" secondItem="4bJ-Eb-Q72" secondAttribute="leading" id="Mwk-iJ-rhi"/> - <constraint firstItem="oyQ-Gx-pj4" firstAttribute="top" secondItem="HkK-Fc-Rgz" secondAttribute="bottom" id="QKe-zy-8DI"/> + <constraint firstAttribute="trailing" secondItem="7cK-Hy-SJm" secondAttribute="trailing" id="OYo-8j-emp"/> <constraint firstItem="HkK-Fc-Rgz" firstAttribute="trailing" secondItem="4bJ-Eb-Q72" secondAttribute="trailing" id="d8m-yC-rcc"/> <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="4bJ-Eb-Q72" secondAttribute="top" id="nQC-v2-YlW"/> + <constraint firstItem="oyQ-Gx-pj4" firstAttribute="top" secondItem="7cK-Hy-SJm" secondAttribute="bottom" id="pg5-fm-Fnq"/> </constraints> </view> <navigationItem key="navigationItem" id="Nf0-zM-NqU"> - <barButtonItem key="rightBarButtonItem" title="Item" image="printer" catalog="system" id="Z0H-Ze-WXm"> - <connections> - <action selector="printTapped:" destination="lAb-mo-IO6" id="cdf-9F-35l"/> - </connections> - </barButtonItem> + <barButtonItem key="rightBarButtonItem" title="Item" image="printer" catalog="system" hidden="YES" id="Z0H-Ze-WXm"/> </navigationItem> <connections> <outlet property="pdfView" destination="HkK-Fc-Rgz" id="3sS-2Q-v88"/> @@ -86,7 +174,7 @@ <navigationController automaticallyAdjustsScrollViewInsets="NO" id="b1K-XK-mdX" sceneMemberID="viewController"> <toolbarItems/> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="zSv-8e-tlI"> - <rect key="frame" x="0.0" y="44" width="414" height="44"/> + <rect key="frame" x="0.0" y="48" width="414" height="44"/> <autoresizingMask key="autoresizingMask"/> </navigationBar> <nil name="viewControllers"/> @@ -100,11 +188,15 @@ </scene> </scenes> <resources> - <image name="pencil.tip.crop.circle" catalog="system" width="128" height="121"/> + <image name="gmail" width="48" height="48"/> + <image name="more" width="76" height="75"/> + <image name="pencil.tip.crop.circle" catalog="system" width="128" height="123"/> <image name="plus.app" catalog="system" width="128" height="114"/> + <image name="print" width="68" height="67"/> <image name="printer" catalog="system" width="128" height="111"/> - <image name="square.and.arrow.up" catalog="system" width="115" height="128"/> - <image name="trash" catalog="system" width="121" height="128"/> + <image name="telegram" width="68" height="67"/> + <image name="trash" catalog="system" width="117" height="128"/> + <image name="whatsapp" width="68" height="67"/> <systemColor name="systemBackgroundColor"> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </systemColor> diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift index b33345a55916f672b950b1b0d30315089818513e..390760695b824aa5b10e949a24ddfd872b82227c 100644 --- a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift +++ b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift @@ -1,5 +1,7 @@ import UIKit import VisionKit +import LNExtensionExecutor +import ZLImageEditor final class DocumentPreviewViewController: UIViewController { @@ -19,7 +21,16 @@ final class DocumentPreviewViewController: UIViewController { var file: File? private var scannedItem: ScannedItem! - + var payload: [Any] = [] + + lazy private var activityIndicator: UIActivityIndicatorView = { + let activityIndicator = UIActivityIndicatorView(style: .large) + activityIndicator.color = .white + activityIndicator.hidesWhenStopped = true + activityIndicator.translatesAutoresizingMaskIntoConstraints = false + return activityIndicator + }() + override func viewDidLoad() { super.viewDidLoad() @@ -27,24 +38,87 @@ final class DocumentPreviewViewController: UIViewController { pdfView.accessibilityIdentifier = "pdfView" navigationItem.title = file?.displayName pdfView.setDocument(file?.pdfDocument) + if let url = file?.fileURL { + payload = [url] + } + + } + + private func directShareWith(extensionBundleIdentifier: String) async { + do { + let executor = try LNExtensionExecutor(extensionBundleIdentifier: extensionBundleIdentifier) + let (completed, returnItems) = try await executor.execute(withActivityItems: payload, on: self) + print("completed: \(completed) return items: \(returnItems)") + + } catch(let error) { + print("error: \(error.localizedDescription)") + } } - @IBAction func printTapped(_ sender: UIBarButtonItem) { - guard let documentURL = file?.fileURL else { return } + func printPDF(from url: URL) { + let printInfo = UIPrintInfo(dictionary:nil) + printInfo.jobName = url.lastPathComponent + printInfo.outputType = .general let printController = UIPrintInteractionController.shared - printController.delegate = self - if UIPrintInteractionController.canPrint(documentURL) { - let printInfo = UIPrintInfo(dictionary: nil) - printInfo.outputType = .photo - printController.printInfo = printInfo - printController.showsNumberOfCopies = true + printController.printInfo = printInfo + + let pdfData = try? Data(contentsOf: url) + if pdfData != nil { + printController.printingItem = pdfData } - printController.printingItems = [documentURL] - printController.present(from: view.frame, in: view, animated: true, completionHandler: nil) + printController.present(animated: true, completionHandler: nil) + } + + @IBAction func whatsappTapped(_ sender: UIButton) { + activityIndicator.startAnimating() + DispatchQueue.main.async { + + Task { + await self.directShareWith(extensionBundleIdentifier: ShareOptions.whatsapp) + } + self.activityIndicator.stopAnimating() + } } + @IBAction func telegramTapped(_ sender: UIButton) { + activityIndicator.startAnimating() + DispatchQueue.main.async { + + Task { + await self.directShareWith(extensionBundleIdentifier: ShareOptions.telegram) + } + self.activityIndicator.stopAnimating() + } + } + + @IBAction func gmailTapped(_ sender: UIButton) { + activityIndicator.startAnimating() + DispatchQueue.main.async { + Task { + await self.directShareWith(extensionBundleIdentifier: ShareOptions.gmail) + self.activityIndicator.stopAnimating() + } + } + } + + @IBAction func printTapped(_ sender: UIButton) { + DispatchQueue.main.async { + self.printPDF(from: self.payload[0] as! URL) + } + } + + @IBAction func moreTapped(_ sender: UIButton) { + DispatchQueue.main.async { + self.activityIndicator.startAnimating() + let shareController = UIActivityViewController(activityItems: self.payload, applicationActivities: nil) + self.present(shareController, animated: true, completion: nil) + self.activityIndicator.stopAnimating() + } + } + + @IBAction func addPageTapped(_ sender: UIBarButtonItem) { let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) @@ -70,13 +144,6 @@ final class DocumentPreviewViewController: UIViewController { present(alertController, animated: true) } - @IBAction func shareTapped(_ sender: UIBarButtonItem) { - guard let documentURL = file?.fileURL else { return } - let controller = UIActivityViewController(activityItems: [documentURL], applicationActivities: nil) - controller.popoverPresentationController?.barButtonItem = sender - present(controller, animated: true) - } - @IBAction func drawTapped(_ sender: UIBarButtonItem) { let previewController = PencilKitViewController() previewController.dataSource = self diff --git a/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift b/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift index 0ac0f2ad679ac43c570b02d4c52d2142d03ab790..7a0b794ac9746ef57adb61b8c90504c6eb563ddd 100644 --- a/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift +++ b/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift @@ -25,12 +25,6 @@ class PencilKitViewController: QLPreviewController { //This hides the share item if let add = self.children.first as? UINavigationController { add.view.subviews.filter { $0 is UINavigationBar }.first?.subviews.last?.isHidden = true - -// if let pencilButton = (add.view.subviews.filter { $0 is UINavigationBar }.first as? UINavigationBar)?.items?.last?.rightBarButtonItem as? UIBarButtonItem { - // pencilButton.action - // UIApplication.shared.sendAction(pencilButton.action!, to: pencilButton.target, from: self, for: nil) - // _ = pencilButton.target?.perform(pencilButton.action, with: nil) -// } } } } diff --git a/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.swift b/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.swift index 4d85546d573fea2bb8efdfc4cd0b012106e2f140..4b48ecc4cb7b386f7241a6fb3d0519a0787f1899 100644 --- a/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.swift +++ b/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.swift @@ -16,6 +16,10 @@ protocol ShareSheetViewControllerDelegate { func saveTapped(name: String) } +protocol PreviewDelegate { + func previewTapped() +} + class ShareSheetViewController: UIViewController { // MARK: - Outlets @IBOutlet weak var pdfImage: UIImageView! @@ -27,12 +31,16 @@ class ShareSheetViewController: UIViewController { @IBOutlet weak var printLabel: UILabel! @IBOutlet weak var moreLabel: UILabel! @IBOutlet weak var backgroundView: UIView! + @IBOutlet weak var previewButton: UIButton! + @IBOutlet weak var shareStackView: UIStackView! + @IBOutlet weak var shareStack_height: NSLayoutConstraint! // MARK: - Properties var session: MultiPageScanSession? var delegate: ShareSheetViewControllerDelegate? var selectedFolder: AppConfigurator.Folder? - + var previewDelegate: PreviewDelegate? + var isShareShown: Bool = true // MARK: - LifeCycle override func viewDidLoad() { super.viewDidLoad() @@ -59,6 +67,9 @@ class ShareSheetViewController: UIViewController { pdfImage.layer.cornerRadius = 10 pdfImage.clipsToBounds = true pdfImage.contentMode = .scaleAspectFill + previewButton.setImage(UIImage(named: "preview")?.tint(with: .mainText), for: .normal) + shareStackView.isHidden = !isShareShown + shareStack_height.constant = isShareShown ? 96 : 0 } private func setup() { @@ -95,6 +106,13 @@ class ShareSheetViewController: UIViewController { } + @IBAction func previewTapped(_ sender: UIButton) { + self.dismiss(animated: true) { + self.previewDelegate?.previewTapped() + } + + } + @IBAction func printTapped(_ sender: UIButton) { delegate?.printTapped() diff --git a/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.xib b/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.xib index c0c864e44c1211772ab66d9bf1076249f858a1e8..94b9b44ff441b6553c51d6215be21531de554808 100644 --- a/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.xib +++ b/MiniScanner/Modules/Documents/CustomViews/ShareSheet/ShareSheetViewController.xib @@ -17,7 +17,10 @@ <outlet property="moreLabel" destination="rwY-MB-Zuv" id="B1K-Il-m8T"/> <outlet property="pagesCountLabel" destination="6Jm-m2-xDU" id="Zmu-ZI-pfw"/> <outlet property="pdfImage" destination="vVX-eM-04Y" id="Qcm-o2-MiA"/> + <outlet property="previewButton" destination="ZUs-PW-eEp" id="PDQ-NI-F6e"/> <outlet property="printLabel" destination="3fw-XH-XNf" id="h0S-9m-GBo"/> + <outlet property="shareStackView" destination="0af-ED-ocV" id="yBK-er-RQl"/> + <outlet property="shareStack_height" destination="c0g-x8-hTW" id="at7-RU-W4E"/> <outlet property="telegramLabel" destination="fo4-eH-W8h" id="JfP-DJ-SHA"/> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> <outlet property="whatsappLabel" destination="FOm-hX-tbN" id="J99-jS-aFh"/> @@ -266,6 +269,7 @@ </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FOm-hX-tbN"> <rect key="frame" x="0.0" y="67" width="66.666666666666671" height="29"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> @@ -305,6 +309,13 @@ <constraint firstAttribute="height" constant="2" id="hg3-mr-Xzb"/> </constraints> </view> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZUs-PW-eEp"> + <rect key="frame" x="314" y="26" width="90" height="125"/> + <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> + <connections> + <action selector="previewTapped:" destination="-1" eventType="touchUpInside" id="chb-bk-XLI"/> + </connections> + </button> </subviews> <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> @@ -320,18 +331,22 @@ <constraint firstItem="t4L-wL-wBw" firstAttribute="top" secondItem="vVX-eM-04Y" secondAttribute="top" id="HXv-mE-RCC"/> <constraint firstItem="YKf-2l-wvo" firstAttribute="top" secondItem="t4L-wL-wBw" secondAttribute="top" id="ILP-zC-yDp"/> <constraint firstItem="vVX-eM-04Y" firstAttribute="leading" secondItem="YKf-2l-wvo" secondAttribute="trailing" constant="24" id="K7w-vT-Dme"/> + <constraint firstItem="ZUs-PW-eEp" firstAttribute="centerX" secondItem="vVX-eM-04Y" secondAttribute="centerX" id="PGE-co-2kK"/> <constraint firstItem="Jzk-DM-xQM" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="Qy6-Xc-XBe"/> <constraint firstItem="6Jm-m2-xDU" firstAttribute="trailing" secondItem="t4L-wL-wBw" secondAttribute="trailing" id="SdD-pI-q8h"/> <constraint firstItem="t4L-wL-wBw" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="24" id="ThO-3x-BxJ"/> <constraint firstItem="Jzk-DM-xQM" firstAttribute="trailing" secondItem="fnl-2z-Ty3" secondAttribute="trailing" id="UyQ-Zi-CPV"/> <constraint firstItem="YKf-2l-wvo" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="24" id="W5k-v0-BvG"/> + <constraint firstItem="ZUs-PW-eEp" firstAttribute="centerY" secondItem="vVX-eM-04Y" secondAttribute="centerY" id="WN1-Bz-oDO"/> <constraint firstItem="vVX-eM-04Y" firstAttribute="leading" secondItem="t4L-wL-wBw" secondAttribute="trailing" constant="24" id="aII-Lz-VFe"/> <constraint firstItem="vVX-eM-04Y" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="26" id="cZS-73-qJ6"/> + <constraint firstItem="ZUs-PW-eEp" firstAttribute="height" secondItem="vVX-eM-04Y" secondAttribute="height" id="cnp-4m-AGp"/> <constraint firstItem="YKf-2l-wvo" firstAttribute="top" secondItem="t4L-wL-wBw" secondAttribute="bottom" id="f1E-zP-fMR"/> <constraint firstItem="JWB-a8-fO9" firstAttribute="leading" secondItem="t4L-wL-wBw" secondAttribute="leading" id="lCd-Cn-wyA"/> <constraint firstAttribute="bottom" secondItem="Jzk-DM-xQM" secondAttribute="bottom" id="nwW-TM-P23"/> <constraint firstItem="6ha-V2-bsb" firstAttribute="top" secondItem="vVX-eM-04Y" secondAttribute="bottom" constant="24" id="uZO-ab-OHn"/> <constraint firstItem="6ha-V2-bsb" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="30" id="yqL-O1-wMN"/> + <constraint firstItem="ZUs-PW-eEp" firstAttribute="width" secondItem="vVX-eM-04Y" secondAttribute="width" id="zPm-aS-dQw"/> </constraints> <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> <variation key="default"> diff --git a/MiniScanner/Modules/Documents/DocumentsTableViewController.swift b/MiniScanner/Modules/Documents/DocumentsTableViewController.swift index 9220f0704177576f1bae3c00cb2df312e90a7115..d7ee0c3ca8ebb3830536e9247201e0eca45bc081 100644 --- a/MiniScanner/Modules/Documents/DocumentsTableViewController.swift +++ b/MiniScanner/Modules/Documents/DocumentsTableViewController.swift @@ -1,7 +1,7 @@ import UIKit import PDFKit import VisionKit -import ImagePicker +import PhotosUI final class DocumentsTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @@ -31,7 +31,10 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate, private var searchedViewModel: [File] = [] private var sortType: SortyFileType = .date - + var options:ImageScannerOptions! + var scannedItem = ScannedItem(originalImage: UIImage()) + var images: [UIImage] = [] + // private let noDocumentsimageView = UIImageView(image: UIImage(named: "box")) private var renameAlertController: UIAlertController? private var renameFileName: String? @@ -40,12 +43,14 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate, private var isSearching: Bool = false private var pageViewControllers: [UIViewController] = [] + private var scanSession: MultiPageScanSession? @IBOutlet weak var allFolderView_height: NSLayoutConstraint! private var localFileManager: LocalFileManager? - override func viewDidLoad() { super.viewDidLoad() + scanSession = MultiPageScanSession() + options = ImageScannerOptions() navigationItem.title = "File Manager" let settingsButton = UIBarButtonItem(image: UIImage(named: "settings"), style: .done, target: self, action: #selector(openSettings)) navigationItem.rightBarButtonItem = settingsButton @@ -100,6 +105,8 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate, override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + scanSession?.removeAll() + self.tabBarController?.tabBar.isHidden = false fetchViewModels() } @@ -114,12 +121,12 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate, self.viewModels = viewModels self.searchedViewModel = viewModels AllFolderView?.set(selectedFolder: folder, delegate: self) - - if viewModels.isEmpty { - noFilesLabel.isHidden = false - } else { - noFilesLabel.isHidden = true - } + + if viewModels.isEmpty { + noFilesLabel.isHidden = false + } else { + noFilesLabel.isHidden = true + } tableView.reloadData() } } @@ -129,6 +136,35 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate, self.navigationController?.pushViewController(settings, animated: false) } + func extractImage(from pdfDocument: PDFDocument, at pageIndex: Int) -> ScannedItem? { + guard pageIndex < pdfDocument.pageCount, let page = pdfDocument.page(at: pageIndex) else { return nil } + + var pageBounds = page.bounds(for: .mediaBox) + + // Calculate the scale factor to downsample the image + let maxDimension: CGFloat = 4096.0 // Adjust this value as needed + let scaleFactor = min(maxDimension / pageBounds.width, maxDimension / pageBounds.height) + + // Downsample the image + pageBounds.size.width *= scaleFactor + pageBounds.size.height *= scaleFactor + + let renderer = UIGraphicsImageRenderer(size: pageBounds.size) + + let image = renderer.image { (context) in + UIColor.white.set() + context.fill(pageBounds) + + context.cgContext.translateBy(x: 0.0, y: pageBounds.size.height) + context.cgContext.scaleBy(x: 1.0, y: -1.0) + + context.cgContext.drawPDFPage(page.pageRef!) + } + self.scannedItem = ScannedItem(originalImage: image,renderImage: image) + return scannedItem + } + + // MARK: - Table view data source func numberOfSections(in tableView: UITableView) -> Int { @@ -227,12 +263,12 @@ final class DocumentsTableViewController: UIViewController, UITableViewDelegate, } private func openGallery() { - - let imagePickerController = ImagePickerController() - imagePickerController.expandGalleryView() - imagePickerController.delegate = self - imagePickerController.modalPresentationStyle = .fullScreen - present(imagePickerController, animated: true, completion: nil) + var configuration = PHPickerConfiguration() + configuration.selectionLimit = 0 // 0 means no limit + configuration.filter = .images // Only show images + let picker = PHPickerViewController(configuration: configuration) + picker.delegate = self + present(picker, animated: true, completion: nil) } private func renameFile(at indexPath: IndexPath) { @@ -429,59 +465,37 @@ extension DocumentsTableViewController: SearchFilesViewDelegate { } } -extension DocumentsTableViewController: ImagePickerDelegate { - - func wrapperDidPress(_ imagePicker: ImagePicker.ImagePickerController, images: [UIImage]) { - guard !images.isEmpty else { return } - - // Create a view controller for each image - let viewControllers = images.map { image -> UIViewController in - let viewController = UIViewController() - viewController.view.backgroundColor = .white - - let imageView = UIImageView(image: image) - imageView.contentMode = .scaleAspectFit - imageView.translatesAutoresizingMaskIntoConstraints = false - - viewController.view.addSubview(imageView) - NSLayoutConstraint.activate([ - imageView.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor), - imageView.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor), - imageView.topAnchor.constraint(equalTo: viewController.view.topAnchor), - imageView.bottomAnchor.constraint(equalTo: viewController.view.bottomAnchor) - ]) - - return viewController - } - - self.pageViewControllers = viewControllers - // Create a page view controller to allow the user to scroll through the images - let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) - pageViewController.dataSource = self - - pageViewController.setViewControllers([viewControllers[0]], direction: .forward, animated: false, completion: nil) - - // Present the page view controller - imagePicker.present(pageViewController, animated: true, completion: nil) - } - - - func doneButtonDidPress(_ imagePicker: ImagePicker.ImagePickerController, images: [UIImage]) { - imagePicker.dismiss(animated: true) { [weak self] in - guard let self = self else { return } - if let folder = selectedFolder { - PDFManager.createMultiImagesPDFDocument(from: images, localFileManager: self.localFileManager, folder: folder) +extension DocumentsTableViewController: PHPickerViewControllerDelegate { + func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { + images.removeAll() + picker.dismiss(animated: true) { + let dispatchGroup = DispatchGroup() + + for result in results { + dispatchGroup.enter() // Enter the group before each task + result.itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in + defer { dispatchGroup.leave() } // Leave the group after each task, regardless of whether it was successful + if let error = error { + print("Error loading image: \(error)") + } else if let image = object as? UIImage { + DispatchQueue.main.async { + self.images.append(image) + } + } + } + } + + dispatchGroup.notify(queue: .main) { + if !self.images.isEmpty { + if let folder = self.selectedFolder { + PDFManager.createMultiImagesPDFDocument(from: self.images, localFileManager: self.localFileManager, folder: folder) + } + } self.fetchViewModels() self.tabBarController?.selectedIndex = 0 } } } - - func cancelButtonDidPress(_ imagePicker: ImagePicker.ImagePickerController) { - imagePicker.dismiss(animated: true) { [weak self] in - self?.tabBarController?.selectedIndex = 0 - } - } } extension DocumentsTableViewController: MultiPageScanSessionViewControllerDelegate { diff --git a/MiniScanner/Modules/EditViewController/EditViewController.swift b/MiniScanner/Modules/EditViewController/EditViewController.swift index 3fd75ad6eedc2f84f4c41bebaa41ef8d2baa2b8a..b8f250eb6d136bd9845d969b477333c6cb552254 100644 --- a/MiniScanner/Modules/EditViewController/EditViewController.swift +++ b/MiniScanner/Modules/EditViewController/EditViewController.swift @@ -182,9 +182,10 @@ public class EditViewController: UIViewController { @IBAction func continueTapped(_ sender: UIButton) { let popup = ShareSheetViewController() popup.session = self.scanSession + popup.isShareShown = false popup.delegate = self popup.selectedFolder = self.selectedFolder - let configuration = NBBottomSheetConfiguration(animationDuration: 0.4, sheetSize: .fixed(322)) + let configuration = NBBottomSheetConfiguration(animationDuration: 0.4, sheetSize: .fixed(200)) let bottomSheetController = NBBottomSheetController(configuration: configuration) bottomSheetController.present(popup, on: self) @@ -228,33 +229,16 @@ public class EditViewController: UIViewController { } @IBAction func whatsappShare(_ sender: UIButton) { - activityIndicator.startAnimating() - DispatchQueue.main.async { - - Task { - await self.directShareWith(extensionBundleIdentifier: ShareOptions.whatsapp) - } - self.activityIndicator.stopAnimating() - } + self.saveFileAndShare(with: ShareOptions.whatsapp, name: "file:\(Date.now)") + } @IBAction func telegramTapped(_ sender: UIButton) { - activityIndicator.startAnimating() - DispatchQueue.main.async { - - Task { - await self.directShareWith(extensionBundleIdentifier: ShareOptions.telegram) - } - self.activityIndicator.stopAnimating() - } + self.saveFileAndShare(with: ShareOptions.telegram, name: "file:\(Date.now)") + } @IBAction func gmailTapped(_ sender: UIButton) { - activityIndicator.startAnimating() - DispatchQueue.main.async { - Task { - await self.directShareWith(extensionBundleIdentifier: ShareOptions.gmail) - self.activityIndicator.stopAnimating() - } - } + self.saveFileAndShare(with: ShareOptions.gmail, name: "file:\(Date.now)") + } @IBAction func printTapped(_ sender: UIButton) { diff --git a/MiniScanner/Supporting Files/CustomWeScan/MultiPageSession/MultiPageScanSession.swift b/MiniScanner/Supporting Files/CustomWeScan/MultiPageSession/MultiPageScanSession.swift index b4d11727b37c0632ada564797715a8bcfa32315e..613c186e3fe8a84371b6e0a91d3951a264d6c30c 100644 --- a/MiniScanner/Supporting Files/CustomWeScan/MultiPageSession/MultiPageScanSession.swift +++ b/MiniScanner/Supporting Files/CustomWeScan/MultiPageSession/MultiPageScanSession.swift @@ -108,6 +108,10 @@ public class MultiPageScanSession { return self } + public func removeAll() { + self.scannedItems.removeAll() + } + } extension ScannedItem { diff --git a/MiniScanner/Supporting Files/CustomWeScan/Scan/ScannerViewController.swift b/MiniScanner/Supporting Files/CustomWeScan/Scan/ScannerViewController.swift index 7425a723119b45e57e4ba2fe50a5ccd44ec2cc3c..aec3addd0463dcc4d78964d1e068bb6fb8987393 100644 --- a/MiniScanner/Supporting Files/CustomWeScan/Scan/ScannerViewController.swift +++ b/MiniScanner/Supporting Files/CustomWeScan/Scan/ScannerViewController.swift @@ -174,7 +174,7 @@ public final class ScannerViewController: UIViewController { captureSessionManager?.start() UIApplication.shared.isIdleTimerDisabled = true navigationController?.navigationBar.isTranslucent = true - navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) + navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.setToolbarHidden(true, animated: true) updateCounterButton() @@ -299,7 +299,7 @@ public final class ScannerViewController: UIViewController { shutterButtonConstraints.append(shutterButtonBottomConstraint) } tabbarView.translatesAutoresizingMaskIntoConstraints = false - + NSLayoutConstraint.activate(quadViewConstraints + activityIndicatorConstraints + blackFlashViewConstraints + tabbarViewConstraints) } @@ -428,7 +428,7 @@ public final class ScannerViewController: UIViewController { private func saveFileAndShare(with: String, name: String) { activityIndicator.startAnimating() - + var images = [URL]() for index in 0..<multipageSession.scannedItems.count { if let url = multipageSession.scannedItems[index].renderedImage { @@ -446,13 +446,20 @@ public final class ScannerViewController: UIViewController { } } + private func previewDocument() { + activityIndicator.startAnimating() + let editViewController = EditViewController(scanSession: self.multipageSession) + editViewController.selectedFolder = self.selectedFolder + self.navigationController?.pushViewController(editViewController, animated: true) + } + private func directShareWith(extensionBundleIdentifier: String) async { do { let executor = try LNExtensionExecutor(extensionBundleIdentifier: extensionBundleIdentifier) let (completed, returnItems) = try await executor.execute(withActivityItems: payload, on: self) print("completed: \(completed) return items: \(returnItems)") activityIndicator.stopAnimating() - + } catch(let error) { print("error: \(error.localizedDescription)") } @@ -470,7 +477,7 @@ extension ScannerViewController: RectangleDetectionDelegateProtocol { func didStartCapturingPicture(for captureSessionManager: CaptureSessionManager) { activityIndicator.startAnimating() -// shutterButton.isUserInteractionEnabled = false + // shutterButton.isUserInteractionEnabled = false } func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didCapturePicture picture: UIImage, withQuad quad: Quadrilateral?) { @@ -533,31 +540,36 @@ extension ScannerViewController: CustomTabBarViewDelegate { let popup = ShareSheetViewController() popup.session = self.multipageSession popup.delegate = self + popup.previewDelegate = self popup.selectedFolder = self.selectedFolder let configuration = NBBottomSheetConfiguration(animationDuration: 0.4, sheetSize: .fixed(322)) let bottomSheetController = NBBottomSheetController(configuration: configuration) - bottomSheetController.present(popup, on: self) + bottomSheetController.present(popup, on: self) } func printPDF(from url: URL) { let printInfo = UIPrintInfo(dictionary:nil) printInfo.jobName = url.lastPathComponent printInfo.outputType = .general - + let printController = UIPrintInteractionController.shared printController.printInfo = printInfo - + let pdfData = try? Data(contentsOf: url) if pdfData != nil { printController.printingItem = pdfData } - + printController.present(animated: true, completionHandler: nil) } } // MARK: - ShareSheetViewControllerDelegate -extension ScannerViewController: ShareSheetViewControllerDelegate { +extension ScannerViewController: ShareSheetViewControllerDelegate, PreviewDelegate { + func previewTapped() { + previewDocument() + } + func whatsappTapped(name: String) { DispatchQueue.main.async { self.saveFileAndShare(with: ShareOptions.whatsapp, name: name) @@ -574,7 +586,7 @@ extension ScannerViewController: ShareSheetViewControllerDelegate { DispatchQueue.main.async { self.saveFileAndShare(with: ShareOptions.gmail, name: name) } - + } func printTapped() { @@ -608,8 +620,8 @@ extension ScannerViewController: ShareSheetViewControllerDelegate { let shareController = UIActivityViewController(activityItems: self.payload, applicationActivities: nil) self.present(shareController, animated: true, completion: nil) self.activityIndicator.stopAnimating() - - + + }) } }