diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..9ea2b9ba490274d67fb1a59bccb330f32cb1c5df
Binary files /dev/null and b/.DS_Store differ
diff --git a/MiniScanner.xcodeproj/project.pbxproj b/MiniScanner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000000000000000000000000000000000..d273ba80f6430b918b907dd7d9215413a19f4b71
--- /dev/null
+++ b/MiniScanner.xcodeproj/project.pbxproj
@@ -0,0 +1,842 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 54;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		53014F8D2C11A8E80071CE39 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 53014F4C2C11A8E80071CE39 /* Localizable.strings */; };
+		53014F8E2C11A8E80071CE39 /* ImageScannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F4F2C11A8E80071CE39 /* ImageScannerController.swift */; };
+		53014F8F2C11A8E80071CE39 /* RectangleFeaturesFunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F532C11A8E80071CE39 /* RectangleFeaturesFunnel.swift */; };
+		53014F902C11A8E80071CE39 /* CaptureSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F542C11A8E80071CE39 /* CaptureSessionManager.swift */; };
+		53014F912C11A8E80071CE39 /* ShutterButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F552C11A8E80071CE39 /* ShutterButton.swift */; };
+		53014F922C11A8E80071CE39 /* ScannedItemRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F562C11A8E80071CE39 /* ScannedItemRenderer.swift */; };
+		53014F932C11A8E80071CE39 /* PDFCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F572C11A8E80071CE39 /* PDFCreator.swift */; };
+		53014F942C11A8E80071CE39 /* DeviceOrientationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F582C11A8E80071CE39 /* DeviceOrientationHelper.swift */; };
+		53014F952C11A8E80071CE39 /* FocusRectangleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F592C11A8E80071CE39 /* FocusRectangleView.swift */; };
+		53014F962C11A8E80071CE39 /* ScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F5A2C11A8E80071CE39 /* ScannerViewController.swift */; };
+		53014F972C11A8E80071CE39 /* AVCaptureVideoOrientation+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F5D2C11A8E80071CE39 /* AVCaptureVideoOrientation+Utils.swift */; };
+		53014F982C11A8E80071CE39 /* URL+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F5E2C11A8E80071CE39 /* URL+Utils.swift */; };
+		53014F992C11A8E80071CE39 /* CGPoint+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F5F2C11A8E80071CE39 /* CGPoint+Utils.swift */; };
+		53014F9A2C11A8E80071CE39 /* CIImage+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F602C11A8E80071CE39 /* CIImage+Utils.swift */; };
+		53014F9B2C11A8E80071CE39 /* CGAffineTransform+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F612C11A8E80071CE39 /* CGAffineTransform+Utils.swift */; };
+		53014F9C2C11A8E80071CE39 /* CGRect+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F622C11A8E80071CE39 /* CGRect+Utils.swift */; };
+		53014F9D2C11A8E80071CE39 /* Array+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F632C11A8E80071CE39 /* Array+Utils.swift */; };
+		53014F9E2C11A8E80071CE39 /* UIImage+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F642C11A8E80071CE39 /* UIImage+Orientation.swift */; };
+		53014F9F2C11A8E80071CE39 /* UIImage+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F652C11A8E80071CE39 /* UIImage+Utils.swift */; };
+		53014FA02C11A8E80071CE39 /* MultiPageScanSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F672C11A8E80071CE39 /* MultiPageScanSession.swift */; };
+		53014FA12C11A8E80071CE39 /* MultiPageScanSessionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F682C11A8E80071CE39 /* MultiPageScanSessionViewController.swift */; };
+		53014FA22C11A8E80071CE39 /* ScannedPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F692C11A8E80071CE39 /* ScannedPageViewController.swift */; };
+		53014FA32C11A8E80071CE39 /* ZoomGestureController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F6B2C11A8E80071CE39 /* ZoomGestureController.swift */; };
+		53014FA42C11A8E80071CE39 /* EditScanViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F6C2C11A8E80071CE39 /* EditScanViewController.swift */; };
+		53014FA52C11A8E80071CE39 /* EditScanCornerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F6F2C11A8E80071CE39 /* EditScanCornerView.swift */; };
+		53014FA62C11A8E80071CE39 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F702C11A8E80071CE39 /* Error.swift */; };
+		53014FA72C11A8E80071CE39 /* VisionRectangleDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F712C11A8E80071CE39 /* VisionRectangleDetector.swift */; };
+		53014FA82C11A8E80071CE39 /* CIRectangleDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F722C11A8E80071CE39 /* CIRectangleDetector.swift */; };
+		53014FA92C11A8E80071CE39 /* QuadrilateralView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F732C11A8E80071CE39 /* QuadrilateralView.swift */; };
+		53014FAA2C11A8E80071CE39 /* Quadrilateral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F742C11A8E80071CE39 /* Quadrilateral.swift */; };
+		53014FAB2C11A8E80071CE39 /* flash.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F782C11A8E80071CE39 /* flash.png */; };
+		53014FAC2C11A8E80071CE39 /* rotate@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F792C11A8E80071CE39 /* rotate@3x.png */; };
+		53014FAD2C11A8E80071CE39 /* rotate.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F7A2C11A8E80071CE39 /* rotate.png */; };
+		53014FAE2C11A8E80071CE39 /* rotate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F7B2C11A8E80071CE39 /* rotate@2x.png */; };
+		53014FAF2C11A8E80071CE39 /* flash@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F7C2C11A8E80071CE39 /* flash@2x.png */; };
+		53014FB02C11A8E80071CE39 /* flashUnavailable@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F7D2C11A8E80071CE39 /* flashUnavailable@2x.png */; };
+		53014FB12C11A8E80071CE39 /* flashUnavailable.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F7E2C11A8E80071CE39 /* flashUnavailable.png */; };
+		53014FB22C11A8E80071CE39 /* flashUnavailable@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F7F2C11A8E80071CE39 /* flashUnavailable@3x.png */; };
+		53014FB32C11A8E80071CE39 /* flash@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F802C11A8E80071CE39 /* flash@3x.png */; };
+		53014FB42C11A8E80071CE39 /* enhance@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F812C11A8E80071CE39 /* enhance@3x.png */; };
+		53014FB52C11A8E80071CE39 /* enhance@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F822C11A8E80071CE39 /* enhance@2x.png */; };
+		53014FB62C11A8E80071CE39 /* enhance.png in Resources */ = {isa = PBXBuildFile; fileRef = 53014F832C11A8E80071CE39 /* enhance.png */; };
+		53014FB72C11A8E80071CE39 /* CaptureDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F852C11A8E80071CE39 /* CaptureDevice.swift */; };
+		53014FB82C11A8E80071CE39 /* Transformable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F862C11A8E80071CE39 /* Transformable.swift */; };
+		53014FBA2C11A8E80071CE39 /* CaptureSession+Flash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F892C11A8E80071CE39 /* CaptureSession+Flash.swift */; };
+		53014FBB2C11A8E80071CE39 /* CaptureSession+Orientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F8A2C11A8E80071CE39 /* CaptureSession+Orientation.swift */; };
+		53014FBC2C11A8E80071CE39 /* CaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F8B2C11A8E80071CE39 /* CaptureSession.swift */; };
+		53014FBD2C11A8E80071CE39 /* CaptureSession+Focus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53014F8C2C11A8E80071CE39 /* CaptureSession+Focus.swift */; };
+		EC0CF1FE254D8BBF00888722 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0CF1FD254D8BBF00888722 /* AppDelegate.swift */; };
+		EC0CF200254D8BBF00888722 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0CF1FF254D8BBF00888722 /* SceneDelegate.swift */; };
+		EC0CF207254D8BC000888722 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC0CF206254D8BC000888722 /* Assets.xcassets */; };
+		EC0CF20A254D8BC000888722 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC0CF208254D8BC000888722 /* LaunchScreen.storyboard */; };
+		EC0CF215254D8DE900888722 /* DocumentsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0CF214254D8DE900888722 /* DocumentsTableViewController.swift */; };
+		EC0CF218254D8DF200888722 /* Documents.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC0CF217254D8DF200888722 /* Documents.storyboard */; };
+		EC0CF21D254D8F3900888722 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0CF21C254D8F3900888722 /* String+Extensions.swift */; };
+		EC702522254DF13200BE1958 /* PencilKitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC702521254DF13200BE1958 /* PencilKitViewController.swift */; };
+		EC70252A254E066400BE1958 /* SettingsViewController+Safari.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC702526254E066400BE1958 /* SettingsViewController+Safari.swift */; };
+		EC70252B254E066400BE1958 /* SettingsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC702527254E066400BE1958 /* SettingsTableViewCell.swift */; };
+		EC70252C254E066400BE1958 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC702528254E066400BE1958 /* SettingsViewController.swift */; };
+		EC702537254E1DE000BE1958 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC702536254E1DE000BE1958 /* UIViewController+Extensions.swift */; };
+		EC702540254E1E7500BE1958 /* WalkthroughViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC70253C254E1E7400BE1958 /* WalkthroughViewController.swift */; };
+		EC702541254E1E7500BE1958 /* ClassicWalkthroughViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC70253D254E1E7400BE1958 /* ClassicWalkthroughViewController.xib */; };
+		EC702542254E1E7500BE1958 /* ClassicWalkthroughViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC70253E254E1E7400BE1958 /* ClassicWalkthroughViewController.swift */; };
+		EC702543254E1E7500BE1958 /* WalkthroughViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC70253F254E1E7400BE1958 /* WalkthroughViewController.xib */; };
+		EC702546254E1E9E00BE1958 /* WalkthroughModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC702545254E1E9E00BE1958 /* WalkthroughModel.swift */; };
+		EC8A9AD0254DB5A400F9AF99 /* AppTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9ACF254DB5A400F9AF99 /* AppTabBarController.swift */; };
+		EC8A9AD5254DB76000F9AF99 /* BaseNavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9AD4254DB76000F9AF99 /* BaseNavigationViewController.swift */; };
+		EC8A9B00254DBFC700F9AF99 /* UserDefaults+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9AFF254DBFC600F9AF99 /* UserDefaults+Extensions.swift */; };
+		EC8A9B03254DC08800F9AF99 /* NSNotification+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B02254DC08800F9AF99 /* NSNotification+Extensions.swift */; };
+		EC8A9B10254DC6DD00F9AF99 /* PDFManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B0F254DC6DD00F9AF99 /* PDFManager.swift */; };
+		EC8A9B14254DC9D300F9AF99 /* LocalFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B13254DC9D300F9AF99 /* LocalFileManager.swift */; };
+		EC8A9B17254DCC2900F9AF99 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B16254DCC2900F9AF99 /* URL+Extensions.swift */; };
+		EC8A9B1A254DCE3E00F9AF99 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B19254DCE3E00F9AF99 /* UIImage+Extensions.swift */; };
+		EC8A9B1D254DCEC600F9AF99 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B1C254DCEC600F9AF99 /* File.swift */; };
+		EC8A9B20254DDC3400F9AF99 /* DocumentsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B1F254DDC3400F9AF99 /* DocumentsTableViewCell.swift */; };
+		EC8A9B24254DE72F00F9AF99 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B23254DE72F00F9AF99 /* UIView+Extensions.swift */; };
+		EC8A9B27254DE91B00F9AF99 /* DocumentPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9B26254DE91B00F9AF99 /* DocumentPreviewViewController.swift */; };
+		ECA1FAA1254DEA6A0081F00B /* DocumentPreview.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ECA1FAA0254DEA6A0081F00B /* DocumentPreview.storyboard */; };
+		ECA1FAA4254DEB140081F00B /* CustomPDFView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA1FAA3254DEB140081F00B /* CustomPDFView.swift */; };
+		ECD43ED625A7BA9500B5A3F2 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECD43ED525A7BA9500B5A3F2 /* ThemeManager.swift */; };
+		ECE9BBAA254E295900D45E43 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECE9BBA9254E295900D45E43 /* Date+Extensions.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		53AF29742C1098AC0046E9C1 /* Embed Frameworks */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+			);
+			name = "Embed Frameworks";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		53014F4D2C11A8E80071CE39 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
+		53014F4E2C11A8E80071CE39 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		53014F4F2C11A8E80071CE39 /* ImageScannerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageScannerController.swift; sourceTree = "<group>"; };
+		53014F502C11A8E80071CE39 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		53014F512C11A8E80071CE39 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
+		53014F532C11A8E80071CE39 /* RectangleFeaturesFunnel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RectangleFeaturesFunnel.swift; sourceTree = "<group>"; };
+		53014F542C11A8E80071CE39 /* CaptureSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureSessionManager.swift; sourceTree = "<group>"; };
+		53014F552C11A8E80071CE39 /* ShutterButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShutterButton.swift; sourceTree = "<group>"; };
+		53014F562C11A8E80071CE39 /* ScannedItemRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScannedItemRenderer.swift; sourceTree = "<group>"; };
+		53014F572C11A8E80071CE39 /* PDFCreator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFCreator.swift; sourceTree = "<group>"; };
+		53014F582C11A8E80071CE39 /* DeviceOrientationHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceOrientationHelper.swift; sourceTree = "<group>"; };
+		53014F592C11A8E80071CE39 /* FocusRectangleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FocusRectangleView.swift; sourceTree = "<group>"; };
+		53014F5A2C11A8E80071CE39 /* ScannerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScannerViewController.swift; sourceTree = "<group>"; };
+		53014F5B2C11A8E80071CE39 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		53014F5D2C11A8E80071CE39 /* AVCaptureVideoOrientation+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureVideoOrientation+Utils.swift"; sourceTree = "<group>"; };
+		53014F5E2C11A8E80071CE39 /* URL+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL+Utils.swift"; sourceTree = "<group>"; };
+		53014F5F2C11A8E80071CE39 /* CGPoint+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGPoint+Utils.swift"; sourceTree = "<group>"; };
+		53014F602C11A8E80071CE39 /* CIImage+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CIImage+Utils.swift"; sourceTree = "<group>"; };
+		53014F612C11A8E80071CE39 /* CGAffineTransform+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGAffineTransform+Utils.swift"; sourceTree = "<group>"; };
+		53014F622C11A8E80071CE39 /* CGRect+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGRect+Utils.swift"; sourceTree = "<group>"; };
+		53014F632C11A8E80071CE39 /* Array+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Utils.swift"; sourceTree = "<group>"; };
+		53014F642C11A8E80071CE39 /* UIImage+Orientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Orientation.swift"; sourceTree = "<group>"; };
+		53014F652C11A8E80071CE39 /* UIImage+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Utils.swift"; sourceTree = "<group>"; };
+		53014F672C11A8E80071CE39 /* MultiPageScanSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiPageScanSession.swift; sourceTree = "<group>"; };
+		53014F682C11A8E80071CE39 /* MultiPageScanSessionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiPageScanSessionViewController.swift; sourceTree = "<group>"; };
+		53014F692C11A8E80071CE39 /* ScannedPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScannedPageViewController.swift; sourceTree = "<group>"; };
+		53014F6B2C11A8E80071CE39 /* ZoomGestureController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZoomGestureController.swift; sourceTree = "<group>"; };
+		53014F6C2C11A8E80071CE39 /* EditScanViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditScanViewController.swift; sourceTree = "<group>"; };
+		53014F6D2C11A8E80071CE39 /* WeScan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeScan.h; sourceTree = "<group>"; };
+		53014F6F2C11A8E80071CE39 /* EditScanCornerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditScanCornerView.swift; sourceTree = "<group>"; };
+		53014F702C11A8E80071CE39 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
+		53014F712C11A8E80071CE39 /* VisionRectangleDetector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VisionRectangleDetector.swift; sourceTree = "<group>"; };
+		53014F722C11A8E80071CE39 /* CIRectangleDetector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIRectangleDetector.swift; sourceTree = "<group>"; };
+		53014F732C11A8E80071CE39 /* QuadrilateralView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuadrilateralView.swift; sourceTree = "<group>"; };
+		53014F742C11A8E80071CE39 /* Quadrilateral.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Quadrilateral.swift; sourceTree = "<group>"; };
+		53014F752C11A8E80071CE39 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
+		53014F762C11A8E80071CE39 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		53014F782C11A8E80071CE39 /* flash.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flash.png; sourceTree = "<group>"; };
+		53014F792C11A8E80071CE39 /* rotate@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "rotate@3x.png"; sourceTree = "<group>"; };
+		53014F7A2C11A8E80071CE39 /* rotate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = rotate.png; sourceTree = "<group>"; };
+		53014F7B2C11A8E80071CE39 /* rotate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "rotate@2x.png"; sourceTree = "<group>"; };
+		53014F7C2C11A8E80071CE39 /* flash@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flash@2x.png"; sourceTree = "<group>"; };
+		53014F7D2C11A8E80071CE39 /* flashUnavailable@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flashUnavailable@2x.png"; sourceTree = "<group>"; };
+		53014F7E2C11A8E80071CE39 /* flashUnavailable.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flashUnavailable.png; sourceTree = "<group>"; };
+		53014F7F2C11A8E80071CE39 /* flashUnavailable@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flashUnavailable@3x.png"; sourceTree = "<group>"; };
+		53014F802C11A8E80071CE39 /* flash@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "flash@3x.png"; sourceTree = "<group>"; };
+		53014F812C11A8E80071CE39 /* enhance@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "enhance@3x.png"; sourceTree = "<group>"; };
+		53014F822C11A8E80071CE39 /* enhance@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "enhance@2x.png"; sourceTree = "<group>"; };
+		53014F832C11A8E80071CE39 /* enhance.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = enhance.png; sourceTree = "<group>"; };
+		53014F852C11A8E80071CE39 /* CaptureDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureDevice.swift; sourceTree = "<group>"; };
+		53014F862C11A8E80071CE39 /* Transformable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Transformable.swift; sourceTree = "<group>"; };
+		53014F892C11A8E80071CE39 /* CaptureSession+Flash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Flash.swift"; sourceTree = "<group>"; };
+		53014F8A2C11A8E80071CE39 /* CaptureSession+Orientation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Orientation.swift"; sourceTree = "<group>"; };
+		53014F8B2C11A8E80071CE39 /* CaptureSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureSession.swift; sourceTree = "<group>"; };
+		53014F8C2C11A8E80071CE39 /* CaptureSession+Focus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CaptureSession+Focus.swift"; sourceTree = "<group>"; };
+		EC0CF1FA254D8BBF00888722 /* MiniScanner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MiniScanner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		EC0CF1FD254D8BBF00888722 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+		EC0CF1FF254D8BBF00888722 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
+		EC0CF206254D8BC000888722 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		EC0CF209254D8BC000888722 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		EC0CF20B254D8BC000888722 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		EC0CF214254D8DE900888722 /* DocumentsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentsTableViewController.swift; sourceTree = "<group>"; };
+		EC0CF217254D8DF200888722 /* Documents.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Documents.storyboard; sourceTree = "<group>"; };
+		EC0CF21C254D8F3900888722 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
+		EC702521254DF13200BE1958 /* PencilKitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PencilKitViewController.swift; sourceTree = "<group>"; };
+		EC702526254E066400BE1958 /* SettingsViewController+Safari.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SettingsViewController+Safari.swift"; sourceTree = "<group>"; };
+		EC702527254E066400BE1958 /* SettingsTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsTableViewCell.swift; sourceTree = "<group>"; };
+		EC702528254E066400BE1958 /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
+		EC702536254E1DE000BE1958 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = "<group>"; };
+		EC70253C254E1E7400BE1958 /* WalkthroughViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalkthroughViewController.swift; sourceTree = "<group>"; };
+		EC70253D254E1E7400BE1958 /* ClassicWalkthroughViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ClassicWalkthroughViewController.xib; sourceTree = "<group>"; };
+		EC70253E254E1E7400BE1958 /* ClassicWalkthroughViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClassicWalkthroughViewController.swift; sourceTree = "<group>"; };
+		EC70253F254E1E7400BE1958 /* WalkthroughViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WalkthroughViewController.xib; sourceTree = "<group>"; };
+		EC702545254E1E9E00BE1958 /* WalkthroughModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalkthroughModel.swift; sourceTree = "<group>"; };
+		EC8A9ACF254DB5A400F9AF99 /* AppTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTabBarController.swift; sourceTree = "<group>"; };
+		EC8A9AD4254DB76000F9AF99 /* BaseNavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNavigationViewController.swift; sourceTree = "<group>"; };
+		EC8A9AFF254DBFC600F9AF99 /* UserDefaults+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Extensions.swift"; sourceTree = "<group>"; };
+		EC8A9B02254DC08800F9AF99 /* NSNotification+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSNotification+Extensions.swift"; sourceTree = "<group>"; };
+		EC8A9B0F254DC6DD00F9AF99 /* PDFManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFManager.swift; sourceTree = "<group>"; };
+		EC8A9B13254DC9D300F9AF99 /* LocalFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalFileManager.swift; sourceTree = "<group>"; };
+		EC8A9B16254DCC2900F9AF99 /* URL+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = "<group>"; };
+		EC8A9B19254DCE3E00F9AF99 /* UIImage+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = "<group>"; };
+		EC8A9B1C254DCEC600F9AF99 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
+		EC8A9B1F254DDC3400F9AF99 /* DocumentsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentsTableViewCell.swift; sourceTree = "<group>"; };
+		EC8A9B23254DE72F00F9AF99 /* UIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = "<group>"; };
+		EC8A9B26254DE91B00F9AF99 /* DocumentPreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPreviewViewController.swift; sourceTree = "<group>"; };
+		ECA1FAA0254DEA6A0081F00B /* DocumentPreview.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DocumentPreview.storyboard; sourceTree = "<group>"; };
+		ECA1FAA3254DEB140081F00B /* CustomPDFView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPDFView.swift; sourceTree = "<group>"; };
+		ECD43ED525A7BA9500B5A3F2 /* ThemeManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
+		ECE9BBA9254E295900D45E43 /* Date+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extensions.swift"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		EC0CF1F7254D8BBF00888722 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		53014F4B2C11A8E80071CE39 /* WeScan */ = {
+			isa = PBXGroup;
+			children = (
+				53014F4C2C11A8E80071CE39 /* Localizable.strings */,
+				53014F4F2C11A8E80071CE39 /* ImageScannerController.swift */,
+				53014F522C11A8E80071CE39 /* Scan */,
+				53014F5C2C11A8E80071CE39 /* Extensions */,
+				53014F662C11A8E80071CE39 /* MultiPageSession */,
+				53014F6A2C11A8E80071CE39 /* Edit */,
+				53014F6D2C11A8E80071CE39 /* WeScan.h */,
+				53014F6E2C11A8E80071CE39 /* Common */,
+				53014F772C11A8E80071CE39 /* Assets */,
+				53014F842C11A8E80071CE39 /* Protocols */,
+				53014F882C11A8E80071CE39 /* Session */,
+			);
+			path = WeScan;
+			sourceTree = "<group>";
+		};
+		53014F522C11A8E80071CE39 /* Scan */ = {
+			isa = PBXGroup;
+			children = (
+				53014F532C11A8E80071CE39 /* RectangleFeaturesFunnel.swift */,
+				53014F542C11A8E80071CE39 /* CaptureSessionManager.swift */,
+				53014F552C11A8E80071CE39 /* ShutterButton.swift */,
+				53014F562C11A8E80071CE39 /* ScannedItemRenderer.swift */,
+				53014F572C11A8E80071CE39 /* PDFCreator.swift */,
+				53014F582C11A8E80071CE39 /* DeviceOrientationHelper.swift */,
+				53014F592C11A8E80071CE39 /* FocusRectangleView.swift */,
+				53014F5A2C11A8E80071CE39 /* ScannerViewController.swift */,
+			);
+			path = Scan;
+			sourceTree = "<group>";
+		};
+		53014F5C2C11A8E80071CE39 /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				53014F5D2C11A8E80071CE39 /* AVCaptureVideoOrientation+Utils.swift */,
+				53014F5E2C11A8E80071CE39 /* URL+Utils.swift */,
+				53014F5F2C11A8E80071CE39 /* CGPoint+Utils.swift */,
+				53014F602C11A8E80071CE39 /* CIImage+Utils.swift */,
+				53014F612C11A8E80071CE39 /* CGAffineTransform+Utils.swift */,
+				53014F622C11A8E80071CE39 /* CGRect+Utils.swift */,
+				53014F632C11A8E80071CE39 /* Array+Utils.swift */,
+				53014F642C11A8E80071CE39 /* UIImage+Orientation.swift */,
+				53014F652C11A8E80071CE39 /* UIImage+Utils.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
+		53014F662C11A8E80071CE39 /* MultiPageSession */ = {
+			isa = PBXGroup;
+			children = (
+				53014F672C11A8E80071CE39 /* MultiPageScanSession.swift */,
+				53014F682C11A8E80071CE39 /* MultiPageScanSessionViewController.swift */,
+				53014F692C11A8E80071CE39 /* ScannedPageViewController.swift */,
+			);
+			path = MultiPageSession;
+			sourceTree = "<group>";
+		};
+		53014F6A2C11A8E80071CE39 /* Edit */ = {
+			isa = PBXGroup;
+			children = (
+				53014F6B2C11A8E80071CE39 /* ZoomGestureController.swift */,
+				53014F6C2C11A8E80071CE39 /* EditScanViewController.swift */,
+			);
+			path = Edit;
+			sourceTree = "<group>";
+		};
+		53014F6E2C11A8E80071CE39 /* Common */ = {
+			isa = PBXGroup;
+			children = (
+				53014F6F2C11A8E80071CE39 /* EditScanCornerView.swift */,
+				53014F702C11A8E80071CE39 /* Error.swift */,
+				53014F712C11A8E80071CE39 /* VisionRectangleDetector.swift */,
+				53014F722C11A8E80071CE39 /* CIRectangleDetector.swift */,
+				53014F732C11A8E80071CE39 /* QuadrilateralView.swift */,
+				53014F742C11A8E80071CE39 /* Quadrilateral.swift */,
+			);
+			path = Common;
+			sourceTree = "<group>";
+		};
+		53014F772C11A8E80071CE39 /* Assets */ = {
+			isa = PBXGroup;
+			children = (
+				53014F782C11A8E80071CE39 /* flash.png */,
+				53014F792C11A8E80071CE39 /* rotate@3x.png */,
+				53014F7A2C11A8E80071CE39 /* rotate.png */,
+				53014F7B2C11A8E80071CE39 /* rotate@2x.png */,
+				53014F7C2C11A8E80071CE39 /* flash@2x.png */,
+				53014F7D2C11A8E80071CE39 /* flashUnavailable@2x.png */,
+				53014F7E2C11A8E80071CE39 /* flashUnavailable.png */,
+				53014F7F2C11A8E80071CE39 /* flashUnavailable@3x.png */,
+				53014F802C11A8E80071CE39 /* flash@3x.png */,
+				53014F812C11A8E80071CE39 /* enhance@3x.png */,
+				53014F822C11A8E80071CE39 /* enhance@2x.png */,
+				53014F832C11A8E80071CE39 /* enhance.png */,
+			);
+			path = Assets;
+			sourceTree = "<group>";
+		};
+		53014F842C11A8E80071CE39 /* Protocols */ = {
+			isa = PBXGroup;
+			children = (
+				53014F852C11A8E80071CE39 /* CaptureDevice.swift */,
+				53014F862C11A8E80071CE39 /* Transformable.swift */,
+			);
+			path = Protocols;
+			sourceTree = "<group>";
+		};
+		53014F882C11A8E80071CE39 /* Session */ = {
+			isa = PBXGroup;
+			children = (
+				53014F892C11A8E80071CE39 /* CaptureSession+Flash.swift */,
+				53014F8A2C11A8E80071CE39 /* CaptureSession+Orientation.swift */,
+				53014F8B2C11A8E80071CE39 /* CaptureSession.swift */,
+				53014F8C2C11A8E80071CE39 /* CaptureSession+Focus.swift */,
+			);
+			path = Session;
+			sourceTree = "<group>";
+		};
+		53AF29712C1098AC0046E9C1 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		EC0CF1F1254D8BBF00888722 = {
+			isa = PBXGroup;
+			children = (
+				EC0CF1FC254D8BBF00888722 /* MiniScanner */,
+				EC0CF1FB254D8BBF00888722 /* Products */,
+				53AF29712C1098AC0046E9C1 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		EC0CF1FB254D8BBF00888722 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				EC0CF1FA254D8BBF00888722 /* MiniScanner.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		EC0CF1FC254D8BBF00888722 /* MiniScanner */ = {
+			isa = PBXGroup;
+			children = (
+				EC702548254E1F9F00BE1958 /* Managers */,
+				EC8A9B0A254DC2FD00F9AF99 /* Extensions */,
+				EC8A9B08254DC2F700F9AF99 /* Common */,
+				EC8A9B2D254DE96300F9AF99 /* Modules */,
+				EC8A9B0C254DC30800F9AF99 /* Supporting Files */,
+			);
+			path = MiniScanner;
+			sourceTree = "<group>";
+		};
+		EC70252F254E066E00BE1958 /* Settings */ = {
+			isa = PBXGroup;
+			children = (
+				EC702527254E066400BE1958 /* SettingsTableViewCell.swift */,
+				EC702528254E066400BE1958 /* SettingsViewController.swift */,
+				EC702526254E066400BE1958 /* SettingsViewController+Safari.swift */,
+			);
+			path = Settings;
+			sourceTree = "<group>";
+		};
+		EC702548254E1F9F00BE1958 /* Managers */ = {
+			isa = PBXGroup;
+			children = (
+				EC8A9B0F254DC6DD00F9AF99 /* PDFManager.swift */,
+				EC8A9B13254DC9D300F9AF99 /* LocalFileManager.swift */,
+				ECD43ED525A7BA9500B5A3F2 /* ThemeManager.swift */,
+			);
+			path = Managers;
+			sourceTree = "<group>";
+		};
+		EC8A9B06254DC2EE00F9AF99 /* Documents */ = {
+			isa = PBXGroup;
+			children = (
+				EC8A9B1C254DCEC600F9AF99 /* File.swift */,
+				EC0CF217254D8DF200888722 /* Documents.storyboard */,
+				EC8A9B1F254DDC3400F9AF99 /* DocumentsTableViewCell.swift */,
+				EC0CF214254D8DE900888722 /* DocumentsTableViewController.swift */,
+			);
+			path = Documents;
+			sourceTree = "<group>";
+		};
+		EC8A9B08254DC2F700F9AF99 /* Common */ = {
+			isa = PBXGroup;
+			children = (
+				ECA1FAA3254DEB140081F00B /* CustomPDFView.swift */,
+				EC8A9ACF254DB5A400F9AF99 /* AppTabBarController.swift */,
+				EC8A9AD4254DB76000F9AF99 /* BaseNavigationViewController.swift */,
+			);
+			path = Common;
+			sourceTree = "<group>";
+		};
+		EC8A9B0A254DC2FD00F9AF99 /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				EC0CF21C254D8F3900888722 /* String+Extensions.swift */,
+				EC8A9AFF254DBFC600F9AF99 /* UserDefaults+Extensions.swift */,
+				EC8A9B19254DCE3E00F9AF99 /* UIImage+Extensions.swift */,
+				EC8A9B23254DE72F00F9AF99 /* UIView+Extensions.swift */,
+				ECE9BBA9254E295900D45E43 /* Date+Extensions.swift */,
+				EC8A9B16254DCC2900F9AF99 /* URL+Extensions.swift */,
+				EC702536254E1DE000BE1958 /* UIViewController+Extensions.swift */,
+				EC8A9B02254DC08800F9AF99 /* NSNotification+Extensions.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
+		EC8A9B0C254DC30800F9AF99 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				53014F4B2C11A8E80071CE39 /* WeScan */,
+				EC0CF206254D8BC000888722 /* Assets.xcassets */,
+				EC0CF1FD254D8BBF00888722 /* AppDelegate.swift */,
+				EC0CF1FF254D8BBF00888722 /* SceneDelegate.swift */,
+				EC0CF208254D8BC000888722 /* LaunchScreen.storyboard */,
+				EC0CF20B254D8BC000888722 /* Info.plist */,
+			);
+			path = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		EC8A9B2C254DE94900F9AF99 /* DocumentPreview */ = {
+			isa = PBXGroup;
+			children = (
+				ECA1FAA0254DEA6A0081F00B /* DocumentPreview.storyboard */,
+				EC8A9B26254DE91B00F9AF99 /* DocumentPreviewViewController.swift */,
+				EC702521254DF13200BE1958 /* PencilKitViewController.swift */,
+			);
+			path = DocumentPreview;
+			sourceTree = "<group>";
+		};
+		EC8A9B2D254DE96300F9AF99 /* Modules */ = {
+			isa = PBXGroup;
+			children = (
+				ECE9BBB2254E331700D45E43 /* Walktrough */,
+				EC8A9B06254DC2EE00F9AF99 /* Documents */,
+				EC8A9B2C254DE94900F9AF99 /* DocumentPreview */,
+				EC70252F254E066E00BE1958 /* Settings */,
+			);
+			path = Modules;
+			sourceTree = "<group>";
+		};
+		ECE9BBB2254E331700D45E43 /* Walktrough */ = {
+			isa = PBXGroup;
+			children = (
+				EC702545254E1E9E00BE1958 /* WalkthroughModel.swift */,
+				EC70253E254E1E7400BE1958 /* ClassicWalkthroughViewController.swift */,
+				EC70253D254E1E7400BE1958 /* ClassicWalkthroughViewController.xib */,
+				EC70253C254E1E7400BE1958 /* WalkthroughViewController.swift */,
+				EC70253F254E1E7400BE1958 /* WalkthroughViewController.xib */,
+			);
+			path = Walktrough;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		EC0CF1F9254D8BBF00888722 /* MiniScanner */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = EC0CF20E254D8BC000888722 /* Build configuration list for PBXNativeTarget "MiniScanner" */;
+			buildPhases = (
+				EC0CF1F6254D8BBF00888722 /* Sources */,
+				EC0CF1F7254D8BBF00888722 /* Frameworks */,
+				EC0CF1F8254D8BBF00888722 /* Resources */,
+				53AF29742C1098AC0046E9C1 /* Embed Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = MiniScanner;
+			productName = MiniScanner;
+			productReference = EC0CF1FA254D8BBF00888722 /* MiniScanner.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		EC0CF1F2254D8BBF00888722 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				BuildIndependentTargetsInParallel = YES;
+				LastSwiftUpdateCheck = 1210;
+				LastUpgradeCheck = 1500;
+				ORGANIZATIONNAME = AppsNectar;
+				TargetAttributes = {
+					EC0CF1F9254D8BBF00888722 = {
+						CreatedOnToolsVersion = 12.1;
+					};
+				};
+			};
+			buildConfigurationList = EC0CF1F5254D8BBF00888722 /* Build configuration list for PBXProject "MiniScanner" */;
+			compatibilityVersion = "Xcode 9.3";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+				de,
+				"zh-Hans",
+				it,
+				"zh-Hant",
+				fr,
+				"pt-PT",
+			);
+			mainGroup = EC0CF1F1254D8BBF00888722;
+			productRefGroup = EC0CF1FB254D8BBF00888722 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				EC0CF1F9254D8BBF00888722 /* MiniScanner */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		EC0CF1F8254D8BBF00888722 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				53014FAD2C11A8E80071CE39 /* rotate.png in Resources */,
+				53014FB02C11A8E80071CE39 /* flashUnavailable@2x.png in Resources */,
+				EC702543254E1E7500BE1958 /* WalkthroughViewController.xib in Resources */,
+				53014FAC2C11A8E80071CE39 /* rotate@3x.png in Resources */,
+				EC0CF20A254D8BC000888722 /* LaunchScreen.storyboard in Resources */,
+				53014FAB2C11A8E80071CE39 /* flash.png in Resources */,
+				EC0CF218254D8DF200888722 /* Documents.storyboard in Resources */,
+				53014FB52C11A8E80071CE39 /* enhance@2x.png in Resources */,
+				53014FAE2C11A8E80071CE39 /* rotate@2x.png in Resources */,
+				53014FB32C11A8E80071CE39 /* flash@3x.png in Resources */,
+				53014FB22C11A8E80071CE39 /* flashUnavailable@3x.png in Resources */,
+				53014FAF2C11A8E80071CE39 /* flash@2x.png in Resources */,
+				53014FB12C11A8E80071CE39 /* flashUnavailable.png in Resources */,
+				53014F8D2C11A8E80071CE39 /* Localizable.strings in Resources */,
+				EC702541254E1E7500BE1958 /* ClassicWalkthroughViewController.xib in Resources */,
+				ECA1FAA1254DEA6A0081F00B /* DocumentPreview.storyboard in Resources */,
+				53014FB62C11A8E80071CE39 /* enhance.png in Resources */,
+				53014FB42C11A8E80071CE39 /* enhance@3x.png in Resources */,
+				EC0CF207254D8BC000888722 /* Assets.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		EC0CF1F6254D8BBF00888722 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				53014FA02C11A8E80071CE39 /* MultiPageScanSession.swift in Sources */,
+				EC8A9B20254DDC3400F9AF99 /* DocumentsTableViewCell.swift in Sources */,
+				53014F9A2C11A8E80071CE39 /* CIImage+Utils.swift in Sources */,
+				EC8A9B17254DCC2900F9AF99 /* URL+Extensions.swift in Sources */,
+				EC70252C254E066400BE1958 /* SettingsViewController.swift in Sources */,
+				EC0CF21D254D8F3900888722 /* String+Extensions.swift in Sources */,
+				EC702540254E1E7500BE1958 /* WalkthroughViewController.swift in Sources */,
+				EC0CF215254D8DE900888722 /* DocumentsTableViewController.swift in Sources */,
+				53014F9D2C11A8E80071CE39 /* Array+Utils.swift in Sources */,
+				53014FAA2C11A8E80071CE39 /* Quadrilateral.swift in Sources */,
+				53014FA42C11A8E80071CE39 /* EditScanViewController.swift in Sources */,
+				EC8A9B1A254DCE3E00F9AF99 /* UIImage+Extensions.swift in Sources */,
+				53014FB72C11A8E80071CE39 /* CaptureDevice.swift in Sources */,
+				53014F8F2C11A8E80071CE39 /* RectangleFeaturesFunnel.swift in Sources */,
+				53014F932C11A8E80071CE39 /* PDFCreator.swift in Sources */,
+				EC702537254E1DE000BE1958 /* UIViewController+Extensions.swift in Sources */,
+				53014F972C11A8E80071CE39 /* AVCaptureVideoOrientation+Utils.swift in Sources */,
+				53014F992C11A8E80071CE39 /* CGPoint+Utils.swift in Sources */,
+				53014FA62C11A8E80071CE39 /* Error.swift in Sources */,
+				53014FA72C11A8E80071CE39 /* VisionRectangleDetector.swift in Sources */,
+				EC0CF1FE254D8BBF00888722 /* AppDelegate.swift in Sources */,
+				53014FA82C11A8E80071CE39 /* CIRectangleDetector.swift in Sources */,
+				EC8A9AD5254DB76000F9AF99 /* BaseNavigationViewController.swift in Sources */,
+				EC8A9B10254DC6DD00F9AF99 /* PDFManager.swift in Sources */,
+				ECE9BBAA254E295900D45E43 /* Date+Extensions.swift in Sources */,
+				53014FA92C11A8E80071CE39 /* QuadrilateralView.swift in Sources */,
+				EC702546254E1E9E00BE1958 /* WalkthroughModel.swift in Sources */,
+				53014F912C11A8E80071CE39 /* ShutterButton.swift in Sources */,
+				53014FBD2C11A8E80071CE39 /* CaptureSession+Focus.swift in Sources */,
+				53014F982C11A8E80071CE39 /* URL+Utils.swift in Sources */,
+				EC8A9B00254DBFC700F9AF99 /* UserDefaults+Extensions.swift in Sources */,
+				EC8A9B03254DC08800F9AF99 /* NSNotification+Extensions.swift in Sources */,
+				EC702522254DF13200BE1958 /* PencilKitViewController.swift in Sources */,
+				53014F902C11A8E80071CE39 /* CaptureSessionManager.swift in Sources */,
+				ECA1FAA4254DEB140081F00B /* CustomPDFView.swift in Sources */,
+				53014FA32C11A8E80071CE39 /* ZoomGestureController.swift in Sources */,
+				EC70252A254E066400BE1958 /* SettingsViewController+Safari.swift in Sources */,
+				53014F9B2C11A8E80071CE39 /* CGAffineTransform+Utils.swift in Sources */,
+				53014FBC2C11A8E80071CE39 /* CaptureSession.swift in Sources */,
+				EC702542254E1E7500BE1958 /* ClassicWalkthroughViewController.swift in Sources */,
+				53014F922C11A8E80071CE39 /* ScannedItemRenderer.swift in Sources */,
+				EC8A9B14254DC9D300F9AF99 /* LocalFileManager.swift in Sources */,
+				53014FBA2C11A8E80071CE39 /* CaptureSession+Flash.swift in Sources */,
+				53014F952C11A8E80071CE39 /* FocusRectangleView.swift in Sources */,
+				53014F9E2C11A8E80071CE39 /* UIImage+Orientation.swift in Sources */,
+				53014FB82C11A8E80071CE39 /* Transformable.swift in Sources */,
+				53014FA22C11A8E80071CE39 /* ScannedPageViewController.swift in Sources */,
+				EC8A9B1D254DCEC600F9AF99 /* File.swift in Sources */,
+				EC8A9B24254DE72F00F9AF99 /* UIView+Extensions.swift in Sources */,
+				EC0CF200254D8BBF00888722 /* SceneDelegate.swift in Sources */,
+				53014FBB2C11A8E80071CE39 /* CaptureSession+Orientation.swift in Sources */,
+				53014F942C11A8E80071CE39 /* DeviceOrientationHelper.swift in Sources */,
+				EC8A9B27254DE91B00F9AF99 /* DocumentPreviewViewController.swift in Sources */,
+				53014F9F2C11A8E80071CE39 /* UIImage+Utils.swift in Sources */,
+				53014F962C11A8E80071CE39 /* ScannerViewController.swift in Sources */,
+				53014FA52C11A8E80071CE39 /* EditScanCornerView.swift in Sources */,
+				53014F8E2C11A8E80071CE39 /* ImageScannerController.swift in Sources */,
+				EC70252B254E066400BE1958 /* SettingsTableViewCell.swift in Sources */,
+				EC8A9AD0254DB5A400F9AF99 /* AppTabBarController.swift in Sources */,
+				ECD43ED625A7BA9500B5A3F2 /* ThemeManager.swift in Sources */,
+				53014F9C2C11A8E80071CE39 /* CGRect+Utils.swift in Sources */,
+				53014FA12C11A8E80071CE39 /* MultiPageScanSessionViewController.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		53014F4C2C11A8E80071CE39 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				53014F4D2C11A8E80071CE39 /* de */,
+				53014F4E2C11A8E80071CE39 /* zh-Hans */,
+				53014F502C11A8E80071CE39 /* en */,
+				53014F512C11A8E80071CE39 /* it */,
+				53014F5B2C11A8E80071CE39 /* zh-Hant */,
+				53014F752C11A8E80071CE39 /* fr */,
+				53014F762C11A8E80071CE39 /* pt-PT */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+		EC0CF208254D8BC000888722 /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				EC0CF209254D8BC000888722 /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		EC0CF20C254D8BC000888722 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				ENABLE_USER_SCRIPT_SANDBOXING = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		EC0CF20D254D8BC000888722 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_USER_SCRIPT_SANDBOXING = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		EC0CF20F254D8BC000888722 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 6;
+				DEVELOPMENT_TEAM = 5L95SU3SLS;
+				INFOPLIST_FILE = "MiniScanner/Supporting Files/Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0.3;
+				PRODUCT_BUNDLE_IDENTIFIER = com.mistergrizzly.MiniScanner;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		EC0CF210254D8BC000888722 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 6;
+				DEVELOPMENT_TEAM = 5L95SU3SLS;
+				INFOPLIST_FILE = "MiniScanner/Supporting Files/Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0.3;
+				PRODUCT_BUNDLE_IDENTIFIER = com.mistergrizzly.MiniScanner;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		EC0CF1F5254D8BBF00888722 /* Build configuration list for PBXProject "MiniScanner" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				EC0CF20C254D8BC000888722 /* Debug */,
+				EC0CF20D254D8BC000888722 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		EC0CF20E254D8BC000888722 /* Build configuration list for PBXNativeTarget "MiniScanner" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				EC0CF20F254D8BC000888722 /* Debug */,
+				EC0CF210254D8BC000888722 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = EC0CF1F2254D8BBF00888722 /* Project object */;
+}
diff --git a/MiniScanner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/MiniScanner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000000000000000000000000000000000..919434a6254f0e9651f402737811be6634a03e9c
--- /dev/null
+++ b/MiniScanner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git a/MiniScanner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MiniScanner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000000000000000000000000000000000000..18d981003d68d0546c4804ac2ff47dd97c6e7921
--- /dev/null
+++ b/MiniScanner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/MiniScanner.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate b/MiniScanner.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000000000000000000000000000000000000..d26f25dc01367ba473483ec2dca193662029f93a
Binary files /dev/null and b/MiniScanner.xcodeproj/project.xcworkspace/xcuserdata/g.makhoul.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/MiniScanner.xcodeproj/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MiniScanner.xcodeproj/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
new file mode 100644
index 0000000000000000000000000000000000000000..426b099412d9bcaa184f835ad12aed2ff9a2c8bb
--- /dev/null
+++ b/MiniScanner.xcodeproj/xcuserdata/g.makhoul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Bucket
+   uuid = "D33AC1E3-63DB-4EB0-8F0E-71361335BCD8"
+   type = "1"
+   version = "2.0">
+</Bucket>
diff --git a/MiniScanner.xcodeproj/xcuserdata/g.makhoul.xcuserdatad/xcschemes/xcschememanagement.plist b/MiniScanner.xcodeproj/xcuserdata/g.makhoul.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000000000000000000000000000000000000..0207cce37434503616e092dda440e92ef4c6a995
--- /dev/null
+++ b/MiniScanner.xcodeproj/xcuserdata/g.makhoul.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>MiniScanner.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/MiniScanner/.DS_Store b/MiniScanner/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..f31b1945701570aeb2b9de2c1046f8e6698a1431
Binary files /dev/null and b/MiniScanner/.DS_Store differ
diff --git a/MiniScanner/Common/AppTabBarController.swift b/MiniScanner/Common/AppTabBarController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..00feccf3683d7e6107014b5e4252a76bd1cd900b
--- /dev/null
+++ b/MiniScanner/Common/AppTabBarController.swift
@@ -0,0 +1,166 @@
+import UIKit
+
+class AppTabBarController: UITabBarController, UITabBarControllerDelegate, WalkthroughViewControllerDelegate {
+  
+  struct Constants {
+    static let reuseIdentifier = String(describing: AppTabBarController.self)
+    static let storyboardName = "Documents"
+  }
+  
+  static func buildViewController() -> AppTabBarController {
+    let controller = UIStoryboard(name: Constants.storyboardName,
+                                  bundle: .main).instantiateViewController(withIdentifier: Constants.reuseIdentifier)
+    return controller as! AppTabBarController
+  }
+  
+  required init?(coder: NSCoder) {
+    super.init(coder: coder)
+  }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    self.delegate = self
+  }
+  
+  override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    if UserDefaults.standard.showWalktroughAtLaunch {
+      perform(#selector(showWalkTrough), with: self, afterDelay: 0.88)
+    }
+  }
+  
+  let walkthroughs = [
+    WalkthroughModel(title: "Quick Overview",
+                        subtitle: "Quickly visualize important business metrics. The overview in the home tab shows the most important metrics to monitor how your business is doing in real time.",
+                        icon: "analytics-icon"),
+    WalkthroughModel(title: "Analytics",
+                        subtitle: "Dive deep into charts to extract valuable insights and come up with data driven product initiatives, to boost the success of your business.",
+                        icon: "bars-icon"),
+    WalkthroughModel(title: "Dashboard Feeds",
+                        subtitle: "View your sales feed, orders, customers, products and employees.",
+                        icon: "activity-feed-icon"),
+    WalkthroughModel(title: "Get Notified",
+                        subtitle: "Receive notifications when critical situations occur to stay on top of everything important.",
+                        icon: "bell-icon"),
+  ]
+  
+  @objc private func showWalkTrough() {
+    let walkthroughVC = self.walkthroughVC()
+    walkthroughVC.delegate = self
+    addChildViewControllerWithView(walkthroughVC)
+  }
+  
+  fileprivate func walkthroughVC() -> WalkthroughViewController {
+    let viewControllers = walkthroughs.map { ClassicWalkthroughViewController(model: $0, nibName: "ClassicWalkthroughViewController", bundle: nil) }
+    return WalkthroughViewController(nibName: "WalkthroughViewController",
+                                        bundle: nil,
+                                        viewControllers: viewControllers)
+  }
+  
+  func walkthroughViewControllerDidFinishFlow(_ vc: WalkthroughViewController) {
+    UIView.transition(with: self.view, duration: 1, options: .transitionCrossDissolve, animations: {
+      vc.view.removeFromSuperview()
+    }, completion: nil)
+  }
+}
+
+class AppTabBar: UITabBar {
+  
+  private var middleButton = UIButton()
+  private var shapeLayer: CALayer?
+  
+  private func addShape() {
+    let shapeLayer = CAShapeLayer()
+    shapeLayer.path = createPath()
+    shapeLayer.strokeColor = UIColor.lightGray.cgColor
+    let tabBackColor = UIColor.barTintColor
+    shapeLayer.fillColor = tabBackColor.cgColor
+    shapeLayer.lineWidth = 0.5
+    
+    //The below 4 lines are for shadow above the bar. you can skip them if you do not want a shadow
+    shapeLayer.shadowOffset = CGSize(width:0, height:0)
+    shapeLayer.shadowRadius = 10
+    shapeLayer.shadowColor = UIColor.gray.cgColor
+    shapeLayer.shadowOpacity = 0.3
+    
+    if let oldShapeLayer = self.shapeLayer {
+      self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
+    } else {
+      self.layer.insertSublayer(shapeLayer, at: 0)
+    }
+    self.shapeLayer = shapeLayer
+  }
+  
+  override func awakeFromNib() {
+    super.awakeFromNib()
+    setupMiddleButton()
+  }
+  
+  override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
+    if self.isHidden {
+      return super.hitTest(point, with: event)
+    }
+    
+    let from = point
+    let to = middleButton.center
+    
+    return sqrt((from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y)) <= 120 ? middleButton : super.hitTest(point, with: event)
+  }
+  
+  override func layoutSubviews() {
+    super.layoutSubviews()
+    middleButton.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: 10)
+  }
+  
+  @objc private func setupMiddleButton() {
+    let image = UIImage(named: "add_doc_icon")
+    middleButton.setImage(image, for: UIControl.State.normal)
+    middleButton.contentVerticalAlignment = .fill
+    middleButton.contentHorizontalAlignment = .fill
+    middleButton.imageEdgeInsets = .zero
+    middleButton.frame.size = CGSize(width: 80, height: 80)
+    middleButton.layer.cornerRadius = 32
+    middleButton.layer.masksToBounds = true
+    middleButton.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: 0)
+    middleButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
+    addSubview(middleButton)
+  }
+  
+  @objc private func buttonPressed() {
+    if let tabBarController = self.window!.rootViewController as? UITabBarController {
+      NotificationCenter.default.post(name: NSNotification.Name.MiddleButtonTapped, object: middleButton)
+      
+      if tabBarController.selectedIndex != 0 {
+        UIView.animate(withDuration: 0.33) {
+          tabBarController.selectedIndex = 0
+        }
+      }
+    }
+  }
+  
+  override func draw(_ rect: CGRect) {
+    self.addShape()
+  }
+  
+  private func createPath() -> CGPath {
+    let height: CGFloat = 37.0
+    let path = UIBezierPath()
+    let centerWidth = self.frame.width / 2
+    path.move(to: CGPoint(x: 0, y: 0)) // start top left
+    path.addLine(to: CGPoint(x: (centerWidth - height-20), y: 0)) // the beginning of the trough
+    
+    path.addCurve(to: CGPoint(x: centerWidth, y: -height-5),
+                  controlPoint1: CGPoint(x: (centerWidth - 40), y:  0), controlPoint2: CGPoint(x: centerWidth-50, y: -height))
+    
+    
+    path.addCurve(to: CGPoint(x: (centerWidth + height+20), y: 0),
+                  controlPoint1: CGPoint(x: centerWidth+50, y:-height), controlPoint2: CGPoint(x: (centerWidth + 40), y: 0))
+    
+    path.addLine(to: CGPoint(x: self.frame.width, y: 0))
+    path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
+    path.addLine(to: CGPoint(x: 0, y: self.frame.height))
+    path.close()
+    
+    return path.cgPath
+  }
+}
diff --git a/MiniScanner/Common/BaseNavigationViewController.swift b/MiniScanner/Common/BaseNavigationViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..68a44ab9cb043dbc2db63e05f46a8defa9a705e6
--- /dev/null
+++ b/MiniScanner/Common/BaseNavigationViewController.swift
@@ -0,0 +1,21 @@
+import UIKit
+
+class BaseNavigationViewController: UINavigationController {
+  
+  struct Constants {
+    static let reuseIdentifier = String(describing: BaseNavigationViewController.self)
+    static let storyboardName = "Documents"
+  }
+  
+  static func buildViewController() -> BaseNavigationViewController {
+    let controller = UIStoryboard(name: Constants.storyboardName,
+                                  bundle: .main).instantiateViewController(withIdentifier: Constants.reuseIdentifier)
+    return controller as! BaseNavigationViewController
+  }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    navigationBar.prefersLargeTitles = true
+    navigationItem.largeTitleDisplayMode = .always
+  }
+}
diff --git a/MiniScanner/Common/CustomPDFView.swift b/MiniScanner/Common/CustomPDFView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..23a2c550d1d312ea63c2fe9b53ce632aeaa8622a
--- /dev/null
+++ b/MiniScanner/Common/CustomPDFView.swift
@@ -0,0 +1,35 @@
+import PDFKit
+
+final class CustomPDFView: PDFView {
+
+  override var canZoomIn: Bool {
+    return false
+  }
+  
+  func setDocument(_ document: PDFDocument?) {
+    displayMode = .singlePage
+    autoScales = true
+    displayDirection = .horizontal
+    autoresizingMask = [.flexibleWidth, .flexibleHeight]
+    self.document = document
+    usePageViewController(true, withViewOptions: nil)
+    hideScrollViewIndicator()
+  }
+}
+
+extension PDFView {
+  func hideScrollViewIndicator() {
+    let scrollView = allSubviews.compactMap { $0 as? UIScrollView }.first
+    scrollView?.showsHorizontalScrollIndicator = false
+    scrollView?.showsVerticalScrollIndicator = false
+  }
+  
+  func getCurrentPageIndex() -> Int {
+    guard let currentPage = visiblePages.first, let document = document else {
+      return 1
+    }
+    
+    let index = document.index(for: currentPage)
+    return index
+  }
+}
diff --git a/MiniScanner/Extensions/Date+Extensions.swift b/MiniScanner/Extensions/Date+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d5fa29f822c92b303f499187bdfe3ec60339adf6
--- /dev/null
+++ b/MiniScanner/Extensions/Date+Extensions.swift
@@ -0,0 +1,34 @@
+import UIKit
+
+enum TimePeriod: TimeInterval {
+    case Second = 1
+    case Minute = 60
+    case Hour = 3600
+    case Day = 86400
+    case Week = 604800
+}
+
+extension Date {
+  func isSameWeekAsDate(_ date: Date) -> Bool {
+    let calendar = Calendar.current
+    let comps: Set<Calendar.Component> = [Calendar.Component.year,
+                                       Calendar.Component.month,
+                                       Calendar.Component.day,
+                                       Calendar.Component.weekOfYear,
+                                       Calendar.Component.hour,
+                                       Calendar.Component.minute,
+                                       Calendar.Component.second,
+                                       Calendar.Component.weekday,
+                                       Calendar.Component.weekdayOrdinal]
+    
+    let components1 = calendar.dateComponents(comps, from: self)
+    let components2 = calendar.dateComponents(comps, from: date)
+
+    // Must be same week. 12/31 and 1/1 will both be week "1" if they are in the same week
+    if components1.weekOfYear != components2.weekOfYear {
+      return false
+    }
+
+    return abs(timeIntervalSince(date)) < TimePeriod.Week.rawValue
+  }
+}
diff --git a/MiniScanner/Extensions/NSNotification+Extensions.swift b/MiniScanner/Extensions/NSNotification+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..50a98a4203197015e0bb6c22106994136e16391a
--- /dev/null
+++ b/MiniScanner/Extensions/NSNotification+Extensions.swift
@@ -0,0 +1,6 @@
+import UIKit
+
+extension NSNotification.Name {
+  static let MiddleButtonTapped = NSNotification.Name("MiddleButtonTapped")
+  static let ReloadViewModels = NSNotification.Name("ReloadViewModels")
+}
diff --git a/MiniScanner/Extensions/String+Extensions.swift b/MiniScanner/Extensions/String+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9dc65e14a6d497ebb9a44aca30b62b252109e11a
--- /dev/null
+++ b/MiniScanner/Extensions/String+Extensions.swift
@@ -0,0 +1,33 @@
+import Foundation
+
+extension String {
+  var toError: Error {
+    return NSError(domain: "",
+                   code: 1313,
+                   userInfo: [NSLocalizedDescriptionKey: self])
+  }
+
+  var localized: String{
+    return NSLocalizedString(self, comment: "")
+  }
+  
+  var deletingPathExtension: String {
+      return NSString(string: self).deletingPathExtension
+  }
+  
+  var deletingLastPathComponent: String {
+      return NSString(string: self).deletingLastPathComponent
+  }
+  
+  static func getDocumentName() -> String {
+    return "Scan".localized + " " + date() + ".pdf"
+  }
+  
+  static func date(_ date: Date = Date()) -> String {
+    let dateForm = DateFormatter()
+    dateForm.dateFormat = "dd:MM:yyyy HH:mm:ss"
+    let stringDate = dateForm.string(from: date)
+    
+    return stringDate
+  }
+}
diff --git a/MiniScanner/Extensions/UIImage+Extensions.swift b/MiniScanner/Extensions/UIImage+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..2a1d67b5a078a1f0a177df2e8d20f7f0f321a386
--- /dev/null
+++ b/MiniScanner/Extensions/UIImage+Extensions.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+extension UIImage {
+  
+  var getJPEGData: Data? {
+    return jpegData(compressionQuality: 0.5)
+  }
+  
+  var toFullData: Data? {
+    return jpegData(compressionQuality: 1)
+  }
+}
+
+extension UIImage {
+  static func localImage(_ name: String, template: Bool = false) -> UIImage {
+    var image = UIImage(named: name)!
+    if template {
+      image = image.withRenderingMode(.alwaysTemplate)
+    }
+    return image
+  }
+}
+
+extension UIImage {
+  /// Tint Image
+  ///
+  /// - Parameter fillColor: UIColor
+  /// - Returns: Image with tint color
+  func tint(with fillColor: UIColor) -> UIImage? {
+    let image = withRenderingMode(.alwaysTemplate)
+    UIGraphicsBeginImageContextWithOptions(size, false, scale)
+    fillColor.set()
+    image.draw(in: CGRect(origin: .zero, size: size))
+    
+    guard let imageColored = UIGraphicsGetImageFromCurrentImageContext() else {
+      return nil
+    }
+    
+    UIGraphicsEndImageContext()
+    return imageColored
+  }
+}
diff --git a/MiniScanner/Extensions/UIView+Extensions.swift b/MiniScanner/Extensions/UIView+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..88cd565d0e0ac1d750209cc429de7d635da63bad
--- /dev/null
+++ b/MiniScanner/Extensions/UIView+Extensions.swift
@@ -0,0 +1,48 @@
+import UIKit
+
+extension UIView {
+  
+  func addShadowView(shadowRadius: CGFloat = 3.0) {
+    //Remove previous shadow views
+    superview?.viewWithTag(119900)?.removeFromSuperview()
+    
+    //Create new shadow view with frame
+    let shadowView = UIView(frame: frame)
+    shadowView.tag = 119900
+    shadowView.layer.shadowColor = UIColor.black.cgColor
+    shadowView.layer.shadowOffset = CGSize(width: 2, height: 3)
+    shadowView.layer.masksToBounds = false
+    
+    shadowView.layer.shadowOpacity = 0.3
+    shadowView.layer.shadowRadius = shadowRadius
+    shadowView.layer.shadowPath = UIBezierPath(rect: bounds).cgPath
+    shadowView.layer.rasterizationScale = UIScreen.main.scale
+    shadowView.layer.shouldRasterize = true
+    
+    superview?.insertSubview(shadowView, belowSubview: self)
+  }
+}
+
+extension UIView {
+  @nonobjc func withAccessibilityIdentifier(_ accessibilityIdentifier: String) -> UIView? {
+    return withAccessibilityIdentifier(accessibilityIdentifier, classType: UIView.self)
+  }
+  
+  @nonobjc func withAccessibilityIdentifier<T: UIView>(_ accessibilityIdentifier: String, classType: T.Type) -> T? {
+    if let selfObject = self as? T, self.accessibilityIdentifier == accessibilityIdentifier {
+      return selfObject
+    }
+    for subview in self.subviews {
+      if let match = subview.withAccessibilityIdentifier(accessibilityIdentifier, classType: classType) {
+        return match
+      }
+    }
+    return nil
+  }
+}
+
+extension UIView {
+  var allSubviews: [UIView] {
+    return self.subviews.flatMap { [$0] + $0.allSubviews }
+  }
+}
diff --git a/MiniScanner/Extensions/UIViewController+Extensions.swift b/MiniScanner/Extensions/UIViewController+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..77d020edcb680c0cb820b5cccd409200176083cc
--- /dev/null
+++ b/MiniScanner/Extensions/UIViewController+Extensions.swift
@@ -0,0 +1,40 @@
+import UIKit
+
+extension UIViewController {
+  
+  func addChildViewControllerWithView(_ childViewController: UIViewController, toView view: UIView? = nil) {
+    let view: UIView = view ?? self.view
+    childViewController.removeFromParent()
+    childViewController.willMove(toParent: self)
+    addChild(childViewController)
+    childViewController.didMove(toParent: self)
+    childViewController.view.translatesAutoresizingMaskIntoConstraints = false
+    view.addSubview(childViewController.view)
+    view.addConstraints([
+      NSLayoutConstraint(item: childViewController.view!, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: -10),
+      NSLayoutConstraint(item: childViewController.view!, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0),
+      NSLayoutConstraint(item: childViewController.view!, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0),
+      NSLayoutConstraint(item: childViewController.view!, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)
+    ])
+    view.layoutIfNeeded()
+  }
+  
+  func removeChildViewController(_ childViewController: UIViewController) {
+    childViewController.removeFromParent()
+    childViewController.willMove(toParent: nil)
+    childViewController.removeFromParent()
+    childViewController.didMove(toParent: nil)
+    childViewController.view.removeFromSuperview()
+    view.layoutIfNeeded()
+  }
+  
+  func hideKeyboardWhenTappedAround() {
+    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
+    tap.cancelsTouchesInView = false
+    view.addGestureRecognizer(tap)
+  }
+  
+  @objc func dismissKeyboard() {
+    view.endEditing(true)
+  }
+}
diff --git a/MiniScanner/Extensions/URL+Extensions.swift b/MiniScanner/Extensions/URL+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c3b5145533c7c4d5b85c904a9aa5ba132f7d2563
--- /dev/null
+++ b/MiniScanner/Extensions/URL+Extensions.swift
@@ -0,0 +1,72 @@
+import UIKit
+
+extension URL {
+  
+  var getFileAttributes: NSDictionary? {
+    let path = self.path
+    
+    do {
+      let attributes = try FileManager.default.attributesOfItem(atPath: path) as NSDictionary
+      
+      return attributes
+    } catch {}
+    
+    return nil
+  }
+  
+  var getFileAttributesOfURL: [FileAttributeKey: Any]? {
+    let path = self.path
+    
+    do {
+      let attributes = try FileManager.default.attributesOfItem(atPath: path)
+      
+      return attributes
+    } catch {
+      print(error.localizedDescription, #function)
+    }
+    
+    return nil
+  }
+  
+  var getDate: String {
+    return getDate(self.getFileAttributesOfURL)
+  }
+  
+  func getDate(_ attributes: [FileAttributeKey: Any]?) -> String {
+    var stringDate = String()
+    if let attributes = attributes, let fileDate = attributes[FileAttributeKey.creationDate] as? Date {
+
+      if Calendar.current.isDateInToday(fileDate) {
+        stringDate = "Today".localized
+      } else if Calendar.current.isDateInYesterday(fileDate) {
+        stringDate = "Yesterday".localized
+      } else if Date().isSameWeekAsDate(fileDate) {
+        stringDate = "This week".localized
+      } else {
+        stringDate = getDateInCurrentLocaleWithHour(fileDate)
+      }
+    }
+    
+    return stringDate
+  }
+  
+  /// This function will return a current date in format ""Jan 23, 2017, 14:59:09""
+  private func getDateInCurrentLocaleWithHour(_ date: Date = Date()) -> String {
+    let currentLocale = Locale.current
+    let dateFormatter = DateFormatter()
+    let dateComponents = "y-MMM-d - H'-'ms"
+    let dateFormat = DateFormatter.dateFormat(fromTemplate: dateComponents, options: 0, locale: currentLocale)
+    dateFormatter.dateFormat = dateFormat
+    
+    return dateFormatter.string(from: date)
+  }
+  
+  var isPDF: Bool {
+    return pathExtension == "pdf"
+  }
+  
+  var toData: Data? {
+    return try? Data(contentsOf: self)
+  }
+}
+
diff --git a/MiniScanner/Extensions/UserDefaults+Extensions.swift b/MiniScanner/Extensions/UserDefaults+Extensions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8dd9b68f8bbaad2a6b15e432fa946a8145814039
--- /dev/null
+++ b/MiniScanner/Extensions/UserDefaults+Extensions.swift
@@ -0,0 +1,49 @@
+import UIKit
+
+extension UserDefaults {
+  
+  var isPhotoEditigOn: Bool {
+    get {
+      return bool(forKey: "isPhotoEditigOn")
+    } set {
+      set(newValue, forKey: "isPhotoEditigOn")
+      synchronize()
+    }
+  }
+  
+  var startsAppWithCamera: Bool {
+    get {
+      return bool(forKey: "startsAppWithCamera")
+    } set {
+      set(newValue, forKey: "startsAppWithCamera")
+      synchronize()
+    }
+  }
+  
+  var askOnSwipeDelete: Bool {
+    get {
+      return bool(forKey: "askOnSwipeDelete")
+    } set {
+      set(newValue, forKey: "askOnSwipeDelete")
+      synchronize()
+    }
+  }
+  
+  var showWalktroughAtLaunch: Bool {
+    get {
+      return bool(forKey: "showWalktroughAtLaunch")
+    } set {
+      set(newValue, forKey: "showWalktroughAtLaunch")
+      synchronize()
+    }
+  }
+  
+  var hideTooltips: Bool {
+    get {
+      return bool(forKey: "hideTooltips")
+    } set {
+      set(newValue, forKey: "hideTooltips")
+      synchronize()
+    }
+  }
+}
diff --git a/MiniScanner/Managers/LocalFileManager.swift b/MiniScanner/Managers/LocalFileManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ca431f559496b38d91f557ab196f3acad2b9a828
--- /dev/null
+++ b/MiniScanner/Managers/LocalFileManager.swift
@@ -0,0 +1,154 @@
+import Foundation
+import UIKit
+
+private var _excludesFileExtensions = [String]()
+private var excludesFilepaths: [URL]?
+
+enum SortyFileType {
+  case name, date
+}
+
+class LocalFileManager {
+  
+  let filesManager = FileManager.default
+  
+  var documentsURL: URL {
+    return filesManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
+  }
+  
+  var scannerURL: URL {
+    let iFinderURL = documentsURL.appendingPathComponent(AppConfigurator.DocumentsFolderName, isDirectory: true)
+    /// Check if file not exist and create
+    if !filesManager.fileExists(atPath: iFinderURL.path) {
+      try? filesManager.createDirectory(at: iFinderURL, withIntermediateDirectories: true, attributes: nil)
+    }
+    
+    return iFinderURL
+  }
+  
+  /// Mapped for case insensitivity
+  var excludesFileExtensions: [String]? {
+    get {
+      return _excludesFileExtensions.map { $0.lowercased() }
+    }
+    set {
+      if let newValue = newValue {
+        _excludesFileExtensions = newValue
+      }
+    }
+  }
+  
+  func getItemsAtPath(_ path: URL) -> [URL]? {
+    return try? filesManager.contentsOfDirectory(at: path, includingPropertiesForKeys: [], options: [])
+  }
+  
+  func filesForDirectory(_ directoryPath: URL, sortType: SortyFileType) -> [File]  {
+    var files = [File]()
+    var fileURLs = [URL]()
+    
+    // Get contents
+    do  {
+      fileURLs = try self.filesManager.contentsOfDirectory(at: directoryPath, includingPropertiesForKeys: [], options: [.skipsHiddenFiles])
+    } catch {
+      return files
+    }
+    
+    // Parse
+    for fileURL in fileURLs {
+      let file = File(fileURL: fileURL)
+      
+      if let excludesFileExtensions = excludesFileExtensions,
+         let fileExtensions = file.fileExtension,
+         excludesFileExtensions.contains(fileExtensions) {  continue }
+      
+      if let excludesFilepaths = excludesFilepaths, excludesFilepaths.contains(file.fileURL) {  continue }
+      
+      if !file.displayName.isEmpty && !file.displayName.lowercased().contains("(a document being saved") { files.append(file) }
+      
+      self.createThumbnailAndOriginalFolders(directoryPath)
+      
+      if file.fileURL.isPDF {
+        let pdfThumbnailURL = getThumbnailFile(for: fileURL)
+        
+        if !self.filesManager.fileExists(atPath: pdfThumbnailURL.path) {
+          switch deviceType {
+          case .pad:
+            if let pdfThumbnail = PDFManager.generatePdfThumbnail(of: CGSize(width: 225, height: 450), for: fileURL)?.toFullData {
+              try? pdfThumbnail.write(to: pdfThumbnailURL)
+            }
+          default:
+            if let pdfThumbnail = PDFManager.generatePdfThumbnail(of: CGSize(width: 120, height: 240), for: fileURL)?.toFullData {
+              try? pdfThumbnail.write(to: pdfThumbnailURL)
+            }
+          }
+        }
+      }
+    }
+    
+    switch sortType {
+    case .date:
+      return files.sorted { compare(date1: $0.fileURL.getFileAttributes?.fileCreationDate(),
+                                    with: $1.fileURL.getFileAttributes?.fileCreationDate()) }
+    case .name:
+      return files.sorted { $0.displayName.lowercased() < $1.displayName.lowercased() }
+    }
+  }
+  
+  private func compare(date1: Date?, with date2: Date?) -> Bool {
+    if let date1 = date1, let date2 = date2 {
+      return date1 > date2
+    }
+    
+    return false
+  }
+  
+  func createThumbnailAndOriginalFolders(_ dirURL: URL) {
+    self.create(folderAtPath: dirURL, withName: AppConfigurator.ThumbnailsFolderName)
+  }
+  
+  func create(folderAtPath path: URL, withName name: String) {
+    let newDirectory = path.appendingPathComponent(name)
+    
+    do {
+      try filesManager.createDirectory(at: newDirectory, withIntermediateDirectories: true, attributes: nil)
+      
+    } catch {
+      print("Cannot create folder at path, error = \(error.localizedDescription)")
+    }
+  }
+  
+  func removeThumbnail(for url: URL) throws {
+    try filesManager.removeItem(at: getThumbnailFile(for: url))
+  }
+  
+  func getThumbnailFile(for url: URL) -> URL {
+    return url.deletingLastPathComponent().appendingPathComponent(AppConfigurator.ThumbnailsFolderName).appendingPathComponent(url.deletingPathExtension().lastPathComponent + ".jpg")
+  }
+  
+  func getThumbnail(for pdfURL: URL) -> UIImage? {
+    let imageURL = getThumbnailFile(for: pdfURL)
+    return UIImage(contentsOfFile: imageURL.path)
+  }
+  
+  func updateThumbnail(forURL fileURL: URL) {
+    let pdfThumbnailURL = getThumbnailFile(for: fileURL)
+    
+    switch deviceType {
+    case .pad:
+      if let pdfThumbnail = PDFManager.generatePdfThumbnail(of: CGSize(width: 225, height: 450), for: fileURL)?.toFullData {
+        try? pdfThumbnail.write(to: pdfThumbnailURL)
+      }
+    default:
+      if let pdfThumbnail = PDFManager.generatePdfThumbnail(of: CGSize(width: 120, height: 240), for: fileURL)?.toFullData {
+        try? pdfThumbnail.write(to: pdfThumbnailURL)
+      }
+    }
+  }
+  
+  func renameFile(at url: URL, withName newName: String) throws {
+    let fileURL = url.deletingLastPathComponent()
+    let newFileName = "\(newName).pdf"
+    try filesManager.moveItem(at: url, to: fileURL.appendingPathComponent(newFileName))
+    try filesManager.removeItem(at: getThumbnailFile(for: url))
+  }
+}
diff --git a/MiniScanner/Managers/PDFManager.swift b/MiniScanner/Managers/PDFManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c51b863daf1c7d597ca066d925482ffc3b4791f8
--- /dev/null
+++ b/MiniScanner/Managers/PDFManager.swift
@@ -0,0 +1,206 @@
+import UIKit
+import PDFKit
+
+class PDFManager {
+  
+  class func pdfThumbnail(url: URL, width: CGFloat = 240) -> UIImage? {
+    guard let data = try? Data(contentsOf: url),
+          let page = PDFDocument(data: data)?.page(at: 0) else {
+      return nil
+    }
+    
+    let pageSize = page.bounds(for: .mediaBox)
+    let pdfScale = width / pageSize.width
+    
+    let scale = UIScreen.main.scale * pdfScale
+    let screenSize = CGSize(width: pageSize.width * scale,
+                            height: pageSize.height * scale)
+    
+    return page.thumbnail(of: screenSize, for: .mediaBox)
+  }
+  
+  class func generatePdfThumbnail(of thumbnailSize: CGSize, for documentUrl: URL) -> UIImage? {
+    guard let data = try? Data(contentsOf: documentUrl),
+          let page = PDFDocument(data: data)?.page(at: 0) else {
+      return nil
+    }
+
+    return page.thumbnail(of: thumbnailSize, for: .trimBox)
+  }
+  
+  class func getPDFPageToImage(page: PDFPage, pageIndex: Int) -> UIImage? {
+    let pageSize = page.bounds(for: .mediaBox)
+    let screenSize = CGSize(width: pageSize.width,
+                            height: pageSize.height)
+
+    return page.thumbnail(of: screenSize, for: .mediaBox)
+  }
+  
+  class func createPDFDocument(from image: UIImage, localFileManager: LocalFileManager?) {
+    guard let scannerURL = localFileManager?.scannerURL else { return }
+    let urlPDFtoSave = scannerURL.appendingPathComponent(String.getDocumentName())
+    let document = PDFDocument()
+    
+    if let pdfPage = PDFPage(image: image) {
+      document.insert(pdfPage, at: 0)
+    }
+    do {
+      try document.dataRepresentation()?.write(to: urlPDFtoSave)
+    } catch {
+      print(error.localizedDescription)
+    }
+  }
+  
+  class func createPDFDocument(from image: UIImage, urlPDFtoSave: URL) {
+    let document = PDFDocument()
+    
+    if let pdfPage = PDFPage(image: image) {
+      document.insert(pdfPage, at: 0)
+    }
+    do {
+      try document.dataRepresentation()?.write(to: urlPDFtoSave)
+    } catch {
+      print(error.localizedDescription)
+    }
+  }
+  
+  // Create PDF from images
+  // images - array of uiimages
+  // urlPDFtoSave - it must be a local pdf url with .pdf extension, otherwise it will be saved as data
+  // url example: let urlPDFtoSave = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("file.pdf")
+    
+//    class func createMultiPDFPage(from images: [UIImage], localFileManager: LocalFileManager?, _ completion: @escaping () -> ()) {
+//    guard let scannerURL = localFileManager?.scannerURL else { return }
+//    let urlPDFtoSave = scannerURL.appendingPathComponent(String.getDocumentName())
+//    
+//    if images.isEmpty { return }
+//    let document = PDFDocument()
+//    
+//    // Iterrate trough images
+//    for (index, image) in images.enumerated() {
+//      if let pdfPage = PDFPage(image: image) {
+//        document.insert(pdfPage, at: index)
+//      }
+//      if document.pageCount == images.count {
+//        do {
+//          try document.dataRepresentation()?.write(to: urlPDFtoSave)
+//            completion()
+//        } catch {
+//          print(error.localizedDescription) // handle error
+//        }
+//      }
+//    }
+//  }
+    
+    class func createMultiPDFPage(from imageURLs: [URL], localFileManager: LocalFileManager?, _ completion: @escaping () -> ()) {
+        guard let scannerURL = localFileManager?.scannerURL else { return }
+        let urlPDFtoSave = scannerURL.appendingPathComponent(String.getDocumentName())
+        
+        if imageURLs.isEmpty { return }
+        let document = PDFDocument()
+
+        let dispatchGroup = DispatchGroup()
+        
+        // Iterate through image URLs
+        for (index, imageURL) in imageURLs.enumerated() {
+            dispatchGroup.enter()
+            DispatchQueue.global().async {
+                if let data = try? Data(contentsOf: imageURL),
+                   let image = UIImage(data: data),
+                   let pdfPage = PDFPage(image: image) {
+                    DispatchQueue.main.async {
+                        document.insert(pdfPage, at: index)
+                        if document.pageCount == imageURLs.count {
+                            do {
+                                try document.dataRepresentation()?.write(to: urlPDFtoSave)
+                                completion()
+                            } catch {
+                                print(error.localizedDescription) // handle error
+                            }
+                        }
+                        dispatchGroup.leave()
+                    }
+                } else {
+                    dispatchGroup.leave()
+                }
+            }
+        }
+        dispatchGroup.notify(queue: .main) {
+            print("All images have been processed")
+        }
+    }
+  
+  class func appendPage(image: UIImage, pdfView: PDFView, documentURL: URL?) {
+    guard let page = PDFPage(image: image),
+          let documentURL = documentURL,
+          let lastIndex = pdfView.document?.pageCount else  { return }
+    pdfView.document?.insert(page, at: lastIndex)
+    pdfView.document?.write(to: documentURL)
+    pdfView.go(to: page)
+    
+    LocalFileManager().updateThumbnail(forURL: documentURL)
+  }
+    
+class func appendPage(imageURL: URL, pdfView: PDFView, documentURL: URL?) {
+        DispatchQueue.global().async {
+            if let data = try? Data(contentsOf: imageURL),
+               let image = UIImage(data: data),
+               let page = PDFPage(image: image),
+               let documentURL = documentURL,
+               let lastIndex = pdfView.document?.pageCount {
+                DispatchQueue.main.async {
+                    pdfView.document?.insert(page, at: lastIndex)
+                    pdfView.document?.write(to: documentURL)
+                    pdfView.go(to: page)
+                    
+                    LocalFileManager().updateThumbnail(forURL: documentURL)
+                }
+            }
+        }
+    }
+  
+  class func appendPage(images: [UIImage], pdfView: PDFView, documentURL: URL?) {
+    guard let documentURL = documentURL else  { return }
+    let currentIndex = pdfView.getCurrentPageIndex()
+    
+    for image in images {
+      if let page = PDFPage(image: image) {
+        pdfView.document?.insert(page, at: currentIndex)
+      }
+    }
+    
+    if let page = pdfView.visiblePages.first {
+      pdfView.document?.write(to: documentURL)
+      pdfView.go(to: page)
+    }
+    
+    LocalFileManager().updateThumbnail(forURL: documentURL)
+    
+    pdfView.document = PDFDocument(url: documentURL)
+    pdfView.layoutDocumentView()
+  }
+  
+  class func deletePage(at index: Int, pdfDocument: PDFDocument?, documentURL: URL?, pdfView: PDFView!) {
+    guard let pdfDocument = pdfDocument, let documentURL = documentURL, let pdfView = pdfView else  { return }
+    pdfDocument.removePage(at: index)
+    pdfDocument.write(to: documentURL)
+    pdfView.document = pdfDocument
+    pdfView.layoutDocumentView()
+    LocalFileManager().updateThumbnail(forURL: documentURL)
+    if pdfView.canGoToNextPage {
+      pdfView.goToNextPage(pdfView)
+    } else if pdfView.canGoToPreviousPage {
+      pdfView.goToPreviousPage(pdfView)
+    } else if pdfView.canGoToLastPage {
+      pdfView.goToLastPage(pdfView)
+    } else if pdfView.canGoForward {
+      pdfView.goForward(pdfView)
+    } else if pdfView.canGoBack {
+      pdfView.goBack(pdfView)
+    } else if pdfView.canGoToFirstPage {
+      pdfView.goToFirstPage(pdfView)
+    } else {
+      pdfView.layoutDocumentView()
+    }
+  }
+}
diff --git a/MiniScanner/Managers/ThemeManager.swift b/MiniScanner/Managers/ThemeManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..05bd3526cfdbeda123a81a6d3772e6f5338b3e48
--- /dev/null
+++ b/MiniScanner/Managers/ThemeManager.swift
@@ -0,0 +1,63 @@
+//
+//  ThemeManager.swift
+//  DocScan
+//
+//  Created by Mister Grizzly.
+//
+
+import UIKit
+
+final class ThemeManager {
+  
+  static let shared = ThemeManager()
+  
+  /// Setups the appearance proxy for the UINavigationBar, UIToolbar and UIButton.
+  func setupTheme() {
+    let navigationBarAppearace = UINavigationBar.appearance()
+    
+    navigationBarAppearace.tintColor = .tintColor
+    navigationBarAppearace.barTintColor = .barTintColor
+    
+    let toolBarAppearace = UIToolbar.appearance()
+    
+    toolBarAppearace.tintColor = .tintColor
+    toolBarAppearace.barTintColor = .barTintColor
+    
+    let buttonAppearance = UIButton.appearance()
+    buttonAppearance.tintColor = .tintColor
+  }
+}
+
+extension UIColor {
+  class var tintColor: UIColor {
+    if UIScreen.isDarkMode {
+      return .white
+    } else {
+      return UIColor(named: "AccentColor")!
+    }
+  }
+  
+  class var barTintColor: UIColor {
+    if UIScreen.isDarkMode {
+      return .darkText
+    } else {
+      return .white
+    }
+  }
+}
+
+extension UIScreen {
+  static var isDarkMode: Bool {
+    return main.traitCollection.userInterfaceStyle == .dark
+  }
+}
+
+extension UIDevice {
+  static var isSimulator: Bool {
+    #if targetEnvironment(simulator)
+    return true
+    #else
+    return false
+    #endif
+  }
+}
diff --git a/MiniScanner/Modules/.DS_Store b/MiniScanner/Modules/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..4dabfe7b45bb262eb746e33cc700f6ce2212a004
Binary files /dev/null and b/MiniScanner/Modules/.DS_Store differ
diff --git a/MiniScanner/Modules/ATCClassicWalkthroughViewController.swift b/MiniScanner/Modules/ATCClassicWalkthroughViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..979efb2b01e51081b9111cf9a6d21d3ba1b1a6cf
--- /dev/null
+++ b/MiniScanner/Modules/ATCClassicWalkthroughViewController.swift
@@ -0,0 +1,41 @@
+import UIKit
+
+class ClassicWalkthroughViewController: UIViewController {
+  @IBOutlet var containerView: UIView!
+  @IBOutlet var imageContainerView: UIView!
+  @IBOutlet var imageView: UIImageView!
+  @IBOutlet var titleLabel: UILabel!
+  @IBOutlet var subtitleLabel: UILabel!
+  
+  let model: WalkthroughModel
+  
+  init(model: WalkthroughModel,
+       nibName nibNameOrNil: String?,
+       bundle nibBundleOrNil: Bundle?) {
+    self.model = model
+    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+  }
+  
+  required init?(coder aDecoder: NSCoder) {
+    fatalError("init(coder:) has not been implemented")
+  }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    imageView.image = UIImage.localImage(model.icon, template: true)
+    imageView.contentMode = .scaleAspectFill
+    imageView.clipsToBounds = true
+    imageView.tintColor = .tintColor
+    imageContainerView.backgroundColor = .clear
+    
+    titleLabel.text = model.title
+    titleLabel.font = UIFont.boldSystemFont(ofSize: 20.0)
+    titleLabel.textColor = .tintColor
+    
+    subtitleLabel.attributedText = NSAttributedString(string: model.subtitle)
+    subtitleLabel.font = UIFont.systemFont(ofSize: 14.0)
+    subtitleLabel.textColor = .tintColor
+    
+    containerView.backgroundColor = .barTintColor
+  }
+}
diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard b/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard
new file mode 100644
index 0000000000000000000000000000000000000000..58e91d199abf5e15b1a40950828addefb11825db
--- /dev/null
+++ b/MiniScanner/Modules/DocumentPreview/DocumentPreview.storyboard
@@ -0,0 +1,112 @@
+<?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">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/>
+        <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>
+    <scenes>
+        <!--Document Preview View Controller-->
+        <scene sceneID="19p-no-z6i">
+            <objects>
+                <viewController storyboardIdentifier="DocumentPreviewViewController" id="lAb-mo-IO6" customClass="DocumentPreviewViewController" customModule="MiniScanner" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="yh9-W2-Nlc">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <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"/>
+                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                            </view>
+                            <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyQ-Gx-pj4">
+                                <rect key="frame" x="0.0" y="818" width="414" height="44"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="44" id="zEZ-cV-RyU"/>
+                                </constraints>
+                                <items>
+                                    <barButtonItem title="Item" image="plus.app" catalog="system" id="sB9-vj-D2V">
+                                        <connections>
+                                            <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>
+                                            <action selector="drawTapped:" destination="lAb-mo-IO6" id="ibK-6x-52U"/>
+                                        </connections>
+                                    </barButtonItem>
+                                    <barButtonItem style="plain" systemItem="flexibleSpace" id="4zG-Cu-94i"/>
+                                    <barButtonItem title="Item" image="trash" catalog="system" id="1Hw-0H-gyu">
+                                        <connections>
+                                            <action selector="deleteTapped:" destination="lAb-mo-IO6" id="yoD-CQ-Iec"/>
+                                        </connections>
+                                    </barButtonItem>
+                                </items>
+                            </toolbar>
+                        </subviews>
+                        <viewLayoutGuide key="safeArea" id="4bJ-Eb-Q72"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <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="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 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"/>
+                        </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>
+                    </navigationItem>
+                    <connections>
+                        <outlet property="pdfView" destination="HkK-Fc-Rgz" id="3sS-2Q-v88"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="B6i-QH-Eiz" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1160.8695652173915" y="177.45535714285714"/>
+        </scene>
+        <!--Navigation Controller-->
+        <scene sceneID="Rky-DJ-9es">
+            <objects>
+                <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"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="lAb-mo-IO6" kind="relationship" relationship="rootViewController" id="5cf-1R-Wz4"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Yra-bk-Gt1" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="250.72463768115944" y="177.45535714285714"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="pencil.tip.crop.circle" catalog="system" width="128" height="121"/>
+        <image name="plus.app" catalog="system" width="128" height="114"/>
+        <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"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>
diff --git a/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b33345a55916f672b950b1b0d30315089818513e
--- /dev/null
+++ b/MiniScanner/Modules/DocumentPreview/DocumentPreviewViewController.swift
@@ -0,0 +1,195 @@
+import UIKit
+import VisionKit
+
+final class DocumentPreviewViewController: UIViewController {
+    
+    
+    struct Constants {
+        static let reuseIdentifier = String(describing: DocumentPreviewViewController.self)
+        static let storyboardName = "DocumentPreview"
+    }
+    
+    static func buildViewController() -> DocumentPreviewViewController {
+        let controller = UIStoryboard(name: Constants.storyboardName,
+                                      bundle: .main).instantiateViewController(withIdentifier: Constants.reuseIdentifier)
+        return controller as! DocumentPreviewViewController
+    }
+    
+    @IBOutlet private weak var pdfView: CustomPDFView!
+    
+    var file: File?
+    private var scannedItem: ScannedItem!
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        // Do any additional setup after loading the view.
+        pdfView.accessibilityIdentifier = "pdfView"
+        navigationItem.title = file?.displayName
+        pdfView.setDocument(file?.pdfDocument)
+    }
+    
+    @IBAction func printTapped(_ sender: UIBarButtonItem) {
+        guard let documentURL = file?.fileURL else { return }
+        
+        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.printingItems = [documentURL]
+        printController.present(from: view.frame, in: view, animated: true, completionHandler: nil)
+    }
+    
+    @IBAction func addPageTapped(_ sender: UIBarButtonItem) {
+        let alertController = UIAlertController(title: nil,
+                                                message: nil, preferredStyle: .actionSheet)
+        
+        let cameraAction = UIAlertAction(title: "Camera".localized, style: .default, handler: { action in
+            self.openCamera()
+        })
+        
+        let galleryAction = UIAlertAction(title: "Gallery".localized, style: .default, handler: { action in
+            self.openGallery()
+        })
+        
+        alertController.addAction(cameraAction)
+        cameraAction.setValue(UIImage(systemName: "camera"), forKey: "image")
+        cameraAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
+        
+        alertController.addAction(galleryAction)
+        galleryAction.setValue(UIImage(systemName: "photo"), forKey: "image")
+        galleryAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
+        
+        alertController.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
+        alertController.popoverPresentationController?.barButtonItem = sender
+        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
+        previewController.delegate = self
+        previewController.modalPresentationStyle = .fullScreen
+        present(previewController, animated: true, completion: nil)
+    }
+    
+    @IBAction func deleteTapped(_ sender: UIBarButtonItem) {
+        let alertController = UIAlertController(title: "Delete".localized,
+                                                message: "Are you sure?".localized, preferredStyle: .actionSheet)
+        
+        if pdfView.document?.pageCount == 1 {
+            let currentPageAction = UIAlertAction(title: "Delete document".localized, style: .default, handler: { action in
+                guard let documentURL = self.file?.fileURL, let pdfView = self.pdfView else { return }
+                if pdfView.document?.pageCount == 1 {
+                    try? FileManager.default.removeItem(at: documentURL)
+                    self.navigationController?.popViewController(animated: true)
+                } else {
+                    PDFManager.deletePage(at: pdfView.getCurrentPageIndex(), pdfDocument: pdfView.document,
+                                          documentURL: self.file?.fileURL, pdfView: pdfView)
+                }
+            })
+            
+            alertController.addAction(currentPageAction)
+        } else {
+            let currentPageAction = UIAlertAction(title: "Current page".localized, style: .default, handler: { action in
+                guard let documentURL = self.file?.fileURL, let pdfView = self.pdfView else { return }
+                if pdfView.document?.pageCount == 1 {
+                    try? FileManager.default.removeItem(at: documentURL)
+                    self.navigationController?.popViewController(animated: true)
+                } else {
+                    PDFManager.deletePage(at: pdfView.getCurrentPageIndex(), pdfDocument: pdfView.document,
+                                          documentURL: self.file?.fileURL, pdfView: pdfView)
+                }
+            })
+            
+            let entireDocumentAction = UIAlertAction(title: "Entire document".localized, style: .default, handler: { action in
+                guard let documentURL = self.file?.fileURL else { return }
+                try? FileManager.default.removeItem(at: documentURL)
+                self.navigationController?.popViewController(animated: true)
+            })
+            
+            alertController.addAction(currentPageAction)
+            alertController.addAction(entireDocumentAction)
+        }
+        
+        alertController.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
+        alertController.popoverPresentationController?.barButtonItem = sender
+        present(alertController, animated: true)
+    }
+}
+
+// MARK: - UIPrintInteractionControllerDelegate
+
+extension DocumentPreviewViewController: UIPrintInteractionControllerDelegate {
+    
+    func printInteractionControllerParentViewController(_ printInteractionController: UIPrintInteractionController) -> UIViewController? {
+        return self.navigationController
+    }
+}
+
+extension DocumentPreviewViewController {
+    private func openCamera() {
+        let scannerOptions = ImageScannerOptions(scanMultipleItems: true,
+                                                 allowAutoScan: false,
+                                                 allowTapToFocus: false,
+                                                 defaultColorRenderOption:.color)
+        let scannerViewController = ImageScannerController(options: scannerOptions)
+        scannerViewController.imageScannerDelegate = self
+        self.present(scannerViewController, animated: true)
+    }
+    
+    private func openGallery() {
+        guard UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.savedPhotosAlbum) else { return }
+        let imagePickerController = UIImagePickerController()
+        imagePickerController.delegate = self
+        
+        imagePickerController.sourceType = UIImagePickerController.SourceType.savedPhotosAlbum
+        imagePickerController.allowsEditing = UserDefaults.standard.isPhotoEditigOn
+        present(imagePickerController, animated: true, completion: nil)
+    }
+}
+
+/// Tells the delegate that the user picked a still image.
+extension DocumentPreviewViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
+    func imagePickerController(_ picker: UIImagePickerController,
+                               didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
+        picker.dismiss(animated: true) { [weak self] in
+            guard let self = self else { return }
+            guard let image = info[UserDefaults.standard.isPhotoEditigOn ? UIImagePickerController.InfoKey.editedImage : UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
+            PDFManager.appendPage(image: image, pdfView: self.pdfView, documentURL: self.file?.fileURL)
+        }
+    }
+}
+
+extension DocumentPreviewViewController: ImageScannerControllerDelegate {
+    func imageScannerController(_ scanner: ImageScannerController, didFinishWithSession session: MultiPageScanSession) {
+        scanner.dismiss(animated: true) { [weak self] in
+            guard let self = self else { return }
+            for index in 0..<session.scannedItems.count {
+                if let url = session.scannedItems[index].renderedImage {
+                    PDFManager.appendPage(imageURL: url, pdfView: self.pdfView, documentURL: self.file?.fileURL)
+                }
+                }
+            }
+        }
+    func imageScannerControllerDidCancel(_ scanner: ImageScannerController) {
+        scanner.dismiss(animated: true)
+    }
+    
+    func imageScannerController(_ scanner: ImageScannerController, didFailWithError error: Error) {
+        scanner.dismiss(animated: true)
+
+    }
+}
diff --git a/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift b/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0ac0f2ad679ac43c570b02d4c52d2142d03ab790
--- /dev/null
+++ b/MiniScanner/Modules/DocumentPreview/PencilKitViewController.swift
@@ -0,0 +1,81 @@
+import UIKit
+import PencilKit
+import QuickLook
+import PDFKit
+
+class PencilKitViewController: QLPreviewController {
+  override var editingInteractionConfiguration: UIEditingInteractionConfiguration {
+    return .none
+  }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    setEditing(true, animated: true)
+    perform(#selector(hideShare), with: self, afterDelay: 1.22)
+    
+    navigationController?.hidesBarsOnTap = true
+  }
+  
+  @objc private func hideShare() {
+    if let shareButton = (children.first?.view.subviews.last as? UIToolbar)?.items?.first {
+      shareButton.isEnabled = false
+      shareButton.tintColor = .clear
+    }
+    
+    //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)
+//      }
+    }
+  }
+}
+
+extension DocumentPreviewViewController: QLPreviewControllerDataSource, QLPreviewControllerDelegate {
+  func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
+    return 1
+  }
+  
+  func previewController(_ controller: QLPreviewController,
+                         previewItemAt index: Int) -> QLPreviewItem {
+    let url = file!.fileURL as NSURL
+    return url as QLPreviewItem
+  }
+  
+  @available(iOS 13.0, *)
+  func previewController(_ controller: QLPreviewController,
+                         editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
+    return .updateContents
+  }
+  
+  func previewController(_ controller: QLPreviewController,
+                         didUpdateContentsOf previewItem: QLPreviewItem) {
+    DispatchQueue.main.async { [weak self] in
+      self?.didUpdateContentsOf((previewItem as! NSURL) as URL)
+    }
+  }
+  
+  func previewController(_ controller: QLPreviewController,
+                         didSaveEditedCopyOf previewItem: QLPreviewItem,
+                         at modifiedContentsURL: URL) {
+    didSaveEditedCopyOf((previewItem as! NSURL) as URL)
+  }
+  
+  func didUpdateContentsOf(_ url: URL) {
+    let pdfView = view.withAccessibilityIdentifier("pdfView", classType: CustomPDFView.self)
+    pdfView?.document = PDFDocument(url: url)
+  }
+  
+  func didSaveEditedCopyOf(_ modifiedContentsURL: URL) {
+    let pdfView = view.withAccessibilityIdentifier("pdfView", classType: CustomPDFView.self)
+    if let data = modifiedContentsURL.toData, let documentURL = pdfView?.document?.documentURL {
+      try? data.write(to: documentURL)
+      pdfView?.document = PDFDocument(url: documentURL)
+      pdfView?.layoutDocumentView()
+    }
+  }
+}
diff --git a/MiniScanner/Modules/DocumentPreview/WeScan b/MiniScanner/Modules/DocumentPreview/WeScan
new file mode 160000
index 0000000000000000000000000000000000000000..3713c93e3379c802f6b272f7aeba1d10dc31a04f
--- /dev/null
+++ b/MiniScanner/Modules/DocumentPreview/WeScan
@@ -0,0 +1 @@
+Subproject commit 3713c93e3379c802f6b272f7aeba1d10dc31a04f
diff --git a/MiniScanner/Modules/Documents/Documents.storyboard b/MiniScanner/Modules/Documents/Documents.storyboard
new file mode 100644
index 0000000000000000000000000000000000000000..59343db3505d19b3d2398ea5ec6c6af11340b39f
--- /dev/null
+++ b/MiniScanner/Modules/Documents/Documents.storyboard
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="NRZ-n7-XkU">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
+        <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>
+    <scenes>
+        <!--Documents Table View Controller-->
+        <scene sceneID="H5o-MQ-blf">
+            <objects>
+                <tableViewController storyboardIdentifier="DocumentsTableViewController" id="gvn-iJ-Pzo" customClass="DocumentsTableViewController" customModule="MiniScanner" customModuleProvider="target" sceneMemberID="viewController">
+                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="bPB-U2-F5q">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <prototypes>
+                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="DocumentsTableViewCell" rowHeight="89" id="Mdk-jc-rWc" customClass="DocumentsTableViewCell" customModule="MiniScanner" customModuleProvider="target">
+                                <rect key="frame" x="0.0" y="28" width="414" height="89"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Mdk-jc-rWc" id="4dt-n0-cfY">
+                                    <rect key="frame" x="0.0" y="0.0" width="414" height="89"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hd6-uF-a8b">
+                                            <rect key="frame" x="16" y="6" width="48" height="77"/>
+                                            <subviews>
+                                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CuC-8c-4CN">
+                                                    <rect key="frame" x="0.0" y="0.0" width="48" height="77"/>
+                                                </imageView>
+                                            </subviews>
+                                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="48" id="3Og-y0-ibV"/>
+                                                <constraint firstItem="CuC-8c-4CN" firstAttribute="top" secondItem="hd6-uF-a8b" secondAttribute="top" id="ARZ-24-m8n"/>
+                                                <constraint firstAttribute="bottom" secondItem="CuC-8c-4CN" secondAttribute="bottom" id="SDz-pF-ke6"/>
+                                                <constraint firstItem="CuC-8c-4CN" firstAttribute="leading" secondItem="hd6-uF-a8b" secondAttribute="leading" id="cDJ-41-VQu"/>
+                                                <constraint firstAttribute="trailing" secondItem="CuC-8c-4CN" secondAttribute="trailing" id="kWY-D6-ax9"/>
+                                            </constraints>
+                                        </view>
+                                        <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="RiV-3W-swR">
+                                            <rect key="frame" x="88" y="21.5" width="298" height="46.5"/>
+                                            <subviews>
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mlw-gT-fds">
+                                                    <rect key="frame" x="0.0" y="0.0" width="41.5" height="20.5"/>
+                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                                    <nil key="textColor"/>
+                                                    <nil key="highlightedColor"/>
+                                                </label>
+                                                <stackView opaque="NO" contentMode="scaleToFill" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="caq-2S-jTm">
+                                                    <rect key="frame" x="0.0" y="28.5" width="298" height="18"/>
+                                                    <subviews>
+                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fzb-F4-kyO">
+                                                            <rect key="frame" x="0.0" y="0.0" width="206" height="18"/>
+                                                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                                            <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                            <nil key="highlightedColor"/>
+                                                        </label>
+                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mYh-EP-J1M">
+                                                            <rect key="frame" x="218" y="0.0" width="80" height="18"/>
+                                                            <constraints>
+                                                                <constraint firstAttribute="width" constant="80" id="dqX-5n-raZ"/>
+                                                            </constraints>
+                                                            <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                                            <color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                                            <nil key="highlightedColor"/>
+                                                        </label>
+                                                    </subviews>
+                                                </stackView>
+                                            </subviews>
+                                            <constraints>
+                                                <constraint firstItem="caq-2S-jTm" firstAttribute="top" secondItem="mlw-gT-fds" secondAttribute="bottom" constant="8" symbolic="YES" id="6Cz-vI-cSS"/>
+                                                <constraint firstItem="caq-2S-jTm" firstAttribute="leading" secondItem="RiV-3W-swR" secondAttribute="leading" id="DV7-WZ-I6W"/>
+                                                <constraint firstAttribute="trailing" secondItem="caq-2S-jTm" secondAttribute="trailing" id="LCF-1Q-5GG"/>
+                                                <constraint firstAttribute="bottom" secondItem="caq-2S-jTm" secondAttribute="bottom" id="RyY-NZ-qQ4"/>
+                                            </constraints>
+                                        </stackView>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstAttribute="bottom" secondItem="hd6-uF-a8b" secondAttribute="bottom" constant="6" id="6zL-tZ-glX"/>
+                                        <constraint firstItem="hd6-uF-a8b" firstAttribute="top" secondItem="4dt-n0-cfY" secondAttribute="top" constant="6" id="Me5-HG-S2S"/>
+                                        <constraint firstItem="hd6-uF-a8b" firstAttribute="leading" secondItem="4dt-n0-cfY" secondAttribute="leading" constant="16" id="NWg-3T-4Dn"/>
+                                        <constraint firstItem="RiV-3W-swR" firstAttribute="centerY" secondItem="4dt-n0-cfY" secondAttribute="centerY" id="e7P-0q-ZbH"/>
+                                        <constraint firstAttribute="trailingMargin" secondItem="RiV-3W-swR" secondAttribute="trailing" constant="8" id="e7f-gh-csV"/>
+                                        <constraint firstItem="RiV-3W-swR" firstAttribute="leading" secondItem="hd6-uF-a8b" secondAttribute="trailing" constant="24" id="sWX-qu-VvC"/>
+                                    </constraints>
+                                </tableViewCellContentView>
+                                <connections>
+                                    <outlet property="containerImageView" destination="hd6-uF-a8b" id="X6Y-sj-Oyz"/>
+                                    <outlet property="dateLabel" destination="fzb-F4-kyO" id="Yh9-WJ-7TN"/>
+                                    <outlet property="nameLabel" destination="mlw-gT-fds" id="7Am-gP-ljS"/>
+                                    <outlet property="pageLabel" destination="mYh-EP-J1M" id="I7V-sG-yVv"/>
+                                    <outlet property="thumbnailImageView" destination="CuC-8c-4CN" id="gzw-0w-ObB"/>
+                                </connections>
+                            </tableViewCell>
+                        </prototypes>
+                        <connections>
+                            <outlet property="dataSource" destination="gvn-iJ-Pzo" id="2VH-HZ-OWN"/>
+                            <outlet property="delegate" destination="gvn-iJ-Pzo" id="AJK-Md-5RF"/>
+                        </connections>
+                    </tableView>
+                    <navigationItem key="navigationItem" id="eDl-rz-mCg"/>
+                </tableViewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="zgv-ee-Jgu" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="2034.7826086956522" y="-98.4375"/>
+        </scene>
+        <!--View Controller-->
+        <scene sceneID="3WQ-hx-1mu">
+            <objects>
+                <viewController id="X96-Kr-3o1" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="2Qx-04-hnQ">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <viewLayoutGuide key="safeArea" id="0jr-1F-ihA"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    </view>
+                    <tabBarItem key="tabBarItem" title="" id="c0v-JQ-z4q"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="69W-NH-TDj" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="100" y="930"/>
+        </scene>
+        <!--Settings View Controller-->
+        <scene sceneID="HKR-9o-RHm">
+            <objects>
+                <tableViewController storyboardIdentifier="SettingsViewController" id="kga-io-JMM" customClass="SettingsViewController" customModule="MiniScanner" customModuleProvider="target" sceneMemberID="viewController">
+                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="0UH-aU-H6Y">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <prototypes>
+                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="SettingsTableViewCell" rowHeight="50" id="1SO-UK-YpT" customClass="SettingsTableViewCell" customModule="MiniScanner" customModuleProvider="target">
+                                <rect key="frame" x="0.0" y="28" width="414" height="50"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="1SO-UK-YpT" id="n7G-Id-eYr">
+                                    <rect key="frame" x="0.0" y="0.0" width="414" height="50"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="UGO-O1-ZkV">
+                                            <rect key="frame" x="24" y="13" width="24" height="24"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="24" id="lUP-lv-Pzj"/>
+                                                <constraint firstAttribute="height" constant="24" id="vvy-Id-nIJ"/>
+                                            </constraints>
+                                        </imageView>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dSx-7P-GzB">
+                                            <rect key="frame" x="62" y="14.5" width="251" height="21"/>
+                                            <fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="18"/>
+                                            <nil key="textColor"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                        <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9GN-Db-fhO">
+                                            <rect key="frame" x="345" y="9.5" width="51" height="31"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="49" id="rxe-pB-rXh"/>
+                                            </constraints>
+                                            <connections>
+                                                <action selector="didTapSwitching:" destination="1SO-UK-YpT" eventType="valueChanged" id="Cwk-Hn-Kz8"/>
+                                            </connections>
+                                        </switch>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="UGO-O1-ZkV" firstAttribute="centerY" secondItem="n7G-Id-eYr" secondAttribute="centerY" id="BjK-Y8-apM"/>
+                                        <constraint firstAttribute="trailing" secondItem="9GN-Db-fhO" secondAttribute="trailing" constant="20" symbolic="YES" id="E6r-FB-ae3"/>
+                                        <constraint firstItem="9GN-Db-fhO" firstAttribute="leading" secondItem="dSx-7P-GzB" secondAttribute="trailing" constant="32" id="V9t-sL-ocu"/>
+                                        <constraint firstItem="dSx-7P-GzB" firstAttribute="leading" secondItem="UGO-O1-ZkV" secondAttribute="trailing" constant="14" id="dSw-ny-XcT"/>
+                                        <constraint firstItem="UGO-O1-ZkV" firstAttribute="leading" secondItem="n7G-Id-eYr" secondAttribute="leading" constant="24" id="fqF-Bv-Vmj"/>
+                                        <constraint firstItem="dSx-7P-GzB" firstAttribute="centerY" secondItem="n7G-Id-eYr" secondAttribute="centerY" id="hV4-ZS-iZ2"/>
+                                        <constraint firstItem="9GN-Db-fhO" firstAttribute="centerY" secondItem="n7G-Id-eYr" secondAttribute="centerY" id="vjy-Ln-n57"/>
+                                    </constraints>
+                                </tableViewCellContentView>
+                                <connections>
+                                    <outlet property="imgView" destination="UGO-O1-ZkV" id="Euj-tU-0Ep"/>
+                                    <outlet property="nameLabel" destination="dSx-7P-GzB" id="OAj-da-382"/>
+                                    <outlet property="settingsSwitch" destination="9GN-Db-fhO" id="q5j-qB-JiC"/>
+                                </connections>
+                            </tableViewCell>
+                        </prototypes>
+                        <connections>
+                            <outlet property="dataSource" destination="kga-io-JMM" id="rqK-Z1-rb4"/>
+                            <outlet property="delegate" destination="kga-io-JMM" id="Sou-5v-bXI"/>
+                        </connections>
+                    </tableView>
+                    <navigationItem key="navigationItem" id="1wT-BT-hl9"/>
+                </tableViewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="zVa-qn-b5u" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="2034.7826086956522" y="606.69642857142856"/>
+        </scene>
+        <!--App Tab Bar Controller-->
+        <scene sceneID="fE7-cR-ZAd">
+            <objects>
+                <tabBarController storyboardIdentifier="AppTabBarController" automaticallyAdjustsScrollViewInsets="NO" id="NRZ-n7-XkU" customClass="AppTabBarController" customModule="MiniScanner" customModuleProvider="target" sceneMemberID="viewController">
+                    <toolbarItems/>
+                    <navigationItem key="navigationItem" id="4z0-Nb-W9s"/>
+                    <tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" itemPositioning="fill" id="UOw-xw-62P" customClass="AppTabBar" customModule="MiniScanner" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <color key="barTintColor" systemColor="systemBackgroundColor"/>
+                    </tabBar>
+                    <connections>
+                        <segue destination="cKa-08-wzp" kind="relationship" relationship="viewControllers" id="smJ-BA-5nz"/>
+                        <segue destination="X96-Kr-3o1" kind="relationship" relationship="viewControllers" id="mEc-1I-9A0"/>
+                        <segue destination="OGd-a1-RyU" kind="relationship" relationship="viewControllers" id="A2s-tX-G5V"/>
+                    </connections>
+                </tabBarController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="OcG-fV-cWh" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="100" y="175"/>
+        </scene>
+        <!--Documents-->
+        <scene sceneID="0Jn-Mr-Pmn">
+            <objects>
+                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="cKa-08-wzp" customClass="BaseNavigationViewController" customModule="MiniScanner" customModuleProvider="target" sceneMemberID="viewController">
+                    <tabBarItem key="tabBarItem" title="Documents" image="folder" catalog="system" id="AZk-pC-62k"/>
+                    <toolbarItems/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="GtO-Qf-J4v">
+                        <rect key="frame" x="0.0" y="44" width="414" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="gvn-iJ-Pzo" kind="relationship" relationship="rootViewController" id="l3w-A7-Zzs"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="ExG-BB-XYZ" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1124.6376811594205" y="-98.4375"/>
+        </scene>
+        <!--Settings-->
+        <scene sceneID="uqv-8W-A0Z">
+            <objects>
+                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="OGd-a1-RyU" sceneMemberID="viewController">
+                    <tabBarItem key="tabBarItem" title="Settings" image="settings" id="zH9-VT-a3h"/>
+                    <toolbarItems/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="HL0-yh-IYt">
+                        <rect key="frame" x="0.0" y="44" width="414" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="kga-io-JMM" kind="relationship" relationship="rootViewController" id="GIJ-Fo-ono"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Iot-Hj-feT" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1124.6376811594205" y="606.69642857142856"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="folder" catalog="system" width="128" height="97"/>
+        <image name="settings" width="24" height="24"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>
diff --git a/MiniScanner/Modules/Documents/DocumentsTableViewCell.swift b/MiniScanner/Modules/Documents/DocumentsTableViewCell.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9e11239774ebb4d93bb3c6b4bb724309f1e5a2ef
--- /dev/null
+++ b/MiniScanner/Modules/Documents/DocumentsTableViewCell.swift
@@ -0,0 +1,34 @@
+import UIKit
+
+final class DocumentsTableViewCell: UITableViewCell {
+  
+  @IBOutlet private weak var thumbnailImageView: UIImageView!
+  @IBOutlet private weak var containerImageView: UIView!
+  @IBOutlet private weak var nameLabel: UILabel!
+  @IBOutlet private weak var dateLabel: UILabel!
+  @IBOutlet private weak var pageLabel: UILabel!
+  
+  struct Constants {
+    static let cornerRadius: CGFloat = 6
+    static let separatorInset: CGFloat = 76
+  }
+  
+  override func awakeFromNib() {
+    super.awakeFromNib()
+    // Initialization code
+    
+    containerImageView.addShadowView(shadowRadius: Constants.cornerRadius)
+    thumbnailImageView.layer.cornerRadius = Constants.cornerRadius
+    thumbnailImageView.clipsToBounds = true
+    containerImageView.layer.cornerRadius = Constants.cornerRadius
+    separatorInset.left = Constants.separatorInset
+    separatorInset.right = Constants.separatorInset
+  }
+  
+  func configure(with viewModel: File, image: UIImage?) {
+    thumbnailImageView.image = image
+    nameLabel.text = viewModel.displayName
+    dateLabel.text = viewModel.date
+    pageLabel.text = viewModel.pagesCount
+  }
+}
diff --git a/MiniScanner/Modules/Documents/DocumentsTableViewController.swift b/MiniScanner/Modules/Documents/DocumentsTableViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..bd29dcf7fc70125753e1d61e99ec857eeb95c500
--- /dev/null
+++ b/MiniScanner/Modules/Documents/DocumentsTableViewController.swift
@@ -0,0 +1,323 @@
+import UIKit
+import VisionKit
+
+final class DocumentsTableViewController: UITableViewController {
+  
+  struct Constants {
+    static let reuseIdentifier = String(describing: DocumentsTableViewController.self)
+    static let storyboardName = "Documents"
+    static let title = Bundle.appName
+    static let rowHeight: CGFloat = 96
+    static let cellReuseIdentifier = String(describing: DocumentsTableViewCell.self)
+    
+    static let topBottom: CGFloat = 120
+    static let margin: CGFloat = 64
+  }
+  
+  static func buildViewController() -> DocumentsTableViewController {
+    let controller = UIStoryboard(name: Constants.storyboardName,
+                                  bundle: .main).instantiateViewController(withIdentifier: Constants.reuseIdentifier)
+    return controller as! DocumentsTableViewController
+  }
+  
+  private var viewModels: [File] = []
+  private var localFileManager: LocalFileManager?
+  private var sortType: SortyFileType = .date
+  
+  private let noDocumentsimageView = UIImageView(image: UIImage(named: "box"))
+  private var renameAlertController: UIAlertController?
+  private var renameFileName: String?
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    navigationItem.title = Constants.title
+    tableView.tableFooterView = UIView()
+    localFileManager = LocalFileManager()
+    
+    tabBarController?.delegate = UIApplication.shared.delegate as? UITabBarControllerDelegate
+    
+    NotificationCenter.default.addObserver(self, selector: #selector(middleButtonTapped(_:)),
+                                           name: NSNotification.Name.MiddleButtonTapped, object: nil)
+    
+    NotificationCenter.default.addObserver(self, selector: #selector(fetchViewModels),
+                                           name: NSNotification.Name.ReloadViewModels, object: nil)
+    
+    if let view = navigationController?.view  {
+      noDocumentsimageView.translatesAutoresizingMaskIntoConstraints = false
+      noDocumentsimageView.contentMode = .scaleAspectFit
+      view.addSubview(noDocumentsimageView)
+      
+      NSLayoutConstraint.activate([
+        noDocumentsimageView.topAnchor.constraint(equalTo: view.topAnchor, constant: Constants.topBottom),
+        noDocumentsimageView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -Constants.topBottom),
+        noDocumentsimageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Constants.margin),
+        noDocumentsimageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Constants.margin)
+      ])
+    }
+    
+    if UserDefaults.standard.startsAppWithCamera {
+      openCamera()
+    }
+  }
+  
+  override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    fetchViewModels()
+  }
+  
+  deinit {
+    NotificationCenter.default.removeObserver(self)
+  }
+  
+  @objc private func fetchViewModels() {
+
+    guard let directoryURL = localFileManager?.scannerURL,
+          let viewModels = localFileManager?.filesForDirectory(directoryURL, sortType: sortType) else { return }
+    self.viewModels = viewModels
+    tableView.reloadData()
+    
+    if viewModels.isEmpty {
+      noDocumentsimageView.isHidden = false
+    } else {
+      noDocumentsimageView.isHidden = true
+    }
+  }
+  
+  // MARK: - Table view data source
+  
+  override func numberOfSections(in tableView: UITableView) -> Int {
+    // #warning Incomplete implementation, return the number of sections
+    return 1
+  }
+  
+  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+    // #warning Incomplete implementation, return the number of rows
+    return viewModels.count
+  }
+  
+  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+    guard let cell = tableView.dequeueReusableCell(withIdentifier: Constants.cellReuseIdentifier,
+                                                   for: indexPath) as? DocumentsTableViewCell else { return UITableViewCell() }
+    
+    // Configure the cell...
+    let viewModel = viewModels[indexPath.row]
+    cell.configure(with: viewModel, image: localFileManager?.getThumbnail(for: viewModel.fileURL))
+    
+    return cell
+  }
+   
+  override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+    return Constants.rowHeight
+  }
+  
+  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    let viewModel = viewModels[indexPath.row]
+    let controller = DocumentPreviewViewController.buildViewController()
+    controller.file = viewModel
+    controller.hidesBottomBarWhenPushed = true
+    navigationController?.pushViewController(controller, animated: true)
+  }
+  
+  override func tableView(_ tableView: UITableView,
+                          editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
+    return .none
+  }
+  
+  override func tableView(_ tableView: UITableView,
+                          trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
+    
+    // Trash action
+    let trash = UIContextualAction(style: .destructive,
+                                   title: "Delete".localized) { [weak self] (_, _, completionHandler) in
+      self?.deleteFile(at: indexPath)
+      completionHandler(true)
+    }
+    trash.backgroundColor = .systemRed
+    trash.image = UIImage(systemName: "trash")?.tint(with: .white)
+    
+    // Rename action
+    let rename = UIContextualAction(style: .normal,
+                                    title: "Rename".localized) { [weak self] (_, _, completionHandler) in
+      self?.renameFile(at: indexPath)
+      completionHandler(true)
+    }
+    rename.backgroundColor = UIColor.black.withAlphaComponent(0.5)
+    rename.image = UIImage(systemName: "square.and.pencil")?.tint(with: .white)
+    
+    let configuration = UISwipeActionsConfiguration(actions: [trash, rename])
+    configuration.performsFirstActionWithFullSwipe = true
+    
+    return configuration
+  }
+  
+  @objc private func middleButtonTapped(_ notification: NSNotification) {
+    let alertController = UIAlertController(title: nil,
+                                  message: nil, preferredStyle: .actionSheet)
+
+    let cameraAction = UIAlertAction(title: "Camera".localized, style: .default, handler: { action in
+      self.openCamera()
+    })
+    
+    let galleryAction = UIAlertAction(title: "Gallery".localized, style: .default, handler: { action in
+      self.openGallery()
+    })
+    
+    alertController.addAction(cameraAction)
+    cameraAction.setValue(UIImage(systemName: "camera"), forKey: "image")
+    cameraAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
+    
+    alertController.addAction(galleryAction)
+    galleryAction.setValue(UIImage(systemName: "photo"), forKey: "image")
+    galleryAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
+    
+    alertController.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
+    alertController.popoverPresentationController?.sourceView = notification.object as? UIButton
+    present(alertController, animated: true)
+  }
+  
+  private func openCamera() {
+      let scannerOptions = ImageScannerOptions(scanMultipleItems: true,
+                                                       allowAutoScan: false,
+                                                       allowTapToFocus: false,
+                                                       defaultColorRenderOption:.color)
+      let scannerViewController = ImageScannerController(options: scannerOptions)
+    scannerViewController.imageScannerDelegate = self
+    present(scannerViewController, animated: true)
+  }
+  
+  private func openGallery() {
+    guard UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) else { return }
+    let imagePickerController = UIImagePickerController()
+    imagePickerController.delegate = self
+    
+    imagePickerController.sourceType = UIImagePickerController.SourceType.savedPhotosAlbum
+    imagePickerController.allowsEditing = UserDefaults.standard.isPhotoEditigOn
+    present(imagePickerController, animated: true, completion: nil)
+  }
+
+  private func renameFile(at indexPath: IndexPath) {
+    let viewModel = viewModels[indexPath.row]
+    renameAlertController = UIAlertController(title: "Rename document".localized, message: nil, preferredStyle: .alert)
+    
+    renameAlertController!.addTextField { [weak self] textField in
+      guard let self = self else { return }
+      textField.placeholder = viewModel.displayName
+      textField.text = viewModel.displayName
+      textField.clearButtonMode = .always
+      self.renameFileName = viewModel.displayName
+      textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
+    }
+    
+    let continueAction = UIAlertAction(title: "Rename".localized,
+                                       style: .default) { [weak self] _ in
+      guard let self = self else { return }
+      guard let textFields = self.renameAlertController?.textFields else { return }
+      
+      if let newName = textFields.first?.text, newName != viewModel.displayName {
+        do {
+          try self.localFileManager?.renameFile(at: viewModel.fileURL, withName: newName)
+          self.fetchViewModels()
+        } catch {
+          return
+        }
+      }
+    }
+
+    renameAlertController!.addAction(continueAction)
+    renameAlertController!.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
+    renameAlertController?.actions.first?.isEnabled = false
+    present(renameAlertController!, animated: true)
+  }
+  
+  private func deleteFile(at indexPath: IndexPath) {
+    let viewModel = viewModels[indexPath.row]
+
+    if UserDefaults.standard.askOnSwipeDelete {
+      let alertController = UIAlertController(title: Bundle.appName,
+                                              message: "Are you sure you want to delete this document?".localized, preferredStyle: .alert)
+            
+      let okAction = UIAlertAction(title: "Yes, delete!".localized, style: .destructive, handler: { [weak self] action in
+        guard let self = self else { return }
+        
+        self.delete(file: viewModel.fileURL, at: indexPath)
+      })
+      
+      alertController.addAction(okAction)
+      
+      alertController.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
+      alertController.popoverPresentationController?.sourceView = tableView.cellForRow(at: indexPath)
+      present(alertController, animated: true)
+    } else {
+      delete(file: viewModel.fileURL, at: indexPath)
+    }
+  }
+  
+  private func delete(file fileURL: URL, at indexPath: IndexPath) {
+    do {
+      try self.localFileManager?.filesManager.removeItem(at: fileURL)
+      try self.localFileManager?.removeThumbnail(for: fileURL)
+      self.viewModels.remove(at: indexPath.row)
+      self.tableView.deleteRows(at: [indexPath], with: .fade)
+    } catch {
+      return
+    }
+    if self.viewModels.isEmpty {
+      self.noDocumentsimageView.isHidden = false
+    }
+  }
+}
+
+/// Tells the delegate that the user picked a still image.
+extension DocumentsTableViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
+  /// Your delegate object’s implementation of this method should pass the specified media on to any custom code that needs it, and should then dismiss the picker view.
+  /// When editing is enabled, the image picker view presents the user with a preview of the currently selected image or movie along with controls for modifying it.
+  /// (This behavior is managed by the picker view prior to calling this method.) If the user modifies the image or movie, the editing information is available in the info parameter.
+  /// The original image is also returned in the info parameter.
+  func imagePickerController(_ picker: UIImagePickerController,
+                             didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
+    picker.dismiss(animated: true) { [weak self] in
+      guard let self = self else { return }
+      guard let image = info[UserDefaults.standard.isPhotoEditigOn ? UIImagePickerController.InfoKey.editedImage : UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
+      PDFManager.createPDFDocument(from: image, localFileManager: self.localFileManager)
+      self.fetchViewModels()
+    }
+  }
+}
+
+extension DocumentsTableViewController: ImageScannerControllerDelegate {
+    func imageScannerController(_ scanner: ImageScannerController, didFinishWithSession session: MultiPageScanSession) {
+        var images = [URL]()
+        
+        for index in 0..<session.scannedItems.count {
+            if let url = session.scannedItems[index].renderedImage {
+                images.append(url)
+            }
+        }
+        print("images: \(images)")
+        
+        PDFManager.createMultiPDFPage(from: images, localFileManager: localFileManager) {
+            scanner.dismiss(animated: true) {
+              self.fetchViewModels()
+            }
+        }
+    }
+    
+    func imageScannerControllerDidCancel(_ scanner: ImageScannerController) {
+        scanner.dismiss(animated: true)
+    }
+    
+    func imageScannerController(_ scanner: ImageScannerController, didFailWithError error: Error) {
+        scanner.dismiss(animated: true)
+
+    }
+  
+  @objc func textFieldDidChange(_ textField: UITextField) {
+    guard let text = textField.text, let renameFileName = renameFileName,
+          renameFileName != text, !text.trimmingCharacters(in: .whitespaces).isEmpty else {
+      renameAlertController?.actions.first?.isEnabled = false
+      return
+    }
+    
+    renameAlertController?.actions.first?.isEnabled = true
+  }
+}
diff --git a/MiniScanner/Modules/Documents/File.swift b/MiniScanner/Modules/Documents/File.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0320c027ea64c2b8661b217400a184090a8356b9
--- /dev/null
+++ b/MiniScanner/Modules/Documents/File.swift
@@ -0,0 +1,36 @@
+import Foundation
+import PDFKit
+
+/// File is a class representing a file in iFinder
+class File: NSObject {
+  /// Display name. String.
+  let displayName: String
+  /// File extension.
+  var fileExtension: String?
+  /// File attributes (including size, creation date etc).
+  let fileAttributes: NSDictionary?
+  /// URL file path.
+  let fileURL: URL
+  /// Creation Date
+  let date: String
+  // Page numbers
+  let pagesCount: String
+  // pdf document
+  var pdfDocument: PDFDocument?
+  
+  /**
+   Initialize an File object with a filePath
+   - parameter filePath: URL filePath
+   - returns: File object.
+   */
+  init(fileURL: URL) {
+    self.fileURL = fileURL
+    self.displayName = fileURL.deletingPathExtension().lastPathComponent
+    self.fileExtension = fileURL.pathExtension
+    self.fileAttributes = fileURL.getFileAttributes
+    self.fileExtension = fileURL.pathExtension
+    self.date = fileURL.getDate
+    pdfDocument = PDFDocument(url: fileURL)
+    self.pagesCount = "\(pdfDocument?.pageCount ?? 1) pages"
+  }
+}
diff --git a/MiniScanner/Modules/Settings/SettingsTableViewCell.swift b/MiniScanner/Modules/Settings/SettingsTableViewCell.swift
new file mode 100644
index 0000000000000000000000000000000000000000..433ab56c7a7f2c227dcccfc5f2a88eaeff50b039
--- /dev/null
+++ b/MiniScanner/Modules/Settings/SettingsTableViewCell.swift
@@ -0,0 +1,47 @@
+import UIKit
+
+enum SettingsType: String {
+  case url, switcher, segment, none
+}
+
+struct SettingsViewModel {
+  let imageName: String
+  let title: String
+  
+  var isSwitchOn = false
+  var isSwitcherOn: ((Bool) -> Void)? = nil
+  
+  var urlString: String? = nil
+  var type = SettingsType.none
+}
+
+final class SettingsTableViewCell: UITableViewCell {
+  
+  static let ReuseIdentifier = String(describing: SettingsTableViewCell.self)
+
+  @IBOutlet private weak var imgView: UIImageView!
+  @IBOutlet private weak var nameLabel: UILabel!
+  @IBOutlet private weak var settingsSwitch: UISwitch!
+  
+  private var isSwitcherOn: ((Bool) -> Void)?
+
+  func configure(with viewModel: SettingsViewModel) {
+    imgView.image = UIImage(systemName: viewModel.imageName)
+    nameLabel.text = viewModel.title
+    isSwitcherOn = viewModel.isSwitcherOn
+    settingsSwitch.isOn = viewModel.isSwitchOn
+    
+    switch viewModel.type {
+    case .segment:
+      settingsSwitch.isHidden = false
+    case .switcher:
+      settingsSwitch.isHidden = true
+    case .url, .none:
+      settingsSwitch.isHidden = true
+    }
+  }
+  
+  @IBAction private func didTapSwitching(_ sender: UISwitch) {
+    isSwitcherOn?(sender.isOn)
+  }
+}
diff --git a/MiniScanner/Modules/Settings/SettingsViewController+Safari.swift b/MiniScanner/Modules/Settings/SettingsViewController+Safari.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d955355c95488b2d15b184c54aeda3b2a092f8e6
--- /dev/null
+++ b/MiniScanner/Modules/Settings/SettingsViewController+Safari.swift
@@ -0,0 +1,15 @@
+import UIKit
+import SafariServices
+
+extension SettingsViewController {
+  /// Shows SFSafariViewController
+  /// entersReaderIfAvailable - A value that specifies whether Safari should enter Reader mode, if it is available.
+  func presentSafariController(with urlString: String) {
+    guard let url = URL(string: urlString) else { return }
+    let config = SFSafariViewController.Configuration()
+    config.entersReaderIfAvailable = true
+    
+    let vc = SFSafariViewController(url: url, configuration: config)
+    present(vc, animated: true)
+  }
+}
diff --git a/MiniScanner/Modules/Settings/SettingsViewController.swift b/MiniScanner/Modules/Settings/SettingsViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e72636a71a074dca55872ccc77be2de51939b5e4
--- /dev/null
+++ b/MiniScanner/Modules/Settings/SettingsViewController.swift
@@ -0,0 +1,121 @@
+import UIKit
+
+final class SettingsViewController: UITableViewController {
+    
+  private var viewModels: [SettingsViewModel] = []
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    
+    // Do any additional setup after loading the view.
+    setupViewModels()
+  }
+  
+  private func setupViewModels() {
+    title = "Settings".localized
+    navigationController?.navigationBar.prefersLargeTitles = true
+    
+    let isPhotoEditing = { isEditing in
+      self.isPhotoEditing(isEditing)
+    }
+    
+    let startsAppWithCamera = { isEnabled in
+      self.startsAppWithCamera(isEnabled)
+    }
+    
+    let showWalktroughAtLaunch = { isEnabled in
+      self.showWalktroughAtLaunch(isEnabled)
+    }
+    
+    let askOnSwipeDelete = { isEnabled in
+      self.askOnDeleteSwipe(isEnabled)
+    }
+    
+    let photoEditing = SettingsViewModel(imageName: "crop",
+                                         title: "Allow gallery photo editing".localized,
+                                         isSwitchOn: UserDefaults.standard.isPhotoEditigOn,
+                                         isSwitcherOn: isPhotoEditing, type: .segment)
+    
+    let cameraEditing = SettingsViewModel(imageName: "camera",
+                                         title: "Start camera at start up".localized,
+                                         isSwitchOn: UserDefaults.standard.startsAppWithCamera,
+                                         isSwitcherOn: startsAppWithCamera, type: .segment)
+    
+    let showWalktrough = SettingsViewModel(imageName: "paperplane",
+                                         title: "Show walktrough at launch".localized,
+                                         isSwitchOn: UserDefaults.standard.showWalktroughAtLaunch,
+                                         isSwitcherOn: showWalktroughAtLaunch, type: .segment)
+    
+    let deleteDocument = SettingsViewModel(imageName: "trash",
+                                         title: "Confirm on swipe delete?".localized,
+                                         isSwitchOn: UserDefaults.standard.askOnSwipeDelete,
+                                         isSwitcherOn: askOnSwipeDelete, type: .segment)
+    
+    let privacy = SettingsViewModel(imageName: "checkmark.shield", title: "Privacy Policy".localized,
+                                    urlString: AppConfigurator.Settings.privacy.rawValue, type: .url)
+    
+    let terms = SettingsViewModel(imageName: "exclamationmark.shield", title: "Terms & Conditions".localized,
+                                  urlString: AppConfigurator.Settings.terms.rawValue, type: .url)
+    
+    viewModels = [photoEditing, cameraEditing, deleteDocument, showWalktrough, privacy, terms]
+    
+    tableView.tableFooterView = UIView()
+    tableView.delegate = self
+    tableView.dataSource = self
+    tableView.reloadData()
+  }
+  
+  private func isPhotoEditing(_ isOn: Bool) {
+    UserDefaults.standard.isPhotoEditigOn = isOn
+    setupViewModels()
+    tableView.reloadData()
+  }
+  
+  private func startsAppWithCamera(_ isOn: Bool) {
+    UserDefaults.standard.startsAppWithCamera = isOn
+    setupViewModels()
+    tableView.reloadData()
+  }
+  
+  private func showWalktroughAtLaunch(_ isOn: Bool) {
+    UserDefaults.standard.showWalktroughAtLaunch = isOn
+    setupViewModels()
+    tableView.reloadData()
+  }
+  
+  private func askOnDeleteSwipe(_ isOn: Bool) {
+    UserDefaults.standard.askOnSwipeDelete = isOn
+    setupViewModels()
+    tableView.reloadData()
+  }
+  
+  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+    return viewModels.count
+  }
+  
+  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+    guard let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.ReuseIdentifier,
+                                                   for: indexPath) as? SettingsTableViewCell else {
+      return UITableViewCell()
+    }
+    
+    cell.configure(with: viewModels[indexPath.row])
+    return cell
+  }
+  
+  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+    let viewModel = viewModels[indexPath.row]
+    
+    switch viewModel.type {
+    case .url:
+      guard let urlString = viewModel.urlString else { return }
+      presentSafariController(with: urlString)
+    default:
+      break
+    }
+  }
+  
+  override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+    return 50.0
+  }
+}
diff --git a/MiniScanner/Modules/Walktrough/ClassicWalkthroughViewController.swift b/MiniScanner/Modules/Walktrough/ClassicWalkthroughViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..979efb2b01e51081b9111cf9a6d21d3ba1b1a6cf
--- /dev/null
+++ b/MiniScanner/Modules/Walktrough/ClassicWalkthroughViewController.swift
@@ -0,0 +1,41 @@
+import UIKit
+
+class ClassicWalkthroughViewController: UIViewController {
+  @IBOutlet var containerView: UIView!
+  @IBOutlet var imageContainerView: UIView!
+  @IBOutlet var imageView: UIImageView!
+  @IBOutlet var titleLabel: UILabel!
+  @IBOutlet var subtitleLabel: UILabel!
+  
+  let model: WalkthroughModel
+  
+  init(model: WalkthroughModel,
+       nibName nibNameOrNil: String?,
+       bundle nibBundleOrNil: Bundle?) {
+    self.model = model
+    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+  }
+  
+  required init?(coder aDecoder: NSCoder) {
+    fatalError("init(coder:) has not been implemented")
+  }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    imageView.image = UIImage.localImage(model.icon, template: true)
+    imageView.contentMode = .scaleAspectFill
+    imageView.clipsToBounds = true
+    imageView.tintColor = .tintColor
+    imageContainerView.backgroundColor = .clear
+    
+    titleLabel.text = model.title
+    titleLabel.font = UIFont.boldSystemFont(ofSize: 20.0)
+    titleLabel.textColor = .tintColor
+    
+    subtitleLabel.attributedText = NSAttributedString(string: model.subtitle)
+    subtitleLabel.font = UIFont.systemFont(ofSize: 14.0)
+    subtitleLabel.textColor = .tintColor
+    
+    containerView.backgroundColor = .barTintColor
+  }
+}
diff --git a/MiniScanner/Modules/Walktrough/ClassicWalkthroughViewController.xib b/MiniScanner/Modules/Walktrough/ClassicWalkthroughViewController.xib
new file mode 100644
index 0000000000000000000000000000000000000000..d3c5470e2f30887c0d54c4e3af3124688024448c
--- /dev/null
+++ b/MiniScanner/Modules/Walktrough/ClassicWalkthroughViewController.xib
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ClassicWalkthroughViewController" customModule="MiniScanner" customModuleProvider="target">
+            <connections>
+                <outlet property="containerView" destination="t6a-rE-WeO" id="rYi-Ci-nug"/>
+                <outlet property="imageContainerView" destination="iBB-wU-Tzs" id="d6w-49-mcW"/>
+                <outlet property="imageView" destination="NRA-v9-Ctm" id="VFH-wj-tKJ"/>
+                <outlet property="subtitleLabel" destination="XDu-W2-TQj" id="sNF-cv-mYa"/>
+                <outlet property="titleLabel" destination="yRL-uJ-wL1" id="gnd-SK-0Kn"/>
+                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="t6a-rE-WeO" userLabel="Container View">
+                    <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                    <subviews>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iBB-wU-Tzs" userLabel="Image Container View">
+                            <rect key="frame" x="137.5" y="200" width="100" height="100"/>
+                            <subviews>
+                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="NRA-v9-Ctm">
+                                    <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="100" id="DVg-Ik-xM8"/>
+                                        <constraint firstAttribute="width" constant="100" id="u60-iy-Hjr"/>
+                                    </constraints>
+                                </imageView>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="NRA-v9-Ctm" firstAttribute="centerX" secondItem="iBB-wU-Tzs" secondAttribute="centerX" id="6Le-Oz-a5U"/>
+                                <constraint firstItem="NRA-v9-Ctm" firstAttribute="centerY" secondItem="iBB-wU-Tzs" secondAttribute="centerY" id="K6B-1U-GQF"/>
+                                <constraint firstAttribute="width" constant="100" id="YzF-gN-n8w"/>
+                                <constraint firstAttribute="height" constant="100" id="thC-4g-cZj"/>
+                            </constraints>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yRL-uJ-wL1" userLabel="Title Label">
+                            <rect key="frame" x="167" y="370" width="41.5" height="20.5"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                            <nil key="textColor"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" usesAttributedText="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XDu-W2-TQj" userLabel="Subtitle Label">
+                            <rect key="frame" x="167" y="420.5" width="41.5" height="51"/>
+                            <attributedString key="attributedText">
+                                <fragment content="Label">
+                                    <attributes>
+                                        <font key="NSFont" metaFont="system" size="17"/>
+                                        <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" lineHeightMultiple="2.5" tighteningFactorForTruncation="0.0"/>
+                                    </attributes>
+                                </fragment>
+                            </attributedString>
+                            <nil key="highlightedColor"/>
+                        </label>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="yRL-uJ-wL1" firstAttribute="centerX" secondItem="t6a-rE-WeO" secondAttribute="centerX" id="DN8-8I-DWK"/>
+                        <constraint firstItem="yRL-uJ-wL1" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="t6a-rE-WeO" secondAttribute="leading" constant="35" id="EZV-u7-UB0"/>
+                        <constraint firstItem="yRL-uJ-wL1" firstAttribute="top" secondItem="iBB-wU-Tzs" secondAttribute="bottom" constant="70" id="EhQ-SF-YAR"/>
+                        <constraint firstItem="XDu-W2-TQj" firstAttribute="top" secondItem="yRL-uJ-wL1" secondAttribute="bottom" constant="30" id="GaY-zA-HO2"/>
+                        <constraint firstItem="iBB-wU-Tzs" firstAttribute="centerX" secondItem="t6a-rE-WeO" secondAttribute="centerX" id="Hae-Ii-Wfx"/>
+                        <constraint firstItem="XDu-W2-TQj" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="t6a-rE-WeO" secondAttribute="leading" constant="35" id="NHJ-Jp-md1"/>
+                        <constraint firstItem="iBB-wU-Tzs" firstAttribute="top" secondItem="t6a-rE-WeO" secondAttribute="top" constant="200" id="Nd1-Ym-R0u"/>
+                        <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="XDu-W2-TQj" secondAttribute="trailing" constant="35" id="RS5-Bh-qRK"/>
+                        <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="yRL-uJ-wL1" secondAttribute="trailing" constant="35" id="c0Z-BG-aZW"/>
+                        <constraint firstItem="XDu-W2-TQj" firstAttribute="centerX" secondItem="t6a-rE-WeO" secondAttribute="centerX" id="sHs-ra-osA"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
+            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="t6a-rE-WeO" firstAttribute="centerX" secondItem="fnl-2z-Ty3" secondAttribute="centerX" id="Jc7-PL-YwG"/>
+                <constraint firstItem="t6a-rE-WeO" firstAttribute="height" secondItem="i5M-Pr-FkT" secondAttribute="height" id="JoM-tr-2rb"/>
+                <constraint firstItem="t6a-rE-WeO" firstAttribute="centerY" secondItem="fnl-2z-Ty3" secondAttribute="centerY" id="RLZ-L3-6JD"/>
+                <constraint firstItem="t6a-rE-WeO" firstAttribute="width" secondItem="i5M-Pr-FkT" secondAttribute="width" id="q4z-7C-Ktu"/>
+            </constraints>
+            <point key="canvasLocation" x="33.5" y="53.5"/>
+        </view>
+    </objects>
+</document>
diff --git a/MiniScanner/Modules/Walktrough/WalkthroughModel.swift b/MiniScanner/Modules/Walktrough/WalkthroughModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e1c61c1a9b74d5afa5b206720cd71b9d0d88d139
--- /dev/null
+++ b/MiniScanner/Modules/Walktrough/WalkthroughModel.swift
@@ -0,0 +1,14 @@
+import UIKit
+
+class WalkthroughModel {
+    var title: String
+    var subtitle: String
+    var icon: String
+
+    init(title: String, subtitle: String, icon: String) {
+        self.title = title
+        self.subtitle = subtitle
+        self.icon = icon
+    }
+}
+
diff --git a/MiniScanner/Modules/Walktrough/WalkthroughViewController.swift b/MiniScanner/Modules/Walktrough/WalkthroughViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1ad0004c4438fc7fbbd565365e965142117afd04
--- /dev/null
+++ b/MiniScanner/Modules/Walktrough/WalkthroughViewController.swift
@@ -0,0 +1,97 @@
+import UIKit
+
+protocol WalkthroughViewControllerDelegate: AnyObject {
+  func walkthroughViewControllerDidFinishFlow(_ vc: WalkthroughViewController)
+}
+
+class WalkthroughViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
+    
+  @IBOutlet var pageControl: UIPageControl!
+  @IBOutlet weak var skipButton: UIButton!
+    
+  weak var delegate: WalkthroughViewControllerDelegate?
+  
+  let viewControllers: [UIViewController]
+  var pageIndex = 0
+  let pageController: UIPageViewController
+  let fakeVC: UIViewController
+  
+  init(nibName nibNameOrNil: String?,
+       bundle nibBundleOrNil: Bundle?,
+       viewControllers: [UIViewController]) {
+    self.viewControllers = viewControllers
+    self.pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
+    self.fakeVC = UIViewController()
+    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+    self.pageController.dataSource = self
+    self.pageController.delegate = self
+  }
+  
+  required init?(coder aDecoder: NSCoder) {
+    fatalError("init(coder:) has not been implemented")
+  }
+  
+  override func viewDidLoad() {
+    pageController.setViewControllers([viewControllers[0]], direction: .forward, animated: true, completion: nil)
+    self.addChildViewControllerWithView(pageController)
+    pageControl.numberOfPages = viewControllers.count
+    self.view.bringSubviewToFront(pageControl)
+    self.view.bringSubviewToFront(skipButton)
+    skipButton.addTarget(self, action: #selector(handleSkip), for: .touchUpInside)
+    super.viewDidLoad()
+  }
+    
+  @objc func handleSkip() {
+      //print("Clicked on Skip Button")
+      self.removeChildViewController(self.pageController)
+      self.delegate?.walkthroughViewControllerDidFinishFlow(self)
+  }
+    
+  public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
+    if let index = self.index(of: viewController) {
+      if index == 0 {
+        return nil
+      }
+      return viewControllers[index - 1]
+    }
+    return nil
+  }
+  
+  public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
+    if let index = self.index(of: viewController) {
+      if index + 1 >= viewControllers.count {
+        return fakeVC
+      }
+      return viewControllers[index + 1]
+    }
+    return nil
+  }
+  
+  public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
+    if !completed {
+      return
+    }
+    if let lastPushedVC = pageViewController.viewControllers?.last {
+      if let index = index(of: lastPushedVC) {
+        pageControl.currentPage = index
+      } else {
+      }
+    }
+  }
+  
+  public func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
+    if pendingViewControllers.first == self.fakeVC {
+      self.removeChildViewController(self.pageController)
+      self.delegate?.walkthroughViewControllerDidFinishFlow(self)
+    }
+  }
+  
+  private func index(of viewController: UIViewController) -> Int? {
+    for (index, vc) in viewControllers.enumerated() {
+      if viewController == vc {
+        return index
+      }
+    }
+    return nil
+  }
+}
diff --git a/MiniScanner/Modules/Walktrough/WalkthroughViewController.xib b/MiniScanner/Modules/Walktrough/WalkthroughViewController.xib
new file mode 100644
index 0000000000000000000000000000000000000000..0d5e4670a72e871b89496fd53c02a40675fadbd3
--- /dev/null
+++ b/MiniScanner/Modules/Walktrough/WalkthroughViewController.xib
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="WalkthroughViewController" customModule="MiniScanner" customModuleProvider="target">
+            <connections>
+                <outlet property="pageControl" destination="15L-4h-hYT" id="InI-Mt-Mz8"/>
+                <outlet property="skipButton" destination="fhv-xL-xB0" id="POC-ux-a9p"/>
+                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <pageControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="15L-4h-hYT">
+                    <rect key="frame" x="130" y="605" width="115.5" height="26"/>
+                    <color key="pageIndicatorTintColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <color key="currentPageIndicatorTintColor" red="0.00067935651169999996" green="0.31003832819999999" blue="0.77692931890000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                </pageControl>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fhv-xL-xB0">
+                    <rect key="frame" x="306" y="60" width="44" height="30"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="44" id="HCd-Vj-Ggv"/>
+                        <constraint firstAttribute="height" constant="30" id="R4B-z3-eKo"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
+                    <state key="normal" title="SKIP"/>
+                </button>
+            </subviews>
+            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
+            <constraints>
+                <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="fhv-xL-xB0" secondAttribute="trailing" constant="25" id="3NO-A0-G7p"/>
+                <constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="15L-4h-hYT" secondAttribute="bottom" constant="36" id="ICv-uv-zBE"/>
+                <constraint firstItem="fhv-xL-xB0" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="60" id="RM9-rx-Qe7"/>
+                <constraint firstItem="15L-4h-hYT" firstAttribute="centerX" secondItem="fnl-2z-Ty3" secondAttribute="centerX" id="yOu-mT-LsU"/>
+            </constraints>
+            <point key="canvasLocation" x="136.80000000000001" y="152.47376311844079"/>
+        </view>
+    </objects>
+</document>
diff --git a/MiniScanner/Supporting Files/.DS_Store b/MiniScanner/Supporting Files/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..5ff795e3c7f8991889736e7530732e705f9ab327
Binary files /dev/null and b/MiniScanner/Supporting Files/.DS_Store differ
diff --git a/MiniScanner/Supporting Files/AppDelegate.swift b/MiniScanner/Supporting Files/AppDelegate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1e90e340a6c401469025a7638376c17fa37397a9
--- /dev/null
+++ b/MiniScanner/Supporting Files/AppDelegate.swift	
@@ -0,0 +1,50 @@
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+  
+  func application(_ application: UIApplication,
+                   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+    // Override point for customization after application launch.
+    ThemeManager.shared.setupTheme()
+    return true
+  }
+  
+  // MARK: UISceneSession Lifecycle
+  
+  func application(_ application: UIApplication,
+                   configurationForConnecting connectingSceneSession: UISceneSession,
+                   options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+    // Called when a new scene session is being created.
+    // Use this method to select a configuration to create the new scene with.
+    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+  }
+  
+  func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
+    // Called when the user discards a scene session.
+    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+  }
+}
+
+struct AppConfigurator {
+  // Privacy policies and term links
+  enum Settings: String {
+    case terms = "https://mistergrizzly.com/terms-and-conditions/"
+    case privacy = "https://mistergrizzly.com/privacy-policy/"
+  }
+  
+  static let DocumentsFolderName = "ScannerApp"
+  static let ThumbnailsFolderName = ".ThumbnailImages"
+}
+
+let deviceType = UIDevice.current.userInterfaceIdiom
+
+extension Bundle {
+  class var appName: String {
+    let bundleDisplayname = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String
+    let bundleName = Bundle.main.infoDictionary![kCFBundleNameKey as String] as! String
+    
+    return bundleDisplayname ?? bundleName
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/.DS_Store b/MiniScanner/Supporting Files/Assets.xcassets/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..67f5aa0da73f72af29c38ff85df48dd76521ff5c
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/.DS_Store differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AccentColor.colorset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..108c717da4d8677a218aa885e34d069c32773e1b
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/AccentColor.colorset/Contents.json	
@@ -0,0 +1,20 @@
+{
+  "colors" : [
+    {
+      "color" : {
+        "color-space" : "srgb",
+        "components" : {
+          "alpha" : "1.000",
+          "blue" : "0.777",
+          "green" : "0.310",
+          "red" : "0.001"
+        }
+      },
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/100.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/100.png
new file mode 100644
index 0000000000000000000000000000000000000000..6758a4f58934f1167b15bf58be906b0f911ea5d8
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/100.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png
new file mode 100644
index 0000000000000000000000000000000000000000..57465cbe91bb2e771fa2d19f28cc884f974cefb8
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/1024.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/114.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/114.png
new file mode 100644
index 0000000000000000000000000000000000000000..90189256f8069f90c24a54621cedea77a0dc3683
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/114.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/120.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/120.png
new file mode 100644
index 0000000000000000000000000000000000000000..4344b60083e4f914f9d8d4a13d59eff4325a5698
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/120.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/144.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/144.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec8d1e59ba06e22d911a13d2f9bfc8be86f829e8
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/144.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/152.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/152.png
new file mode 100644
index 0000000000000000000000000000000000000000..81d776358e6f4ea99f3c693f53474b4abe2c9afe
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/152.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/167.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/167.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5428407cc8f809f9804f54fc3fb937244d34f1b
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/167.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/180.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/180.png
new file mode 100644
index 0000000000000000000000000000000000000000..e22abc672ec1565a2e81a3538b44b2dac747d738
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/180.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/20.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/20.png
new file mode 100644
index 0000000000000000000000000000000000000000..a0ebef501e4779c9f179ec18e348acb14af28155
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/20.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/29.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/29.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e3b0fd9f1f0bd8c3eb89d4214521233306442ae
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/29.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/40.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/40.png
new file mode 100644
index 0000000000000000000000000000000000000000..a34a1cce8d1d33912aca1d7e5ced647cd8f0bf8b
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/40.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/50.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/50.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6470ec6a2a40950afc07890417f08c5e723d530
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/50.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/57.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/57.png
new file mode 100644
index 0000000000000000000000000000000000000000..7eb0d6933c54d850c4f7765fd55a8cce7eab8ff2
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/57.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/58.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/58.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd94e7c681d60e1518f6fe6cbbfcd18036b09ebc
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/58.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/60.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/60.png
new file mode 100644
index 0000000000000000000000000000000000000000..9eea7188e46e940ca04c4375baa46777147d4925
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/60.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/72.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/72.png
new file mode 100644
index 0000000000000000000000000000000000000000..fe04eba6d8f9efd9566cfbe195cffda48a58de2a
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/72.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/76.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/76.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c2310b1323e1d23502407640cd0bc2de3fb06fe
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/76.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/80.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/80.png
new file mode 100644
index 0000000000000000000000000000000000000000..27a1d7e85e191786e6effcd71873e2a50214e563
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/80.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/87.png b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/87.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1f5da54f038c8bf043e4383b266e8893cd15cae
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/87.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..4fdf88263a71873625448bca07fdc5cb865707fe
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json	
@@ -0,0 +1,158 @@
+{
+  "images" : [
+    {
+      "filename" : "40.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "60.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "29.png",
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "58.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "87.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "80.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "120.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "57.png",
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "size" : "57x57"
+    },
+    {
+      "filename" : "114.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "57x57"
+    },
+    {
+      "filename" : "120.png",
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "180.png",
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "20.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "40.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "29.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "58.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "40.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "80.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "50.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "50x50"
+    },
+    {
+      "filename" : "100.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "50x50"
+    },
+    {
+      "filename" : "72.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "72x72"
+    },
+    {
+      "filename" : "144.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "72x72"
+    },
+    {
+      "filename" : "76.png",
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "size" : "76x76"
+    },
+    {
+      "filename" : "152.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "76x76"
+    },
+    {
+      "filename" : "167.png",
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "size" : "83.5x83.5"
+    },
+    {
+      "filename" : "1024.png",
+      "idiom" : "ios-marketing",
+      "scale" : "1x",
+      "size" : "1024x1024"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..73c00596a7fca3f3d4bdd64053b69d86745f9e10
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/Contents.json	
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/activity-feed-icon.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/activity-feed-icon.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..668e6511bf9f8eb89f903cfbeb37f3d0b6fe6607
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/activity-feed-icon.imageset/Contents.json	
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "rss.pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/activity-feed-icon.imageset/rss.pdf b/MiniScanner/Supporting Files/Assets.xcassets/activity-feed-icon.imageset/rss.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..1d9badf04ae78ce947b281cd5b51a7dcecf17dc9
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/activity-feed-icon.imageset/rss.pdf differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..b6eb40319242b176733784f14a957b53e6cd80e0
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/Contents.json	
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "ui_listview_scan_atlantis98x99.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ui_listview_scan_atlantis98x99@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ui_listview_scan_atlantis98x99@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99.png b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99.png
new file mode 100644
index 0000000000000000000000000000000000000000..dac95011afb5de6ce093f4b648d1ab98049eda50
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99@2x.png b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b4f9f04389854b0b2bdc81f524b4c9d7bf3f56a
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99@2x.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99@3x.png b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..6bff4b5256a5126522dcf588bc7c40aed8230fbe
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/add_doc_icon.imageset/ui_listview_scan_atlantis98x99@3x.png differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/analytics-icon.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/analytics-icon.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..d4d8e695a9213a6c7c441be9c4516e8133402e60
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/analytics-icon.imageset/Contents.json	
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "analytics.pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/analytics-icon.imageset/analytics.pdf b/MiniScanner/Supporting Files/Assets.xcassets/analytics-icon.imageset/analytics.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..96e86da8ad709d39621c2c8ddc9fa9be18b9e750
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/analytics-icon.imageset/analytics.pdf differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/bars-icon.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/bars-icon.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..af4b5454d6abcf420d2c5e1cda9b296bb00e5539
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/bars-icon.imageset/Contents.json	
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "analytics (1).pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/bars-icon.imageset/analytics (1).pdf b/MiniScanner/Supporting Files/Assets.xcassets/bars-icon.imageset/analytics (1).pdf
new file mode 100644
index 0000000000000000000000000000000000000000..7d85d6cdcc30868524e30843b1467b81925f348c
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/bars-icon.imageset/analytics (1).pdf differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/bell-icon.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/bell-icon.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..729d33a130fd71d0c3f3dd417a788033d91fa596
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/bell-icon.imageset/Contents.json	
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "notification-bell.pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/bell-icon.imageset/notification-bell.pdf b/MiniScanner/Supporting Files/Assets.xcassets/bell-icon.imageset/notification-bell.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..4cbff81f1e59b80609ee216262fdb7b2b2951ecc
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/bell-icon.imageset/notification-bell.pdf differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/Artboard.pdf b/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/Artboard.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..f18b0316ea954091f404e425aec0e98e27e2a349
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/Artboard.pdf differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..0399be699ffc05c376578faf26211c809889d18d
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/Contents.json	
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "filename" : "Artboard.pdf",
+      "idiom" : "universal"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "filename" : "no_files_dark.pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/no_files_dark.pdf b/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/no_files_dark.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..12688b92d03343fbc304a7767c9f7e9833cf2a73
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/box.imageset/no_files_dark.pdf differ
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/settings.imageset/Contents.json b/MiniScanner/Supporting Files/Assets.xcassets/settings.imageset/Contents.json
new file mode 100644
index 0000000000000000000000000000000000000000..8b72e351eac6ae0ef1f8c24ea8ca6d6d2f9f466d
--- /dev/null
+++ b/MiniScanner/Supporting Files/Assets.xcassets/settings.imageset/Contents.json	
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "settings (1).pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/MiniScanner/Supporting Files/Assets.xcassets/settings.imageset/settings (1).pdf b/MiniScanner/Supporting Files/Assets.xcassets/settings.imageset/settings (1).pdf
new file mode 100644
index 0000000000000000000000000000000000000000..0d270fafe4bb4959483a04c37212a3efa9887819
Binary files /dev/null and b/MiniScanner/Supporting Files/Assets.xcassets/settings.imageset/settings (1).pdf differ
diff --git a/MiniScanner/Supporting Files/Base.lproj/LaunchScreen.storyboard b/MiniScanner/Supporting Files/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000000000000000000000000000000000000..865e9329f3767a7c1dd66294b8025bf81dee7d2c
--- /dev/null
+++ b/MiniScanner/Supporting Files/Base.lproj/LaunchScreen.storyboard	
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/MiniScanner/Supporting Files/Info.plist b/MiniScanner/Supporting Files/Info.plist
new file mode 100644
index 0000000000000000000000000000000000000000..41d7cee8557cf194219c0e147fcbd952b27564d8
--- /dev/null
+++ b/MiniScanner/Supporting Files/Info.plist	
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleDisplayName</key>
+	<string>MiniScanner</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(MARKETING_VERSION)</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSCameraUsageDescription</key>
+	<string>Let the $(PRODUCT_NAME) use device camera in order to scan your documents</string>
+	<key>NSPhotoLibraryUsageDescription</key>
+	<string>Let the $(PRODUCT_NAME) use device photo library in order to scan your documents</string>
+	<key>UIApplicationSceneManifest</key>
+	<dict>
+		<key>UIApplicationSupportsMultipleScenes</key>
+		<true/>
+		<key>UISceneConfigurations</key>
+		<dict>
+			<key>UIWindowSceneSessionRoleApplication</key>
+			<array>
+				<dict>
+					<key>UISceneConfigurationName</key>
+					<string>Default Configuration</string>
+					<key>UISceneDelegateClassName</key>
+					<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
+				</dict>
+			</array>
+		</dict>
+	</dict>
+	<key>UIApplicationSupportsIndirectInputEvents</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UIRequiresFullScreen</key>
+	<true/>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>
diff --git a/MiniScanner/Supporting Files/SceneDelegate.swift b/MiniScanner/Supporting Files/SceneDelegate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..28988ff20927c6e071abec158880668cef0436b2
--- /dev/null
+++ b/MiniScanner/Supporting Files/SceneDelegate.swift	
@@ -0,0 +1,47 @@
+import UIKit
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+  
+  var window: UIWindow?
+  
+  func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
+             options connectionOptions: UIScene.ConnectionOptions) {
+    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+    guard let windowScene = (scene as? UIWindowScene) else { return }
+    
+    window = UIWindow(windowScene: windowScene)
+    let navigationController = AppTabBarController.buildViewController()//BaseNavigationViewController.buildViewController()
+    window?.rootViewController = navigationController
+    window?.makeKeyAndVisible()
+  }
+  
+  func sceneDidDisconnect(_ scene: UIScene) {
+    // Called as the scene is being released by the system.
+    // This occurs shortly after the scene enters the background, or when its session is discarded.
+    // Release any resources associated with this scene that can be re-created the next time the scene connects.
+    // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+  }
+  
+  func sceneDidBecomeActive(_ scene: UIScene) {
+    // Called when the scene has moved from an inactive state to an active state.
+    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+  }
+  
+  func sceneWillResignActive(_ scene: UIScene) {
+    // Called when the scene will move from an active state to an inactive state.
+    // This may occur due to temporary interruptions (ex. an incoming phone call).
+  }
+  
+  func sceneWillEnterForeground(_ scene: UIScene) {
+    // Called as the scene transitions from the background to the foreground.
+    // Use this method to undo the changes made on entering the background.
+  }
+  
+  func sceneDidEnterBackground(_ scene: UIScene) {
+    // Called as the scene transitions from the foreground to the background.
+    // Use this method to save data, release shared resources, and store enough scene-specific state information
+    // to restore the scene back to its current state.
+  }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/enhance.png b/MiniScanner/Supporting Files/WeScan/Assets/enhance.png
new file mode 100644
index 0000000000000000000000000000000000000000..e87fc945f9919c1632d925e557da7adb81f883b4
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/enhance.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/enhance@2x.png b/MiniScanner/Supporting Files/WeScan/Assets/enhance@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..bbbb80f88007044e603e193da02abcd71688e1c5
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/enhance@2x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/enhance@3x.png b/MiniScanner/Supporting Files/WeScan/Assets/enhance@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a58b69fc417df613963a7b15f4ccdd473c58a6f
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/enhance@3x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/flash.png b/MiniScanner/Supporting Files/WeScan/Assets/flash.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0d04da92286ec2808d63f2977d0e4a881b9a4f4
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/flash.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/flash@2x.png b/MiniScanner/Supporting Files/WeScan/Assets/flash@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c21bba43c8bea1ec11f150f3a5a00f054f2bb9d
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/flash@2x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/flash@3x.png b/MiniScanner/Supporting Files/WeScan/Assets/flash@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..acae8b959cf215693c8e0b8128b4c6c60dda3e5f
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/flash@3x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable.png b/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable.png
new file mode 100644
index 0000000000000000000000000000000000000000..38204fb2bc3816f0d72fb278892d3d2d03f1722b
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable@2x.png b/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..585bed6ef3577d193f444e76475598cfc8ff4e36
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable@2x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable@3x.png b/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..3202abee780b5a48f7a6d22aae0cd0165942beb4
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/flashUnavailable@3x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/rotate.png b/MiniScanner/Supporting Files/WeScan/Assets/rotate.png
new file mode 100644
index 0000000000000000000000000000000000000000..281d40b2490bdb7d90f74efea53c38827643f384
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/rotate.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/rotate@2x.png b/MiniScanner/Supporting Files/WeScan/Assets/rotate@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..eb6d5b2242731563f01caad47ae7ffbf640da334
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/rotate@2x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Assets/rotate@3x.png b/MiniScanner/Supporting Files/WeScan/Assets/rotate@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..67db171e3232108c8d3f0e20cc03a9b16532ed14
Binary files /dev/null and b/MiniScanner/Supporting Files/WeScan/Assets/rotate@3x.png differ
diff --git a/MiniScanner/Supporting Files/WeScan/Common/CIRectangleDetector.swift b/MiniScanner/Supporting Files/WeScan/Common/CIRectangleDetector.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a1fe4374299853ae4b69a237e079bf4e66392bb8
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Common/CIRectangleDetector.swift	
@@ -0,0 +1,41 @@
+//
+//  RectangleDetector.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/13/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+import CoreImage
+
+/// Class used to detect rectangles from an image.
+struct CIRectangleDetector {
+    
+    static let rectangleDetector = CIDetector(ofType: CIDetectorTypeRectangle,
+                                              context: CIContext(options: nil),
+                                              options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
+    
+    /// Detects rectangles from the given image on iOS 10.
+    ///
+    /// - Parameters:
+    ///   - image: The image to detect rectangles on.
+    /// - Returns: The biggest detected rectangle on the image.
+    static func rectangle(forImage image: CIImage, completion: @escaping ((Quadrilateral?) -> Void)) {
+        let biggestRectangle = rectangle(forImage: image)
+        completion(biggestRectangle)
+    }
+    
+    static func rectangle(forImage image: CIImage) -> Quadrilateral? {
+        guard let rectangleFeatures = rectangleDetector?.features(in: image) as? [CIRectangleFeature] else {
+            return nil
+        }
+        
+        let quads = rectangleFeatures.map { rectangle in
+            return Quadrilateral(rectangleFeature: rectangle)
+        }
+        
+        return quads.biggest()
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Common/EditScanCornerView.swift b/MiniScanner/Supporting Files/WeScan/Common/EditScanCornerView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..96dd5b43c4f7bb713ae804317c60d62258bf6a4c
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Common/EditScanCornerView.swift	
@@ -0,0 +1,67 @@
+//
+//  EditScanCornerView.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 3/5/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+
+/// A UIView used by corners of a quadrilateral that is aware of its position.
+final class EditScanCornerView: UIView {
+    
+    let position: CornerPosition
+    
+    /// The image to display when the corner view is highlighted.
+    private var image: UIImage?
+    private(set) var isHighlighted = false
+    
+    lazy private var circleLayer: CAShapeLayer = {
+        let layer = CAShapeLayer()
+        layer.fillColor = UIColor.clear.cgColor
+        layer.strokeColor = UIColor.white.cgColor
+        layer.lineWidth = 1.0
+        return layer
+    }()
+    
+    init(frame: CGRect, position: CornerPosition) {
+        self.position = position
+        super.init(frame: frame)
+        backgroundColor = UIColor.clear
+        clipsToBounds = true
+        layer.addSublayer(circleLayer)
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        layer.cornerRadius = bounds.width / 2.0
+    }
+    
+    override func draw(_ rect: CGRect) {
+        super.draw(rect)
+        
+        let bezierPath = UIBezierPath(ovalIn: rect.insetBy(dx: circleLayer.lineWidth, dy: circleLayer.lineWidth))
+        circleLayer.frame = rect
+        circleLayer.path = bezierPath.cgPath
+        
+        image?.draw(in: rect)
+    }
+    
+    func highlightWithImage(_ image: UIImage) {
+        isHighlighted = true
+        self.image = image
+        self.setNeedsDisplay()
+    }
+    
+    func reset() {
+        isHighlighted = false
+        image = nil
+        setNeedsDisplay()
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Common/Error.swift b/MiniScanner/Supporting Files/WeScan/Common/Error.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e81fb168e47586eaeb84f1d69889bfbad9843cfa
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Common/Error.swift	
@@ -0,0 +1,38 @@
+//
+//  Error.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/28/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+
+/// Errors related to the `ImageScannerController`
+public enum ImageScannerControllerError: Error {
+    /// The user didn't grant permission to use the camera.
+    case authorization
+    /// An error occured when setting up the user's device.
+    case inputDevice
+    /// An error occured when trying to capture a picture.
+    case capture
+    /// Error when creating the CIImage.
+    case ciImageCreation
+}
+
+extension ImageScannerControllerError: LocalizedError {
+    
+    public var errorDescription: String? {
+        switch self {
+        case .authorization:
+            return "Failed to get the user's authorization for camera."
+        case .inputDevice:
+            return "Could not setup input device."
+        case .capture:
+            return "Could not capture pitcure."
+        case .ciImageCreation:
+            return "Internal Error - Could not create CIImage"
+        }
+    }
+
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Common/Quadrilateral.swift b/MiniScanner/Supporting Files/WeScan/Common/Quadrilateral.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a9244f80ea5fdb67c7958e96d31355532cf748fc
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Common/Quadrilateral.swift	
@@ -0,0 +1,221 @@
+//
+//  Quadrilateral.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/8/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+import Vision
+import CoreImage
+import UIKit
+
+/// A data structure representing a quadrilateral and its position. This class exists to bypass the fact that CIRectangleFeature is read-only.
+public struct Quadrilateral: Transformable {
+    
+    /// A point that specifies the top left corner of the quadrilateral.
+    public var topLeft: CGPoint
+    
+    /// A point that specifies the top right corner of the quadrilateral.
+    public var topRight: CGPoint
+    
+    /// A point that specifies the bottom right corner of the quadrilateral.
+    public var bottomRight: CGPoint
+    
+    /// A point that specifies the bottom left corner of the quadrilateral.
+    public var bottomLeft: CGPoint
+    
+    init(rectangleFeature: CIRectangleFeature) {
+        self.topLeft = rectangleFeature.topLeft
+        self.topRight = rectangleFeature.topRight
+        self.bottomLeft = rectangleFeature.bottomLeft
+        self.bottomRight = rectangleFeature.bottomRight
+    }
+
+    @available(iOS 11.0, *)
+    init(rectangleObservation: VNRectangleObservation) {
+        self.topLeft = rectangleObservation.topLeft
+        self.topRight = rectangleObservation.topRight
+        self.bottomLeft = rectangleObservation.bottomLeft
+        self.bottomRight = rectangleObservation.bottomRight
+    }
+
+    init(topLeft: CGPoint, topRight: CGPoint, bottomRight: CGPoint, bottomLeft: CGPoint) {
+        self.topLeft = topLeft
+        self.topRight = topRight
+        self.bottomRight = bottomRight
+        self.bottomLeft = bottomLeft
+    }
+    
+    public var description: String {
+        return "topLeft: \(topLeft), topRight: \(topRight), bottomRight: \(bottomRight), bottomLeft: \(bottomLeft)"
+    }
+    
+    /// The path of the Quadrilateral as a `UIBezierPath`
+    var path: UIBezierPath {
+        let path = UIBezierPath()
+        path.move(to: topLeft)
+        path.addLine(to: topRight)
+        path.addLine(to: bottomRight)
+        path.addLine(to: bottomLeft)
+        path.close()
+        
+        return path
+    }
+    
+    /// The perimeter of the Quadrilateral
+    var perimeter: Double {
+        let perimeter = topLeft.distanceTo(point: topRight) + topRight.distanceTo(point: bottomRight) + bottomRight.distanceTo(point: bottomLeft) + bottomLeft.distanceTo(point: topLeft)
+        return Double(perimeter)
+    }
+    
+    /// Applies a `CGAffineTransform` to the quadrilateral.
+    ///
+    /// - Parameters:
+    ///   - t: the transform to apply.
+    /// - Returns: The transformed quadrilateral.
+    func applying(_ transform: CGAffineTransform) -> Quadrilateral {
+        let quadrilateral = Quadrilateral(topLeft: topLeft.applying(transform), topRight: topRight.applying(transform), bottomRight: bottomRight.applying(transform), bottomLeft: bottomLeft.applying(transform))
+        
+        return quadrilateral
+    }
+    
+    /// Checks whether the quadrilateral is withing a given distance of another quadrilateral.
+    ///
+    /// - Parameters:
+    ///   - distance: The distance (threshold) to use for the condition to be met.
+    ///   - rectangleFeature: The other rectangle to compare this instance with.
+    /// - Returns: True if the given rectangle is within the given distance of this rectangle instance.
+    func isWithin(_ distance: CGFloat, ofRectangleFeature rectangleFeature: Quadrilateral) -> Bool {
+        
+        let topLeftRect = topLeft.surroundingSquare(withSize: distance)
+        if !topLeftRect.contains(rectangleFeature.topLeft) {
+            return false
+        }
+        
+        let topRightRect = topRight.surroundingSquare(withSize: distance)
+        if !topRightRect.contains(rectangleFeature.topRight) {
+            return false
+        }
+        
+        let bottomRightRect = bottomRight.surroundingSquare(withSize: distance)
+        if !bottomRightRect.contains(rectangleFeature.bottomRight) {
+            return false
+        }
+        
+        let bottomLeftRect = bottomLeft.surroundingSquare(withSize: distance)
+        if !bottomLeftRect.contains(rectangleFeature.bottomLeft) {
+            return false
+        }
+        
+        return true
+    }
+    
+    /// Reorganizes the current quadrilateal, making sure that the points are at their appropriate positions. For example, it ensures that the top left point is actually the top and left point point of the quadrilateral.
+    mutating func reorganize() {
+        let points = [topLeft, topRight, bottomRight, bottomLeft]
+        let ySortedPoints = sortPointsByYValue(points)
+        
+        guard ySortedPoints.count == 4 else {
+            return
+        }
+        
+        let topMostPoints = Array(ySortedPoints[0..<2])
+        let bottomMostPoints = Array(ySortedPoints[2..<4])
+        let xSortedTopMostPoints = sortPointsByXValue(topMostPoints)
+        let xSortedBottomMostPoints = sortPointsByXValue(bottomMostPoints)
+        
+        guard xSortedTopMostPoints.count > 1,
+            xSortedBottomMostPoints.count > 1 else {
+                return
+        }
+        
+        topLeft = xSortedTopMostPoints[0]
+        topRight = xSortedTopMostPoints[1]
+        bottomRight = xSortedBottomMostPoints[1]
+        bottomLeft = xSortedBottomMostPoints[0]
+    }
+    
+    /// Scales the quadrilateral based on the ratio of two given sizes, and optionaly applies a rotation.
+    ///
+    /// - Parameters:
+    ///   - fromSize: The size the quadrilateral is currently related to.
+    ///   - toSize: The size to scale the quadrilateral to.
+    ///   - rotationAngle: The optional rotation to apply.
+    /// - Returns: The newly scaled and potentially rotated quadrilateral.
+    func scale(_ fromSize: CGSize, _ toSize: CGSize, withRotationAngle rotationAngle: CGFloat = 0.0) -> Quadrilateral {
+        var invertedfromSize = fromSize
+        let rotated = rotationAngle != 0.0
+        
+        if rotated && rotationAngle != CGFloat.pi {
+            invertedfromSize = CGSize(width: fromSize.height, height: fromSize.width)
+        }
+        
+        var transformedQuad = self
+        let invertedFromSizeWidth = invertedfromSize.width == 0 ? .leastNormalMagnitude : invertedfromSize.width
+        
+        let scale = toSize.width / invertedFromSizeWidth
+        let scaledTransform = CGAffineTransform(scaleX: scale, y: scale)
+        transformedQuad = transformedQuad.applying(scaledTransform)
+        
+        if rotated {
+            let rotationTransform = CGAffineTransform(rotationAngle: rotationAngle)
+            
+            let fromImageBounds = CGRect(origin: .zero, size: fromSize).applying(scaledTransform).applying(rotationTransform)
+            
+            let toImageBounds = CGRect(origin: .zero, size: toSize)
+            let translationTransform = CGAffineTransform.translateTransform(fromCenterOfRect: fromImageBounds, toCenterOfRect: toImageBounds)
+            
+            transformedQuad = transformedQuad.applyTransforms([rotationTransform, translationTransform])
+        }
+        
+        return transformedQuad
+    }
+    
+    // Convenience functions
+    
+    /// Sorts the given `CGPoints` based on their y value.
+    /// - Parameters:
+    ///   - points: The poinmts to sort.
+    /// - Returns: The points sorted based on their y value.
+    private func sortPointsByYValue(_ points: [CGPoint]) -> [CGPoint] {
+        return points.sorted { (point1, point2) -> Bool in
+            point1.y < point2.y
+        }
+    }
+    
+    /// Sorts the given `CGPoints` based on their x value.
+    /// - Parameters:
+    ///   - points: The points to sort.
+    /// - Returns: The points sorted based on their x value.
+    private func sortPointsByXValue(_ points: [CGPoint]) -> [CGPoint] {
+        return points.sorted { (point1, point2) -> Bool in
+            point1.x < point2.x
+        }
+    }
+}
+
+extension Quadrilateral {
+    
+    /// Converts the current to the cartesian coordinate system (where 0 on the y axis is at the bottom).
+    ///
+    /// - Parameters:
+    ///   - height: The height of the rect containing the quadrilateral.
+    /// - Returns: The same quadrilateral in the cartesian corrdinate system.
+    func toCartesian(withHeight height: CGFloat) -> Quadrilateral {
+        let topLeft = self.topLeft.cartesian(withHeight: height)
+        let topRight = self.topRight.cartesian(withHeight: height)
+        let bottomRight = self.bottomRight.cartesian(withHeight: height)
+        let bottomLeft = self.bottomLeft.cartesian(withHeight: height)
+        
+        return Quadrilateral(topLeft: topLeft, topRight: topRight, bottomRight: bottomRight, bottomLeft: bottomLeft)
+    }
+}
+
+extension Quadrilateral: Equatable {
+    public static func == (lhs: Quadrilateral, rhs: Quadrilateral) -> Bool {
+        return lhs.topLeft == rhs.topLeft && lhs.topRight == rhs.topRight && lhs.bottomRight == rhs.bottomRight && lhs.bottomLeft == rhs.bottomLeft
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Common/QuadrilateralView.swift b/MiniScanner/Supporting Files/WeScan/Common/QuadrilateralView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a7d75e5686bf480d0ef7810ee06acde2d3fbe187
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Common/QuadrilateralView.swift	
@@ -0,0 +1,298 @@
+//
+//  RectangleView.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/8/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+/// Simple enum to keep track of the position of the corners of a quadrilateral.
+enum CornerPosition {
+    case topLeft
+    case topRight
+    case bottomRight
+    case bottomLeft
+}
+
+/// The `QuadrilateralView` is a simple `UIView` subclass that can draw a quadrilateral, and optionally edit it.
+final class QuadrilateralView: UIView {
+    
+    private let quadLayer: CAShapeLayer = {
+        let layer = CAShapeLayer()
+        layer.strokeColor = UIColor.white.cgColor
+        layer.lineWidth = 1.0
+        layer.opacity = 1.0
+        layer.isHidden = true
+        
+        return layer
+    }()
+    
+    /// We want the corner views to be displayed under the outline of the quadrilateral.
+    /// Because of that, we need the quadrilateral to be drawn on a UIView above them.
+    private let quadView: UIView = {
+        let view = UIView()
+        view.backgroundColor = UIColor.clear
+        view.translatesAutoresizingMaskIntoConstraints = false
+        return view
+    }()
+    
+    /// The quadrilateral drawn on the view.
+    private(set) var quad: Quadrilateral?
+    
+    public var editable = false {
+        didSet {
+            cornerViews(hidden: !editable)
+            quadLayer.fillColor = editable ? UIColor(white: 0.0, alpha: 0.6).cgColor : UIColor(white: 1.0, alpha: 0.5).cgColor
+            guard let quad = quad else {
+                return
+            }
+            drawQuad(quad, animated: false)
+            layoutCornerViews(forQuad: quad)
+        }
+    }
+    
+    private var isHighlighted = false {
+        didSet (oldValue) {
+            guard oldValue != isHighlighted else {
+                return
+            }
+            quadLayer.fillColor = isHighlighted ? UIColor.clear.cgColor : UIColor(white: 0.0, alpha: 0.6).cgColor
+            isHighlighted ? bringSubviewToFront(quadView) : sendSubviewToBack(quadView)
+        }
+    }
+    
+    lazy private var topLeftCornerView: EditScanCornerView = {
+        return EditScanCornerView(frame: CGRect(origin: .zero, size: cornerViewSize), position: .topLeft)
+    }()
+    
+    lazy private var topRightCornerView: EditScanCornerView = {
+        return EditScanCornerView(frame: CGRect(origin: .zero, size: cornerViewSize), position: .topRight)
+    }()
+    
+    lazy private var bottomRightCornerView: EditScanCornerView = {
+        return EditScanCornerView(frame: CGRect(origin: .zero, size: cornerViewSize), position: .bottomRight)
+    }()
+    
+    lazy private var bottomLeftCornerView: EditScanCornerView = {
+        return EditScanCornerView(frame: CGRect(origin: .zero, size: cornerViewSize), position: .bottomLeft)
+    }()
+    
+    private let highlightedCornerViewSize = CGSize(width: 75.0, height: 75.0)
+    private let cornerViewSize = CGSize(width: 20.0, height: 20.0)
+    
+    // MARK: - Life Cycle
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        commonInit()
+    }
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    private func commonInit() {
+        addSubview(quadView)
+        setupCornerViews()
+        setupConstraints()
+        quadView.layer.addSublayer(quadLayer)
+    }
+    
+    private func setupConstraints() {
+        let quadViewConstraints = [
+            quadView.topAnchor.constraint(equalTo: topAnchor),
+            quadView.leadingAnchor.constraint(equalTo: leadingAnchor),
+            bottomAnchor.constraint(equalTo: quadView.bottomAnchor),
+            trailingAnchor.constraint(equalTo: quadView.trailingAnchor)
+        ]
+        
+        NSLayoutConstraint.activate(quadViewConstraints)
+    }
+    
+    private func setupCornerViews() {
+        addSubview(topLeftCornerView)
+        addSubview(topRightCornerView)
+        addSubview(bottomRightCornerView)
+        addSubview(bottomLeftCornerView)
+    }
+    
+    override public func layoutSubviews() {
+        super.layoutSubviews()
+        guard quadLayer.frame != bounds else {
+            return
+        }
+        
+        quadLayer.frame = bounds
+        if let quad = quad {
+            drawQuadrilateral(quad: quad, animated: false)
+        }
+    }
+    
+    // MARK: - Drawings
+    
+    /// Draws the passed in quadrilateral.
+    ///
+    /// - Parameters:
+    ///   - quad: The quadrilateral to draw on the view. It should be in the coordinates of the current `QuadrilateralView` instance.
+    func drawQuadrilateral(quad: Quadrilateral, animated: Bool) {
+        self.quad = quad
+        drawQuad(quad, animated: animated)
+        if editable {
+            cornerViews(hidden: false)
+            layoutCornerViews(forQuad: quad)
+        }
+    }
+    
+    private func drawQuad(_ quad: Quadrilateral, animated: Bool) {
+        var path = quad.path
+        
+        if editable {
+            path = path.reversing()
+            let rectPath = UIBezierPath(rect: bounds)
+            path.append(rectPath)
+        }
+        
+        if animated == true {
+            let pathAnimation = CABasicAnimation(keyPath: "path")
+            pathAnimation.duration = 0.2
+            quadLayer.add(pathAnimation, forKey: "path")
+        }
+        
+        quadLayer.path = path.cgPath
+        quadLayer.isHidden = false
+    }
+    
+    private func layoutCornerViews(forQuad quad: Quadrilateral) {
+        topLeftCornerView.center = quad.topLeft
+        topRightCornerView.center = quad.topRight
+        bottomLeftCornerView.center = quad.bottomLeft
+        bottomRightCornerView.center = quad.bottomRight
+    }
+    
+    func removeQuadrilateral() {
+        quadLayer.path = nil
+        quadLayer.isHidden = true
+    }
+    
+    // MARK: - Actions
+    
+    func moveCorner(cornerView: EditScanCornerView, atPoint point: CGPoint) {
+        guard let quad = quad else {
+            return
+        }
+        
+        let validPoint = self.validPoint(point, forCornerViewOfSize: cornerView.bounds.size, inView: self)
+        
+        cornerView.center = validPoint
+        let updatedQuad = update(quad, withPosition: validPoint, forCorner: cornerView.position)
+        
+        self.quad = updatedQuad
+        drawQuad(updatedQuad, animated: false)
+    }
+    
+    func highlightCornerAtPosition(position: CornerPosition, with image: UIImage) {
+        guard editable else {
+            return
+        }
+        isHighlighted = true
+        
+        let cornerView = cornerViewForCornerPosition(position: position)
+        guard cornerView.isHighlighted == false else {
+            cornerView.highlightWithImage(image)
+            return
+        }
+
+        let origin = CGPoint(x: cornerView.frame.origin.x - (highlightedCornerViewSize.width - cornerViewSize.width) / 2.0,
+                             y: cornerView.frame.origin.y - (highlightedCornerViewSize.height - cornerViewSize.height) / 2.0)
+        cornerView.frame = CGRect(origin: origin, size: highlightedCornerViewSize)
+        cornerView.highlightWithImage(image)
+    }
+    
+    func resetHighlightedCornerViews() {
+        isHighlighted = false
+        resetHighlightedCornerViews(cornerViews: [topLeftCornerView, topRightCornerView, bottomLeftCornerView, bottomRightCornerView])
+    }
+    
+    private func resetHighlightedCornerViews(cornerViews: [EditScanCornerView]) {
+        cornerViews.forEach { (cornerView) in
+            resetHightlightedCornerView(cornerView: cornerView)
+        }
+    }
+    
+    private func resetHightlightedCornerView(cornerView: EditScanCornerView) {
+        cornerView.reset()
+        let origin = CGPoint(x: cornerView.frame.origin.x + (cornerView.frame.size.width - cornerViewSize.width) / 2.0,
+                             y: cornerView.frame.origin.y + (cornerView.frame.size.height - cornerViewSize.width) / 2.0)
+        cornerView.frame = CGRect(origin: origin, size: cornerViewSize)
+        cornerView.setNeedsDisplay()
+    }
+    
+    // MARK: Validation
+    
+    /// Ensures that the given point is valid - meaning that it is within the bounds of the passed in `UIView`.
+    ///
+    /// - Parameters:
+    ///   - point: The point that needs to be validated.
+    ///   - cornerViewSize: The size of the corner view representing the given point.
+    ///   - view: The view which should include the point.
+    /// - Returns: A new point which is within the passed in view.
+    private func validPoint(_ point: CGPoint, forCornerViewOfSize cornerViewSize: CGSize, inView view: UIView) -> CGPoint {
+        var validPoint = point
+        
+        if point.x > view.bounds.width {
+            validPoint.x = view.bounds.width
+        } else if point.x < 0.0 {
+            validPoint.x = 0.0
+        }
+        
+        if point.y > view.bounds.height {
+            validPoint.y = view.bounds.height
+        } else if point.y < 0.0 {
+            validPoint.y = 0.0
+        }
+        
+        return validPoint
+    }
+    
+    // MARK: - Convenience
+    
+    private func cornerViews(hidden: Bool) {
+        topLeftCornerView.isHidden = hidden
+        topRightCornerView.isHidden = hidden
+        bottomRightCornerView.isHidden = hidden
+        bottomLeftCornerView.isHidden = hidden
+    }
+    
+    private func update(_ quad: Quadrilateral, withPosition position: CGPoint, forCorner corner: CornerPosition) -> Quadrilateral {
+        var quad = quad
+        
+        switch corner {
+        case .topLeft:
+            quad.topLeft = position
+        case .topRight:
+            quad.topRight = position
+        case .bottomRight:
+            quad.bottomRight = position
+        case .bottomLeft:
+            quad.bottomLeft = position
+        }
+        
+        return quad
+    }
+    
+    func cornerViewForCornerPosition(position: CornerPosition) -> EditScanCornerView {
+        switch position {
+        case .topLeft:
+            return topLeftCornerView
+        case .topRight:
+            return topRightCornerView
+        case .bottomLeft:
+            return bottomLeftCornerView
+        case .bottomRight:
+            return bottomRightCornerView
+        }
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Common/VisionRectangleDetector.swift b/MiniScanner/Supporting Files/WeScan/Common/VisionRectangleDetector.swift
new file mode 100644
index 0000000000000000000000000000000000000000..00ae5730f666c7e48e220fd73888334de79f5f58
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Common/VisionRectangleDetector.swift	
@@ -0,0 +1,82 @@
+//
+//  VisionRectangleDetector.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 28/7/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Vision
+import Foundation
+import CoreImage
+
+/// Class used to detect rectangles from an image.
+@available(iOS 11.0, *)
+struct VisionRectangleDetector {
+
+    private static func completeImageRequest(for request: VNImageRequestHandler, width: CGFloat, height: CGFloat, completion: @escaping ((Quadrilateral?) -> Void)) {
+        // Create the rectangle request, and, if found, return the biggest rectangle (else return nothing).
+        let rectangleDetectionRequest: VNDetectRectanglesRequest = {
+            let rectDetectRequest = VNDetectRectanglesRequest(completionHandler: { (request, error) in
+                guard error == nil, let results = request.results as? [VNRectangleObservation], !results.isEmpty else {
+                    completion(nil)
+                    return
+                }
+
+                let quads: [Quadrilateral] = results.map(Quadrilateral.init)
+
+                guard let biggest = quads.biggest() else { // This can't fail because the earlier guard protected against an empty array, but we use guard because of SwiftLint
+                    completion(nil)
+                    return
+                }
+
+                let transform = CGAffineTransform.identity
+                    .scaledBy(x: width, y: height)
+
+                completion(biggest.applying(transform))
+            })
+
+            rectDetectRequest.minimumConfidence = 0.8
+            rectDetectRequest.maximumObservations = 15
+            rectDetectRequest.minimumAspectRatio = 0.3
+
+            return rectDetectRequest
+        }()
+
+        // Send the requests to the request handler.
+        do {
+            try request.perform([rectangleDetectionRequest])
+        } catch {
+            completion(nil)
+            return
+        }
+
+    }
+	
+    /// Detects rectangles from the given CVPixelBuffer/CVImageBuffer on iOS 11 and above.
+    ///
+    /// - Parameters:
+    ///   - pixelBuffer: The pixelBuffer to detect rectangles on.
+    ///   - completion: The biggest rectangle on the CVPixelBuffer
+    static func rectangle(forPixelBuffer pixelBuffer: CVPixelBuffer, completion: @escaping ((Quadrilateral?) -> Void)) {
+        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
+        VisionRectangleDetector.completeImageRequest(
+            for: imageRequestHandler,
+            width: CGFloat(CVPixelBufferGetWidth(pixelBuffer)),
+            height: CGFloat(CVPixelBufferGetHeight(pixelBuffer)),
+            completion: completion)
+    }
+    
+    /// Detects rectangles from the given image on iOS 11 and above.
+    ///
+    /// - Parameters:
+    ///   - image: The image to detect rectangles on.
+    /// - Returns: The biggest rectangle detected on the image.
+    static func rectangle(forImage image: CIImage, completion: @escaping ((Quadrilateral?) -> Void)) {
+        let imageRequestHandler = VNImageRequestHandler(ciImage: image, options: [:])
+        VisionRectangleDetector.completeImageRequest(
+            for: imageRequestHandler, width: image.extent.width,
+            height: image.extent.height, completion: completion)
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Edit/EditScanViewController.swift b/MiniScanner/Supporting Files/WeScan/Edit/EditScanViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..75e947a1e51be7526a599ca9cb3c0fbac1eb47d5
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Edit/EditScanViewController.swift	
@@ -0,0 +1,192 @@
+//
+//  EditScanViewController.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/12/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+protocol EditScanViewControllerDelegate:NSObjectProtocol {
+    func editScanViewControllerDidCancel(_ editScanViewController:EditScanViewController)
+    func editScanViewController(_ editScanViewController:EditScanViewController, finishedEditing item:ScannedItem)
+}
+
+/// The `EditScanViewController` offers an interface for the user to edit the detected quadrilateral.
+final class EditScanViewController: UIViewController {
+    
+    lazy private var imageView: UIImageView = {
+        let imageView = UIImageView()
+        imageView.clipsToBounds = true
+        imageView.isOpaque = true
+        imageView.image = image
+        imageView.backgroundColor = .black
+        imageView.contentMode = .scaleAspectFit
+        imageView.translatesAutoresizingMaskIntoConstraints = false
+        return imageView
+    }()
+    
+    lazy private var quadView: QuadrilateralView = {
+        let quadView = QuadrilateralView()
+        quadView.editable = true
+        quadView.translatesAutoresizingMaskIntoConstraints = false
+        return quadView
+    }()
+    
+    lazy private var doneButton: UIBarButtonItem = {
+        let title = NSLocalizedString("wescan.edit.button.done", tableName: nil, bundle: Bundle(for: EditScanViewController.self), value: "Done", comment: "A generic done button")
+        let button = UIBarButtonItem(title: title, style: .done, target: self, action: #selector(handleDone))
+        button.tintColor = navigationController?.navigationBar.tintColor
+        return button
+    }()
+
+    /// The image the quadrilateral was detected on.
+    private let image: UIImage?
+    
+    /// The detected quadrilateral that can be edited by the user. Uses the image's coordinates.
+    private var quad: Quadrilateral
+    
+    /// The object that acts as the delegate of the `EditScanViewController`.
+    weak public var delegate: EditScanViewControllerDelegate?
+    
+    private var scannedItem:ScannedItem
+    
+    private var zoomGestureController: ZoomGestureController!
+    
+    private var quadViewWidthConstraint = NSLayoutConstraint()
+    private var quadViewHeightConstraint = NSLayoutConstraint()
+    
+    // MARK: - Life Cycle
+    
+    init(scannedItem:ScannedItem) {
+        self.scannedItem = scannedItem
+        let scannedImage = scannedItem.originalImage?.retrieveImage()
+        self.image = scannedImage?.applyingPortraitOrientation()
+        
+        let quad = scannedItem.quad ?? EditScanViewController.defaultQuad(forImage: scannedImage)
+        self.quad = quad
+        super.init(nibName: nil, bundle: nil)
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        setupViews()
+        setupConstraints()
+        title = NSLocalizedString("wescan.edit.title", tableName: nil, bundle: Bundle(for: EditScanViewController.self), value: "Edit Scan", comment: "The title of the EditScanViewController")
+        navigationItem.rightBarButtonItem = doneButton
+        
+        zoomGestureController = ZoomGestureController(image: image, quadView: quadView)
+        
+        let touchDown = UILongPressGestureRecognizer(target: zoomGestureController, action: #selector(zoomGestureController.handle(pan:)))
+        touchDown.minimumPressDuration = 0
+        view.addGestureRecognizer(touchDown)
+    }
+    
+    override func viewDidLayoutSubviews() {
+        super.viewDidLayoutSubviews()
+        adjustQuadViewConstraints()
+        displayQuad()
+    }
+    
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        
+        // Work around for an iOS 11.2 bug where UIBarButtonItems don't get back to their normal state after being pressed.
+        navigationController?.navigationBar.tintAdjustmentMode = .normal
+        navigationController?.navigationBar.tintAdjustmentMode = .automatic
+    }
+    
+    // MARK: - Setups
+    
+    private func setupViews() {
+        view.addSubview(imageView)
+        view.addSubview(quadView)
+    }
+    
+    private func setupConstraints() {
+        let imageViewConstraints = [
+            imageView.topAnchor.constraint(equalTo: view.topAnchor),
+            imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+            view.bottomAnchor.constraint(equalTo: imageView.bottomAnchor),
+            view.leadingAnchor.constraint(equalTo: imageView.leadingAnchor)
+        ]
+
+        quadViewWidthConstraint = quadView.widthAnchor.constraint(equalToConstant: 0.0)
+        quadViewHeightConstraint = quadView.heightAnchor.constraint(equalToConstant: 0.0)
+        
+        let quadViewConstraints = [
+            quadView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
+            quadView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
+            quadViewWidthConstraint,
+            quadViewHeightConstraint
+        ]
+        
+        NSLayoutConstraint.activate(quadViewConstraints + imageViewConstraints)
+    }
+    
+    // MARK: - Actions
+    
+    @objc func handleDone() {
+        
+        guard let quad = quadView.quad, let image = image else {
+            // TODO: Return error
+            return
+        }
+        
+        let scaledQuad = quad.scale(quadView.bounds.size, image.size)
+        self.quad = scaledQuad
+        
+        var cartesianScaledQuad = scaledQuad.toCartesian(withHeight: image.size.height)
+        cartesianScaledQuad.reorganize()
+        
+        scannedItem.quad = scaledQuad
+        
+        self.delegate?.editScanViewController(self, finishedEditing: scannedItem)
+    }
+    
+    private func displayQuad() {
+        if let image = image {
+            let imageSize = image.size
+            let imageFrame = CGRect(origin: quadView.frame.origin, size: CGSize(width: quadViewWidthConstraint.constant, height: quadViewHeightConstraint.constant))
+            
+            let scaleTransform = CGAffineTransform.scaleTransform(forSize: imageSize, aspectFillInSize: imageFrame.size)
+            let transforms = [scaleTransform]
+            let transformedQuad = quad.applyTransforms(transforms)
+            
+            quadView.drawQuadrilateral(quad: transformedQuad, animated: false)
+        }
+    }
+    
+    /// The quadView should be lined up on top of the actual image displayed by the imageView.
+    /// Since there is no way to know the size of that image before run time, we adjust the constraints to make sure that the quadView is on top of the displayed image.
+    private func adjustQuadViewConstraints() {
+        if let image = image {
+            let frame = AVMakeRect(aspectRatio: image.size, insideRect: imageView.bounds)
+            quadViewWidthConstraint.constant = frame.size.width
+            quadViewHeightConstraint.constant = frame.size.height
+        }
+    }
+    
+    /// Generates a `Quadrilateral` object that's centered and one third of the size of the passed in image.
+    public static func defaultQuad(forImage image: UIImage?) -> Quadrilateral {
+        if let image = image {
+            let topLeft = CGPoint(x: image.size.width / 3.0, y: image.size.height / 3.0)
+            let topRight = CGPoint(x: 2.0 * image.size.width / 3.0, y: image.size.height / 3.0)
+            let bottomRight = CGPoint(x: 2.0 * image.size.width / 3.0, y: 2.0 * image.size.height / 3.0)
+            let bottomLeft = CGPoint(x: image.size.width / 3.0, y: 2.0 * image.size.height / 3.0)
+            
+            let quad = Quadrilateral(topLeft: topLeft, topRight: topRight, bottomRight: bottomRight, bottomLeft: bottomLeft)
+            
+            return quad
+        }
+        return Quadrilateral(topLeft: CGPoint.zero, topRight: CGPoint.zero, bottomRight: CGPoint.zero, bottomLeft: CGPoint.zero)
+    }
+
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Edit/ZoomGestureController.swift b/MiniScanner/Supporting Files/WeScan/Edit/ZoomGestureController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e11a19d7e7c84a53124e2014cc574555bc320f08
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Edit/ZoomGestureController.swift	
@@ -0,0 +1,61 @@
+//
+//  ZoomGestureController.swift
+//  WeScan
+//
+//  Created by Bobo on 5/31/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+import UIKit
+
+final class ZoomGestureController {
+    
+    private let image: UIImage?
+    private let quadView: QuadrilateralView
+    
+    init(image: UIImage?, quadView: QuadrilateralView) {
+        self.image = image
+        self.quadView = quadView
+    }
+    
+    private var previousPanPosition: CGPoint?
+    private var closestCorner: CornerPosition?
+    
+    @objc func handle(pan: UIGestureRecognizer) {
+        guard let drawnQuad = quadView.quad, let image = image else {
+            return
+        }
+        
+        guard pan.state != .ended else {
+            self.previousPanPosition = nil
+            self.closestCorner = nil
+            quadView.resetHighlightedCornerViews()
+            return
+        }
+        
+        let position = pan.location(in: quadView)
+        
+        let previousPanPosition = self.previousPanPosition ?? position
+        let closestCorner = self.closestCorner ?? position.closestCornerFrom(quad: drawnQuad)
+        
+        let offset = CGAffineTransform(translationX: position.x - previousPanPosition.x, y: position.y - previousPanPosition.y)
+        let cornerView = quadView.cornerViewForCornerPosition(position: closestCorner)
+        let draggedCornerViewCenter = cornerView.center.applying(offset)
+        
+        quadView.moveCorner(cornerView: cornerView, atPoint: draggedCornerViewCenter)
+        
+        self.previousPanPosition = position
+        self.closestCorner = closestCorner
+        
+        let scale = image.size.width / quadView.bounds.size.width
+        let scaledDraggedCornerViewCenter = CGPoint(x: draggedCornerViewCenter.x * scale, y: draggedCornerViewCenter.y * scale)
+        guard let zoomedImage = image.scaledImage(atPoint: scaledDraggedCornerViewCenter, scaleFactor: 2.5, targetSize: quadView.bounds.size) else {
+            return
+        }
+        
+        quadView.highlightCornerAtPosition(position: closestCorner, with: zoomedImage)
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/AVCaptureVideoOrientation+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/AVCaptureVideoOrientation+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7587c0664d7de77665a39c20bef4e4497a7cd2e8
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/AVCaptureVideoOrientation+Utils.swift	
@@ -0,0 +1,35 @@
+//
+//  UIDeviceOrientation+Utils.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/13/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+import UIKit
+
+extension AVCaptureVideoOrientation {
+    
+    /// Maps UIDeviceOrientation to AVCaptureVideoOrientation
+    init?(deviceOrientation: UIDeviceOrientation) {
+        switch deviceOrientation {
+        case .portrait:
+            self.init(rawValue: AVCaptureVideoOrientation.portrait.rawValue)
+        case .portraitUpsideDown:
+            self.init(rawValue: AVCaptureVideoOrientation.portraitUpsideDown.rawValue)
+        case .landscapeLeft:
+            self.init(rawValue: AVCaptureVideoOrientation.landscapeLeft.rawValue)
+        case .landscapeRight:
+            self.init(rawValue: AVCaptureVideoOrientation.landscapeRight.rawValue)
+        case .faceUp:
+            self.init(rawValue: AVCaptureVideoOrientation.portrait.rawValue)
+        case .faceDown:
+            self.init(rawValue: AVCaptureVideoOrientation.portraitUpsideDown.rawValue)
+        default:
+            self.init(rawValue: AVCaptureVideoOrientation.portrait.rawValue)
+        }
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/Array+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/Array+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..79214aba530e827255f25580af9504c388442b75
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/Array+Utils.swift	
@@ -0,0 +1,23 @@
+//
+//  Array+Utils.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/8/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Vision
+import Foundation
+
+extension Array where Element == Quadrilateral {
+    
+    /// Finds the biggest rectangle within an array of `Quadrilateral` objects.
+    func biggest() -> Quadrilateral? {
+        let biggestRectangle = self.max(by: { (rect1, rect2) -> Bool in
+            return rect1.perimeter < rect2.perimeter
+        })
+        
+        return biggestRectangle
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/CGAffineTransform+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/CGAffineTransform+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..96bf7de92b1f9de55db5a875e5b775c2cd6a715a
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/CGAffineTransform+Utils.swift	
@@ -0,0 +1,35 @@
+//
+//  CGAffineTransform+Utils.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/15/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+
+extension CGAffineTransform {
+    
+    /// Convenience function to easily get a scale `CGAffineTransform` instance.
+    ///
+    /// - Parameters:
+    ///   - fromSize: The size that needs to be transformed to fit (aspect fill) in the other given size.
+    ///   - toSize: The size that should be matched by the `fromSize` parameter.
+    /// - Returns: The transform that will make the `fromSize` parameter fir (aspect fill) inside the `toSize` parameter.
+    static func scaleTransform(forSize fromSize: CGSize, aspectFillInSize toSize: CGSize) -> CGAffineTransform {
+        let scale = max(toSize.width / fromSize.width, toSize.height / fromSize.height)
+        return CGAffineTransform(scaleX: scale, y: scale)
+    }
+    
+    /// Convenience function to easily get a translate `CGAffineTransform` instance.
+    ///
+    /// - Parameters:
+    ///   - fromRect: The rect which center needs to be translated to the center of the other passed in rect.
+    ///   - toRect: The rect that should be matched.
+    /// - Returns: The transform that will translate the center of the `fromRect` parameter to the center of the `toRect` parameter.
+    static func translateTransform(fromCenterOfRect fromRect: CGRect, toCenterOfRect toRect: CGRect) -> CGAffineTransform {
+        let translate = CGPoint(x: toRect.midX - fromRect.midX, y: toRect.midY - fromRect.midY)
+        return CGAffineTransform(translationX: translate.x, y: translate.y)
+    }
+        
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/CGPoint+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/CGPoint+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..71a94ff39b76efe7630b6e16ec7b30e5e5945d19
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/CGPoint+Utils.swift	
@@ -0,0 +1,69 @@
+//
+//  CGPoint+Utils.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/9/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+
+extension CGPoint {
+    
+    /// Returns a rectangle of a given size surounding the point.
+    ///
+    /// - Parameters:
+    ///   - size: The size of the rectangle that should surround the points.
+    /// - Returns: A `CGRect` instance that surrounds this instance of `CGpoint`.
+    func surroundingSquare(withSize size: CGFloat) -> CGRect {
+        return CGRect(x: x - size / 2.0, y: y - size / 2.0, width: size, height: size)
+    }
+    
+    /// Checks wether this point is within a given distance of another point.
+    ///
+    /// - Parameters:
+    ///   - delta: The minimum distance to meet for this distance to return true.
+    ///   - point: The second point to compare this instance with.
+    /// - Returns: True if the given `CGPoint` is within the given distance of this instance of `CGPoint`.
+    func isWithin(delta: CGFloat, ofPoint point: CGPoint) -> Bool {
+        return (abs(x - point.x) <= delta) && (abs(y - point.y) <= delta)
+    }
+    
+    /// Returns the same `CGPoint` in the cartesian coordinate system.
+    ///
+    /// - Parameters:
+    ///   - height: The height of the bounds this points belong to, in the current coordinate system.
+    /// - Returns: The same point in the cartesian coordinate system.
+    func cartesian(withHeight height: CGFloat) -> CGPoint {
+        return CGPoint(x: x, y: height - y)
+    }
+    
+    /// Returns the distance between two points
+    func distanceTo(point: CGPoint) -> CGFloat {
+        return hypot((self.x - point.x), (self.y - point.y))
+    }
+    
+    /// Returns the closest corner from the point
+    func closestCornerFrom(quad: Quadrilateral) -> CornerPosition {
+        var smallestDistance = distanceTo(point: quad.topLeft)
+        var closestCorner = CornerPosition.topLeft
+        
+        if distanceTo(point: quad.topRight) < smallestDistance {
+            smallestDistance = distanceTo(point: quad.topRight)
+            closestCorner = .topRight
+        }
+        
+        if distanceTo(point: quad.bottomRight) < smallestDistance {
+            smallestDistance = distanceTo(point: quad.bottomRight)
+            closestCorner = .bottomRight
+        }
+        
+        if distanceTo(point: quad.bottomLeft) < smallestDistance {
+            smallestDistance = distanceTo(point: quad.bottomLeft)
+            closestCorner = .bottomLeft
+        }
+        
+        return closestCorner
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/CGRect+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/CGRect+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0b16e2555113b9de2c85a580d48553e62b339525
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/CGRect+Utils.swift	
@@ -0,0 +1,27 @@
+//
+//  CGRect+Utils.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/26/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+
+extension CGRect {
+    
+    /// Returns a new `CGRect` instance scaled up or down, with the same center as the original `CGRect` instance.
+    /// - Parameters:
+    ///   - ratio: The ratio to scale the `CGRect` instance by.
+    /// - Returns: A new instance of `CGRect` scaled by the given ratio and centered with the original rect.
+    func scaleAndCenter(withRatio ratio: CGFloat) -> CGRect {
+        let scaleTransform = CGAffineTransform(scaleX: ratio, y: ratio)
+        let scaledRect = applying(scaleTransform)
+        
+        let translateTransform = CGAffineTransform(translationX: origin.x * (1 - ratio) + (width - scaledRect.width) / 2.0, y: origin.y * (1 - ratio) + (height - scaledRect.height) / 2.0)
+        let translatedRect = scaledRect.applying(translateTransform)
+        
+        return translatedRect
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/CIImage+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/CIImage+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c34c14841dc442be542cd1f4a6f6cf736b591029
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/CIImage+Utils.swift	
@@ -0,0 +1,40 @@
+//
+//  CIImage+Utils.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 14/11/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import CoreImage
+import Foundation
+import UIKit
+
+extension CIImage {
+    /// Applies an AdaptiveThresholding filter to the image, which enhances the image and makes it completely gray scale
+    func applyingAdaptiveThreshold() -> UIImage? {
+        guard let colorKernel = CIColorKernel(source:
+            """
+            kernel vec4 color(__sample pixel, float inputEdgeO, float inputEdge1)
+            {
+                float luma = dot(pixel.rgb, vec3(0.2126, 0.7152, 0.0722));
+                float threshold = smoothstep(inputEdgeO, inputEdge1, luma);
+                return vec4(threshold, threshold, threshold, 1.0);
+            }
+            """
+            ) else { return nil }
+        
+        let firstInputEdge = 0.25
+        let secondInputEdge = 0.75
+        
+        let arguments: [Any] = [self, firstInputEdge, secondInputEdge]
+
+        guard let enhancedCIImage = colorKernel.apply(extent: self.extent, arguments: arguments) else { return nil }
+
+        if let cgImage = CIContext(options: nil).createCGImage(enhancedCIImage, from: enhancedCIImage.extent) {
+            return UIImage(cgImage: cgImage)
+        } else {
+            return UIImage(ciImage: enhancedCIImage, scale: 1.0, orientation: .up)
+        }
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/UIImage+Orientation.swift b/MiniScanner/Supporting Files/WeScan/Extensions/UIImage+Orientation.swift
new file mode 100644
index 0000000000000000000000000000000000000000..603618b39ef613687a7437c2f18d0b677aa09993
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/UIImage+Orientation.swift	
@@ -0,0 +1,99 @@
+//
+//  UIImage+Orientation.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/16/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+extension UIImage {
+    
+    /// Returns the same image with a portrait orientation.
+    func applyingPortraitOrientation() -> UIImage {
+        switch imageOrientation {
+        case .up:
+            return rotated(by: Measurement(value: Double.pi, unit: .radians), options: []) ?? self
+        case .down:
+            return rotated(by: Measurement(value: Double.pi, unit: .radians), options: [.flipOnVerticalAxis, .flipOnHorizontalAxis]) ?? self
+        case .left:
+            return self
+        case .right:
+            return rotated(by: Measurement(value: Double.pi / 2.0, unit: .radians), options: []) ?? self
+        default:
+            return self
+        }
+    }
+    
+    /// Data structure to easily express rotation options.
+    struct RotationOptions: OptionSet {
+        let rawValue: Int
+        
+        static let flipOnVerticalAxis = RotationOptions(rawValue: 1)
+        static let flipOnHorizontalAxis = RotationOptions(rawValue: 2)
+    }
+    
+    /// Rotate the image by the given angle, and perform other transformations based on the passed in options.
+    ///
+    /// - Parameters:
+    ///   - rotationAngle: The angle to rotate the image by.
+    ///   - options: Options to apply to the image.
+    /// - Returns: The new image rotated and optentially flipped (@see options).
+    func rotated(by rotationAngle: Measurement<UnitAngle>, options: RotationOptions = []) -> UIImage? {
+        guard let cgImage = self.cgImage else { return nil }
+        
+        let rotationInRadians = CGFloat(rotationAngle.converted(to: .radians).value)
+        let transform = CGAffineTransform(rotationAngle: rotationInRadians)
+        let cgImageSize = CGSize(width: cgImage.width, height: cgImage.height)
+        var rect = CGRect(origin: .zero, size: cgImageSize).applying(transform)
+        rect.origin = .zero
+        
+        let format = UIGraphicsImageRendererFormat()
+        format.scale = 1
+        
+        let renderer = UIGraphicsImageRenderer(size: rect.size, format: format)
+        
+        let image = renderer.image { renderContext in
+            renderContext.cgContext.translateBy(x: rect.midX, y: rect.midY)
+            renderContext.cgContext.rotate(by: rotationInRadians)
+            
+            let x = options.contains(.flipOnVerticalAxis) ? -1.0 : 1.0
+            let y = options.contains(.flipOnHorizontalAxis) ? 1.0 : -1.0
+            renderContext.cgContext.scaleBy(x: CGFloat(x), y: CGFloat(y))
+            
+            let drawRect = CGRect(origin: CGPoint(x: -cgImageSize.width / 2.0, y: -cgImageSize.height / 2.0), size: cgImageSize)
+            renderContext.cgContext.draw(cgImage, in: drawRect)
+        }
+        
+        return image
+    }
+    
+    /// Rotates the image based on the information collected by the accelerometer
+    func withFixedOrientation() -> UIImage {
+        var imageAngle: Double = 0.0
+        
+        var shouldRotate = true
+        switch CaptureSession.current.editImageOrientation {
+        case .up:
+            shouldRotate = false
+        case .left:
+            imageAngle = Double.pi / 2
+        case .right:
+            imageAngle = -(Double.pi / 2)
+        case .down:
+            imageAngle = Double.pi
+        default:
+            shouldRotate = false
+        }
+        
+        if shouldRotate,
+            let finalImage = rotated(by: Measurement(value: imageAngle, unit: .radians)) {
+            return finalImage
+        } else {
+            return self
+        }
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/UIImage+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/UIImage+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0a92f7384cd5e627c2938e5dac7369e514710a2d
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/UIImage+Utils.swift	
@@ -0,0 +1,80 @@
+//
+//  UIImage+Utils.swift
+//  WeScan
+//
+//  Created by Bobo on 5/25/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+extension UIImage {
+    
+    /// Draws a new cropped and scaled (zoomed in) image.
+    ///
+    /// - Parameters:
+    ///   - point: The center of the new image.
+    ///   - scaleFactor: Factor by which the image should be zoomed in.
+    ///   - size: The size of the rect the image will be displayed in.
+    /// - Returns: The scaled and cropped image.
+    func scaledImage(atPoint point: CGPoint, scaleFactor: CGFloat, targetSize size: CGSize) -> UIImage? {
+      
+        guard let cgImage = self.cgImage else {
+            return nil
+        }
+        
+        let scaledSize = CGSize(width: size.width / scaleFactor, height: size.height / scaleFactor)
+        let midX = point.x - scaledSize.width / 2.0
+        let midY = point.y - scaledSize.height / 2.0
+        let newRect = CGRect(x: midX, y: midY, width: scaledSize.width, height: scaledSize.height)
+        
+        guard let croppedImage = cgImage.cropping(to: newRect) else {
+            return nil
+        }
+        
+        return UIImage(cgImage: croppedImage)
+    }
+    
+    func resizeImage(newWidth: CGFloat) -> UIImage? {
+        let scale = newWidth / self.size.width
+        let newHeight = self.size.height * scale
+        UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
+        self.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
+        let newImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return newImage
+    }
+    
+
+    /// Function gathered from [here](https://stackoverflow.com/questions/44462087/how-to-convert-a-uiimage-to-a-cvpixelbuffer) to convert UIImage to CVPixelBuffer
+    ///
+    /// - Returns: new [CVPixelBuffer](apple-reference-documentation://hsVf8OXaJX)
+    func pixelBuffer() -> CVPixelBuffer? {
+        let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
+        var pixelBufferOpt: CVPixelBuffer?
+        let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(self.size.width), Int(self.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBufferOpt)
+        guard status == kCVReturnSuccess, let pixelBuffer = pixelBufferOpt else {
+            return nil
+        }
+
+        CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
+        let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer)
+
+        let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
+        guard let context = CGContext(data: pixelData, width: Int(self.size.width), height: Int(self.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) else {
+          return nil
+        }
+
+        context.translateBy(x: 0, y: self.size.height)
+        context.scaleBy(x: 1.0, y: -1.0)
+
+        UIGraphicsPushContext(context)
+        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
+        UIGraphicsPopContext()
+        CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
+
+        return pixelBuffer
+    }
+
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Extensions/URL+Utils.swift b/MiniScanner/Supporting Files/WeScan/Extensions/URL+Utils.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a99599072e4c12f10b51dee9e5992019eb95b9fe
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Extensions/URL+Utils.swift	
@@ -0,0 +1,32 @@
+//
+//  URL+Utils.swift
+//  WeScan
+//
+//  Created by Juan Luis Montero Roca on 19/05/2020.
+//  Copyright © 2020 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+extension URL {
+    func saveImage(image: UIImage?) -> URL? {
+        if let jpgRepresentation = image?.jpegData(compressionQuality: 1.0) {
+            do  {
+                try jpgRepresentation.write(to: self,
+                                            options: .atomic)
+                return self
+            } catch let err {
+                print("Saving file resulted in error: ", err)
+            }
+        }
+        return nil
+    }
+    
+    func retrieveImage() -> UIImage? {
+        if let fileData = FileManager.default.contents(atPath: path), let image = UIImage(data: fileData)?.withFixedOrientation() {
+            return image
+        }
+        return nil
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/ImageScannerController.swift b/MiniScanner/Supporting Files/WeScan/ImageScannerController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..31b8e24abf0d4656f001f452eb86e5f6db5c2f07
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/ImageScannerController.swift	
@@ -0,0 +1,110 @@
+//
+//  ImageScannerController.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/12/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+public struct ImageScannerOptions {
+    public let scanMultipleItems:Bool
+    public let allowAutoScan:Bool
+    public let allowTapToFocus:Bool
+    public let defaultColorRenderOption:ScannedItemColorOption
+    
+    public init(scanMultipleItems:Bool = true, allowAutoScan:Bool = true, allowTapToFocus:Bool = true, defaultColorRenderOption:ScannedItemColorOption = .color) {
+        self.scanMultipleItems = scanMultipleItems
+        self.allowAutoScan = allowAutoScan
+        self.allowTapToFocus = allowTapToFocus
+        self.defaultColorRenderOption = defaultColorRenderOption
+    }
+}
+
+public protocol ImageScannerControllerDelegate: NSObjectProtocol {
+    func imageScannerController(_ scanner: ImageScannerController,
+                                didFinishWithSession session:MultiPageScanSession)
+    
+    func imageScannerControllerDidCancel(_ scanner: ImageScannerController)
+    
+    func imageScannerController(_ scanner: ImageScannerController,
+                                didFailWithError error: Error)
+}
+
+public final class ImageScannerController: UINavigationController {
+    // MARK: - Properties
+    weak public var imageScannerDelegate: ImageScannerControllerDelegate?
+    
+    // MARK: - Life Cycle
+    internal let blackFlashView: UIView = {
+        let view = UIView()
+        view.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
+        view.isHidden = true
+        view.translatesAutoresizingMaskIntoConstraints = false
+        return view
+    }()
+    
+    public required init(options: ImageScannerOptions?) {
+        let scannerViewController = ScannerViewController(scanSession: nil, options: options)
+        super.init(rootViewController: scannerViewController)
+        scannerViewController.delegate = self
+        navigationBar.tintColor = .white
+        navigationBar.isTranslucent = false
+        self.view.addSubview(blackFlashView)
+        setupConstraints()
+    }
+    
+    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+    }
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    private func setupConstraints() {
+        let blackFlashViewConstraints = [
+            blackFlashView.topAnchor.constraint(equalTo: view.topAnchor),
+            blackFlashView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+            view.bottomAnchor.constraint(equalTo: blackFlashView.bottomAnchor),
+            view.trailingAnchor.constraint(equalTo: blackFlashView.trailingAnchor)
+        ]
+        
+        NSLayoutConstraint.activate(blackFlashViewConstraints)
+    }
+    
+    override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
+        return .portrait
+    }
+    
+}
+
+extension ImageScannerController: ScannerViewControllerDelegate{
+    
+    func scannerViewController(_ scannerViewController: ScannerViewController,
+                               didFail withError: Error) {
+        self.imageScannerDelegate?.imageScannerController(self, didFailWithError: withError)
+    }
+    
+    func scannerViewControllerDidCancel(_ scannerViewController: ScannerViewController) {
+        self.imageScannerDelegate?.imageScannerControllerDidCancel(self)
+    }
+    
+    func scannerViewController(_ scannerViewController: ScannerViewController,
+                               reviewItems inSession: MultiPageScanSession) {
+        
+        let multipageScanViewController = MultiPageScanSessionViewController(scanSession: inSession)
+        multipageScanViewController.delegate = self
+        self.pushViewController(multipageScanViewController, animated: true)
+    }
+}
+
+extension ImageScannerController: MultiPageScanSessionViewControllerDelegate {
+    
+    public func multiPageScanSessionViewController(_ multiPageScanSessionViewController: MultiPageScanSessionViewController,
+                                                   finished session: MultiPageScanSession) {
+        self.imageScannerDelegate?.imageScannerController(self, didFinishWithSession: session)
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/MultiPageSession/MultiPageScanSession.swift b/MiniScanner/Supporting Files/WeScan/MultiPageSession/MultiPageScanSession.swift
new file mode 100644
index 0000000000000000000000000000000000000000..86039cf7c84fca24565b6472bff397904dc9562f
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/MultiPageSession/MultiPageScanSession.swift	
@@ -0,0 +1,76 @@
+//
+//  MultiPageScanSession.swift
+//  WeScan
+//
+//  Created by Enrique Rodriguez on 07/01/2019.
+//  Copyright © 2019 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+public enum ScannedItemColorOption{
+    case color
+    case grayscale
+}
+
+/// Data structure containing information about one page scanned
+public class ScannedItem{
+    
+    /// The original image taken by the user, prior to the cropping applied by WeScan.
+    var originalImage:URL?
+
+    /// The detected rectangle which was used to generate the `scannedImage`.
+    var quad:Quadrilateral?
+    
+    /// The rotation applied to the resulting image
+    var rotation:Double = 0.0
+    
+    /// The color preference for the output of this image
+    var colorOption:ScannedItemColorOption = .color
+    
+    /// The deskewed and cropped orignal image using the detected rectangle, without any filters.
+    var renderedImage:URL? = nil
+
+    public init(originalImage:UIImage, quad:Quadrilateral? = nil, colorOption:ScannedItemColorOption = .color) {
+        self.originalImage = filePath().saveImage(image: originalImage.withFixedOrientation())
+        self.quad = quad
+        self.colorOption = colorOption
+    }
+    
+    public func render(completion: @escaping (_ image:URL?)->Void){
+        ScannedItemRenderer().render(scannedItem: self) { (image) in
+            self.renderedImage = self.filePath().saveImage(image: image?.withFixedOrientation())
+            completion(self.renderedImage)
+        }
+    }
+    public func getRender(completion: @escaping (_ image:UIImage?)->Void){
+        ScannedItemRenderer().render(scannedItem: self) { (image) in
+            self.renderedImage = self.filePath().saveImage(image: image?.withFixedOrientation())
+            completion(image)
+        }
+    }
+}
+
+public class MultiPageScanSession {
+    
+    public private(set) var scannedItems:Array<ScannedItem> = []
+    
+    public init(){}
+    
+    public func add(item:ScannedItem){
+        self.scannedItems.append(item)
+    }
+    
+    public func remove(index:Int){
+        self.scannedItems.remove(at: index)
+    }
+    
+}
+
+extension ScannedItem {
+    private func filePath() -> URL {
+        let documentURL = URL(fileURLWithPath: NSTemporaryDirectory())
+        return documentURL.appendingPathComponent("\(UUID().uuidString).jpg")
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/MultiPageSession/MultiPageScanSessionViewController.swift b/MiniScanner/Supporting Files/WeScan/MultiPageSession/MultiPageScanSessionViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b689c482f9f39ebf6b5f1529ef9a561312de69fb
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/MultiPageSession/MultiPageScanSessionViewController.swift	
@@ -0,0 +1,251 @@
+//
+//  MultiPageScanSessionViewController.swift
+//  WeScan
+//
+//  Created by Enrique Rodriguez on 07/01/2019.
+//  Copyright © 2019 WeTransfer. All rights reserved.
+//
+
+import UIKit
+
+public protocol MultiPageScanSessionViewControllerDelegate:NSObjectProtocol {
+    func multiPageScanSessionViewController(_ multiPageScanSessionViewController:MultiPageScanSessionViewController, finished session:MultiPageScanSession)
+}
+
+public class MultiPageScanSessionViewController: UIViewController {
+
+    private var scanSession:MultiPageScanSession
+    private var pages:Array<ScannedPageViewController> = []
+    
+    weak public var delegate:MultiPageScanSessionViewControllerDelegate?
+    
+    lazy private var saveButton: UIBarButtonItem = {
+        let title = NSLocalizedString("wescan.edit.button.save", tableName: nil, bundle: Bundle(for: MultiPageScanSessionViewController.self), value: "Save", comment: "Save button")
+        let button = UIBarButtonItem(title: title, style: .done, target: self, action: #selector(handleSave))
+        button.tintColor = navigationController?.navigationBar.tintColor
+        return button
+    }()
+    
+    lazy private var pageController: UIPageViewController = {
+        let pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
+        pageController.dataSource = self
+        pageController.delegate = self
+        return pageController
+    }()
+    
+    lazy private var pageControl: UIPageControl = {
+        let pageControl = UIPageControl()
+        pageControl.translatesAutoresizingMaskIntoConstraints = false
+        return pageControl
+    }()
+    
+    public init(scanSession:MultiPageScanSession){
+        self.scanSession = scanSession
+        super.init(nibName: nil, bundle: nil)
+        setupPages()
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) should not be called for this class")
+    }
+    
+    // MARK: - View lifecycle
+    
+    override public func viewDidLoad() {
+        super.viewDidLoad()
+        self.view.backgroundColor = UIColor.black
+        self.setupViews()
+    }
+    
+    override public func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        self.navigationController?.setNavigationBarHidden(false, animated: true)
+        self.navigationController?.setToolbarHidden(false, animated: true)
+        navigationController?.interactivePopGestureRecognizer?.isEnabled = false
+    }
+    
+    // MARK: - Private
+    
+    private func setupPages(){
+        self.scanSession.scannedItems.forEach { (scannedItem) in
+            let vc = ScannedPageViewController(scannedItem: scannedItem)
+            vc.view.isUserInteractionEnabled = false
+            self.pages.append(vc)
+        }
+        self.gotoLastPage()
+    }
+    
+    private func setupViews(){
+        // Page Controller
+        let constraints = [self.pageController.view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0.0),
+                           self.pageController.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0.0),
+                           self.pageController.view.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0.0),
+                           self.pageController.view.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0.0)]
+        self.view.addSubview(self.pageController.view)
+        NSLayoutConstraint.activate(constraints)
+        self.addChild(self.pageController)
+        
+        // Page Control
+        let pageControlConstraints = [self.pageControl.bottomAnchor.constraint(equalTo: self.view!.bottomAnchor, constant:0.0),
+                                      self.pageControl.centerXAnchor.constraint(equalTo: self.view.centerXAnchor)]
+        self.view.addSubview(self.pageControl)
+        NSLayoutConstraint.activate(pageControlConstraints)
+        
+        // Navigation
+        self.navigationController?.navigationBar.isTranslucent = false
+        self.navigationItem.rightBarButtonItem = self.saveButton
+        
+        // Toolbar
+        self.navigationController?.toolbar.isTranslucent = false
+        let editItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(handleEdit))
+        let deleteItem = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(handleTrash))
+        let rotateIconImage = UIImage(named: "rotate", in: Bundle(for: MultiPageScanSessionViewController.self), compatibleWith: nil)
+        let rotateItem = UIBarButtonItem(image: rotateIconImage, style: .plain, target: self, action: #selector(handleRotate))
+        
+        let flexibleItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
+        
+        self.toolbarItems = [editItem, flexibleItem, rotateItem, flexibleItem, deleteItem]
+    }
+    
+    private func getCurrentViewController()->ScannedPageViewController{
+        return self.pageController.viewControllers!.first! as! ScannedPageViewController
+    }
+    
+    private func getCurrentPageIndex()->Int?{
+        let currentViewController = self.getCurrentViewController()
+        return self.pages.firstIndex(of:currentViewController)
+    }
+    
+    private func getCurrentItem()->ScannedItem?{
+        if let currentIndex = self.getCurrentPageIndex(){
+            return self.scanSession.scannedItems[currentIndex]
+        }
+        return nil
+    }
+    
+    private func updateTitle(index:Int){
+        self.title = "\(index + 1) / \(self.pages.count)"
+    }
+    
+    private func gotoLastPage(direction:UIPageViewController.NavigationDirection? = .forward){
+        let lastIndex = self.pages.count - 1
+        self.gotoPage(index: lastIndex, direction: direction)
+    }
+    
+    private func gotoPage(index:Int, direction:UIPageViewController.NavigationDirection? = .forward){
+        self.pageController.setViewControllers([self.pages[index]], direction: direction!, animated: true, completion: nil)
+        self.pageControl.numberOfPages = self.pages.count
+        self.pageControl.currentPage = index
+        self.updateTitle(index: index)
+    }
+    
+    private func trashCurrentPage(){
+        if let currentIndex = self.getCurrentPageIndex(){
+            self.scanSession.remove(index: currentIndex)
+            self.pages.remove(at: currentIndex)
+            if (self.scanSession.scannedItems.count > 0){
+                let previousIndex  = currentIndex - 1
+                let newIndex = (previousIndex >= 0 ? previousIndex : 0)
+                let direction:UIPageViewController.NavigationDirection = (newIndex == 0 ? .forward : .reverse)
+                self.gotoPage(index: newIndex, direction: direction)
+            } else {
+                self.navigationController?.popViewController(animated: true)
+            }
+        }
+    }
+    
+    // MARK: Button handlers
+    
+    @objc private func handleSave(){
+        self.delegate?.multiPageScanSessionViewController(self, finished: self.scanSession)
+    }
+    
+    @objc private func handleRotate(){
+        if let currentItem = self.getCurrentItem(){
+            currentItem.rotation -= 90.0
+            self.getCurrentViewController().reRender(item: currentItem)
+        }
+    }
+    
+    @objc private func handleTrash(){
+        let alertController = UIAlertController(title: "Confirm",
+                                                message: "Are you sure you want to delete this page?",
+                                                preferredStyle: .alert)
+        let okAction = UIAlertAction(title: "Delete", style: .destructive) { (action) in
+            self.trashCurrentPage()
+        }
+        
+        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
+        alertController.addAction(okAction)
+        alertController.addAction(cancelAction)
+        self.present(alertController, animated: true, completion: nil)
+    }
+    
+    @objc private func handleEdit(){
+        if let currentIndex = self.getCurrentPageIndex(){
+            let currentItem = self.scanSession.scannedItems[currentIndex]
+            
+            let editViewController = EditScanViewController(scannedItem: currentItem)
+            editViewController.delegate = self
+            let navController = UINavigationController(rootViewController: editViewController)
+            self.present(navController, animated: true, completion: nil)
+        } else {
+            fatalError("Current viewcontroller cannot be found")
+        }
+    }
+}
+
+extension MultiPageScanSessionViewController:EditScanViewControllerDelegate {
+
+    func editScanViewControllerDidCancel(_ editScanViewController: EditScanViewController) {
+        self.dismiss(animated: true, completion: nil)
+    }
+    
+    func editScanViewController(_ editScanViewController: EditScanViewController, finishedEditing item: ScannedItem) {
+        self.dismiss(animated: true, completion: nil)
+        let currentViewController = self.getCurrentViewController()
+        currentViewController.reRender(item: item)
+    }
+}
+
+extension MultiPageScanSessionViewController:UIPageViewControllerDataSource{
+    
+    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
+        if let index = pages.firstIndex(of: (viewController as! ScannedPageViewController)){
+            let previousIndex = index - 1
+            if (previousIndex >= 0){
+                return self.pages[previousIndex]
+            }
+        }
+        return nil
+    }
+    
+    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
+        if let index = pages.firstIndex(of: (viewController as! ScannedPageViewController)){
+            let nextIndex = index + 1
+            if (nextIndex < pages.count){
+                return self.pages[nextIndex]
+            }
+        }
+        return nil
+    }
+    
+}
+
+extension MultiPageScanSessionViewController:UIPageViewControllerDelegate{
+    
+    public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
+        
+        guard completed else { return }
+        
+        let currentViewController = self.getCurrentViewController()
+        let index = self.pages.firstIndex(of:currentViewController)
+        
+        if let index = index {
+            self.updateTitle(index:index)
+            self.pageControl.currentPage = index
+        }
+    }
+    
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/MultiPageSession/ScannedPageViewController.swift b/MiniScanner/Supporting Files/WeScan/MultiPageSession/ScannedPageViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..73a7b05f01362e055b2591352bd16118b4faa398
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/MultiPageSession/ScannedPageViewController.swift	
@@ -0,0 +1,94 @@
+//
+//  ScannedPageViewController.swift
+//  WeScan
+//
+//  Created by Enrique Rodriguez on 07/01/2019.
+//  Copyright © 2019 WeTransfer. All rights reserved.
+//
+
+import UIKit
+
+class ScannedPageViewController: UIViewController {
+
+    private var scannedItem:ScannedItem
+    private var renderedImageView:UIImageView!
+    private var activityIndicator:UIActivityIndicatorView!
+    
+    init(scannedItem:ScannedItem){
+        self.scannedItem = scannedItem
+        super.init(nibName: nil, bundle: nil)
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) should not be called for this class")
+    }
+    
+    // MARK: - View lifecycle
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.setupViews()
+    }
+        
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        self.render()
+    }
+    
+    override func viewDidDisappear(_ animated: Bool) {
+        self.renderedImageView.image = nil
+        super.viewDidDisappear(animated)
+    }
+
+    // MARK: - Private methods
+    
+    private func setupViews(){
+        // Image View
+        self.renderedImageView = UIImageView(image: nil)
+        self.renderedImageView.translatesAutoresizingMaskIntoConstraints = false
+        self.renderedImageView.contentMode = .scaleAspectFit
+        
+        let constraints = [self.renderedImageView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0.0),
+                           self.renderedImageView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0.0),
+                           self.renderedImageView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0.0),
+                           self.renderedImageView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0.0)]
+        self.view.addSubview(self.renderedImageView)
+        NSLayoutConstraint.activate(constraints)
+        
+        // Spinner
+        self.activityIndicator = UIActivityIndicatorView(style: .white)
+        self.activityIndicator.startAnimating()
+        self.activityIndicator.hidesWhenStopped = true
+        self.activityIndicator.translatesAutoresizingMaskIntoConstraints = false
+        let activityIndicatorConstraints = [self.activityIndicator.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
+                                            self.activityIndicator.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)]
+        self.view.addSubview(activityIndicator)
+        NSLayoutConstraint.activate(activityIndicatorConstraints)
+    }
+    
+    // MARK: - Public methods
+    
+    public func reRender(item:ScannedItem){
+        self.renderedImageView.image = nil
+        self.scannedItem.renderedImage = nil
+        self.scannedItem = item
+        self.render()
+    }
+    
+    public func render(){
+        if (self.renderedImageView.image == nil){
+            if self.scannedItem.renderedImage != nil{
+                self.renderedImageView.image = self.scannedItem.renderedImage?.retrieveImage()
+                self.activityIndicator.stopAnimating()
+            } else {
+                self.activityIndicator.isHidden = false
+                self.activityIndicator.startAnimating()
+                
+                scannedItem.render { (image) in
+                    self.renderedImageView.image = image?.retrieveImage()
+                    self.activityIndicator.stopAnimating()
+                }
+            }
+        }
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Protocols/CaptureDevice.swift b/MiniScanner/Supporting Files/WeScan/Protocols/CaptureDevice.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fd685a879cd6fd8be64dadf09551971f3a1b9d8c
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Protocols/CaptureDevice.swift	
@@ -0,0 +1,63 @@
+//
+//  CaptureDevice.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 28/11/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+
+protocol CaptureDevice: class {
+    func unlockForConfiguration()
+    func lockForConfiguration() throws
+    
+    var torchMode: AVCaptureDevice.TorchMode { get set }
+    var isTorchAvailable: Bool { get }
+    
+    var focusMode: AVCaptureDevice.FocusMode { get set }
+    var focusPointOfInterest: CGPoint { get set }
+    var isFocusPointOfInterestSupported: Bool { get }
+    func isFocusModeSupported(_ focusMode: AVCaptureDevice.FocusMode) -> Bool
+    
+    var exposureMode: AVCaptureDevice.ExposureMode { get set }
+    var exposurePointOfInterest: CGPoint { get set }
+    var isExposurePointOfInterestSupported: Bool { get }
+    func isExposureModeSupported(_ exposureMode: AVCaptureDevice.ExposureMode) -> Bool
+    
+    var isSubjectAreaChangeMonitoringEnabled: Bool { get set }
+}
+
+extension AVCaptureDevice: CaptureDevice { }
+
+final class MockCaptureDevice: CaptureDevice {
+    func unlockForConfiguration() {
+        return
+    }
+    
+    func lockForConfiguration() throws {
+        return
+    }
+    
+    var torchMode: AVCaptureDevice.TorchMode = .off
+    var isTorchAvailable: Bool = true
+    
+    var focusMode: AVCaptureDevice.FocusMode = .continuousAutoFocus
+    var focusPointOfInterest: CGPoint = .zero
+    var isFocusPointOfInterestSupported: Bool = true
+    
+    var exposureMode: AVCaptureDevice.ExposureMode = .continuousAutoExposure
+    var exposurePointOfInterest: CGPoint = .zero
+    var isExposurePointOfInterestSupported: Bool = true
+    
+    func isFocusModeSupported(_ focusMode: AVCaptureDevice.FocusMode) -> Bool {
+        return true
+    }
+    
+    func isExposureModeSupported(_ exposureMode: AVCaptureDevice.ExposureMode) -> Bool {
+        return true
+    }
+    
+    var isSubjectAreaChangeMonitoringEnabled: Bool = false
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Protocols/Transformable.swift b/MiniScanner/Supporting Files/WeScan/Protocols/Transformable.swift
new file mode 100644
index 0000000000000000000000000000000000000000..cd7a93778821e78921358b5a867f68abecd120e7
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Protocols/Transformable.swift	
@@ -0,0 +1,41 @@
+//
+//  Extendable.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/15/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+
+/// Objects that conform to the Transformable protocol are capable of being transformed with a `CGAffineTransform`.
+protocol Transformable {
+    
+    /// Applies the given `CGAffineTransform`.
+    ///
+    /// - Parameters:
+    ///   - t: The transform to apply
+    /// - Returns: The same object transformed by the passed in `CGAffineTransform`.
+    func applying(_ transform: CGAffineTransform) -> Self
+
+}
+
+extension Transformable {
+    
+    /// Applies multiple given transforms in the given order.
+    ///
+    /// - Parameters:
+    ///   - transforms: The transforms to apply.
+    /// - Returns: The same object transformed by the passed in `CGAffineTransform`s.
+    func applyTransforms(_ transforms: [CGAffineTransform]) -> Self {
+        
+        var transformableObject = self
+        
+        transforms.forEach { (transform) in
+            transformableObject = transformableObject.applying(transform)
+        }
+        
+        return transformableObject
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/CaptureSessionManager.swift b/MiniScanner/Supporting Files/WeScan/Scan/CaptureSessionManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ec3c0800e5fdd0f9b55cb4a29fbf9b38ca2544ea
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/CaptureSessionManager.swift	
@@ -0,0 +1,338 @@
+//
+//  CaptureManager.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/8/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import CoreMotion
+import AVFoundation
+import UIKit
+
+/// A set of functions that inform the delegate object of the state of the detection.
+protocol RectangleDetectionDelegateProtocol: NSObjectProtocol {
+    
+    /// Called when the capture of a picture has started.
+    ///
+    /// - Parameters:
+    ///   - captureSessionManager: The `CaptureSessionManager` instance that started capturing a picture.
+    func didStartCapturingPicture(for captureSessionManager: CaptureSessionManager)
+    
+    /// Called when a quadrilateral has been detected.
+    /// - Parameters:
+    ///   - captureSessionManager: The `CaptureSessionManager` instance that has detected a quadrilateral.
+    ///   - quad: The detected quadrilateral in the coordinates of the image.
+    ///   - imageSize: The size of the image the quadrilateral has been detected on.
+    func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didDetectQuad quad: Quadrilateral?, _ imageSize: CGSize)
+    
+    /// Called when a picture with or without a quadrilateral has been captured.
+    ///
+    /// - Parameters:
+    ///   - captureSessionManager: The `CaptureSessionManager` instance that has captured a picture.
+    ///   - picture: The picture that has been captured.
+    ///   - quad: The quadrilateral that was detected in the picture's coordinates if any.
+    func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didCapturePicture picture: UIImage, withQuad quad: Quadrilateral?)
+    
+    /// Called when an error occured with the capture session manager.
+    /// - Parameters:
+    ///   - captureSessionManager: The `CaptureSessionManager` that encountered an error.
+    ///   - error: The encountered error.
+    func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didFailWithError error: Error)
+}
+
+/// The CaptureSessionManager is responsible for setting up and managing the AVCaptureSession and the functions related to capturing.
+final class CaptureSessionManager: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate {
+    
+    private let videoPreviewLayer: AVCaptureVideoPreviewLayer
+    private let captureSession = AVCaptureSession()
+    private let rectangleFunnel = RectangleFeaturesFunnel()
+    weak var delegate: RectangleDetectionDelegateProtocol?
+    private var displayedRectangleResult: RectangleDetectorResult?
+    private var photoOutput = AVCapturePhotoOutput()
+    
+    /// Whether the CaptureSessionManager should be detecting quadrilaterals.
+    private var isDetecting = true
+    
+    /// The number of times no rectangles have been found in a row.
+    private var noRectangleCount = 0
+    
+    /// The minimum number of time required by `noRectangleCount` to validate that no rectangles have been found.
+    private let noRectangleThreshold = 3
+    
+    // MARK: Life Cycle
+    
+    init?(videoPreviewLayer: AVCaptureVideoPreviewLayer) {
+        self.videoPreviewLayer = videoPreviewLayer
+        super.init()
+        
+        guard let device = AVCaptureDevice.default(for: AVMediaType.video) else {
+            let error = ImageScannerControllerError.inputDevice
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return nil
+        }
+        
+        captureSession.beginConfiguration()
+        captureSession.sessionPreset = AVCaptureSession.Preset.photo
+        
+        photoOutput.isHighResolutionCaptureEnabled = true
+        
+        let videoOutput = AVCaptureVideoDataOutput()
+        videoOutput.alwaysDiscardsLateVideoFrames = true
+        
+        defer {
+            device.unlockForConfiguration()
+            captureSession.commitConfiguration()
+        }
+        
+        guard let deviceInput = try? AVCaptureDeviceInput(device: device),
+            captureSession.canAddInput(deviceInput),
+            captureSession.canAddOutput(photoOutput),
+            captureSession.canAddOutput(videoOutput) else {
+                let error = ImageScannerControllerError.inputDevice
+                delegate?.captureSessionManager(self, didFailWithError: error)
+                return
+        }
+        
+        do {
+            try device.lockForConfiguration()
+        } catch {
+            let error = ImageScannerControllerError.inputDevice
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return
+        }
+        
+        device.isSubjectAreaChangeMonitoringEnabled = true
+        
+        captureSession.addInput(deviceInput)
+        captureSession.addOutput(photoOutput)
+        captureSession.addOutput(videoOutput)
+        
+        videoPreviewLayer.session = captureSession
+        videoPreviewLayer.videoGravity = .resizeAspectFill
+        
+        videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "video_ouput_queue"))
+    }
+    
+    // MARK: Capture Session Life Cycle
+    
+    /// Starts the camera and detecting quadrilaterals.
+    internal func start() {
+        let authorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
+        
+        switch authorizationStatus {
+        case .authorized:
+            DispatchQueue.main.async {
+                self.captureSession.startRunning()
+            }
+            isDetecting = true
+        case .notDetermined:
+            AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (_) in
+                DispatchQueue.main.async { [weak self] in
+                    self?.start()
+                }
+            })
+        default:
+            let error = ImageScannerControllerError.authorization
+            delegate?.captureSessionManager(self, didFailWithError: error)
+        }
+    }
+    
+    internal func stop() {
+        captureSession.stopRunning()
+    }
+    
+    internal func capturePhoto() {
+        guard let connection = photoOutput.connection(with: .video), connection.isEnabled, connection.isActive else {
+            let error = ImageScannerControllerError.capture
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return
+        }
+        
+        let photoSettings = AVCapturePhotoSettings()
+        photoSettings.isHighResolutionPhotoEnabled = true
+        photoSettings.isAutoStillImageStabilizationEnabled = true
+        
+        photoOutput.capturePhoto(with: photoSettings, delegate: self)
+    }
+    
+    // MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
+    
+    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
+        guard isDetecting == true,
+            let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
+            return
+        }
+
+        let imageSize = CGSize(width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))
+
+        if #available(iOS 11.0, *) {
+            VisionRectangleDetector.rectangle(forPixelBuffer: pixelBuffer) { (rectangle) in
+                self.processRectangle(rectangle: rectangle, imageSize: imageSize)
+            }
+        } else {
+            let finalImage = CIImage(cvPixelBuffer: pixelBuffer)
+            CIRectangleDetector.rectangle(forImage: finalImage) { (rectangle) in
+                self.processRectangle(rectangle: rectangle, imageSize: imageSize)
+            }
+        }
+    }
+    
+    private func processRectangle(rectangle: Quadrilateral?, imageSize: CGSize) {
+        if let rectangle = rectangle {
+            
+            self.noRectangleCount = 0
+            self.rectangleFunnel.add(rectangle, currentlyDisplayedRectangle: self.displayedRectangleResult?.rectangle) { [weak self] (result, rectangle) in
+                
+                guard let strongSelf = self else {
+                    return
+                }
+                
+                let shouldAutoScan = (result == .showAndAutoScan)
+                strongSelf.displayRectangleResult(rectangleResult: RectangleDetectorResult(rectangle: rectangle, imageSize: imageSize))
+                if shouldAutoScan, CaptureSession.current.isAutoScanEnabled, !CaptureSession.current.isEditing {
+                    capturePhoto()
+                }
+            }
+            
+        } else {
+            
+            DispatchQueue.main.async { [weak self] in
+                guard let strongSelf = self else {
+                    return
+                }
+                strongSelf.noRectangleCount += 1
+                
+                if strongSelf.noRectangleCount > strongSelf.noRectangleThreshold {
+                    // Reset the currentAutoScanPassCount, so the threshold is restarted the next time a rectangle is found
+                    strongSelf.rectangleFunnel.currentAutoScanPassCount = 0
+                    
+                    // Remove the currently displayed rectangle as no rectangles are being found anymore
+                    strongSelf.displayedRectangleResult = nil
+                    strongSelf.delegate?.captureSessionManager(strongSelf, didDetectQuad: nil, imageSize)
+                }
+            }
+            return
+            
+        }
+    }
+    
+    @discardableResult private func displayRectangleResult(rectangleResult: RectangleDetectorResult) -> Quadrilateral {
+        displayedRectangleResult = rectangleResult
+        
+        let quad = rectangleResult.rectangle.toCartesian(withHeight: rectangleResult.imageSize.height)
+        
+        DispatchQueue.main.async { [weak self] in
+            guard let strongSelf = self else {
+                return
+            }
+            
+            strongSelf.delegate?.captureSessionManager(strongSelf, didDetectQuad: quad, rectangleResult.imageSize)
+        }
+        
+        return quad
+    }
+    
+}
+
+extension CaptureSessionManager: AVCapturePhotoCaptureDelegate {
+    
+    func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
+        if let error = error {
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return
+        }
+        
+        CaptureSession.current.setImageOrientation()
+        
+        isDetecting = false
+        rectangleFunnel.currentAutoScanPassCount = 0
+        delegate?.didStartCapturingPicture(for: self)
+        
+        if let sampleBuffer = photoSampleBuffer,
+            let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: nil) {
+            completeImageCapture(with: imageData)
+        } else {
+            let error = ImageScannerControllerError.capture
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return
+        }
+        
+    }
+    
+    @available(iOS 11.0, *)
+    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
+        if let error = error {
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return
+        }
+        
+        CaptureSession.current.setImageOrientation()
+        
+        isDetecting = false
+        rectangleFunnel.currentAutoScanPassCount = 0
+        delegate?.didStartCapturingPicture(for: self)
+        
+        if let imageData = photo.fileDataRepresentation() {
+            completeImageCapture(with: imageData)
+        } else {
+            let error = ImageScannerControllerError.capture
+            delegate?.captureSessionManager(self, didFailWithError: error)
+            return
+        }
+    }
+    
+    /// Completes the image capture by processing the image, and passing it to the delegate object.
+    /// This function is necessary because the capture functions for iOS 10 and 11 are decoupled.
+    private func completeImageCapture(with imageData: Data) {
+        DispatchQueue.global(qos: .background).async { [weak self] in
+            CaptureSession.current.isEditing = true
+            guard let image = UIImage(data: imageData) else {
+                let error = ImageScannerControllerError.capture
+                DispatchQueue.main.async {
+                    guard let strongSelf = self else {
+                        return
+                    }
+                    strongSelf.delegate?.captureSessionManager(strongSelf, didFailWithError: error)
+                }
+                return
+            }
+            
+            var angle: CGFloat = 0.0
+            
+            switch image.imageOrientation {
+            case .right:
+                angle = CGFloat.pi / 2
+            case .up:
+                angle = CGFloat.pi
+            default:
+                break
+            }
+            
+            var quad: Quadrilateral?
+            if let displayedRectangleResult = self?.displayedRectangleResult {
+                quad = self?.displayRectangleResult(rectangleResult: displayedRectangleResult)
+                quad = quad?.scale(displayedRectangleResult.imageSize, image.size, withRotationAngle: angle)
+            }
+            
+            DispatchQueue.main.async {
+                guard let strongSelf = self else {
+                    return
+                }
+                strongSelf.delegate?.captureSessionManager(strongSelf, didCapturePicture: image, withQuad: quad)
+            }
+        }
+    }
+}
+
+/// Data structure representing the result of the detection of a quadrilateral.
+private struct RectangleDetectorResult {
+    
+    /// The detected quadrilateral.
+    let rectangle: Quadrilateral
+    
+    /// The size of the image the quadrilateral was detected on.
+    let imageSize: CGSize
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/DeviceOrientationHelper.swift b/MiniScanner/Supporting Files/WeScan/Scan/DeviceOrientationHelper.swift
new file mode 100644
index 0000000000000000000000000000000000000000..bedc5ecabbb76e7cb7c756b32221b17e6b79dbe5
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/DeviceOrientationHelper.swift	
@@ -0,0 +1,75 @@
+//
+//  DeviceOrientationHelper.swift
+//  WeScan
+//
+//  Created by Enrique Rodriguez on 23/01/2019.
+//  Copyright © 2019 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import CoreMotion
+import UIKit
+
+class DeviceOrientationHelper {
+    static let shared = DeviceOrientationHelper() 
+    
+    private let motionManager: CMMotionManager
+    private let queue: OperationQueue
+    
+    typealias DeviceOrientationHandler = ((_ deviceOrientation: UIDeviceOrientation) -> Void)?
+    private var deviceOrientationAction: DeviceOrientationHandler?
+    
+    private (set) var currentDeviceOrientation: UIDeviceOrientation = .portrait
+    
+    private let motionLimit: Double = 0.6 // Smallers values makes it much sensitive to detect an orientation change. [0 to 1]
+    
+    init() {
+        motionManager = CMMotionManager()
+        motionManager.accelerometerUpdateInterval = 0.2 // Specify an update interval in seconds, personally found this value provides a good UX
+        
+        queue = OperationQueue()
+    }
+    
+    public func startDeviceOrientationNotifier(with handler: DeviceOrientationHandler) {
+        self.deviceOrientationAction = handler
+        
+        //  Using main queue is not recommended. So create new operation queue and pass it to startAccelerometerUpdatesToQueue.
+        //  Dispatch U/I code to main thread using dispach_async in the handler.
+        
+        motionManager.startAccelerometerUpdates(to: queue) { (data, error) in
+            if let accelerometerData = data {
+                var newDeviceOrientation: UIDeviceOrientation?
+                
+                if (accelerometerData.acceleration.x >= self.motionLimit) {
+                    newDeviceOrientation = .landscapeLeft
+                }
+                else if (accelerometerData.acceleration.x <= -self.motionLimit) {
+                    newDeviceOrientation = .landscapeRight
+                }
+                else if (accelerometerData.acceleration.y <= -self.motionLimit) {
+                    newDeviceOrientation = .portrait
+                }
+                else if (accelerometerData.acceleration.y >= self.motionLimit) {
+                    newDeviceOrientation = .portraitUpsideDown
+                }
+                else {
+                    return
+                }
+                
+                // Only if a different orientation is detect, execute handler
+                if let newDeviceOrientation = newDeviceOrientation, newDeviceOrientation != self.currentDeviceOrientation {
+                    self.currentDeviceOrientation = newDeviceOrientation
+                    if let deviceOrientationHandler = self.deviceOrientationAction {
+                        DispatchQueue.main.async {
+                            deviceOrientationHandler!(self.currentDeviceOrientation)
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    public func stopDeviceOrientationNotifier() {
+        motionManager.stopAccelerometerUpdates()
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/FocusRectangleView.swift b/MiniScanner/Supporting Files/WeScan/Scan/FocusRectangleView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1146deaacaba9a1202979ae181baad9e4c61c3a9
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/FocusRectangleView.swift	
@@ -0,0 +1,35 @@
+//
+//  FocusRectangleView.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 16/11/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+
+/// A yellow rectangle used to display the last 'tap to focus' point
+final class FocusRectangleView: UIView {
+    convenience init(touchPoint: CGPoint) {
+        let originalSize: CGFloat = 200
+        let finalSize: CGFloat = 80
+        
+        // Here, we create the frame to be the `originalSize`, with it's center being the `touchPoint`.
+        self.init(frame: CGRect(x: touchPoint.x - (originalSize / 2), y: touchPoint.y - (originalSize / 2), width: originalSize, height: originalSize))
+        
+        backgroundColor = .clear
+        layer.borderWidth = 2.0
+        layer.cornerRadius = 6.0
+        layer.borderColor = UIColor.yellow.cgColor
+        
+        // Here, we animate the rectangle from the `originalSize` to the `finalSize` by calculating the difference.
+        UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseOut, animations: {
+            self.frame.origin.x += (originalSize - finalSize) / 2
+            self.frame.origin.y += (originalSize - finalSize) / 2
+            
+            self.frame.size.width -= (originalSize - finalSize)
+            self.frame.size.height -= (originalSize - finalSize)
+        })
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/PDFCreator.swift b/MiniScanner/Supporting Files/WeScan/Scan/PDFCreator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..cc682ef3835fedea9692c5356a2b6f2e32ff6ba7
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/PDFCreator.swift	
@@ -0,0 +1,91 @@
+//
+//  ImageToPDF.swift
+//  WeScan
+//
+//  Created by Enrique Rodriguez on 08/01/2019.
+//  Copyright © 2019 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+public typealias PDFCreatorProgressBlock = ((_ fractionCompleted:Double) -> Void)
+public typealias PDFCreatorCompletionBlock = ((_ error:Error?) -> Void)
+
+public class PDFCreator {
+    
+    var currentIndex = 0
+    var images = [URL]()
+
+    private let scanSession:MultiPageScanSession
+    private let outputPath:String
+    private let outputResolution:CGFloat?
+    
+    private var completion:PDFCreatorCompletionBlock!
+    private var progress:PDFCreatorProgressBlock!
+    
+    public init(scanSession:MultiPageScanSession, in path:String, outputResolution:CGFloat? = 0){
+        self.scanSession = scanSession
+        self.outputPath = path
+        self.outputResolution = outputResolution
+    }
+    
+    // MARK: Public methods
+    
+    public func createPDF(completion:@escaping PDFCreatorCompletionBlock, progress:@escaping PDFCreatorProgressBlock){
+        self.completion = completion
+        self.progress = progress
+
+        self.currentIndex = 0
+        self.renderNextImage()
+    }
+    
+    // MARK: Private methods
+    
+    private func renderNextImage(){
+        if (self.currentIndex < scanSession.scannedItems.count){
+            let scannedItem = scanSession.scannedItems[currentIndex]
+            if let renderedImage = scannedItem.renderedImage{
+                self.images.append(renderedImage)
+                self.currentIndex = self.currentIndex + 1
+                self.progress(Double(self.currentIndex)/Double(self.scanSession.scannedItems.count))
+                self.renderNextImage()
+            } else {
+                print("Rendering image \(self.currentIndex)")
+                scannedItem.render { (image) in
+                    if let image = image {
+                        self.images.append(image)
+                    }
+                    self.currentIndex =  self.currentIndex + 1
+                    self.progress(Double(self.currentIndex)/Double(self.scanSession.scannedItems.count))
+                    self.renderNextImage()
+                }
+            }
+        } else {
+            print("Finished!")
+            self.makePDFFromImages()
+            completion(nil)
+        }
+    }
+    
+    private func makePDFFromImages(){
+        
+        UIGraphicsBeginPDFContextToFile(self.outputPath, CGRect.zero, nil);
+        
+        self.images.forEach { (image) in
+            var outputImage:UIImage! = nil
+            if let outputResolution = self.outputResolution,
+                outputResolution > 0.0,
+                let reducedImage = image.retrieveImage()?.resizeImage(newWidth: outputResolution){
+                outputImage = reducedImage
+            } else {
+                outputImage = image.retrieveImage()
+            }
+            UIGraphicsBeginPDFPageWithInfo(CGRect(x:0, y:0, width:outputImage.size.width, height:outputImage.size.height), nil);
+            outputImage.draw(in: CGRect(x: 0, y: 0, width: outputImage.size.width, height: outputImage.size.height))
+        }
+        UIGraphicsEndPDFContext();
+    }
+    
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/RectangleFeaturesFunnel.swift b/MiniScanner/Supporting Files/WeScan/Scan/RectangleFeaturesFunnel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1c47e78ce5809e391ac9317f632a3b378616e800
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/RectangleFeaturesFunnel.swift	
@@ -0,0 +1,189 @@
+//
+//  RectangleFeaturesFunnel.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/9/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+
+enum AddResult {
+    case showAndAutoScan
+    case showOnly
+}
+
+/// `RectangleFeaturesFunnel` is used to improve the confidence of the detected rectangles.
+/// Feed rectangles to a `RectangleFeaturesFunnel` instance, and it will call the completion block with a rectangle whose confidence is high enough to be displayed.
+final class RectangleFeaturesFunnel {
+    
+    /// `RectangleMatch` is a class used to assign matching scores to rectangles.
+    private final class RectangleMatch: NSObject {
+        /// The rectangle feature object associated to this `RectangleMatch` instance.
+        let rectangleFeature: Quadrilateral
+        
+        /// The score to indicate how strongly the rectangle of this instance matches other recently added rectangles.
+        /// A higher score indicates that many recently added rectangles are very close to the rectangle of this instance.
+        var matchingScore = 0
+        
+        init(rectangleFeature: Quadrilateral) {
+            self.rectangleFeature = rectangleFeature
+        }
+        
+        override var description: String {
+            return "Matching score: \(matchingScore) - Rectangle: \(rectangleFeature)"
+        }
+        
+        /// Whether the rectangle of this instance is within the distance of the given rectangle.
+        ///
+        /// - Parameters:
+        ///   - rectangle: The rectangle to compare the rectangle of this instance with.
+        ///   - threshold: The distance used to determinate if the rectangles match in pixels.
+        /// - Returns: True if both rectangles are within the given distance of each other.
+        func matches(_ rectangle: Quadrilateral, withThreshold threshold: CGFloat) -> Bool {
+            return rectangleFeature.isWithin(threshold, ofRectangleFeature: rectangle)
+        }
+    }
+    
+    /// The queue of last added rectangles. The first rectangle is oldest one, and the last rectangle is the most recently added one.
+    private var rectangles = [RectangleMatch]()
+    
+    /// The maximum number of rectangles to compare newly added rectangles with. Determines the maximum size of `rectangles`. Increasing this value will impact performance.
+    let maxNumberOfRectangles = 8
+    
+    /// The minimum number of rectangles needed to start making comparaisons and determining which rectangle to display. This value should always be inferior than `maxNumberOfRectangles`.
+    /// A higher value will delay the first time a rectangle is displayed.
+    let minNumberOfRectangles = 3
+    
+    /// The value in pixels used to determine if two rectangle match or not. A higher value will prevent displayed rectangles to be refreshed. On the opposite, a smaller value will make new rectangles be displayed constantly.
+    let matchingThreshold: CGFloat = 40.0
+    
+    /// The minumum number of matching rectangles (within the `rectangle` queue), to be confident enough to display a rectangle.
+    let minNumberOfMatches = 3
+    
+    /// The number of similar rectangles that need to be found to auto scan.
+    let autoScanThreshold = 35
+    
+    /// The number of times the rectangle has passed the threshold to be auto-scanned
+    var currentAutoScanPassCount = 0
+    
+    /// The value in pixels used to determine if a rectangle is accurate enough to be auto scanned.
+    /// A higher value means the auto scan is quicker, but the rectangle will be less accurate. On the other hand, the lower the value, the longer it'll take for the auto scan, but it'll be way more accurate
+    var autoScanMatchingThreshold: CGFloat = 6.0
+    
+    /// Add a rectangle to the funnel, and if a new rectangle should be displayed, the completion block will be called.
+    /// The algorithm works the following way:
+    /// 1. Makes sure that the funnel has been fed enough rectangles
+    /// 2. Removes old rectangles if needed
+    /// 3. Compares all of the recently added rectangles to find out which one match each other
+    /// 4. Within all of the recently added rectangles, finds the "best" one (@see `bestRectangle(withCurrentlyDisplayedRectangle:)`)
+    /// 5. If the best rectangle is different than the currently displayed rectangle, informs the listener that a new rectangle should be displayed
+    ///     5a. The currentAutoScanPassCount is incremented every time a new rectangle is displayed. If it passes the autoScanThreshold, we tell the listener to scan the document.
+    /// - Parameters:
+    ///   - rectangleFeature: The rectangle to feed to the funnel.
+    ///   - currentRectangle: The currently displayed rectangle. This is used to avoid displaying very close rectangles.
+    ///   - completion: The completion block called when a new rectangle should be displayed.
+    func add(_ rectangleFeature: Quadrilateral, currentlyDisplayedRectangle currentRectangle: Quadrilateral?, completion: (AddResult, Quadrilateral) -> Void) {
+        let rectangleMatch = RectangleMatch(rectangleFeature: rectangleFeature)
+        rectangles.append(rectangleMatch)
+        
+        guard rectangles.count >= minNumberOfRectangles else {
+            return
+        }
+        
+        if rectangles.count > maxNumberOfRectangles {
+            rectangles.removeFirst()
+        }
+        
+        updateRectangleMatches()
+        
+        guard let bestRectangle = bestRectangle(withCurrentlyDisplayedRectangle: currentRectangle) else {
+            return
+        }
+        
+        if let previousRectangle = currentRectangle,
+            bestRectangle.rectangleFeature.isWithin(autoScanMatchingThreshold, ofRectangleFeature: previousRectangle) {
+            currentAutoScanPassCount += 1
+            if currentAutoScanPassCount > autoScanThreshold {
+                currentAutoScanPassCount = 0
+                completion(AddResult.showAndAutoScan, bestRectangle.rectangleFeature)
+            }
+        } else {
+            completion(AddResult.showOnly, bestRectangle.rectangleFeature)
+        }
+    }
+    
+    /// Determines which rectangle is best to displayed.
+    /// The criteria used to find the best rectangle is its matching score.
+    /// If multiple rectangles have the same matching score, we use a tie breaker to find the best rectangle (@see breakTie(forRectangles:)).
+    /// Parameters:
+    ///   - currentRectangle: The currently displayed rectangle. This is used to avoid displaying very close rectangles.
+    /// Returns: The best rectangle to display given the current history.
+    private func bestRectangle(withCurrentlyDisplayedRectangle currentRectangle: Quadrilateral?) -> RectangleMatch? {
+        var bestMatch: RectangleMatch?
+        guard !rectangles.isEmpty else { return nil }
+        rectangles.reversed().forEach { (rectangle) in
+            guard let best = bestMatch else {
+                bestMatch = rectangle
+                return
+            }
+            
+            if rectangle.matchingScore > best.matchingScore {
+                bestMatch = rectangle
+                return
+            } else if rectangle.matchingScore == best.matchingScore {
+                guard let currentRectangle = currentRectangle else {
+                    return
+                }
+                
+                bestMatch = breakTie(between: best, rect2: rectangle, currentRectangle: currentRectangle)
+            }
+        }
+        
+        return bestMatch
+    }
+    
+    /// Breaks a tie between two rectangles to find out which is best to display.
+    /// The first passed rectangle is returned if no other criteria could be used to break the tie.
+    /// If the first passed rectangle (rect1) is close to the currently displayed rectangle, we pick it.
+    /// Otherwise if the second passed rectangle (rect2) is close to the currently displayed rectangle, we pick this one.
+    /// Finally, if none of the passed in rectangles are close to the currently displayed rectangle, we arbitrary pick the first one.
+    /// - Parameters:
+    ///   - rect1: The first rectangle to compare.
+    ///   - rect2: The second rectangle to compare.
+    ///   - currentRectangle: The currently displayed rectangle. This is used to avoid displaying very close rectangles.
+    /// - Returns: The best rectangle to display between two rectangles with the same matching score.
+    private func breakTie(between rect1: RectangleMatch, rect2: RectangleMatch, currentRectangle: Quadrilateral) -> RectangleMatch {
+        if rect1.rectangleFeature.isWithin(matchingThreshold, ofRectangleFeature: currentRectangle) {
+            return rect1
+        } else if rect2.rectangleFeature.isWithin(matchingThreshold, ofRectangleFeature: currentRectangle) {
+            return rect2
+        }
+        
+        return rect1
+    }
+    
+    /// Loops through all of the rectangles of the queue, and gives them a score depending on how many they match. @see `RectangleMatch.matchingScore`
+    private func updateRectangleMatches() {
+        resetMatchingScores()
+        guard !rectangles.isEmpty else { return }
+        for (i, currentRect) in rectangles.enumerated() {
+            for (j, rect) in rectangles.enumerated() {
+                if j > i && currentRect.matches(rect.rectangleFeature, withThreshold: matchingThreshold) {
+                    currentRect.matchingScore += 1
+                    rect.matchingScore += 1
+                }
+            }
+        }
+    }
+    
+    /// Resets the matching score of all of the rectangles in the queue to 0
+    private func resetMatchingScores() {
+        guard !rectangles.isEmpty else { return }
+        for rectangle in rectangles {
+            rectangle.matchingScore = 1
+        }
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/ScannedItemRenderer.swift b/MiniScanner/Supporting Files/WeScan/Scan/ScannedItemRenderer.swift
new file mode 100644
index 0000000000000000000000000000000000000000..afea856e744c7d187ad5b791a5e5f4fc2630c2e3
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/ScannedItemRenderer.swift	
@@ -0,0 +1,60 @@
+//
+//  ScannedItemRenderer.swift
+//  WeScan
+//
+//  Created by Enrique Rodriguez on 09/01/2019.
+//  Copyright © 2019 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+public struct ScannedItemRendererOptions{
+    let targetSize:CGSize
+}
+
+public class ScannedItemRenderer{
+    
+    public func render(scannedItem:ScannedItem, completion: @escaping (_ image:UIImage?)->Void){
+        DispatchQueue.global(qos: .userInitiated).async {
+            let originalImage = scannedItem.originalImage
+            let image = originalImage?.retrieveImage()?.withFixedOrientation().applyingPortraitOrientation()
+
+            var uiImage: UIImage!
+            
+            if let quad = scannedItem.quad, let image = image, let ciImage = CIImage(image: image) {
+                var cartesianScaledQuad = quad.toCartesian(withHeight: image.size.height)
+                cartesianScaledQuad.reorganize()
+                
+                let filteredImage = ciImage.applyingFilter("CIPerspectiveCorrection", parameters: [
+                    "inputTopLeft": CIVector(cgPoint: cartesianScaledQuad.bottomLeft),
+                    "inputTopRight": CIVector(cgPoint: cartesianScaledQuad.bottomRight),
+                    "inputBottomLeft": CIVector(cgPoint: cartesianScaledQuad.topLeft),
+                    "inputBottomRight": CIVector(cgPoint: cartesianScaledQuad.topRight)
+                    ])
+                
+                // Let's try to generate the CGImage from the CIImage before creating a UIImage.
+                if let cgImage = CIContext(options: nil).createCGImage(filteredImage, from: filteredImage.extent) {
+                    uiImage = UIImage(cgImage: cgImage)
+                } else {
+                    uiImage = UIImage(ciImage: filteredImage, scale: 1.0, orientation: .up)
+                }
+            } else {
+                uiImage = image
+            }
+            
+            if scannedItem.colorOption == .grayscale{
+                if let grayscaleImage = CIImage.init(image: uiImage)?.applyingAdaptiveThreshold(){
+                    uiImage = grayscaleImage
+                }
+            }
+            
+            if scannedItem.rotation != 0.0{
+                uiImage = uiImage.rotated(by: Measurement(value: scannedItem.rotation, unit: .degrees))
+            }
+            
+            DispatchQueue.main.async { completion(uiImage.withFixedOrientation()) }
+        }
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/ScannerViewController.swift b/MiniScanner/Supporting Files/WeScan/Scan/ScannerViewController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4324acda8a0f771323e5c8f29883efc53c3353da
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/ScannerViewController.swift	
@@ -0,0 +1,459 @@
+//
+//  ScannerViewController.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/8/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+/// An enum used to know if the flashlight was toggled successfully.
+enum FlashResult {
+    case successful
+    case notSuccessful
+}
+
+protocol ScannerViewControllerDelegate:NSObjectProtocol{
+    func scannerViewController(_ scannerViewController:ScannerViewController, reviewItems inSession:MultiPageScanSession)
+    func scannerViewController(_ scannerViewController:ScannerViewController, didFail withError:Error)
+    func scannerViewControllerDidCancel(_ scannerViewController:ScannerViewController)
+}
+
+public final class ScannerViewController: UIViewController {
+    
+     var captureSessionManager: CaptureSessionManager?
+     let videoPreviewLayer = AVCaptureVideoPreviewLayer()
+     weak var delegate: ScannerViewControllerDelegate?
+     var focusRectangle: FocusRectangleView!
+     let quadView = QuadrilateralView()
+     let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
+     var flashEnabled = false
+     var deviceOrientationHelper = DeviceOrientationHelper()
+     var multipageSession:MultiPageScanSession!
+     var options:ImageScannerOptions!
+    
+    public override var prefersStatusBarHidden: Bool {
+        return true
+    }
+    
+    /// The original bar style that was set by the host app
+    private var originalBarStyle: UIBarStyle?
+    
+    lazy private var shutterButton: ShutterButton = {
+        let button = ShutterButton()
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.addTarget(self, action: #selector(captureImage(_:)), for: .touchUpInside)
+        return button
+    }()
+    
+    lazy private var cancelButton: UIButton = {
+        let button = UIButton()
+        button.setTitle(NSLocalizedString("wescan.scanning.cancel", tableName: nil, bundle: Bundle(for: ScannerViewController.self), value: "Cancel", comment: "The cancel button"), for: .normal)
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.addTarget(self, action: #selector(cancelImageScannerController), for: .touchUpInside)
+        return button
+    }()
+    
+    lazy private var counterButton: UIButton = {
+        let button = UIButton()
+        button.setTitle("0 >", for: .normal)
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.backgroundColor = UIColor.init(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.5)
+        button.layer.borderColor = UIColor.white.cgColor
+        button.layer.borderWidth = 1.0
+        button.layer.cornerRadius = 5.0
+        button.setTitleColor(UIColor.white, for: .normal)
+        button.isHidden = true
+        button.addTarget(self, action: #selector(counterImageScannerController), for: .touchUpInside)
+        return button
+    }()
+    
+    /// A black UIView, used to quickly display a black screen when the shutter button is presseed.
+    internal let blackFlashView: UIView = {
+        let view = UIView()
+        view.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
+        view.isHidden = true
+        view.translatesAutoresizingMaskIntoConstraints = false
+        return view
+    }()
+    
+    lazy private var autoScanButton: UIBarButtonItem = {
+        var title = NSLocalizedString("wescan.scanning.auto", tableName: nil, bundle: Bundle(for: ScannerViewController.self), value: "Auto", comment: "The auto button state")
+        if !self.options.allowAutoScan{
+            title = NSLocalizedString("wescan.scanning.manual", tableName: nil, bundle: Bundle(for: ScannerViewController.self), value: "Manual", comment: "The manual button state")
+        }
+        
+        let button = UIBarButtonItem(title: title, style: .plain, target: self, action: #selector(toggleAutoScan))
+        button.tintColor = .white
+        
+        return button
+    }()
+    
+    lazy private var flashButton: UIBarButtonItem = {
+        let flashImage = UIImage(named: "flash", in: Bundle(for: ScannerViewController.self), compatibleWith: nil)
+        let flashButton = UIBarButtonItem(image: flashImage, style: .plain, target: self, action: #selector(toggleFlash))
+        flashButton.tintColor = .white
+        
+        return flashButton
+    }()
+    
+    lazy private var activityIndicator: UIActivityIndicatorView = {
+        let activityIndicator = UIActivityIndicatorView(style: .gray)
+        activityIndicator.hidesWhenStopped = true
+        activityIndicator.translatesAutoresizingMaskIntoConstraints = false
+        return activityIndicator
+    }()
+    
+    // MARK: - Initializers
+    
+    public init(scanSession:MultiPageScanSession?, options:ImageScannerOptions?) {
+        self.multipageSession = scanSession ?? MultiPageScanSession()
+        self.options = options ?? ImageScannerOptions()
+        super.init(nibName: nil, bundle: nil)
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    // MARK: - Life Cycle
+    
+    public override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        title = nil
+        
+        setupViews()
+        setupNavigationBar()
+        setupConstraints()
+        
+        captureSessionManager = CaptureSessionManager(videoPreviewLayer: videoPreviewLayer)
+        captureSessionManager?.delegate = self
+        CaptureSession.current.isAutoScanEnabled = self.options.allowAutoScan
+        
+        originalBarStyle = navigationController?.navigationBar.barStyle
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(subjectAreaDidChange), name: Notification.Name.AVCaptureDeviceSubjectAreaDidChange, object: nil)
+    }
+    
+    public override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        setNeedsStatusBarAppearanceUpdate()
+        
+        CaptureSession.current.isEditing = false
+        quadView.removeQuadrilateral()
+        captureSessionManager?.start()
+        UIApplication.shared.isIdleTimerDisabled = true
+        navigationController?.navigationBar.isTranslucent = true
+        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
+        navigationController?.navigationBar.addSubview(visualEffectView)
+        navigationController?.navigationBar.sendSubviewToBack(visualEffectView)
+        navigationController?.navigationBar.barStyle = .blackTranslucent
+        
+        navigationController?.setToolbarHidden(true, animated: true)
+        
+        updateCounterButton()
+        
+        deviceOrientationHelper.startDeviceOrientationNotifier { (deviceOrientation) in
+            self.orientationChanged(deviceOrientation: deviceOrientation)
+        }
+    }
+    
+    public override func viewDidDisappear(_ animated: Bool) {
+        deviceOrientationHelper.stopDeviceOrientationNotifier()
+        super.viewDidDisappear(true)
+    }
+    
+    public override func viewDidLayoutSubviews() {
+        super.viewDidLayoutSubviews()
+        
+        videoPreviewLayer.frame = view.layer.bounds
+        
+        let statusBarHeight = UIApplication.shared.statusBarFrame.size.height
+        let visualEffectRect = self.navigationController?.navigationBar.bounds.insetBy(dx: 0, dy: -(statusBarHeight)).offsetBy(dx: 0, dy: -statusBarHeight)
+        
+        visualEffectView.frame = visualEffectRect ?? CGRect.zero
+    }
+    
+    public override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        UIApplication.shared.isIdleTimerDisabled = false
+        
+        visualEffectView.removeFromSuperview()
+        navigationController?.navigationBar.isTranslucent = false
+        navigationController?.navigationBar.barStyle = originalBarStyle ?? .default
+        
+        guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
+        if device.torchMode == .on {
+            toggleFlash()
+        }
+    }
+    
+    // MARK: - Setups
+    
+    private func setupViews() {
+        view.layer.addSublayer(videoPreviewLayer)
+        quadView.translatesAutoresizingMaskIntoConstraints = false
+        quadView.editable = false
+        view.addSubview(quadView)
+        view.addSubview(cancelButton)
+        view.addSubview(counterButton)
+        view.addSubview(shutterButton)
+        view.addSubview(activityIndicator)
+        view.addSubview(blackFlashView)
+    }
+    
+    private func setupNavigationBar() {
+        navigationItem.setLeftBarButton(flashButton, animated: false)
+        navigationItem.setRightBarButton(autoScanButton, animated: false)
+        
+        if UIImagePickerController.isFlashAvailable(for: .rear) == false {
+            let flashOffImage = UIImage(named: "flashUnavailable", in: Bundle(for: ScannerViewController.self), compatibleWith: nil)
+            flashButton.image = flashOffImage
+            flashButton.tintColor = UIColor.lightGray
+        }
+    }
+    
+    private func setupConstraints() {
+        var quadViewConstraints = [NSLayoutConstraint]()
+        var cancelButtonConstraints = [NSLayoutConstraint]()
+        var shutterButtonConstraints = [NSLayoutConstraint]()
+        var activityIndicatorConstraints = [NSLayoutConstraint]()
+        var counterButtonConstraints = [NSLayoutConstraint]()
+        var blackFlashViewConstraints = [NSLayoutConstraint]()
+        
+        quadViewConstraints = [
+            quadView.topAnchor.constraint(equalTo: view.topAnchor),
+            view.bottomAnchor.constraint(equalTo: quadView.bottomAnchor),
+            view.trailingAnchor.constraint(equalTo: quadView.trailingAnchor),
+            quadView.leadingAnchor.constraint(equalTo: view.leadingAnchor)
+        ]
+        
+        shutterButtonConstraints = [
+            shutterButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
+            shutterButton.widthAnchor.constraint(equalToConstant: 65.0),
+            shutterButton.heightAnchor.constraint(equalToConstant: 65.0)
+        ]
+        
+        activityIndicatorConstraints = [
+            activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor),
+            activityIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor)
+        ]
+        
+        blackFlashViewConstraints = [
+            blackFlashView.topAnchor.constraint(equalTo: view.topAnchor),
+            blackFlashView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+            view.bottomAnchor.constraint(equalTo: blackFlashView.bottomAnchor),
+            view.trailingAnchor.constraint(equalTo: blackFlashView.trailingAnchor)
+        ]
+        
+        if #available(iOS 11.0, *) {
+            cancelButtonConstraints = [
+                cancelButton.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 24.0),
+                view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: cancelButton.bottomAnchor, constant: (65.0 / 2) - 10.0)
+            ]
+            
+            counterButtonConstraints = [
+                counterButton.centerYAnchor.constraint(equalTo: shutterButton.centerYAnchor),
+                counterButton.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: -24.0),
+                counterButton.widthAnchor.constraint(equalToConstant: 44.0),
+                counterButton.heightAnchor.constraint(equalToConstant: 44.0)
+            ]
+            
+            let shutterButtonBottomConstraint = view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: shutterButton.bottomAnchor, constant: 8.0)
+            shutterButtonConstraints.append(shutterButtonBottomConstraint)
+        } else {
+            cancelButtonConstraints = [
+                cancelButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 24.0),
+                view.bottomAnchor.constraint(equalTo: cancelButton.bottomAnchor, constant: (65.0 / 2) - 10.0)
+            ]
+            
+            let shutterButtonBottomConstraint = view.bottomAnchor.constraint(equalTo: shutterButton.bottomAnchor, constant: 8.0)
+            shutterButtonConstraints.append(shutterButtonBottomConstraint)
+        }
+        
+        NSLayoutConstraint.activate(quadViewConstraints + cancelButtonConstraints + shutterButtonConstraints + activityIndicatorConstraints + counterButtonConstraints + blackFlashViewConstraints)
+    }
+    
+    private func flashToBlack() {
+        view.bringSubviewToFront(blackFlashView)
+        blackFlashView.isHidden = false
+        let flashDuration = DispatchTime.now() + 0.05
+        DispatchQueue.main.asyncAfter(deadline: flashDuration) {
+            self.blackFlashView.isHidden = true
+        }
+    }
+    
+    // MARK: - Tap to Focus
+    
+    /// Called when the AVCaptureDevice detects that the subject area has changed significantly. When it's called, we reset the focus so the camera is no longer out of focus.
+    @objc private func subjectAreaDidChange() {
+        /// Reset the focus and exposure back to automatic
+        do {
+            try CaptureSession.current.resetFocusToAuto()
+        } catch {
+            let error = ImageScannerControllerError.inputDevice
+            guard let captureSessionManager = captureSessionManager else { return }
+            captureSessionManager.delegate?.captureSessionManager(captureSessionManager, didFailWithError: error)
+            return
+        }
+        
+        /// Remove the focus rectangle if one exists
+        CaptureSession.current.removeFocusRectangleIfNeeded(focusRectangle, animated: true)
+    }
+    
+    public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
+        super.touchesBegan(touches, with: event)
+        
+        if self.options.allowTapToFocus{
+            guard  let touch = touches.first else { return }
+            let touchPoint = touch.location(in: view)
+            let convertedTouchPoint: CGPoint = videoPreviewLayer.captureDevicePointConverted(fromLayerPoint: touchPoint)
+            
+            CaptureSession.current.removeFocusRectangleIfNeeded(focusRectangle, animated: false)
+            
+            focusRectangle = FocusRectangleView(touchPoint: touchPoint)
+            view.addSubview(focusRectangle)
+            
+            do {
+                try CaptureSession.current.setFocusPointToTapPoint(convertedTouchPoint)
+            } catch {
+                let error = ImageScannerControllerError.inputDevice
+                guard let captureSessionManager = captureSessionManager else { return }
+                captureSessionManager.delegate?.captureSessionManager(captureSessionManager, didFailWithError: error)
+                return
+            }
+        }
+    }
+    
+    private func updateCounterButton(){
+        self.counterButton.isHidden = self.multipageSession.scannedItems.count < 1
+        self.counterButton.setTitle("\(self.multipageSession.scannedItems.count) >", for: .normal)
+    }
+    
+    // MARK: Rotation methods
+    private func orientationChanged(deviceOrientation: UIDeviceOrientation) {
+        print("Orientation changed: \(self.deviceOrientationHelper.currentDeviceOrientation.rawValue)")
+    }
+    
+    private func getCurrentRotationAngle()->Double{
+        switch self.deviceOrientationHelper.currentDeviceOrientation {
+        case .landscapeRight:
+            return -90.0
+        case .landscapeLeft:
+            return 90.0
+        case .portrait:
+            return 0.0
+        case .portraitUpsideDown:
+            return 180.0
+        default:
+            return 0.0
+        }
+    }
+    
+    // MARK: - Actions
+    
+    @objc private func captureImage(_ sender: UIButton) {
+        self.flashToBlack()
+        shutterButton.isUserInteractionEnabled = false
+        captureSessionManager?.capturePhoto()
+    }
+    
+    @objc private func toggleAutoScan() {
+        if CaptureSession.current.isAutoScanEnabled {
+            CaptureSession.current.isAutoScanEnabled = false
+            autoScanButton.title = NSLocalizedString("wescan.scanning.manual", tableName: nil, bundle: Bundle(for: ScannerViewController.self), value: "Manual", comment: "The manual button state")
+        } else {
+            CaptureSession.current.isAutoScanEnabled = true
+            autoScanButton.title = NSLocalizedString("wescan.scanning.auto", tableName: nil, bundle: Bundle(for: ScannerViewController.self), value: "Auto", comment: "The auto button state")
+        }
+    }
+    
+    @objc private func toggleFlash() {
+        let state = CaptureSession.current.toggleFlash()
+        
+        let flashImage = UIImage(named: "flash", in: Bundle(for: ScannerViewController.self), compatibleWith: nil)
+        let flashOffImage = UIImage(named: "flashUnavailable", in: Bundle(for: ScannerViewController.self), compatibleWith: nil)
+        
+        switch state {
+        case .on:
+            flashEnabled = true
+            flashButton.image = flashImage
+            flashButton.tintColor = .yellow
+        case .off:
+            flashEnabled = false
+            flashButton.image = flashImage
+            flashButton.tintColor = .white
+        case .unknown, .unavailable:
+            flashEnabled = false
+            flashButton.image = flashOffImage
+            flashButton.tintColor = UIColor.lightGray
+        }
+    }
+    
+    @objc private func cancelImageScannerController() {
+        self.delegate?.scannerViewControllerDidCancel(self)
+    }
+    
+    @objc private func counterImageScannerController(){
+        self.delegate?.scannerViewController(self, reviewItems: self.multipageSession)
+    }
+    
+}
+
+extension ScannerViewController: RectangleDetectionDelegateProtocol {
+    func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didFailWithError error: Error) {
+        
+        activityIndicator.stopAnimating()
+        shutterButton.isUserInteractionEnabled = true
+        
+        self.delegate?.scannerViewController(self, didFail: error)
+    }
+    
+    func didStartCapturingPicture(for captureSessionManager: CaptureSessionManager) {
+        activityIndicator.startAnimating()
+        shutterButton.isUserInteractionEnabled = false
+    }
+    
+    func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didCapturePicture picture: UIImage, withQuad quad: Quadrilateral?) {
+        activityIndicator.stopAnimating()
+        
+        let scannedItem = ScannedItem(originalImage:picture, quad:quad)
+        scannedItem.rotation = self.getCurrentRotationAngle()
+        scannedItem.colorOption = self.options.defaultColorRenderOption
+        scannedItem.render { (_) in }   // Renders the image so we have it ready instead of doing it while reviewing (this speeds the proces a lot because is done in the background)
+        self.multipageSession.add(item: scannedItem)
+        self.updateCounterButton()
+        
+        shutterButton.isUserInteractionEnabled = true
+        self.captureSessionManager?.start()
+    }
+    
+    func captureSessionManager(_ captureSessionManager: CaptureSessionManager, didDetectQuad quad: Quadrilateral?, _ imageSize: CGSize) {
+        guard let quad = quad else {
+            // If no quad has been detected, we remove the currently displayed on on the quadView.
+            quadView.removeQuadrilateral()
+            return
+        }
+        
+        let portraitImageSize = CGSize(width: imageSize.height, height: imageSize.width)
+        
+        let scaleTransform = CGAffineTransform.scaleTransform(forSize: portraitImageSize, aspectFillInSize: quadView.bounds.size)
+        let scaledImageSize = imageSize.applying(scaleTransform)
+        
+        let rotationTransform = CGAffineTransform(rotationAngle: CGFloat.pi / 2.0)
+        
+        let imageBounds = CGRect(origin: .zero, size: scaledImageSize).applying(rotationTransform)
+        
+        let translationTransform = CGAffineTransform.translateTransform(fromCenterOfRect: imageBounds, toCenterOfRect: quadView.bounds)
+        
+        let transforms = [scaleTransform, rotationTransform, translationTransform]
+        
+        let transformedQuad = quad.applyTransforms(transforms)
+        
+        quadView.drawQuadrilateral(quad: transformedQuad, animated: true)
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Scan/ShutterButton.swift b/MiniScanner/Supporting Files/WeScan/Scan/ShutterButton.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6c2f5366f563fc4144f30ff7d075d8ea4d8448d1
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Scan/ShutterButton.swift	
@@ -0,0 +1,101 @@
+//
+//  ShutterButton.swift
+//  WeScan
+//
+//  Created by Boris Emorine on 2/26/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import UIKit
+
+/// A simple button used for the shutter.
+final class ShutterButton: UIControl {
+    
+    private let outterRingLayer = CAShapeLayer()
+    private let innerCircleLayer = CAShapeLayer()
+    
+    private let outterRingRatio: CGFloat = 0.80
+    private let innerRingRatio: CGFloat = 0.75
+    
+    private let impactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
+    
+    override var isHighlighted: Bool {
+        didSet {
+            if oldValue != isHighlighted {
+                animateInnerCircleLayer(forHighlightedState: isHighlighted)
+            }
+        }
+    }
+    
+    // MARL: Life Cycle
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        layer.addSublayer(outterRingLayer)
+        layer.addSublayer(innerCircleLayer)
+        backgroundColor = .clear
+        isAccessibilityElement = true
+        accessibilityTraits = UIAccessibilityTraits.button
+        impactFeedbackGenerator.prepare()
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    // MARK: - Drawing
+    
+    override func draw(_ rect: CGRect) {
+        super.draw(rect)
+
+        outterRingLayer.frame = rect
+        outterRingLayer.path = pathForOutterRing(inRect: rect).cgPath
+        outterRingLayer.fillColor = UIColor.white.cgColor
+        outterRingLayer.rasterizationScale = UIScreen.main.scale
+        outterRingLayer.shouldRasterize = true
+        
+        innerCircleLayer.frame = rect
+        innerCircleLayer.path = pathForInnerCircle(inRect: rect).cgPath
+        innerCircleLayer.fillColor = UIColor.white.cgColor
+        innerCircleLayer.rasterizationScale = UIScreen.main.scale
+        innerCircleLayer.shouldRasterize = true
+    }
+    
+    // MARK: - Animation
+    
+    private func animateInnerCircleLayer(forHighlightedState isHighlighted: Bool) {
+        let animation = CAKeyframeAnimation(keyPath: "transform")
+        var values = [CATransform3DMakeScale(1.0, 1.0, 1.0), CATransform3DMakeScale(0.9, 0.9, 0.9), CATransform3DMakeScale(0.93, 0.93, 0.93), CATransform3DMakeScale(0.9, 0.9, 0.9)]
+        if isHighlighted == false {
+            values = [CATransform3DMakeScale(0.9, 0.9, 0.9), CATransform3DMakeScale(1.0, 1.0, 1.0)]
+        }
+        animation.values = values
+        animation.isRemovedOnCompletion = false
+        animation.fillMode = CAMediaTimingFillMode.forwards
+        animation.duration = isHighlighted ? 0.35 : 0.10
+        
+        innerCircleLayer.add(animation, forKey: "transform")
+        impactFeedbackGenerator.impactOccurred()
+    }
+    
+    // MARK: - Paths
+    
+    private func pathForOutterRing(inRect rect: CGRect) -> UIBezierPath {
+        let path = UIBezierPath(ovalIn: rect)
+        
+        let innerRect = rect.scaleAndCenter(withRatio: outterRingRatio)
+        let innerPath = UIBezierPath(ovalIn: innerRect).reversing()
+        
+        path.append(innerPath)
+        
+        return path
+    }
+    
+    private func pathForInnerCircle(inRect rect: CGRect) -> UIBezierPath {
+        let rect = rect.scaleAndCenter(withRatio: innerRingRatio)
+        let path = UIBezierPath(ovalIn: rect)
+        
+        return path
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Flash.swift b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Flash.swift
new file mode 100644
index 0000000000000000000000000000000000000000..5a37cb6cc2afc3388d8124d268139e7fb02d5cdc
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Flash.swift	
@@ -0,0 +1,45 @@
+//
+//  CaptureSession+Flash.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 28/11/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+
+/// Extension to CaptureSession to manage the device flashlight
+extension CaptureSession {
+    /// The possible states that the current device's flashlight can be in
+    enum FlashState {
+        case on
+        case off
+        case unavailable
+        case unknown
+    }
+    
+    /// Toggles the current device's flashlight on or off.
+    func toggleFlash() -> FlashState {
+        guard let device = device, device.isTorchAvailable else { return .unavailable }
+        
+        do {
+            try device.lockForConfiguration()
+        } catch {
+            return .unknown
+        }
+        
+        defer {
+            device.unlockForConfiguration()
+        }
+        
+        if device.torchMode == .on {
+            device.torchMode = .off
+            return .off
+        } else if device.torchMode == .off {
+            device.torchMode = .on
+            return .on
+        }
+        
+        return .unknown
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Focus.swift b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Focus.swift
new file mode 100644
index 0000000000000000000000000000000000000000..244bbb7d4c00b79eaf4e86ec4a4322a017129c04
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Focus.swift	
@@ -0,0 +1,73 @@
+//
+//  CaptureSession+Focus.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 28/11/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+/// Extension to CaptureSession that controls auto focus
+extension CaptureSession {
+    /// Sets the camera's exposure and focus point to the given point
+    func setFocusPointToTapPoint(_ tapPoint: CGPoint) throws {
+        guard let device = device else {
+            let error = ImageScannerControllerError.inputDevice
+            throw error
+        }
+        
+        try device.lockForConfiguration()
+        
+        defer {
+            device.unlockForConfiguration()
+        }
+        
+        if device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.autoFocus) {
+            device.focusPointOfInterest = tapPoint
+            device.focusMode = .autoFocus
+        }
+        
+        if device.isExposurePointOfInterestSupported, device.isExposureModeSupported(.continuousAutoExposure) {
+            device.exposurePointOfInterest = tapPoint
+            device.exposureMode = .continuousAutoExposure
+        }
+    }
+    
+    /// Resets the camera's exposure and focus point to automatic
+    func resetFocusToAuto() throws {
+        guard let device = device else {
+            let error = ImageScannerControllerError.inputDevice
+            throw error
+        }
+        
+        try device.lockForConfiguration()
+        
+        defer {
+            device.unlockForConfiguration()
+        }
+        
+        if device.isFocusPointOfInterestSupported && device.isFocusModeSupported(.continuousAutoFocus) {
+            device.focusMode = .continuousAutoFocus
+        }
+        
+        if device.isExposurePointOfInterestSupported, device.isExposureModeSupported(.continuousAutoExposure) {
+            device.exposureMode = .continuousAutoExposure
+        }
+    }
+    
+    /// Removes an existing focus rectangle if one exists, optionally animating the exit
+    func removeFocusRectangleIfNeeded(_ focusRectangle: FocusRectangleView?, animated: Bool) {
+        guard let focusRectangle = focusRectangle else { return }
+        if animated {
+            UIView.animate(withDuration: 0.3, delay: 1.0, animations: {
+                focusRectangle.alpha = 0.0
+            }, completion: { (_) in
+                focusRectangle.removeFromSuperview()
+            })
+        } else {
+            focusRectangle.removeFromSuperview()
+        }
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Orientation.swift b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Orientation.swift
new file mode 100644
index 0000000000000000000000000000000000000000..522adf96cd577ea1f17a15d7f9f364496e341558
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession+Orientation.swift	
@@ -0,0 +1,60 @@
+//
+//  CaptureSession+Orientation.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 23/11/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import CoreMotion
+import Foundation
+import UIKit
+
+/// Extension to CaptureSession with support for automatically detecting the current orientation via CoreMotion
+/// Which works even if the user has enabled portrait lock.
+extension CaptureSession {
+    /// Detect the current orientation of the device with CoreMotion and use it to set the `editImageOrientation`.
+    func setImageOrientation() {
+        let motion = CMMotionManager()
+        
+        /// This value should be 0.2, but since we only need one cycle (and stop updates immediately),
+        /// we set it low to get the orientation immediately
+        motion.accelerometerUpdateInterval = 0.01
+        
+        guard motion.isAccelerometerAvailable else { return }
+        
+        motion.startAccelerometerUpdates(to: OperationQueue()) { data, error in
+            guard let data = data, error == nil else { return }
+            
+            /// The minimum amount of sensitivity for the landscape orientations
+            /// This is to prevent the landscape orientation being incorrectly used
+            /// Higher = easier for landscape to be detected, lower = easier for portrait to be detected
+            let motionThreshold = 0.35
+            
+            if data.acceleration.x >= motionThreshold {
+                self.editImageOrientation = .left
+            } else if data.acceleration.x <= -motionThreshold {
+                self.editImageOrientation = .right
+            } else {
+                /// This means the device is either in the 'up' or 'down' orientation, BUT,
+                /// it's very rare for someone to be using their phone upside down, so we use 'up' all the time
+                /// Which prevents accidentally making the document be scanned upside down
+                self.editImageOrientation = .up
+            }
+            
+            motion.stopAccelerometerUpdates()
+            
+            // If the device is reporting a specific landscape orientation, we'll use it over the accelerometer's update.
+            // We don't use this to check for "portrait" because only the accelerometer works when portrait lock is enabled.
+            // For some reason, the left/right orientations are incorrect (flipped) :/
+            switch UIDevice.current.orientation {
+            case .landscapeLeft:
+                self.editImageOrientation = .right
+            case .landscapeRight:
+                self.editImageOrientation = .left
+            default:
+                break
+            }
+        }
+    }
+}
diff --git a/MiniScanner/Supporting Files/WeScan/Session/CaptureSession.swift b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1348abfb501515e455f73b90979d53c6ef522460
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/Session/CaptureSession.swift	
@@ -0,0 +1,37 @@
+//
+//  CaptureSession.swift
+//  WeScan
+//
+//  Created by Julian Schiavo on 23/9/2018.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+
+/// A class containing global variables and settings for this capture session
+final class CaptureSession {
+    
+    static let current = CaptureSession()
+    
+    /// The AVCaptureDevice used for the flash and focus setting
+    var device: CaptureDevice?
+    
+    /// Whether the user is past the scanning screen or not (needed to disable auto scan on other screens)
+    var isEditing: Bool
+    
+    /// The status of auto scan. Auto scan tries to automatically scan a detected rectangle if it has a high enough accuracy.
+    var isAutoScanEnabled: Bool
+    
+    /// The orientation of the captured image
+    var editImageOrientation: CGImagePropertyOrientation
+    
+    private init(isAutoScanEnabled: Bool = true, editImageOrientation: CGImagePropertyOrientation = .up) {
+        self.device = AVCaptureDevice.default(for: .video)
+        
+        self.isEditing = false
+        self.isAutoScanEnabled = isAutoScanEnabled
+        self.editImageOrientation = editImageOrientation
+    }
+    
+}
diff --git a/MiniScanner/Supporting Files/WeScan/WeScan.h b/MiniScanner/Supporting Files/WeScan/WeScan.h
new file mode 100644
index 0000000000000000000000000000000000000000..5a06c9892ae39254b0829db7d07bce209f19f8be
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/WeScan.h	
@@ -0,0 +1,17 @@
+//
+//  WeScan.h
+//  WeScan
+//
+//  Created by Boris Emorine on 2/8/18.
+//  Copyright © 2018 WeTransfer. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+//! Project version number for Scanner.
+FOUNDATION_EXPORT double ScannerVersionNumber;
+
+//! Project version string for Scanner.
+FOUNDATION_EXPORT const unsigned char ScannerVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <Scanner/PublicHeader.h>
diff --git a/MiniScanner/Supporting Files/WeScan/de.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/de.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..6ae9dfb6d529c817a6211281a0f707f7ceb28d3f
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/de.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/*
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+ */
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "Weiter";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "Scan editieren";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "Überprüfen";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "Abbrechen";
+"wescan.scanning.auto" = "Auto";
+"wescan.scanning.manual" = "Manuell";
diff --git a/MiniScanner/Supporting Files/WeScan/en.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/en.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..ec645987447f59bb264e5c7cda8af4348a54cb42
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/en.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/* 
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+*/
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "Next";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "Edit Scan";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "Review";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "Cancel";
+"wescan.scanning.auto" = "Auto";
+"wescan.scanning.manual" = "Manual";
diff --git a/MiniScanner/Supporting Files/WeScan/fr.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/fr.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..b05f258eac508c3b29ff2a16abf6e2b55dc5b033
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/fr.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/*
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+ */
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "Suivant";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "Modifier";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "Aperçu";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "Annuler";
+"wescan.scanning.auto" = "Auto";
+"wescan.scanning.manual" = "Manuel";
diff --git a/MiniScanner/Supporting Files/WeScan/it.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/it.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..ed4b1867e5144b235af4f926d9625929eb4a09ae
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/it.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/* 
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+*/
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "Avanti";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "Modifica Scansione";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "Analisi";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "Annulla";
+"wescan.scanning.auto" = "Auto";
+"wescan.scanning.manual" = "Manuale";
diff --git a/MiniScanner/Supporting Files/WeScan/pt-PT.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/pt-PT.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..44da26d1632171cb429b1237bdc85991e1e72ed9
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/pt-PT.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/* 
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+*/
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "Avançar";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "Editar imagem";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "Rever";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "Cancelar";
+"wescan.scanning.auto" = "Auto";
+"wescan.scanning.manual" = "Manual";
diff --git a/MiniScanner/Supporting Files/WeScan/zh-Hans.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/zh-Hans.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..d136a22c2b4e8edc36d11e4ff612dc438b8d1979
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/zh-Hans.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/* 
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+*/
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "下一步";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "编辑";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "回顾";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "取消";
+"wescan.scanning.auto" = "自动";
+"wescan.scanning.manual" = "手动";
diff --git a/MiniScanner/Supporting Files/WeScan/zh-Hant.lproj/Localizable.strings b/MiniScanner/Supporting Files/WeScan/zh-Hant.lproj/Localizable.strings
new file mode 100644
index 0000000000000000000000000000000000000000..e560c2f89d9b6f52c50d488cc5337a54fe9ab385
--- /dev/null
+++ b/MiniScanner/Supporting Files/WeScan/zh-Hant.lproj/Localizable.strings	
@@ -0,0 +1,21 @@
+/* 
+    localizable.strings
+    WeScanSampleProject
+
+    Created by Boris Emorine on 2/27/18.
+    Copyright © 2018 WeTransfer. All rights reserved.
+*/
+
+/* The "Next" button on the right side of the navigation bar on the Edit screen. */
+"wescan.edit.button.next" = "下一步";
+
+/* The title on the navigation bar of the Edit screen. */
+"wescan.edit.title" = "編輯";
+
+/* The title on the navigation bar of the Review screen. */
+"wescan.review.title" = "回顧";
+
+/* The button titles on the Scanning screen. */
+"wescan.scanning.cancel" = "取消";
+"wescan.scanning.auto" = "自動";
+"wescan.scanning.manual" = "手動";
diff --git a/README.md b/README.md
deleted file mode 100644
index 7bd1dc0bf40d19fc1d43749246083d477b4f3053..0000000000000000000000000000000000000000
--- a/README.md
+++ /dev/null
@@ -1,93 +0,0 @@
-# CamScanner
-
-
-
-## Getting started
-
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
-
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
-
-```
-cd existing_repo
-git remote add origin https://git.beinmedia.com/George/camscanner.git
-git branch -M main
-git push -uf origin main
-```
-
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://git.beinmedia.com/George/camscanner/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
-
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
-
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
-
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
-
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
-
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
-
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
-
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
-
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
-
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
-
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
-
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
-
-## License
-For open source projects, say how it is licensed.
-
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.