From 093d82893b020811e2824091003296e328b8d44b Mon Sep 17 00:00:00 2001 From: Christoph Hagen Date: Fri, 10 Jun 2022 21:20:49 +0200 Subject: [PATCH] Start version 2 --- Caps.xcodeproj/project.pbxproj | 526 +++--- .../xcshareddata/swiftpm/Package.resolved | 51 +- .../UserInterfaceState.xcuserstate | Bin 25583 -> 61444 bytes .../UserInterfaceState.xcuserstate | Bin 56289 -> 0 bytes .../xcshareddata/xcschemes/Caps.xcscheme | 78 + .../xcschemes/xcschememanagement.plist | 19 - .../xcdebugger/Breakpoints_v2.xcbkptlist | 2 +- .../xcschemes/xcschememanagement.plist | 48 +- .../xcschemes/xcschememanagement.plist | 19 - .../xcschemes/xcschememanagement.plist | 35 - Caps/AppDelegate.swift | 126 -- .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 100 +- ...{bottle-cap180.png => bottle-cap180-1.png} | Bin Caps/Assets.xcassets/Contents.json | 6 +- .../camera.imageset/Contents.json | 21 - .../camera.imageset/camera.png | Bin 27639 -> 0 bytes .../camera_square.imageset/Contents.json | 21 - .../camera_square.imageset/camera_square.png | Bin 27499 -> 0 bytes .../cancel.imageset/Contents.json | 21 - .../cancel.imageset/cancel.png | Bin 17002 -> 0 bytes .../launch.imageset/Contents.json | 21 - .../launch.imageset/launch.png | Bin 305451 -> 0 bytes .../mosaic.imageset/Contents.json | 23 - .../mosaic.imageset/picture28.png | Bin 2306 -> 0 bytes .../mosaic.imageset/picture56.png | Bin 2883 -> 0 bytes .../mosaic.imageset/picture84.png | Bin 3380 -> 0 bytes .../search_icon.imageset/Contents.json | 21 - .../search_icon.imageset/search_icon.png | Bin 20367 -> 0 bytes .../settings.imageset/Contents.json | 23 - .../button_settings_white@1x.png | Bin 1708 -> 0 bytes .../button_settings_white@2x.png | Bin 2461 -> 0 bytes .../button_settings_white@3x.png | Bin 3082 -> 0 bytes Caps/Base.lproj/LaunchScreen.storyboard | 46 - Caps/Base.lproj/Main.storyboard | 429 ----- Caps/Camera/CameraError.swift | 32 + Caps/Camera/CameraManager.swift | 172 ++ Caps/Camera/CameraView.swift | 127 ++ Caps/Camera/ContentViewModel.swift | 57 + Caps/Camera/ErrorView.swift | 27 + Caps/Camera/FrameManager.swift | 70 + Caps/Camera/FrameView.swift | 30 + Caps/CapsApp.swift | 18 + Caps/Capture/CameraController.swift | 146 -- Caps/Capture/CameraView.swift | 224 --- Caps/Capture/PhotoCaptureHandler.swift | 56 - Caps/ContentView.swift | 339 ++++ Caps/Data/Cap.swift | 277 ++- Caps/Data/CapData.swift | 32 + Caps/Data/Classifier.swift | 32 +- Caps/Data/Colors.swift | 132 -- Caps/Data/Database.swift | 1572 ++++++----------- Caps/Data/Download.swift | 358 ---- Caps/Data/SortCriteria.swift | 28 + Caps/Data/Storage.swift | 374 ---- Caps/Data/TileImage.swift | 134 -- Caps/Data/Upload.swift | 212 --- Caps/Extensions/Array+Extensions.swift | 30 - Caps/Extensions/CGImage+Extensions.swift | 30 + ...GImagePropertyOrientation+Extensions.swift | 8 - Caps/Extensions/Data+Extensions.swift | 59 + .../Extensions/DispatchGroup+Extensions.swift | 28 - .../UIAlertControllerExtensions.swift | 61 - Caps/Extensions/UIColor+Extensions.swift | 22 - Caps/Extensions/UIImage+Extensions.swift | 50 +- .../UINavigationItem+Extensions.swift | 31 - Caps/Extensions/UIViewExtensions.swift | 23 - Caps/Extensions/URL+Extensions.swift | 25 + .../Extensions/ViewControllerExtensions.swift | 28 - Caps/Info.plist | 76 - Caps/Logger.swift | 18 +- Caps/Presentation/CapCell.swift | 39 - Caps/Presentation/GridViewController.swift | 360 ---- Caps/Presentation/ImageCell.swift | 15 - Caps/Presentation/ImageSelector.swift | 186 -- Caps/Presentation/NavigationController.swift | 33 - .../SearchAndDisplayAccessory.swift | 161 -- .../SearchAndDisplayAccessory.xib | 112 -- Caps/Presentation/SortController.swift | 113 -- .../Preview Assets.xcassets/Contents.json | 6 + Caps/TableView.swift | 885 ---------- Caps/View Components/AlwaysShowPopup.swift | 42 - Caps/View Components/CropView.swift | 53 - Caps/View Components/RoundedButton.swift | 99 -- Caps/View Components/RoundedImageView.swift | 31 - Caps/Views/CapNameEntryView.swift | 31 + Caps/Views/CapRowView.swift | 77 + Caps/Views/GridView.swift | 13 + Caps/Views/SearchField.swift | 40 + Caps/Views/SettingsStatisticRow.swift | 30 + Caps/Views/SettingsView.swift | 74 + Caps/Views/SortCaseRowView.swift | 33 + Caps/Views/SortSelectionView.swift | 95 + 93 files changed, 2604 insertions(+), 6509 deletions(-) delete mode 100644 Caps.xcodeproj/project.xcworkspace/xcuserdata/imac.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Caps.xcodeproj/xcshareddata/xcschemes/Caps.xcscheme delete mode 100644 Caps.xcodeproj/xcuserdata/User.xcuserdatad/xcschemes/xcschememanagement.plist rename Caps.xcodeproj/xcuserdata/{imac.xcuserdatad => ch.xcuserdatad}/xcdebugger/Breakpoints_v2.xcbkptlist (65%) delete mode 100644 Caps.xcodeproj/xcuserdata/christoph.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Caps/AppDelegate.swift create mode 100644 Caps/Assets.xcassets/AccentColor.colorset/Contents.json rename Caps/Assets.xcassets/AppIcon.appiconset/{bottle-cap180.png => bottle-cap180-1.png} (100%) delete mode 100644 Caps/Assets.xcassets/camera.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/camera.imageset/camera.png delete mode 100644 Caps/Assets.xcassets/camera_square.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/camera_square.imageset/camera_square.png delete mode 100644 Caps/Assets.xcassets/cancel.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/cancel.imageset/cancel.png delete mode 100644 Caps/Assets.xcassets/launch.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/launch.imageset/launch.png delete mode 100644 Caps/Assets.xcassets/mosaic.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/mosaic.imageset/picture28.png delete mode 100644 Caps/Assets.xcassets/mosaic.imageset/picture56.png delete mode 100644 Caps/Assets.xcassets/mosaic.imageset/picture84.png delete mode 100644 Caps/Assets.xcassets/search_icon.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/search_icon.imageset/search_icon.png delete mode 100644 Caps/Assets.xcassets/settings.imageset/Contents.json delete mode 100644 Caps/Assets.xcassets/settings.imageset/button_settings_white@1x.png delete mode 100644 Caps/Assets.xcassets/settings.imageset/button_settings_white@2x.png delete mode 100644 Caps/Assets.xcassets/settings.imageset/button_settings_white@3x.png delete mode 100644 Caps/Base.lproj/LaunchScreen.storyboard delete mode 100644 Caps/Base.lproj/Main.storyboard create mode 100644 Caps/Camera/CameraError.swift create mode 100644 Caps/Camera/CameraManager.swift create mode 100644 Caps/Camera/CameraView.swift create mode 100644 Caps/Camera/ContentViewModel.swift create mode 100644 Caps/Camera/ErrorView.swift create mode 100644 Caps/Camera/FrameManager.swift create mode 100644 Caps/Camera/FrameView.swift create mode 100644 Caps/CapsApp.swift delete mode 100644 Caps/Capture/CameraController.swift delete mode 100644 Caps/Capture/CameraView.swift delete mode 100644 Caps/Capture/PhotoCaptureHandler.swift create mode 100644 Caps/ContentView.swift create mode 100644 Caps/Data/CapData.swift delete mode 100644 Caps/Data/Colors.swift delete mode 100644 Caps/Data/Download.swift create mode 100644 Caps/Data/SortCriteria.swift delete mode 100644 Caps/Data/Storage.swift delete mode 100644 Caps/Data/TileImage.swift delete mode 100644 Caps/Data/Upload.swift delete mode 100644 Caps/Extensions/Array+Extensions.swift create mode 100644 Caps/Extensions/CGImage+Extensions.swift create mode 100644 Caps/Extensions/Data+Extensions.swift delete mode 100644 Caps/Extensions/DispatchGroup+Extensions.swift delete mode 100644 Caps/Extensions/UIAlertControllerExtensions.swift delete mode 100644 Caps/Extensions/UIColor+Extensions.swift delete mode 100644 Caps/Extensions/UINavigationItem+Extensions.swift delete mode 100644 Caps/Extensions/UIViewExtensions.swift create mode 100644 Caps/Extensions/URL+Extensions.swift delete mode 100644 Caps/Extensions/ViewControllerExtensions.swift delete mode 100644 Caps/Info.plist delete mode 100644 Caps/Presentation/CapCell.swift delete mode 100644 Caps/Presentation/GridViewController.swift delete mode 100644 Caps/Presentation/ImageCell.swift delete mode 100644 Caps/Presentation/ImageSelector.swift delete mode 100644 Caps/Presentation/NavigationController.swift delete mode 100644 Caps/Presentation/SearchAndDisplayAccessory.swift delete mode 100644 Caps/Presentation/SearchAndDisplayAccessory.xib delete mode 100644 Caps/Presentation/SortController.swift create mode 100644 Caps/Preview Content/Preview Assets.xcassets/Contents.json delete mode 100644 Caps/TableView.swift delete mode 100644 Caps/View Components/AlwaysShowPopup.swift delete mode 100644 Caps/View Components/CropView.swift delete mode 100644 Caps/View Components/RoundedButton.swift delete mode 100644 Caps/View Components/RoundedImageView.swift create mode 100644 Caps/Views/CapNameEntryView.swift create mode 100644 Caps/Views/CapRowView.swift create mode 100644 Caps/Views/GridView.swift create mode 100644 Caps/Views/SearchField.swift create mode 100644 Caps/Views/SettingsStatisticRow.swift create mode 100644 Caps/Views/SettingsView.swift create mode 100644 Caps/Views/SortCaseRowView.swift create mode 100644 Caps/Views/SortSelectionView.swift diff --git a/Caps.xcodeproj/project.pbxproj b/Caps.xcodeproj/project.pbxproj index fce0092..1f8e577 100644 --- a/Caps.xcodeproj/project.pbxproj +++ b/Caps.xcodeproj/project.pbxproj @@ -3,227 +3,196 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 55; objects = { /* Begin PBXBuildFile section */ - 5904C33A2199C9FA0046A573 /* SortController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5904C3392199C9FA0046A573 /* SortController.swift */; }; - 5904C33C2199D0260046A573 /* AlwaysShowPopup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5904C33B2199D0260046A573 /* AlwaysShowPopup.swift */; }; - 59158B1621E37B0200D90CB0 /* GridViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59158B1521E37B0200D90CB0 /* GridViewController.swift */; }; - 59158B1821E4C9AC00D90CB0 /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59158B1721E4C9AC00D90CB0 /* NavigationController.swift */; }; - 591832CE21A2A97E00E5987D /* Cap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 591832CD21A2A97E00E5987D /* Cap.swift */; }; - 591FDD1E234E151600AA379E /* SearchAndDisplayAccessory.xib in Resources */ = {isa = PBXBuildFile; fileRef = 591FDD1D234E151600AA379E /* SearchAndDisplayAccessory.xib */; }; - 591FDD20234E162000AA379E /* SearchAndDisplayAccessory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 591FDD1F234E162000AA379E /* SearchAndDisplayAccessory.swift */; }; - 88A89ECE25AF420F00323B64 /* DispatchGroup+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88A89ECD25AF420F00323B64 /* DispatchGroup+Extensions.swift */; }; - CE0A501124752A9800A9E753 /* TileImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0A501024752A9800A9E753 /* TileImage.swift */; }; - CE0A5013247D745200A9E753 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0A5012247D745200A9E753 /* Colors.swift */; }; - CE56CECE209D81DE00932C01 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CECD209D81DE00932C01 /* AppDelegate.swift */; }; - CE56CED3209D81DE00932C01 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE56CED1209D81DE00932C01 /* Main.storyboard */; }; - CE56CED5209D81E000932C01 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE56CED4209D81E000932C01 /* Assets.xcassets */; }; - CE56CED8209D81E000932C01 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE56CED6209D81E000932C01 /* LaunchScreen.storyboard */; }; - CE56CEF8209D83B800932C01 /* CapCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEE0209D83B200932C01 /* CapCell.swift */; }; - CE56CEFE209D83B800932C01 /* RoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEE6209D83B300932C01 /* RoundedButton.swift */; }; - CE56CEFF209D83B800932C01 /* CameraController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEE7209D83B300932C01 /* CameraController.swift */; }; - CE56CF02209D83B800932C01 /* RoundedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEEA209D83B400932C01 /* RoundedImageView.swift */; }; - CE56CF03209D83B800932C01 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEEB209D83B400932C01 /* TableView.swift */; }; - CE56CF04209D83B800932C01 /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEEC209D83B400932C01 /* UIViewExtensions.swift */; }; - CE56CF05209D83B800932C01 /* ViewControllerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEED209D83B400932C01 /* ViewControllerExtensions.swift */; }; - CE56CF06209D83B800932C01 /* CameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEEE209D83B500932C01 /* CameraView.swift */; }; - CE56CF07209D83B800932C01 /* ImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEEF209D83B500932C01 /* ImageCell.swift */; }; - CE56CF08209D83B800932C01 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF0209D83B500932C01 /* Storage.swift */; }; - CE56CF09209D83B800932C01 /* Classifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF1209D83B500932C01 /* Classifier.swift */; }; - CE56CF0A209D83B800932C01 /* CropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF2209D83B600932C01 /* CropView.swift */; }; - CE56CF0B209D83B800932C01 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF3209D83B600932C01 /* Logger.swift */; }; - CE56CF0D209D83B800932C01 /* ImageSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF5209D83B600932C01 /* ImageSelector.swift */; }; - CE56CF0E209D83B800932C01 /* PhotoCaptureHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF6209D83B700932C01 /* PhotoCaptureHandler.swift */; }; - CE56CF0F209D83B800932C01 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE56CEF7209D83B700932C01 /* UIImage+Extensions.swift */; }; - CE5B7CFC24562673002E5C06 /* Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5B7CFB24562673002E5C06 /* Download.swift */; }; - CE5B7CFE245626D3002E5C06 /* Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5B7CFD245626D3002E5C06 /* Upload.swift */; }; - CE5B7D032458C921002E5C06 /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = CE5B7D022458C921002E5C06 /* Reachability */; }; - CE6E4828246C304100570CB0 /* CGImagePropertyOrientation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6E4827246C304100570CB0 /* CGImagePropertyOrientation+Extensions.swift */; }; - CE85AA16246A96C3002D1074 /* UINavigationItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE85AA15246A96C3002D1074 /* UINavigationItem+Extensions.swift */; }; - CE85AA18246B012B002D1074 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE85AA17246B012B002D1074 /* Array+Extensions.swift */; }; - CEB269572445DB56004B74B3 /* SQLite in Frameworks */ = {isa = PBXBuildFile; productRef = CEB269562445DB56004B74B3 /* SQLite */; }; - CEB269592445DB72004B74B3 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB269582445DB72004B74B3 /* Database.swift */; }; - CEB2695B2445E54E004B74B3 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB2695A2445E54E004B74B3 /* UIColor+Extensions.swift */; }; + E25AAC7C283D855D006E9E7F /* CapsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC7B283D855D006E9E7F /* CapsApp.swift */; }; + E25AAC7E283D855D006E9E7F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC7D283D855D006E9E7F /* ContentView.swift */; }; + E25AAC80283D855F006E9E7F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E25AAC7F283D855F006E9E7F /* Assets.xcassets */; }; + E25AAC83283D855F006E9E7F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E25AAC82283D855F006E9E7F /* Preview Assets.xcassets */; }; + E25AAC8B283D868D006E9E7F /* Classifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC8A283D868D006E9E7F /* Classifier.swift */; }; + E25AAC8D283D86CF006E9E7F /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC8C283D86CF006E9E7F /* Logger.swift */; }; + E25AAC90283D871E006E9E7F /* CGImagePropertyOrientation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC8F283D871E006E9E7F /* CGImagePropertyOrientation+Extensions.swift */; }; + E25AAC92283D8808006E9E7F /* CapData.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC91283D8808006E9E7F /* CapData.swift */; }; + E25AAC94283D88A4006E9E7F /* Cap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC93283D88A4006E9E7F /* Cap.swift */; }; + E25AAC96283E14DF006E9E7F /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC95283E14DF006E9E7F /* Database.swift */; }; + E25AAC9B283E3395006E9E7F /* CapRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E25AAC9A283E3395006E9E7F /* CapRowView.swift */; }; + E27E15E1283E418600F6804A /* CachedAsyncImage in Frameworks */ = {isa = PBXBuildFile; productRef = E27E15E0283E418600F6804A /* CachedAsyncImage */; }; + E2EA00C3283E672A00F7B269 /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = E2EA00C2283E672A00F7B269 /* SFSafeSymbols */; }; + E2EA00C5283EA72000F7B269 /* SortCriteria.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00C4283EA72000F7B269 /* SortCriteria.swift */; }; + E2EA00C7283EAA0100F7B269 /* SortSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00C6283EAA0100F7B269 /* SortSelectionView.swift */; }; + E2EA00CA283EACB200F7B269 /* BottomSheet in Frameworks */ = {isa = PBXBuildFile; productRef = E2EA00C9283EACB200F7B269 /* BottomSheet */; }; + E2EA00CC283EB43E00F7B269 /* SortCaseRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00CB283EB43E00F7B269 /* SortCaseRowView.swift */; }; + E2EA00CE283EBEB600F7B269 /* SearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00CD283EBEB600F7B269 /* SearchField.swift */; }; + E2EA00D1283EDD6300F7B269 /* CameraManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00D0283EDD6300F7B269 /* CameraManager.swift */; }; + E2EA00D3283EDDF700F7B269 /* CameraError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00D2283EDDF700F7B269 /* CameraError.swift */; }; + E2EA00D5283EDFA200F7B269 /* FrameManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00D4283EDFA200F7B269 /* FrameManager.swift */; }; + E2EA00D9283F5BB900F7B269 /* CameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00D8283F5BB900F7B269 /* CameraView.swift */; }; + E2EA00DB283F5C0600F7B269 /* ContentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00DA283F5C0600F7B269 /* ContentViewModel.swift */; }; + E2EA00DD283F5C6A00F7B269 /* FrameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00DC283F5C6A00F7B269 /* FrameView.swift */; }; + E2EA00DF283F5CA000F7B269 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00DE283F5CA000F7B269 /* ErrorView.swift */; }; + E2EA00E1283F658E00F7B269 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00E0283F658E00F7B269 /* SettingsView.swift */; }; + E2EA00E3283F662800F7B269 /* GridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00E2283F662800F7B269 /* GridView.swift */; }; + E2EA00E5283F69DF00F7B269 /* SettingsStatisticRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00E4283F69DF00F7B269 /* SettingsStatisticRow.swift */; }; + E2EA00E7283F6D0800F7B269 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00E6283F6D0800F7B269 /* URL+Extensions.swift */; }; + E2EA00EB284109CC00F7B269 /* CGImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00EA284109CC00F7B269 /* CGImage+Extensions.swift */; }; + E2EA00ED2841170100F7B269 /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00EC2841170100F7B269 /* UIImage+Extensions.swift */; }; + E2EA00EF28420AA000F7B269 /* Data+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00EE28420AA000F7B269 /* Data+Extensions.swift */; }; + E2EA00F328438E6B00F7B269 /* CapNameEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EA00F228438E6B00F7B269 /* CapNameEntryView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 5904C3392199C9FA0046A573 /* SortController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortController.swift; sourceTree = ""; }; - 5904C33B2199D0260046A573 /* AlwaysShowPopup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlwaysShowPopup.swift; sourceTree = ""; }; - 59158B1521E37B0200D90CB0 /* GridViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridViewController.swift; sourceTree = ""; }; - 59158B1721E4C9AC00D90CB0 /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = ""; }; - 591832CD21A2A97E00E5987D /* Cap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cap.swift; sourceTree = ""; }; - 591FDD1D234E151600AA379E /* SearchAndDisplayAccessory.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SearchAndDisplayAccessory.xib; sourceTree = ""; }; - 591FDD1F234E162000AA379E /* SearchAndDisplayAccessory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchAndDisplayAccessory.swift; sourceTree = ""; }; - 88A89ECD25AF420F00323B64 /* DispatchGroup+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DispatchGroup+Extensions.swift"; sourceTree = ""; }; - CE0A501024752A9800A9E753 /* TileImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileImage.swift; sourceTree = ""; }; - CE0A5012247D745200A9E753 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; - CE56CECA209D81DD00932C01 /* Caps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Caps.app; sourceTree = BUILT_PRODUCTS_DIR; }; - CE56CECD209D81DE00932C01 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - CE56CED2209D81DE00932C01 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - CE56CED4209D81E000932C01 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - CE56CED7209D81E000932C01 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - CE56CED9209D81E000932C01 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CE56CEE0209D83B200932C01 /* CapCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CapCell.swift; sourceTree = ""; }; - CE56CEE6209D83B300932C01 /* RoundedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoundedButton.swift; sourceTree = ""; }; - CE56CEE7209D83B300932C01 /* CameraController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraController.swift; sourceTree = ""; }; - CE56CEE8209D83B300932C01 /* UIAlertControllerExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIAlertControllerExtensions.swift; sourceTree = ""; }; - CE56CEEA209D83B400932C01 /* RoundedImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoundedImageView.swift; sourceTree = ""; }; - CE56CEEB209D83B400932C01 /* TableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TableView.swift; path = ../TableView.swift; sourceTree = ""; }; - CE56CEEC209D83B400932C01 /* UIViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewExtensions.swift; sourceTree = ""; }; - CE56CEED209D83B400932C01 /* ViewControllerExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewControllerExtensions.swift; sourceTree = ""; }; - CE56CEEE209D83B500932C01 /* CameraView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = ""; }; - CE56CEEF209D83B500932C01 /* ImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCell.swift; sourceTree = ""; }; - CE56CEF0209D83B500932C01 /* Storage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; - CE56CEF1209D83B500932C01 /* Classifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Classifier.swift; sourceTree = ""; }; - CE56CEF2209D83B600932C01 /* CropView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropView.swift; sourceTree = ""; }; - CE56CEF3209D83B600932C01 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; - CE56CEF5209D83B600932C01 /* ImageSelector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageSelector.swift; sourceTree = ""; }; - CE56CEF6209D83B700932C01 /* PhotoCaptureHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoCaptureHandler.swift; sourceTree = ""; }; - CE56CEF7209D83B700932C01 /* UIImage+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = ""; }; - CE5B7CFB24562673002E5C06 /* Download.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Download.swift; sourceTree = ""; }; - CE5B7CFD245626D3002E5C06 /* Upload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Upload.swift; sourceTree = ""; }; - CE6E4827246C304100570CB0 /* CGImagePropertyOrientation+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGImagePropertyOrientation+Extensions.swift"; sourceTree = ""; }; - CE85AA15246A96C3002D1074 /* UINavigationItem+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+Extensions.swift"; sourceTree = ""; }; - CE85AA17246B012B002D1074 /* Array+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = ""; }; - CEB269582445DB72004B74B3 /* Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = ""; }; - CEB2695A2445E54E004B74B3 /* UIColor+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extensions.swift"; sourceTree = ""; }; + E25AAC78283D855D006E9E7F /* Caps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Caps.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E25AAC7B283D855D006E9E7F /* CapsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapsApp.swift; sourceTree = ""; }; + E25AAC7D283D855D006E9E7F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + E25AAC7F283D855F006E9E7F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E25AAC82283D855F006E9E7F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + E25AAC8A283D868D006E9E7F /* Classifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Classifier.swift; sourceTree = ""; }; + E25AAC8C283D86CF006E9E7F /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; + E25AAC8F283D871E006E9E7F /* CGImagePropertyOrientation+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGImagePropertyOrientation+Extensions.swift"; sourceTree = ""; }; + E25AAC91283D8808006E9E7F /* CapData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapData.swift; sourceTree = ""; }; + E25AAC93283D88A4006E9E7F /* Cap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cap.swift; sourceTree = ""; }; + E25AAC95283E14DF006E9E7F /* Database.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = ""; }; + E25AAC9A283E3395006E9E7F /* CapRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapRowView.swift; sourceTree = ""; }; + E2EA00C4283EA72000F7B269 /* SortCriteria.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortCriteria.swift; sourceTree = ""; }; + E2EA00C6283EAA0100F7B269 /* SortSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortSelectionView.swift; sourceTree = ""; }; + E2EA00CB283EB43E00F7B269 /* SortCaseRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortCaseRowView.swift; sourceTree = ""; }; + E2EA00CD283EBEB600F7B269 /* SearchField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchField.swift; sourceTree = ""; }; + E2EA00D0283EDD6300F7B269 /* CameraManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraManager.swift; sourceTree = ""; }; + E2EA00D2283EDDF700F7B269 /* CameraError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraError.swift; sourceTree = ""; }; + E2EA00D4283EDFA200F7B269 /* FrameManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameManager.swift; sourceTree = ""; }; + E2EA00D8283F5BB900F7B269 /* CameraView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = ""; }; + E2EA00DA283F5C0600F7B269 /* ContentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewModel.swift; sourceTree = ""; }; + E2EA00DC283F5C6A00F7B269 /* FrameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameView.swift; sourceTree = ""; }; + E2EA00DE283F5CA000F7B269 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = ""; }; + E2EA00E0283F658E00F7B269 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + E2EA00E2283F662800F7B269 /* GridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridView.swift; sourceTree = ""; }; + E2EA00E4283F69DF00F7B269 /* SettingsStatisticRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsStatisticRow.swift; sourceTree = ""; }; + E2EA00E6283F6D0800F7B269 /* URL+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = ""; }; + E2EA00EA284109CC00F7B269 /* CGImage+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGImage+Extensions.swift"; sourceTree = ""; }; + E2EA00EC2841170100F7B269 /* UIImage+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = ""; }; + E2EA00EE28420AA000F7B269 /* Data+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Extensions.swift"; sourceTree = ""; }; + E2EA00F228438E6B00F7B269 /* CapNameEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapNameEntryView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - CE56CEC7209D81DD00932C01 /* Frameworks */ = { + E25AAC75283D855D006E9E7F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CEB269572445DB56004B74B3 /* SQLite in Frameworks */, - CE5B7D032458C921002E5C06 /* Reachability in Frameworks */, + E2EA00C3283E672A00F7B269 /* SFSafeSymbols in Frameworks */, + E2EA00CA283EACB200F7B269 /* BottomSheet in Frameworks */, + E27E15E1283E418600F6804A /* CachedAsyncImage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - CE56CEC1209D81DD00932C01 = { + E25AAC6F283D855D006E9E7F = { isa = PBXGroup; children = ( - CE56CECC209D81DD00932C01 /* Caps */, - CE56CECB209D81DD00932C01 /* Products */, + E25AAC7A283D855D006E9E7F /* Caps */, + E25AAC79283D855D006E9E7F /* Products */, ); sourceTree = ""; }; - CE56CECB209D81DD00932C01 /* Products */ = { + E25AAC79283D855D006E9E7F /* Products */ = { isa = PBXGroup; children = ( - CE56CECA209D81DD00932C01 /* Caps.app */, + E25AAC78283D855D006E9E7F /* Caps.app */, ); name = Products; sourceTree = ""; }; - CE56CECC209D81DD00932C01 /* Caps */ = { + E25AAC7A283D855D006E9E7F /* Caps */ = { isa = PBXGroup; children = ( - CE56CECD209D81DE00932C01 /* AppDelegate.swift */, - CE56CED1209D81DE00932C01 /* Main.storyboard */, - CEF3874D209D9378001C8D3C /* Capture */, - CEF38750209D93D1001C8D3C /* Data */, - CEF3874B209D932E001C8D3C /* View Components */, - CEF3874F209D93A6001C8D3C /* Presentation */, - CEF3874C209D935E001C8D3C /* Extensions */, - CE56CEF3209D83B600932C01 /* Logger.swift */, - CE56CEDF209D81FD00932C01 /* Support */, + E25AAC7B283D855D006E9E7F /* CapsApp.swift */, + E25AAC7D283D855D006E9E7F /* ContentView.swift */, + E2EA00CF283EDD2C00F7B269 /* Camera */, + E25AAC97283E337C006E9E7F /* Views */, + E25AAC89283D8666006E9E7F /* Data */, + E25AAC7F283D855F006E9E7F /* Assets.xcassets */, + E25AAC8E283D870F006E9E7F /* Extensions */, + E25AAC8C283D86CF006E9E7F /* Logger.swift */, + E25AAC81283D855F006E9E7F /* Preview Content */, ); path = Caps; sourceTree = ""; }; - CE56CEDF209D81FD00932C01 /* Support */ = { + E25AAC81283D855F006E9E7F /* Preview Content */ = { isa = PBXGroup; children = ( - CE56CED4209D81E000932C01 /* Assets.xcassets */, - CE56CED6209D81E000932C01 /* LaunchScreen.storyboard */, - CE56CED9209D81E000932C01 /* Info.plist */, + E25AAC82283D855F006E9E7F /* Preview Assets.xcassets */, ); - name = Support; + path = "Preview Content"; sourceTree = ""; }; - CEF3874B209D932E001C8D3C /* View Components */ = { + E25AAC89283D8666006E9E7F /* Data */ = { isa = PBXGroup; children = ( - 5904C33B2199D0260046A573 /* AlwaysShowPopup.swift */, - CE56CEF2209D83B600932C01 /* CropView.swift */, - CE56CEEA209D83B400932C01 /* RoundedImageView.swift */, - CE56CEE6209D83B300932C01 /* RoundedButton.swift */, + E25AAC8A283D868D006E9E7F /* Classifier.swift */, + E2EA00C4283EA72000F7B269 /* SortCriteria.swift */, + E25AAC93283D88A4006E9E7F /* Cap.swift */, + E25AAC91283D8808006E9E7F /* CapData.swift */, + E25AAC95283E14DF006E9E7F /* Database.swift */, ); - path = "View Components"; + path = Data; sourceTree = ""; }; - CEF3874C209D935E001C8D3C /* Extensions */ = { + E25AAC8E283D870F006E9E7F /* Extensions */ = { isa = PBXGroup; children = ( - CE56CEE8209D83B300932C01 /* UIAlertControllerExtensions.swift */, - CE6E4827246C304100570CB0 /* CGImagePropertyOrientation+Extensions.swift */, - CE85AA17246B012B002D1074 /* Array+Extensions.swift */, - CE85AA15246A96C3002D1074 /* UINavigationItem+Extensions.swift */, - CEB2695A2445E54E004B74B3 /* UIColor+Extensions.swift */, - CE56CEF7209D83B700932C01 /* UIImage+Extensions.swift */, - CE56CEEC209D83B400932C01 /* UIViewExtensions.swift */, - CE56CEED209D83B400932C01 /* ViewControllerExtensions.swift */, - 88A89ECD25AF420F00323B64 /* DispatchGroup+Extensions.swift */, + E25AAC8F283D871E006E9E7F /* CGImagePropertyOrientation+Extensions.swift */, + E2EA00EC2841170100F7B269 /* UIImage+Extensions.swift */, + E2EA00E6283F6D0800F7B269 /* URL+Extensions.swift */, + E2EA00EA284109CC00F7B269 /* CGImage+Extensions.swift */, + E2EA00EE28420AA000F7B269 /* Data+Extensions.swift */, ); path = Extensions; sourceTree = ""; }; - CEF3874D209D9378001C8D3C /* Capture */ = { + E25AAC97283E337C006E9E7F /* Views */ = { isa = PBXGroup; children = ( - CE56CEE7209D83B300932C01 /* CameraController.swift */, - CE56CEEE209D83B500932C01 /* CameraView.swift */, - CE56CEF6209D83B700932C01 /* PhotoCaptureHandler.swift */, + E25AAC9A283E3395006E9E7F /* CapRowView.swift */, + E2EA00E2283F662800F7B269 /* GridView.swift */, + E2EA00E0283F658E00F7B269 /* SettingsView.swift */, + E2EA00E4283F69DF00F7B269 /* SettingsStatisticRow.swift */, + E2EA00CD283EBEB600F7B269 /* SearchField.swift */, + E2EA00F228438E6B00F7B269 /* CapNameEntryView.swift */, + E2EA00C6283EAA0100F7B269 /* SortSelectionView.swift */, + E2EA00CB283EB43E00F7B269 /* SortCaseRowView.swift */, ); - path = Capture; + path = Views; sourceTree = ""; }; - CEF3874F209D93A6001C8D3C /* Presentation */ = { + E2EA00CF283EDD2C00F7B269 /* Camera */ = { isa = PBXGroup; children = ( - CE56CEEB209D83B400932C01 /* TableView.swift */, - 591FDD1D234E151600AA379E /* SearchAndDisplayAccessory.xib */, - 591FDD1F234E162000AA379E /* SearchAndDisplayAccessory.swift */, - 59158B1721E4C9AC00D90CB0 /* NavigationController.swift */, - CE56CEE0209D83B200932C01 /* CapCell.swift */, - CE56CEF5209D83B600932C01 /* ImageSelector.swift */, - CE56CEEF209D83B500932C01 /* ImageCell.swift */, - 5904C3392199C9FA0046A573 /* SortController.swift */, - 59158B1521E37B0200D90CB0 /* GridViewController.swift */, + E2EA00D0283EDD6300F7B269 /* CameraManager.swift */, + E2EA00D8283F5BB900F7B269 /* CameraView.swift */, + E2EA00DA283F5C0600F7B269 /* ContentViewModel.swift */, + E2EA00DC283F5C6A00F7B269 /* FrameView.swift */, + E2EA00D4283EDFA200F7B269 /* FrameManager.swift */, + E2EA00D2283EDDF700F7B269 /* CameraError.swift */, + E2EA00DE283F5CA000F7B269 /* ErrorView.swift */, ); - path = Presentation; - sourceTree = ""; - }; - CEF38750209D93D1001C8D3C /* Data */ = { - isa = PBXGroup; - children = ( - CE56CEF1209D83B500932C01 /* Classifier.swift */, - 591832CD21A2A97E00E5987D /* Cap.swift */, - CE56CEF0209D83B500932C01 /* Storage.swift */, - CE5B7CFB24562673002E5C06 /* Download.swift */, - CE5B7CFD245626D3002E5C06 /* Upload.swift */, - CEB269582445DB72004B74B3 /* Database.swift */, - CE0A5012247D745200A9E753 /* Colors.swift */, - CE0A501024752A9800A9E753 /* TileImage.swift */, - ); - path = Data; + path = Camera; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - CE56CEC9209D81DD00932C01 /* Caps */ = { + E25AAC77283D855D006E9E7F /* Caps */ = { isa = PBXNativeTarget; - buildConfigurationList = CE56CEDC209D81E000932C01 /* Build configuration list for PBXNativeTarget "Caps" */; + buildConfigurationList = E25AAC86283D855F006E9E7F /* Build configuration list for PBXNativeTarget "Caps" */; buildPhases = ( - CE56CEC6209D81DD00932C01 /* Sources */, - CE56CEC7209D81DD00932C01 /* Frameworks */, - CE56CEC8209D81DD00932C01 /* Resources */, + E25AAC74283D855D006E9E7F /* Sources */, + E25AAC75283D855D006E9E7F /* Frameworks */, + E25AAC76283D855D006E9E7F /* Resources */, ); buildRules = ( ); @@ -231,141 +200,110 @@ ); name = Caps; packageProductDependencies = ( - CEB269562445DB56004B74B3 /* SQLite */, - CE5B7D022458C921002E5C06 /* Reachability */, + E27E15E0283E418600F6804A /* CachedAsyncImage */, + E2EA00C2283E672A00F7B269 /* SFSafeSymbols */, + E2EA00C9283EACB200F7B269 /* BottomSheet */, ); - productName = CapCollector; - productReference = CE56CECA209D81DD00932C01 /* Caps.app */; + productName = Caps; + productReference = E25AAC78283D855D006E9E7F /* Caps.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - CE56CEC2209D81DD00932C01 /* Project object */ = { + E25AAC70283D855D006E9E7F /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0940; - LastUpgradeCheck = 1200; - ORGANIZATIONNAME = CH; + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1340; + LastUpgradeCheck = 1340; TargetAttributes = { - CE56CEC9209D81DD00932C01 = { - CreatedOnToolsVersion = 9.4; - LastSwiftMigration = 1100; - SystemCapabilities = { - com.apple.BackgroundModes = { - enabled = 0; - }; - }; + E25AAC77283D855D006E9E7F = { + CreatedOnToolsVersion = 13.4; }; }; }; - buildConfigurationList = CE56CEC5209D81DD00932C01 /* Build configuration list for PBXProject "Caps" */; - compatibilityVersion = "Xcode 9.3"; + buildConfigurationList = E25AAC73283D855D006E9E7F /* Build configuration list for PBXProject "Caps" */; + compatibilityVersion = "Xcode 13.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = CE56CEC1209D81DD00932C01; + mainGroup = E25AAC6F283D855D006E9E7F; packageReferences = ( - CEB269552445DB56004B74B3 /* XCRemoteSwiftPackageReference "SQLite" */, - CE5B7D012458C921002E5C06 /* XCRemoteSwiftPackageReference "Reachability" */, + E27E15DF283E418600F6804A /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */, + E2EA00C1283E672A00F7B269 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */, + E2EA00C8283EACB200F7B269 /* XCRemoteSwiftPackageReference "bottom-sheet" */, ); - productRefGroup = CE56CECB209D81DD00932C01 /* Products */; + productRefGroup = E25AAC79283D855D006E9E7F /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - CE56CEC9209D81DD00932C01 /* Caps */, + E25AAC77283D855D006E9E7F /* Caps */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - CE56CEC8209D81DD00932C01 /* Resources */ = { + E25AAC76283D855D006E9E7F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - CE56CED8209D81E000932C01 /* LaunchScreen.storyboard in Resources */, - 591FDD1E234E151600AA379E /* SearchAndDisplayAccessory.xib in Resources */, - CE56CED5209D81E000932C01 /* Assets.xcassets in Resources */, - CE56CED3209D81DE00932C01 /* Main.storyboard in Resources */, + E25AAC83283D855F006E9E7F /* Preview Assets.xcassets in Resources */, + E25AAC80283D855F006E9E7F /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - CE56CEC6209D81DD00932C01 /* Sources */ = { + E25AAC74283D855D006E9E7F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CE56CF09209D83B800932C01 /* Classifier.swift in Sources */, - CE0A5013247D745200A9E753 /* Colors.swift in Sources */, - 5904C33A2199C9FA0046A573 /* SortController.swift in Sources */, - CE56CF0B209D83B800932C01 /* Logger.swift in Sources */, - CE56CF04209D83B800932C01 /* UIViewExtensions.swift in Sources */, - 59158B1821E4C9AC00D90CB0 /* NavigationController.swift in Sources */, - 591832CE21A2A97E00E5987D /* Cap.swift in Sources */, - CE56CF08209D83B800932C01 /* Storage.swift in Sources */, - CE56CF0F209D83B800932C01 /* UIImage+Extensions.swift in Sources */, - CE5B7CFC24562673002E5C06 /* Download.swift in Sources */, - CE85AA18246B012B002D1074 /* Array+Extensions.swift in Sources */, - CE56CF03209D83B800932C01 /* TableView.swift in Sources */, - CEB2695B2445E54E004B74B3 /* UIColor+Extensions.swift in Sources */, - 591FDD20234E162000AA379E /* SearchAndDisplayAccessory.swift in Sources */, - 59158B1621E37B0200D90CB0 /* GridViewController.swift in Sources */, - CE5B7CFE245626D3002E5C06 /* Upload.swift in Sources */, - CE56CECE209D81DE00932C01 /* AppDelegate.swift in Sources */, - CE56CF0D209D83B800932C01 /* ImageSelector.swift in Sources */, - CE56CEFF209D83B800932C01 /* CameraController.swift in Sources */, - CE56CF05209D83B800932C01 /* ViewControllerExtensions.swift in Sources */, - CE56CF0E209D83B800932C01 /* PhotoCaptureHandler.swift in Sources */, - CE56CEFE209D83B800932C01 /* RoundedButton.swift in Sources */, - CE56CF07209D83B800932C01 /* ImageCell.swift in Sources */, - CE56CF06209D83B800932C01 /* CameraView.swift in Sources */, - CE56CF0A209D83B800932C01 /* CropView.swift in Sources */, - 5904C33C2199D0260046A573 /* AlwaysShowPopup.swift in Sources */, - CE85AA16246A96C3002D1074 /* UINavigationItem+Extensions.swift in Sources */, - CEB269592445DB72004B74B3 /* Database.swift in Sources */, - CE56CF02209D83B800932C01 /* RoundedImageView.swift in Sources */, - 88A89ECE25AF420F00323B64 /* DispatchGroup+Extensions.swift in Sources */, - CE0A501124752A9800A9E753 /* TileImage.swift in Sources */, - CE56CEF8209D83B800932C01 /* CapCell.swift in Sources */, - CE6E4828246C304100570CB0 /* CGImagePropertyOrientation+Extensions.swift in Sources */, + E25AAC7E283D855D006E9E7F /* ContentView.swift in Sources */, + E2EA00F328438E6B00F7B269 /* CapNameEntryView.swift in Sources */, + E25AAC8B283D868D006E9E7F /* Classifier.swift in Sources */, + E25AAC94283D88A4006E9E7F /* Cap.swift in Sources */, + E2EA00D9283F5BB900F7B269 /* CameraView.swift in Sources */, + E2EA00E3283F662800F7B269 /* GridView.swift in Sources */, + E2EA00EB284109CC00F7B269 /* CGImage+Extensions.swift in Sources */, + E2EA00DF283F5CA000F7B269 /* ErrorView.swift in Sources */, + E2EA00D5283EDFA200F7B269 /* FrameManager.swift in Sources */, + E25AAC90283D871E006E9E7F /* CGImagePropertyOrientation+Extensions.swift in Sources */, + E2EA00CE283EBEB600F7B269 /* SearchField.swift in Sources */, + E2EA00C7283EAA0100F7B269 /* SortSelectionView.swift in Sources */, + E2EA00DD283F5C6A00F7B269 /* FrameView.swift in Sources */, + E2EA00EF28420AA000F7B269 /* Data+Extensions.swift in Sources */, + E2EA00C5283EA72000F7B269 /* SortCriteria.swift in Sources */, + E25AAC7C283D855D006E9E7F /* CapsApp.swift in Sources */, + E2EA00D1283EDD6300F7B269 /* CameraManager.swift in Sources */, + E25AAC9B283E3395006E9E7F /* CapRowView.swift in Sources */, + E2EA00DB283F5C0600F7B269 /* ContentViewModel.swift in Sources */, + E2EA00CC283EB43E00F7B269 /* SortCaseRowView.swift in Sources */, + E2EA00E7283F6D0800F7B269 /* URL+Extensions.swift in Sources */, + E2EA00D3283EDDF700F7B269 /* CameraError.swift in Sources */, + E25AAC92283D8808006E9E7F /* CapData.swift in Sources */, + E25AAC96283E14DF006E9E7F /* Database.swift in Sources */, + E25AAC8D283D86CF006E9E7F /* Logger.swift in Sources */, + E2EA00ED2841170100F7B269 /* UIImage+Extensions.swift in Sources */, + E2EA00E5283F69DF00F7B269 /* SettingsStatisticRow.swift in Sources */, + E2EA00E1283F658E00F7B269 /* SettingsView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXVariantGroup section */ - CE56CED1209D81DE00932C01 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - CE56CED2209D81DE00932C01 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - CE56CED6209D81E000932C01 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - CE56CED7209D81E000932C01 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ - CE56CEDA209D81E000932C01 /* Debug */ = { + E25AAC84283D855F006E9E7F /* 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_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -391,7 +329,6 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -410,8 +347,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -419,14 +357,13 @@ }; name = Debug; }; - CE56CEDB209D81E000932C01 /* Release */ = { + E25AAC85283D855F006E9E7F /* 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_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -452,7 +389,6 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -465,8 +401,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.5; MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -474,47 +411,63 @@ }; name = Release; }; - CE56CEDD209D81E000932C01 /* Debug */ = { + E25AAC87283D855F006E9E7F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Caps/Preview Content\""; DEVELOPMENT_TEAM = H8WR4M6QQ4; - INFOPLIST_FILE = "$(SRCROOT)/Caps/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSCameraUsageDescription = "Take images to identify matching caps and register new ones"; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.4; + MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = de.christophhagen.Caps; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; name = Debug; }; - CE56CEDE209D81E000932C01 /* Release */ = { + E25AAC88283D855F006E9E7F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "iPhone Developer"; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Caps/Preview Content\""; DEVELOPMENT_TEAM = H8WR4M6QQ4; - INFOPLIST_FILE = "$(SRCROOT)/Caps/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 14.0; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSCameraUsageDescription = "Take images to identify matching caps and register new ones"; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.4; + MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = de.christophhagen.Caps; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; }; @@ -523,20 +476,20 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - CE56CEC5209D81DD00932C01 /* Build configuration list for PBXProject "Caps" */ = { + E25AAC73283D855D006E9E7F /* Build configuration list for PBXProject "Caps" */ = { isa = XCConfigurationList; buildConfigurations = ( - CE56CEDA209D81E000932C01 /* Debug */, - CE56CEDB209D81E000932C01 /* Release */, + E25AAC84283D855F006E9E7F /* Debug */, + E25AAC85283D855F006E9E7F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CE56CEDC209D81E000932C01 /* Build configuration list for PBXNativeTarget "Caps" */ = { + E25AAC86283D855F006E9E7F /* Build configuration list for PBXNativeTarget "Caps" */ = { isa = XCConfigurationList; buildConfigurations = ( - CE56CEDD209D81E000932C01 /* Debug */, - CE56CEDE209D81E000932C01 /* Release */, + E25AAC87283D855F006E9E7F /* Debug */, + E25AAC88283D855F006E9E7F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -544,36 +497,49 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - CE5B7D012458C921002E5C06 /* XCRemoteSwiftPackageReference "Reachability" */ = { + E27E15DF283E418600F6804A /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/ashleymills/Reachability.swift"; + repositoryURL = "https://github.com/lorenzofiamingo/swiftui-cached-async-image"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 5.0.0; + minimumVersion = 2.0.0; }; }; - CEB269552445DB56004B74B3 /* XCRemoteSwiftPackageReference "SQLite" */ = { + E2EA00C1283E672A00F7B269 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = { isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/stephencelis/SQLite.swift"; + repositoryURL = "https://github.com/SFSafeSymbols/SFSafeSymbols"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 0.12.2; + minimumVersion = 3.0.0; + }; + }; + E2EA00C8283EACB200F7B269 /* XCRemoteSwiftPackageReference "bottom-sheet" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/weitieda/bottom-sheet"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - CE5B7D022458C921002E5C06 /* Reachability */ = { + E27E15E0283E418600F6804A /* CachedAsyncImage */ = { isa = XCSwiftPackageProductDependency; - package = CE5B7D012458C921002E5C06 /* XCRemoteSwiftPackageReference "Reachability" */; - productName = Reachability; + package = E27E15DF283E418600F6804A /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */; + productName = CachedAsyncImage; }; - CEB269562445DB56004B74B3 /* SQLite */ = { + E2EA00C2283E672A00F7B269 /* SFSafeSymbols */ = { isa = XCSwiftPackageProductDependency; - package = CEB269552445DB56004B74B3 /* XCRemoteSwiftPackageReference "SQLite" */; - productName = SQLite; + package = E2EA00C1283E672A00F7B269 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */; + productName = SFSafeSymbols; + }; + E2EA00C9283EACB200F7B269 /* BottomSheet */ = { + isa = XCSwiftPackageProductDependency; + package = E2EA00C8283EACB200F7B269 /* XCRemoteSwiftPackageReference "bottom-sheet" */; + productName = BottomSheet; }; /* End XCSwiftPackageProductDependency section */ }; - rootObject = CE56CEC2209D81DD00932C01 /* Project object */; + rootObject = E25AAC70283D855D006E9E7F /* Project object */; } diff --git a/Caps.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Caps.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 96e9cea..bcf05e2 100644 --- a/Caps.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Caps.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,25 +1,32 @@ { - "object": { - "pins": [ - { - "package": "Reachability", - "repositoryURL": "https://github.com/ashleymills/Reachability.swift", - "state": { - "branch": null, - "revision": "c01bbdf2d633cf049ae1ed1a68a2020a8bda32e2", - "version": "5.1.0" - } - }, - { - "package": "SQLite.swift", - "repositoryURL": "https://github.com/stephencelis/SQLite.swift", - "state": { - "branch": null, - "revision": "5f5ad81ac0d0a0f3e56e39e646e8423c617df523", - "version": "0.13.2" - } + "pins" : [ + { + "identity" : "bottom-sheet", + "kind" : "remoteSourceControl", + "location" : "https://github.com/weitieda/bottom-sheet", + "state" : { + "revision" : "4e074d49f3148577ac66cf47b85a99d016480d01", + "version" : "1.0.10" } - ] - }, - "version": 1 + }, + { + "identity" : "sfsafesymbols", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SFSafeSymbols/SFSafeSymbols", + "state" : { + "revision" : "c8c33d947d8a1c883aa19fd24e14fd738b06e369", + "version" : "3.3.2" + } + }, + { + "identity" : "swiftui-cached-async-image", + "kind" : "remoteSourceControl", + "location" : "https://github.com/lorenzofiamingo/swiftui-cached-async-image", + "state" : { + "revision" : "eeb1565d780d1b75d045e21b5ca2a1e3650b0fc2", + "version" : "2.1.0" + } + } + ], + "version" : 2 } diff --git a/Caps.xcodeproj/project.xcworkspace/xcuserdata/ch.xcuserdatad/UserInterfaceState.xcuserstate b/Caps.xcodeproj/project.xcworkspace/xcuserdata/ch.xcuserdatad/UserInterfaceState.xcuserstate index 858f0c442c873d30abe61ac0a445de4acbdb3da9..ee68d55921c2f8e3c9b688959d13e9fb5030230e 100644 GIT binary patch literal 61444 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 M+YR<}d+hc90aZnaKmY&$ literal 25583 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 diff --git a/Caps.xcodeproj/project.xcworkspace/xcuserdata/imac.xcuserdatad/UserInterfaceState.xcuserstate b/Caps.xcodeproj/project.xcworkspace/xcuserdata/imac.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index bed6008030f44224b89d465e8f8cafb598bb5e8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56289 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 vWAWiP;{r}wWt=-&w?|2opq8H@QZ83Hii diff --git a/Caps.xcodeproj/xcshareddata/xcschemes/Caps.xcscheme b/Caps.xcodeproj/xcshareddata/xcschemes/Caps.xcscheme new file mode 100644 index 0000000..794df71 --- /dev/null +++ b/Caps.xcodeproj/xcshareddata/xcschemes/Caps.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Caps.xcodeproj/xcuserdata/User.xcuserdatad/xcschemes/xcschememanagement.plist b/Caps.xcodeproj/xcuserdata/User.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 6ac819e..0000000 --- a/Caps.xcodeproj/xcuserdata/User.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SchemeUserState - - CapCollector.xcscheme - - orderHint - 0 - - CapCollector.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist similarity index 65% rename from Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist rename to Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index d502ec3..f129b62 100644 --- a/Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -1,6 +1,6 @@ diff --git a/Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcschemes/xcschememanagement.plist b/Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcschemes/xcschememanagement.plist index 4dd0d17..be3d187 100644 --- a/Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Caps.xcodeproj/xcuserdata/ch.xcuserdatad/xcschemes/xcschememanagement.plist @@ -4,52 +4,18 @@ SchemeUserState - CapCollector.xcscheme_^#shared#^_ + Caps.xcscheme_^#shared#^_ - orderHint - 1 - - SQLite (Playground) 1.xcscheme - - isShown - - orderHint - 3 - - SQLite (Playground) 2.xcscheme - - isShown - - orderHint - 4 - - SQLite (Playground) 3.xcscheme - - isShown - orderHint 0 - SQLite (Playground) 4.xcscheme + + SuppressBuildableAutocreation + + E25AAC77283D855D006E9E7F - isShown - - orderHint - 5 - - SQLite (Playground) 5.xcscheme - - isShown - - orderHint - 6 - - SQLite (Playground).xcscheme - - isShown - - orderHint - 2 + primary + diff --git a/Caps.xcodeproj/xcuserdata/christoph.xcuserdatad/xcschemes/xcschememanagement.plist b/Caps.xcodeproj/xcuserdata/christoph.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 6938457..0000000 --- a/Caps.xcodeproj/xcuserdata/christoph.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,19 +0,0 @@ - - - - - SchemeUserState - - CapCollector.xcscheme - - orderHint - 3 - - CapCollector.xcscheme_^#shared#^_ - - orderHint - 3 - - - - diff --git a/Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist b/Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 30f9840..0000000 --- a/Caps.xcodeproj/xcuserdata/imac.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,35 +0,0 @@ - - - - - SchemeUserState - - CapCollector.xcscheme_^#shared#^_ - - orderHint - 0 - - SQLite (Playground) 1.xcscheme - - isShown - - orderHint - 2 - - SQLite (Playground) 2.xcscheme - - isShown - - orderHint - 3 - - SQLite (Playground).xcscheme - - isShown - - orderHint - 1 - - - - diff --git a/Caps/AppDelegate.swift b/Caps/AppDelegate.swift deleted file mode 100644 index c21eea4..0000000 --- a/Caps/AppDelegate.swift +++ /dev/null @@ -1,126 +0,0 @@ -// -// AppDelegate.swift -// CapFinder -// -// Created by User on 31.01.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit -import CoreData - -import Reachability - -#warning("ImageSelector: Allow deletion and moving of an image of a cap") -#warning("ImageSelector: Show icons for failed downloads") -#warning("GridController: Allow sorting of caps by color") -#warning("GridController: Reorder caps by dragging") -#warning("TableView: Fix blur background of search bar after transition") -#warning("TableView: Add banner to jump down to unmatched caps / bottom") -#warning("Only show total size and percentage for classifier download") -#warning("After classifier download, test is not started") -#warning("Add result info when update button is pressed") -var shouldLaunchCamera = false - -var app: AppDelegate! - -private let unlockCode = 3849 - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - // MARK: Static Properties - - /// Main tint color of the app - static let tintColor = UIColor(red: 122/255, green: 155/255, blue: 41/255, alpha: 1) - - var window: UIWindow? - - var mainStoryboard: UIStoryboard { .init(name: "Main", bundle: nil) } - - let documentsFolder = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) - - var database: Database! - - var reachability: Reachability! - - var dbUrl: URL { - documentsFolder.appendingPathComponent("db.sqlite3") - } - - /// Indicate if the user has write permissions. - private(set) var isUnlocked: Bool { - get { - UserDefaults.standard.bool(forKey: "unlocked") - } - set { - UserDefaults.standard.set(newValue, forKey: "unlocked") - } - } - - let serverUrl = URL(string: "https://christophhagen.de:6000")! - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - app = self - - reachability = try! Reachability() - - //resetToFactoryState() - - database = Database(url: dbUrl, server: serverUrl, storageFolder: documentsFolder) - return true - } - - private func resetToFactoryState() { - for path in try! FileManager.default.contentsOfDirectory(at: documentsFolder, includingPropertiesForKeys: nil) { - try! FileManager.default.removeItem(at: path) - } - UserDefaults.standard.removeObject(forKey: Classifier.userDefaultsKey) - } - - func lock() { - isUnlocked = false - } - - func checkUnlock(with pin: Int) -> Bool { - isUnlocked = pin == unlockCode - return isUnlocked - } - - private func handleShortCutItem(_ shortcutItem: UIApplicationShortcutItem) -> Bool { - log("Shortcut pressed") - shouldLaunchCamera = true - return true - } - - func applicationDidBecomeActive(_ application: UIApplication) { - guard shouldLaunchCamera else { return } - shouldLaunchCamera = false - if let c = (frontmostViewController as? UINavigationController)?.topViewController as? TableView { - c.showCameraView() - } - } - - /* - Called when the user activates your application by selecting a shortcut on the home screen, except when - application(_:,willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions) returns `false`. - You should handle the shortcut in those callbacks and return `false` if possible. In that case, this - callback is used if your application is already launched in the background. - */ - func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { - let handledShortCutItem = handleShortCutItem(shortcutItem) - completionHandler(handledShortCutItem) - } - - var frontmostViewController: UIViewController? { - var controller = window?.rootViewController - while let presentedViewController = controller?.presentedViewController { - controller = presentedViewController - } - return controller - } - - -} - -extension AppDelegate: Logger { } diff --git a/Caps/Assets.xcassets/AccentColor.colorset/Contents.json b/Caps/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Caps/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Caps/Assets.xcassets/AppIcon.appiconset/Contents.json b/Caps/Assets.xcassets/AppIcon.appiconset/Contents.json index 02dd3cb..b4a35da 100644 --- a/Caps/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Caps/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,107 +1,107 @@ { "images" : [ { - "size" : "20x20", - "idiom" : "iphone", "filename" : "bottle-cap40.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" }, { - "size" : "20x20", - "idiom" : "iphone", "filename" : "bottle-cap60.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" }, { - "size" : "29x29", - "idiom" : "iphone", "filename" : "bottle-cap58.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" }, { - "size" : "29x29", - "idiom" : "iphone", "filename" : "bottle-cap87.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" }, { - "size" : "40x40", - "idiom" : "iphone", "filename" : "bottle-cap80.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" }, { - "size" : "40x40", - "idiom" : "iphone", "filename" : "bottle-cap120.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" }, { - "size" : "60x60", - "idiom" : "iphone", "filename" : "bottle-cap120-1.png", - "scale" : "2x" - }, - { - "size" : "60x60", "idiom" : "iphone", - "filename" : "bottle-cap180.png", - "scale" : "3x" + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "bottle-cap180-1.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" }, { "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" + "scale" : "1x", + "size" : "20x20" }, { "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" + "scale" : "1x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" + "scale" : "1x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" + "scale" : "1x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" + "scale" : "2x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" + "scale" : "2x", + "size" : "83.5x83.5" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", "filename" : "bottle-cap1024.png", - "scale" : "1x" + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Caps/Assets.xcassets/AppIcon.appiconset/bottle-cap180.png b/Caps/Assets.xcassets/AppIcon.appiconset/bottle-cap180-1.png similarity index 100% rename from Caps/Assets.xcassets/AppIcon.appiconset/bottle-cap180.png rename to Caps/Assets.xcassets/AppIcon.appiconset/bottle-cap180-1.png diff --git a/Caps/Assets.xcassets/Contents.json b/Caps/Assets.xcassets/Contents.json index da4a164..73c0059 100644 --- a/Caps/Assets.xcassets/Contents.json +++ b/Caps/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Caps/Assets.xcassets/camera.imageset/Contents.json b/Caps/Assets.xcassets/camera.imageset/Contents.json deleted file mode 100644 index 1518837..0000000 --- a/Caps/Assets.xcassets/camera.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "camera.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Caps/Assets.xcassets/camera.imageset/camera.png b/Caps/Assets.xcassets/camera.imageset/camera.png deleted file mode 100644 index 6067088e0911c55a185c4de0b5dbc7afa547dd4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27639 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

F!GFxhGZG9cjI)@~0C?U14H2B$- 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 Dc1kfK diff --git a/Caps/Assets.xcassets/camera_square.imageset/Contents.json b/Caps/Assets.xcassets/camera_square.imageset/Contents.json deleted file mode 100644 index 5096c74..0000000 --- a/Caps/Assets.xcassets/camera_square.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "camera_square.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Caps/Assets.xcassets/camera_square.imageset/camera_square.png b/Caps/Assets.xcassets/camera_square.imageset/camera_square.png deleted file mode 100644 index 8c48ff3c8272985fe36924d3898c279cda36a56b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27499 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 diff --git a/Caps/Assets.xcassets/launch.imageset/Contents.json b/Caps/Assets.xcassets/launch.imageset/Contents.json deleted file mode 100644 index 5989f83..0000000 --- a/Caps/Assets.xcassets/launch.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "launch.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Caps/Assets.xcassets/launch.imageset/launch.png b/Caps/Assets.xcassets/launch.imageset/launch.png deleted file mode 100644 index 8802657e89b7d044b2136b44c1a5db89dc314207..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305451 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 XCQ3Ra=^$*Z1 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®lPTe>%Q?-H zSNGZ3!W9LxM;*OcsHA4Tv1+X=BjeV+#`?^)uRpz-sE;6G^xsOlUk)bk84{_*Cg9sn;&t2vxV=Ik&i>I_vj8Tea4Yuiag*-AF$|3v~BS3kS*@ z>Qbj{d;SZ&4qts~dy?lZMp)Gr$r^BF%$G}doS)!tnR9h~*Gk?o;M^10{*l*rr!=(l zX|gwQOYLJPg7~RdW-Jz6`^WAJC8}HMvuE*>Q*Z9rw0`AptqDsfWzYJ-+LZqNrM4wo z6T>BK)SJ_Da$x4u`bVq$C>lVwq+OXhhAE=%J*Sm?%kQcTC))ytWiq~qB+Gj?N-dX-+=JCO` z%;9G9h|%F1GVxGe>($PLk-v<2Z$V(e43qO_)2K0Y$DP3?myaL%D$OK6_p0+^^YV^$ p-6bRZ^KI9Mt5?_Ep4vI`3R^cTQhe^A~@~9(Mo$ diff --git a/Caps/Assets.xcassets/mosaic.imageset/picture56.png b/Caps/Assets.xcassets/mosaic.imageset/picture56.png deleted file mode 100644 index 7adcab30af08d745fbb1d150b2b0596740281093..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2883 zcmb_e30Mq!I(DPWGIYjpZr8CoE=PxlbLWXvpvojC zw7QsFGm(;;pvH1DF&WOC9>JMrL+Aho!h&*a2ECC&Y~kGAxCnji9OiR5y%0-gI5*Ns z$VpWta^$3$;D~r)0E1wVBa!hSF$jyGDI5U^N%)|M4~hX0LO>}ZfH?ghF3o1fHAu2z zWWV(yCN0j<;$t7+e&TMQNqe=r71y(UdyJMDUXdip(-& zgwjgO40dK?LgZ!wwUA~tN$Lk0l{g@oBbPfHBjtpuP)uiZ=JEa;vj_!hA;P&%1OQ3^ z5LQDH1QsD8K^Q1NK(G(0B5|E2#|4!Epn(3WAqatCL?jM#wtE0d`vylX=>G)c7@{G~ z29(ZPXFxLuzR8%u<+y5z$VokErip2F!Z*ib2V zD@ZKM=>zBdz9oT^7#-smc?61zWjKrhgjkafz!I1Mq#B_HfIy58Ng)}ArDFrpW}9{N zszmi~Ms=#f>4-EhB*fAo0EJ~502WFx02Rt00EaX}5EW`PC=NQk-)ko%Mn}<&&goxG zDa4ZgE4_}>>mUThoGT-oi#aVp;N1RU-COGMPR#xDv$X^r^fz46$4-$NOEzjIA~WdP zy_*&Jzm@@oT7O$VDgo)*;5Z<`g%|(}WHLZ1(a<)a+bNO?WfELU_p?u!OFwO02!Nz& z0f<1fb-@Aa{%-yK1eg{zW)Sp-%jf?7jNZ+m|DDlW7vujqBffL9?K2$zKfT!d?2V0? zZfWljz1ur4U9TDX#`U5ijC8Tg^lM1EDrp>p!5k5*h*WD=b#7gt9Ujd-v-0Uyg-Pmn%ll%iBH>^MN>|+otjaUP;+_$dza@2-#?od zcac5l>GJVI99`$ic7KyRMxC?rOqhSr?!i{~%%s`Xk@m2Pu{}V^(qbt8yDMEjx5rF6 z>hXy?P`n&Ib>}m_d{M$9?|&9`dTn`c^zp6sXlCr+JX_sn<&9XCa=m8{?^|)+@P;bp zj{O^&GyM_y&YvG`4Jik9zTX_uG1tC0zinj2`O-UXQ$M~*u>w}_S?kcb-Q2L&vA2Pg z7I-yG9>0Oz{8D~)xA9m!E5h%mmcf=QtemrU$@UZZi}r841yn2zO<@CAFvnmE;K zuV)GQ3%51b+&decl6s|Ki`S<`5q8ES@4rlZlG)yL?D15w|318JQd^v6L&}y58w)uz zf+xQ`UijE=*~=0(Ifx9p_@@xLmsWk7jCJ#e|%E=fN9P7Nno$|WY{)Vf@cJ_ z*g9sNOtPdXa5UQCuueJc*fjC0(lpP9m!B60RwwG9hc1R zJppChp~}y7M<=e^UVH>jdy&_2GNjz?>-FdUTtAuAkF}OG&hyq+?%MOZscBZVchB7T zQJVWLRKWee*X?gnuCUlY+dlN${Ei9b%H`~`lJ&Vc2a|-Ol$Un0uSRXa^D1r(jxnEL z-a3$9=@t|~@iN=RRrP@vI%4U`L%-jB8lK zdd+AG8r3#qV`HJ!km9XxPGCh|dsStcKeIC8WSd2KG5T)Y%!tIr{;%qDF9mz%us$kt zPiw98?a*8CCT1nG3tiDvHaV(}_tM=_UOfHOnh{ZMxz0-BiD2OQ_LVPxk&X$;T02 z+%##V`sL{QsjnVXdLGIT+j3pHD(*b+MOQ@i)jFH^A@z_SZg0k3j7{}wV9lxU4TRm- oht^g75M&zhcw*)7uEdAI&kQNc40W5&IRECxDiai6M=e_YFL<9V;s5{u diff --git a/Caps/Assets.xcassets/mosaic.imageset/picture84.png b/Caps/Assets.xcassets/mosaic.imageset/picture84.png deleted file mode 100644 index a6964254d050ff3d6581fb7b815586809ab9df7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3380 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 NYv`$G9X=WOKLDr%QD6W7 diff --git a/Caps/Assets.xcassets/settings.imageset/Contents.json b/Caps/Assets.xcassets/settings.imageset/Contents.json deleted file mode 100644 index bb670f1..0000000 --- a/Caps/Assets.xcassets/settings.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "button_settings_white@1x.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "button_settings_white@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "button_settings_white@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Caps/Assets.xcassets/settings.imageset/button_settings_white@1x.png b/Caps/Assets.xcassets/settings.imageset/button_settings_white@1x.png deleted file mode 100644 index f8ca6af22b69e4e109567deb5afece915c70d651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1708 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 diff --git a/Caps/Base.lproj/LaunchScreen.storyboard b/Caps/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 75652b9..0000000 --- a/Caps/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Caps/Base.lproj/Main.storyboard b/Caps/Base.lproj/Main.storyboard deleted file mode 100644 index ef42e55..0000000 --- a/Caps/Base.lproj/Main.storyboard +++ /dev/null @@ -1,429 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Caps/Camera/CameraError.swift b/Caps/Camera/CameraError.swift new file mode 100644 index 0000000..ae4b2e2 --- /dev/null +++ b/Caps/Camera/CameraError.swift @@ -0,0 +1,32 @@ +import Foundation + +enum CameraError: Error { + case cameraUnavailable + case cannotAddInput + case cannotAddOutput + case createCaptureInput(Error) + case deniedAuthorization + case restrictedAuthorization + case unknownAuthorization +} + +extension CameraError: LocalizedError { + var errorDescription: String? { + switch self { + case .cameraUnavailable: + return "Camera unavailable" + case .cannotAddInput: + return "Cannot add capture input to session" + case .cannotAddOutput: + return "Cannot add video output to session" + case .createCaptureInput(let error): + return "Creating capture input for camera: \(error.localizedDescription)" + case .deniedAuthorization: + return "Camera access denied" + case .restrictedAuthorization: + return "Attempting to access a restricted capture device" + case .unknownAuthorization: + return "Unknown authorization status for capture device" + } + } +} diff --git a/Caps/Camera/CameraManager.swift b/Caps/Camera/CameraManager.swift new file mode 100644 index 0000000..5dc4bf8 --- /dev/null +++ b/Caps/Camera/CameraManager.swift @@ -0,0 +1,172 @@ +import Foundation +import AVFoundation + +class CameraManager: ObservableObject { + enum Status { + case unconfigured + case configured + case unauthorized + case failed + } + + static let shared = CameraManager() + + @Published var error: CameraError? + + let session = AVCaptureSession() + + private let sessionQueue = DispatchQueue(label: "de.christophhagen.cam") + private let videoOutput = AVCaptureVideoDataOutput() + private let photoOutput = AVCapturePhotoOutput() + private var status = Status.unconfigured + + private init() { + configure() + } + + private func set(error: CameraError?) { + DispatchQueue.main.async { + self.error = error + } + } + + private func checkPermissions() { + switch AVCaptureDevice.authorizationStatus(for: .video) { + case .notDetermined: + sessionQueue.suspend() + AVCaptureDevice.requestAccess(for: .video) { authorized in + if !authorized { + self.status = .unauthorized + self.set(error: .deniedAuthorization) + } + self.sessionQueue.resume() + } + case .restricted: + status = .unauthorized + set(error: .restrictedAuthorization) + case .denied: + status = .unauthorized + set(error: .deniedAuthorization) + case .authorized: + break + @unknown default: + status = .unauthorized + set(error: .unknownAuthorization) + } + } + + private func configureCaptureSession() { + guard status == .unconfigured else { + return + } + + session.beginConfiguration() + session.sessionPreset = .photo + + defer { + session.commitConfiguration() + } + + let device = AVCaptureDevice.default( + .builtInWideAngleCamera, + for: .video, + position: .back) + guard let camera = device else { + set(error: .cameraUnavailable) + status = .failed + return + } + + let cameraInput: AVCaptureDeviceInput + do { + cameraInput = try AVCaptureDeviceInput(device: camera) + } catch { + set(error: .createCaptureInput(error)) + status = .failed + return + } + guard session.canAddInput(cameraInput) else { + set(error: .cannotAddInput) + status = .failed + return + } + session.addInput(cameraInput) + + + if session.canAddOutput(videoOutput) { + session.addOutput(videoOutput) + + videoOutput.videoSettings = + [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA] + + let videoConnection = videoOutput.connection(with: .video) + videoConnection?.videoOrientation = .portrait + } else { + set(error: .cannotAddOutput) + status = .failed + return + } + + guard session.canAddOutput(photoOutput) else { + set(error: .cannotAddOutput) + status = .failed + return + } + session.addOutput(photoOutput) + photoOutput.isHighResolutionCaptureEnabled = true + photoOutput.isDepthDataDeliveryEnabled = false + photoOutput.isLivePhotoCaptureEnabled = false + + status = .configured + } + + private func configure() { + checkPermissions() + + sessionQueue.async { + self.configureCaptureSession() + self.session.startRunning() + } + } + + func setVideoDelegate(_ delegate: AVCaptureVideoDataOutputSampleBufferDelegate, + queue: DispatchQueue) { + sessionQueue.async { + self.videoOutput.setSampleBufferDelegate(delegate, queue: queue) + } + } + + func stopVideoCaptureSession() { + sessionQueue.async { + guard self.status == .configured else { + return + } + guard self.session.isRunning else { + return + } + self.session.stopRunning() + } + } + + func startVideoCapture() { + guard status == .configured else { + return + } + sessionQueue.async { + guard !self.session.isRunning else { + return + } + self.session.startRunning() + } + } + + // MARK: Photo Capture + + func capturePhoto(delegate: AVCapturePhotoCaptureDelegate) { + sessionQueue.async { + let photoSettings = AVCapturePhotoSettings() + photoSettings.flashMode = .off + self.photoOutput.capturePhoto(with: photoSettings, delegate: delegate) + } + } +} diff --git a/Caps/Camera/CameraView.swift b/Caps/Camera/CameraView.swift new file mode 100644 index 0000000..2889865 --- /dev/null +++ b/Caps/Camera/CameraView.swift @@ -0,0 +1,127 @@ +import SwiftUI +import SFSafeSymbols + +struct CameraView: View { + + static let cameraImagePadding: CGFloat = 300 + + private static let circleSize: CGFloat = 180 + private var circleSize: CGFloat { + CameraView.circleSize + } + + static var circleCropFactor: CGFloat { + let fullWidth = UIScreen.main.bounds.width + 2 * cameraImagePadding + return circleSize / fullWidth + } + + private let circleStrength: CGFloat = 3 + + private let circleColor: Color = .green + + private let captureButtonSize: CGFloat = 110 + private let captureButtonHeight: CGFloat = 40 + private let captureButtonWidth: CGFloat = 50 + + private let cancelButtonSize: CGFloat = 75 + private let cancelIconSize: CGFloat = 25 + + @Binding + var isPresented: Bool + + @Binding + var image: UIImage? + + @Binding + var capId: Int? + + @StateObject + private var model = ContentViewModel() + + @EnvironmentObject + var database: Database + + var body: some View { + ZStack { + FrameView(image: model.frame) + .edgesIgnoringSafeArea(.all) + .padding(-CameraView.cameraImagePadding) + + ErrorView(error: model.error) + VStack { + Spacer() + HStack { + Spacer() + Button(action: dismiss) { + Image(systemSymbol: .xmark) + .resizable() + .frame(width: cancelIconSize, height: cancelIconSize) + .padding((cancelButtonSize-cancelIconSize)/2) + .background(.thinMaterial) + .cornerRadius(cancelButtonSize/2) + }.padding() + } + } + VStack { + Spacer() + HStack { + Spacer() + Button(action: capture) { + Image(systemSymbol: .camera) + .resizable() + .frame(width: captureButtonWidth, height: captureButtonHeight) + .padding(.horizontal, (captureButtonSize - captureButtonWidth)/2) + .padding(.vertical, (captureButtonSize - captureButtonHeight)/2) + .background(.thinMaterial) + .cornerRadius(captureButtonSize / 2) + }.padding() + Spacer() + } + } + VStack { + Spacer() + HStack { + Spacer() + Text("") + .frame(width: circleSize, height: circleSize, alignment: .center) + .overlay(RoundedRectangle(cornerRadius: circleSize/2) + .stroke(lineWidth: circleStrength) + .foregroundColor(circleColor)) + + Spacer() + } + Spacer() + }.ignoresSafeArea() + + } + .onAppear() { + model.startCapture() + } + .onDisappear { + model.endCapture() + }.onChange(of: model.image) { image in + if let capId = capId, let image = image { + database.save(image, for: capId) + } else { + database.image = image + } + dismiss() + } + } + + private func dismiss() { + isPresented = false + } + + private func capture() { + model.captureImage() + } +} + +struct CameraView_Previews: PreviewProvider { + static var previews: some View { + CameraView(isPresented: .constant(true), + image: .constant(nil), + capId: .constant(nil)) + } +} diff --git a/Caps/Camera/ContentViewModel.swift b/Caps/Camera/ContentViewModel.swift new file mode 100644 index 0000000..c506130 --- /dev/null +++ b/Caps/Camera/ContentViewModel.swift @@ -0,0 +1,57 @@ +import CoreImage +import AVFoundation +import UIKit + +class ContentViewModel: ObservableObject { + + @Published var error: Error? + @Published var frame: CGImage? + @Published var image: UIImage? + + private let context = CIContext() + + private let cameraManager = CameraManager.shared + private let frameManager = FrameManager.shared + + init() { + setupSubscriptions() + } + + func setupSubscriptions() { + frameManager.image = nil + frameManager.current = nil + + cameraManager.$error + .receive(on: RunLoop.main) + .map { $0 } + .assign(to: &$error) + + frameManager.$current + .receive(on: RunLoop.main) + .compactMap { buffer in + guard let image = CGImage.create(from: buffer) else { + return nil + } + + let ciImage = CIImage(cgImage: image) + return self.context.createCGImage(ciImage, from: ciImage.extent) + } + .assign(to: &$frame) + + frameManager.$image + .receive(on: RunLoop.main) + .assign(to: &$image) + } + + func endCapture() { + cameraManager.stopVideoCaptureSession() + } + + func startCapture() { + cameraManager.startVideoCapture() + } + + func captureImage() { + cameraManager.capturePhoto(delegate: frameManager) + } +} diff --git a/Caps/Camera/ErrorView.swift b/Caps/Camera/ErrorView.swift new file mode 100644 index 0000000..4bb7d4f --- /dev/null +++ b/Caps/Camera/ErrorView.swift @@ -0,0 +1,27 @@ +import SwiftUI + +struct ErrorView: View { + var error: Error? + + var body: some View { + VStack { + Text(error?.localizedDescription ?? "") + .bold() + .multilineTextAlignment(.center) + .frame(maxWidth: .infinity) + .padding(8) + .foregroundColor(.white) + .background(Color.red.edgesIgnoringSafeArea(.top)) + .opacity(error == nil ? 0.0 : 1.0) + .animation(.easeInOut, value: 0.25) + + Spacer() + } + } +} + +struct ErrorView_Previews: PreviewProvider { + static var previews: some View { + ErrorView(error: CameraError.cannotAddInput) + } +} diff --git a/Caps/Camera/FrameManager.swift b/Caps/Camera/FrameManager.swift new file mode 100644 index 0000000..c4a8412 --- /dev/null +++ b/Caps/Camera/FrameManager.swift @@ -0,0 +1,70 @@ +import AVFoundation +import CoreGraphics +import UIKit + +class FrameManager: NSObject, ObservableObject { + + static let shared = FrameManager() + + @Published var current: CVPixelBuffer? + + @Published var image: UIImage? + + let videoOutputQueue = DispatchQueue( + label: "de.christophhagen.videoout", + qos: .userInitiated, + attributes: [], + autoreleaseFrequency: .workItem) + + private override init() { + super.init() + + CameraManager.shared.setVideoDelegate(self, queue: videoOutputQueue) + } +} + +extension FrameManager: AVCaptureVideoDataOutputSampleBufferDelegate { + + func captureOutput( + _ output: AVCaptureOutput, + didOutput sampleBuffer: CMSampleBuffer, + from connection: AVCaptureConnection + ) { + if let buffer = sampleBuffer.imageBuffer { + DispatchQueue.main.async { + self.current = buffer + } + } + } +} + +extension FrameManager: AVCapturePhotoCaptureDelegate { + + func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { + let image = convert(photo, error: error) + DispatchQueue.main.async { + self.image = image + } + } + + private func convert(_ photo: AVCapturePhoto, error: Error?) -> UIImage? { + guard error == nil else { + log("PhotoCaptureHandler: \(error!)") + return nil + } + + guard let cgImage = photo.cgImageRepresentation() else { + log("PhotoCaptureHandler: No image captured") + return nil + } + let image = UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .right) + guard let masked = image.crop(factor: CameraView.circleCropFactor).circleMasked else { + log("Could not mask image") + return nil + } + print(image.size) + print(masked.size) + print(masked.scale) + return masked + } +} diff --git a/Caps/Camera/FrameView.swift b/Caps/Camera/FrameView.swift new file mode 100644 index 0000000..5378548 --- /dev/null +++ b/Caps/Camera/FrameView.swift @@ -0,0 +1,30 @@ +import SwiftUI + +struct FrameView: View { + var image: CGImage? + + private let label = Text("Video feed") + + var body: some View { + if let image = image { + GeometryReader { geometry in + Image(image, scale: 1.0, orientation: .up, label: label) + .resizable() + .scaledToFill() + .frame( + width: geometry.size.width, + height: geometry.size.height, + alignment: .center) + .clipped() + } + } else { + EmptyView() + } + } +} + +struct FrameView_Previews: PreviewProvider { + static var previews: some View { + FrameView(image: nil) + } +} diff --git a/Caps/CapsApp.swift b/Caps/CapsApp.swift new file mode 100644 index 0000000..cc11b99 --- /dev/null +++ b/Caps/CapsApp.swift @@ -0,0 +1,18 @@ +import SwiftUI + +#warning("TODO: Create new caps") +#warning("TODO: Add colors") +#warning("TODO: Grid view") + +@main +struct CapsApp: App { + + let database = Database(server: URL(string: "https://christophhagen.de/caps")!) + + var body: some Scene { + WindowGroup { + ContentView() + .environmentObject(database) + } + } +} diff --git a/Caps/Capture/CameraController.swift b/Caps/Capture/CameraController.swift deleted file mode 100644 index a7773f5..0000000 --- a/Caps/Capture/CameraController.swift +++ /dev/null @@ -1,146 +0,0 @@ -// -// CameraController.swift -// CapFinder -// -// Created by User on 22.02.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - -protocol CameraControllerDelegate { - - func didCapture(image: UIImage) - - func didCancel() -} - -class CameraController: UIViewController { - - // MARK: Outlets - - @IBOutlet weak var imageButton: UIButton! - - @IBOutlet weak var cropView: CropView! - - @IBOutlet weak var cancelButton: UIButton! - - @IBOutlet weak var cameraView: CameraView! { - didSet { - cameraView.configure() - } - } - - var delegate: CameraControllerDelegate? - - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return .portrait - } - - override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - return .portrait - } - - override var shouldAutorotate: Bool { - return false - } - - // MARK: Actions - - @IBAction func backButtonPressed() { - self.giveFeedback(.medium) - delegate?.didCancel() - self.dismiss(animated: true) - } - - @IBAction func imageButtonPressed() { - self.giveFeedback(.medium) - imageButton.isEnabled = false - cameraView.capture() - } - - // MARK: Life cycle - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - cameraView.delegate = self - - cameraView.launch { success, error in - guard let err = error else { - return - } - switch err { - case "No camera access": self.showNoCameraAccessAlert() - case "Camera error": self.showAlert("Unable to capture media") - default: self.showAlert("Error in camera setup") - } - } - self.imageButton.isEnabled = true - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - cameraView.complete() - } - - private func giveFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle) { - let generator = UIImpactFeedbackGenerator(style: style) - generator.impactOccurred() - } - - // MARK: Alerts - - private func showNoCameraAccessAlert() { - let alert = UIAlertController(title: "Unable to access the Camera", - message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.", - preferredStyle: .alert)//, - //blurStyle: .dark) - - let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil) - alert.addAction(okAction) - - let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in - // Take the user to Settings app to possibly change permission. - guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return } - if UIApplication.shared.canOpenURL(settingsUrl) { - UIApplication.shared.open(settingsUrl, completionHandler: nil) - } - }) - alert.addAction(settingsAction) - self.present(alert, animated: true, completion: nil) - } - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - cameraView.didReceiveTouch(touches.first!) - } -} - -extension CameraController: PhotoCaptureHandlerDelegate { - - func didCapture(_ image: UIImage?) { - log("Image captured") - let factor = CGFloat(cropView.relativeSize) - self.dismiss(animated: true) - guard let img = image else { - self.error("No image captured") - return - } - - guard delegate != nil else { - self.error("No delegate") - return - } - - guard let masked = img.crop(factor: factor).circleMasked else { - self.error("Could not mask image") - return - } - - let scaled = masked.resize(to: Cap.imageSize) - - delegate!.didCapture(image: scaled) - } -} - -extension CameraController: Logger { } diff --git a/Caps/Capture/CameraView.swift b/Caps/Capture/CameraView.swift deleted file mode 100644 index 92e46e7..0000000 --- a/Caps/Capture/CameraView.swift +++ /dev/null @@ -1,224 +0,0 @@ -// -// CameraView.swift -// CapFinder -// -// Created by User on 07.02.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit -import AVFoundation - -class CameraView: UIView { - - // MARK: UIView overrides - - /** - Override for AVCapture - */ - override class var layerClass: AnyClass { - return AVCaptureVideoPreviewLayer.self - } - - // MARK: Enums - - private enum SessionSetupResult { - case success - case notAuthorized - case configurationFailed - } - - // MARK: Variables - - var delegate: PhotoCaptureHandlerDelegate? { - get { - return photoCaptureProcessor.delegate - } - set { - photoCaptureProcessor.delegate = newValue - } - } - - private let session = AVCaptureSession() - - private var isSessionRunning = false - - /// Communicate with the session and other session objects on this queue. - private let sessionQueue = DispatchQueue(label: "session queue") - - private var setupResult: SessionSetupResult = .success - - var videoDeviceInput: AVCaptureDeviceInput! - - private let photoOutput = AVCapturePhotoOutput() - - private var cameraDevice: AVCaptureDevice? - - private let photoCaptureProcessor = PhotoCaptureHandler() - - var videoPreviewLayer: AVCaptureVideoPreviewLayer { - return layer as! AVCaptureVideoPreviewLayer - } - - // MARK: Life cycle - - func configure() { - videoPreviewLayer.session = session - - checkPermission() - - // Setup the capture session. - sessionQueue.async { - self.configureSession() - } - } - - func launch(completionHandler: @escaping (Bool, String?) -> ()) { - sessionQueue.async { - switch self.setupResult { - case .success: - // Only setup observers and start the session running if setup succeeded. - self.session.startRunning() - self.isSessionRunning = self.session.isRunning - - case .notAuthorized: - DispatchQueue.main.async { - completionHandler(false, "No camera access") - } - - case .configurationFailed: - DispatchQueue.main.async { - completionHandler(false, "Camera error") - } - } - } - } - - func complete() { - sessionQueue.async { - if self.setupResult == .success { - self.session.stopRunning() - self.isSessionRunning = self.session.isRunning - } - } - } - - // MARK: Photo Capture - - func capture() { - sessionQueue.async { - self.photoOutput.capturePhoto( - with: self.photoCaptureProcessor.photoSettings, - delegate: self.photoCaptureProcessor) - } - } - - // MARK: Camera permissions - - private func checkPermission() { - switch AVCaptureDevice.authorizationStatus(for: .video) { - case .authorized: break - case .notDetermined: - sessionQueue.suspend() - AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in - if !granted { - self.setupResult = .notAuthorized - } - self.sessionQueue.resume() - }) - - default: - // The user has previously denied access. - setupResult = .notAuthorized - } - } - - // Call this on the session queue. - private func configureSession() { - if setupResult != .success { - return - } - - session.beginConfiguration() - - /* - We do not create an AVCaptureMovieFileOutput when setting up the session because the - AVCaptureMovieFileOutput does not support movie recording with AVCaptureSession.Preset.Photo. - */ - session.sessionPreset = .photo - - // Add video input. - - guard let backCameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { - error("No camera on device") - setupResult = .configurationFailed - session.commitConfiguration() - return - } - - let videoDeviceInput: AVCaptureDeviceInput - do { - videoDeviceInput = try AVCaptureDeviceInput(device: backCameraDevice) - } catch { - self.error("Could not create video device input: \(error)") - setupResult = .configurationFailed - session.commitConfiguration() - return - } - - guard session.canAddInput(videoDeviceInput) else { - error("Could not add video device input to the session") - setupResult = .configurationFailed - session.commitConfiguration() - return - } - - session.addInput(videoDeviceInput) - self.videoDeviceInput = videoDeviceInput - self.cameraDevice = backCameraDevice - DispatchQueue.main.async { - self.videoPreviewLayer.connection?.videoOrientation = .portrait - } - - // Add photo output. - guard session.canAddOutput(photoOutput) else { - error("Could not add photo output to the session") - setupResult = .configurationFailed - session.commitConfiguration() - return - } - session.addOutput(photoOutput) - - photoOutput.isHighResolutionCaptureEnabled = true - photoOutput.isDepthDataDeliveryEnabled = false - //photoOutput.isDualCameraDualPhotoDeliveryEnabled = false - photoOutput.isLivePhotoCaptureEnabled = false - session.commitConfiguration() - } - - func didReceiveTouch(_ touch: UITouch) { - let screenSize = bounds.size - let location = touch.location(in: self) - let focusPoint = CGPoint(x: location.y / screenSize.height, y: 1.0 - location.x / screenSize.width) - log("Focusing on point (\(focusPoint.x),\(focusPoint.y))") - if let device = cameraDevice { - do { - try device.lockForConfiguration() - - if device.isFocusPointOfInterestSupported { - device.focusPointOfInterest = focusPoint - device.focusMode = .autoFocus - } -// if device.isExposurePointOfInterestSupported { -// device.exposurePointOfInterest = focusPoint -// device.exposureMode = .autoExpose -// } - device.unlockForConfiguration() - } catch { - self.error("Could not lock device for configuration: \(error)") - } - } - } -} - -extension CameraView: Logger { } diff --git a/Caps/Capture/PhotoCaptureHandler.swift b/Caps/Capture/PhotoCaptureHandler.swift deleted file mode 100644 index e163c52..0000000 --- a/Caps/Capture/PhotoCaptureHandler.swift +++ /dev/null @@ -1,56 +0,0 @@ -/* -See LICENSE.txt for this sample’s licensing information. - -Abstract: -Photo capture delegate. -*/ - -import AVFoundation -import Photos -import UIKit - -protocol PhotoCaptureHandlerDelegate { - - func didCapture(_ image: UIImage?) -} - -class PhotoCaptureHandler: NSObject { - - var delegate: PhotoCaptureHandlerDelegate? - - var photoSettings: AVCapturePhotoSettings { - let photoSettings = AVCapturePhotoSettings() - photoSettings.flashMode = .off - return photoSettings - } -} - -extension PhotoCaptureHandler: AVCapturePhotoCaptureDelegate { - /* - This extension includes all the delegate callbacks for AVCapturePhotoCaptureDelegate protocol - */ - - func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { - - guard error == nil else { - log("PhotoCaptureHandler: \(error!)") - delegate?.didCapture(nil) - return - } - - guard let cgImage = photo.cgImageRepresentation() else { - log("PhotoCaptureHandler: No image captured") - delegate?.didCapture(nil) - return - } - - let image = UIImage(cgImage: cgImage, scale: 1.0, orientation: .right) - DispatchQueue.main.async { - self.delegate?.didCapture(image) - } - } -} - -extension PhotoCaptureHandler: Logger { - -} diff --git a/Caps/ContentView.swift b/Caps/ContentView.swift new file mode 100644 index 0000000..bbe4863 --- /dev/null +++ b/Caps/ContentView.swift @@ -0,0 +1,339 @@ +import SwiftUI +import SFSafeSymbols +import BottomSheet + +struct ContentView: View { + + private let bottomIconSize: CGFloat = 25 + + private let bottomIconPadding: CGFloat = 7 + + private let capturedImageSize: CGFloat = 80 + + private let plusIconSize: CGFloat = 20 + + private var scale: CGFloat { + UIScreen.main.scale + } + + @EnvironmentObject + var database: Database + + @State + var searchString = "" + + @State + var sortType: SortCriteria = .id + + @State + var sortAscending = false + + @State + var showSortPopover = false + + @State + var showCameraSheet = false + + @State + var showSettingsSheet = false + + @State + var showGridView = false + + @State + var showNewClassifierAlert = false + + @State + var isEnteringNewCapName = false + + @State + private var capIdOfNextPhoto: Int? + + var filteredCaps: [Cap] { + let text = searchString + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() + guard text != "" else { + return Array(database.caps.values) + } + let textParts = text.components(separatedBy: " ").filter { $0 != "" } + return database.caps.values.compactMap { cap -> Cap? in + // For each part of text, check if name contains it + for textItem in textParts { + if !cap.cleanName.contains(textItem) { + return nil + } + } + return cap + } + } + + var shownCaps: [Cap] { + let caps = filteredCaps + if sortAscending { + switch sortType { + case .id: + return caps.sorted { $0.id < $1.id } + case .count: + return caps.sorted { + $0.imageCount < $1.imageCount + } + case .name: + return caps.sorted { + $0.name < $1.name + } + case .match: + return caps.sorted { + match(for: $0.id) ?? 0 < match(for: $1.id) ?? 0 + } + } + } else { + switch sortType { + case .id: + return caps.sorted { $0.id > $1.id } + case .count: + return caps.sorted { + $0.imageCount > $1.imageCount + } + case .name: + return caps.sorted { + $0.name > $1.name + } + case .match: + return caps.sorted { + match(for: $0.id) ?? 0 > match(for: $1.id) ?? 0 + } + } + } + } + + func match(for cap: Int) -> Float? { + database.matches[cap] + } + + var body: some View { + NavigationView { + ZStack { + List(shownCaps) { cap in + CapRowView(cap: cap, match: match(for: cap.id)) + .onTapGesture { + didTap(cap: cap) + } + } + .refreshable { + refresh() + } + .navigationTitle("Caps") + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button(action: showSettings) { + Image(systemSymbol: .gearshape) + } + } + } + VStack(spacing: 0) { + Spacer() + if let image = database.image { + HStack(alignment: .bottom, spacing: 0) { + Spacer() + if isEnteringNewCapName { + Text(String(format: "ID: %d", database.nextCapId)) + .font(.headline) + .padding(.vertical, 3) + .padding(.horizontal, 8) + .background(.regularMaterial) + .cornerRadius(5) + .padding(5) + } + Button(action: didTapClassifiedImage) { + ZStack(alignment: Alignment.bottomTrailing) { + Image(uiImage: image.resize(to: CGSize(width: capturedImageSize, height: capturedImageSize))) + .frame(width: capturedImageSize, height: capturedImageSize) + .background(.gray) + .cornerRadius(capturedImageSize/2) + .padding(5) + .background(.regularMaterial) + .cornerRadius(capturedImageSize/2 + 5) + .padding(5) + if !isEnteringNewCapName { + Image(systemSymbol: .plus) + .frame(width: plusIconSize, height: plusIconSize) + .padding(6) + .background(.regularMaterial) + .cornerRadius(plusIconSize/2 + 6) + .padding(5) + } + } + } + } + } + HStack(spacing: 0) { + if isEnteringNewCapName { + Button(action: removeCapturedImage) { + Image(systemSymbol: .xmark) + .resizable() + .frame(width: bottomIconSize-6, + height: bottomIconSize-6) + .padding() + .padding(3) + } + } else { + Button(action: filter) { + Image(systemSymbol: .line3HorizontalDecreaseCircle) + .resizable() + .frame(width: bottomIconSize, + height: bottomIconSize) + .padding() + } + } + if isEnteringNewCapName { + CapNameEntryView(name: $searchString) + .disableAutocorrection(true) + } else { + SearchField(searchString: $searchString) + .disableAutocorrection(true) + } + if isEnteringNewCapName { + Button(action: saveNewCap) { + Image(systemSymbol: .squareAndArrowDown) + .resizable() + .frame(width: bottomIconSize-3, + height: bottomIconSize) + .padding() + .padding(.horizontal, (bottomIconPadding-3)/2) + } + } else if database.image != nil { + Button(action: removeCapturedImage) { + Image(systemSymbol: .xmark) + .resizable() + .frame(width: bottomIconSize-6, + height: bottomIconSize-6) + .padding(3) + .padding(bottomIconPadding) + } + } else { + Button(action: openCamera) { + Image(systemSymbol: .camera) + .resizable() + .frame(width: bottomIconSize+bottomIconPadding, + height: bottomIconSize) + .padding() + } + } + } + .background(.regularMaterial) + } + } + } + .onAppear { + UIScrollView.appearance().keyboardDismissMode = .onDrag + } + .bottomSheet(isPresented: $showSortPopover, height: 280) { + SortSelectionView( + hasMatches: !database.matches.isEmpty, + isPresented: $showSortPopover, + sortType: $sortType, + sortAscending: $sortAscending, + showGridView: $showGridView) + } + .sheet(isPresented: $showCameraSheet) { + CameraView(isPresented: $showCameraSheet, + image: $database.image, + capId: $capIdOfNextPhoto) + } + .bottomSheet(isPresented: $showSettingsSheet, height: 360) { + SettingsView(isPresented: $showSettingsSheet) + } + .sheet(isPresented: $showGridView) { + GridView() + }.alert(isPresented: $showNewClassifierAlert) { + Alert(title: Text("New classifier available"), + message: Text("Classifier \(database.serverClassifierVersion) is available. You have version \(database.classifierVersion). Do you want to download it now?"), + primaryButton: .default(Text("Download"), action: downloadClassifier), + secondaryButton: .cancel()) + } + .onChange(of: database.image) { newImage in + if newImage != nil { + sortType = .id + sortAscending = false + return + } + }.onChange(of: database.matches) { newMatches in + if newMatches.isEmpty { + sortType = .id + sortAscending = false + } else { + sortType = .match + sortAscending = false + } + } + } + + private func refresh() { + Task { + await database.downloadCaps() + let hasNewClassifier = await database.serverHasNewClassifier() + guard hasNewClassifier else { + return + } + DispatchQueue.main.async { + self.showNewClassifierAlert = true + } + } + } + + private func filter() { + showSortPopover.toggle() + } + + private func openCamera() { + removeCapturedImage() + showCameraSheet.toggle() + } + + private func showSettings() { + showSettingsSheet.toggle() + } + + private func downloadClassifier() { + Task { + await database.downloadClassifier() + } + } + + private func didTapClassifiedImage() { + isEnteringNewCapName = true + } + + private func removeCapturedImage() { + database.image = nil + } + + private func didTap(cap: Cap) { + guard let image = database.image else { + capIdOfNextPhoto = cap.id + openCamera() + return + } + database.save(image, for: cap.id) + database.image = nil + } + + private func saveNewCap() { + guard let image = database.image else { + return + } + let name = searchString.trimmingCharacters(in: .whitespacesAndNewlines) + let newCap = database.save(newCap: name) + database.save(image, for: newCap.id) + removeCapturedImage() + isEnteringNewCapName = false + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + .environmentObject(Database.mock) + } +} diff --git a/Caps/Data/Cap.swift b/Caps/Data/Cap.swift index 361e4b5..bd8d9f0 100644 --- a/Caps/Data/Cap.swift +++ b/Caps/Data/Cap.swift @@ -1,202 +1,159 @@ -// -// Cap.swift -// CapCollector -// -// Created by Christoph on 19.11.18. -// Copyright © 2018 CH. All rights reserved. -// - import Foundation -import UIKit -import CoreImage - -import SQLite struct Cap { - - // MARK: - Static constants - - static let sufficientImageCount = 10 - - static let imageWidth = 299 // New for XCode models, 227/229 for turicreate - static let imageSize = CGSize(width: imageWidth, height: imageWidth) - - static let jpgQuality: CGFloat = 0.3 - - private static let mosaicColumns = 40 - - static let mosaicCellSize: CGFloat = 60 - - private static let mosaicRowHeight = mosaicCellSize * 0.866 - - private static let mosaicMargin = mosaicCellSize - mosaicRowHeight - - // MARK: - Variables - /// The unique number of the cap let id: Int - + /// The name of the cap - let name: String - + var name: String + /// The name of the cap without special characters - let cleanName: String - + var cleanName: String + /// The number of images existing for the cap - let count: Int - - /// Indicate if the cap can be found by the recognition model - let matched: Bool - - /// Indicate if the cap is present on the server - let uploaded: Bool - - // MARK: Init - - init(name: String, id: Int) { - self.id = id - self.count = 1 - self.name = name - self.cleanName = "" - self.matched = false - self.uploaded = false + var imageCount: Int + + /// The index of the main image for the cap + var mainImage: Int + + /// The version of the first classifier capable of recognizing the cap + var classifierVersion: Int? + + var color: Color? + + /// The subpath to the main image on the server + var mainImagePath: String { + String(format: "images/%04d/%04d-%02d.jpg", id, id, mainImage) } - - init(id: Int, name: String, count: Int) { + + /** + Create a new cap. + - Parameter id: The unique id of the cap + - Parameter name: The name associated with the cap + */ + init(id: Int, name: String, classifier: Int? = nil) { self.id = id self.name = name - self.count = count self.cleanName = name.clean - self.matched = false - self.uploaded = true + self.imageCount = 1 + self.mainImage = 0 + self.classifierVersion = classifier } - - func renamed(to name: String) -> Cap { - Cap(from: self, renamed: name) - } - - init(from cap: Cap, renamed newName: String) { - self.id = cap.id - self.count = cap.count - self.name = newName - self.cleanName = newName.clean - self.matched = cap.matched - self.uploaded = cap.uploaded - } - - // MARK: SQLite - - init(row: Row) { - self.id = row[Cap.columnId] - self.name = row[Cap.columnName] - self.count = row[Cap.columnCount] - self.cleanName = name.clean - self.matched = row[Cap.columnMatched] - self.uploaded = row[Cap.columnUploaded] + init(data: CapData) { + self.id = data.id + self.name = data.name + self.cleanName = data.name.clean + self.imageCount = data.count + self.mainImage = data.mainImage + self.classifierVersion = data.classifierVersion } - - static let table = Table("data") - - static var createQuery: String { - table.create(ifNotExists: true) { t in - t.column(columnId, primaryKey: true) - t.column(columnName) - t.column(columnCount) - t.column(columnMatched) - t.column(columnUploaded) - } - } - - static let columnId = Expression("id") - - static let columnName = Expression("name") - - static let columnCount = Expression("count") - - static let columnMatched = Expression("matched") - - static let columnUploaded = Expression("uploaded") - - var insertQuery: Insert { - return Cap.table.insert( - Cap.columnId <- id, - Cap.columnName <- name, - Cap.columnCount <- count, - Cap.columnMatched <- matched, - Cap.columnUploaded <- uploaded) - } - - // MARK: Display - - func matchLabelText(match: Float?, appIsUnlocked: Bool) -> String { - if let match = match { - let percent = Int((match * 100).rounded()) - return String(format: "%d %%", arguments: [percent]) - } - - guard matched else { - return "📵" - } - guard appIsUnlocked, !hasSufficientImages else { - return "" - } - return "⚠️" - } - - func countLabelText(appIsUnlocked: Bool) -> String { - guard appIsUnlocked else { - return "\(id)" - } - guard count != 1 else { - return "\(id) (1 image)" - } - return "\(id) (\(count) images)" - } - - // MARK: Images - var hasSufficientImages: Bool { - count >= Cap.sufficientImageCount + mutating func update(with data: CapData) { + self.name = data.name + self.cleanName = data.name.clean + self.imageCount = data.count + self.mainImage = data.mainImage + self.classifierVersion = data.classifierVersion } - - static func thumbnail(for image: UIImage) -> UIImage { - let len = GridViewController.len * 2 - return image.resize(to: CGSize.init(width: len, height: len)) + + static func ==(lhs: Cap, rhs: CapData) -> Bool { + lhs.id == rhs.id && + lhs.name == rhs.name && + lhs.imageCount == rhs.count && + lhs.mainImage == rhs.mainImage && + lhs.classifierVersion == rhs.classifierVersion + } + + static func !=(lhs: Cap, rhs: CapData) -> Bool { + !(lhs == rhs) + } + + func classifiable(by classifierVersion: Int?) -> Bool { + guard let version = classifierVersion else { + return false + } + guard let own = self.classifierVersion else { + return false + } + return version >= own } } -// MARK: - Protocol Hashable +extension Cap { + + struct Color: Codable, Equatable { + + let r: Int + + let g: Int + + let b: Int + } +} + +// MARK: Protocol Identifiable + +extension Cap: Identifiable { + +} + +// MARK: Protocol Comparable + +extension Cap: Codable { + + enum CodingKeys: String, CodingKey { + case id = "u" + case name = "n" + case cleanName = "c" + case imageCount = "i" + case mainImage = "m" + case classifierVersion = "v" + case color = "f" + } +} + +// MARK: Protocol Comparable + +extension Cap: Comparable { + + static func < (lhs: Cap, rhs: Cap) -> Bool { + lhs.id < rhs.id + } +} + +// MARK: Protocol Equatable + +extension Cap: Equatable { -extension Cap: Hashable { - static func == (lhs: Cap, rhs: Cap) -> Bool { return lhs.id == rhs.id } - +} + +// MARK: Protocol Hashable + +extension Cap: Hashable { + func hash(into hasher: inout Hasher) { hasher.combine(id) } } -// MARK: - Protocol Logger +// MARK: String extension -extension Cap: Logger { } +private extension String { -// MARK: - String extension - -extension String { - var clean: String { return lowercased().replacingOccurrences(of: "[^a-z0-9 ]", with: "", options: .regularExpression) } } -// MARK: - Int extension +// MARK: Int extension private extension Int { - + var isEven: Bool { return self % 2 == 0 } diff --git a/Caps/Data/CapData.swift b/Caps/Data/CapData.swift new file mode 100644 index 0000000..7413694 --- /dev/null +++ b/Caps/Data/CapData.swift @@ -0,0 +1,32 @@ +import Foundation + +struct CapData: Codable { + + let id: Int + + var name: String + + var count: Int + + var mainImage: Int + + var classifierVersion: Int? + + var color: Cap.Color? + + enum CodingKeys: String, CodingKey { + case id = "i" + case name = "n" + case count = "c" + case mainImage = "m" + case classifierVersion = "v" + case color = "f" + } +} + +extension CapData: Comparable { + + static func < (lhs: CapData, rhs: CapData) -> Bool { + lhs.id < rhs.id + } +} diff --git a/Caps/Data/Classifier.swift b/Caps/Data/Classifier.swift index 50b2241..446231e 100644 --- a/Caps/Data/Classifier.swift +++ b/Caps/Data/Classifier.swift @@ -1,11 +1,3 @@ -// -// VisionHandler.swift -// CapFinder -// -// Created by User on 12.02.18. -// Copyright © 2018 User. All rights reserved. -// - import Foundation import Vision import CoreML @@ -13,28 +5,24 @@ import UIKit /// Recognise categories in images class Classifier: Logger { - + static let userDefaultsKey = "classifier.version" - + let model: VNCoreMLModel - + init(model: VNCoreMLModel) { self.model = model } /** Classify an image - Parameter image: The image to classify + - Parameter completion: The callback with the match results + - Parameter matches: A dictionary with a map from cap id to classifier match - Note: This method should not be scheduled on the main thread. */ - func recognize(image: UIImage, completion: @escaping (_ matches: [Int: Float]?) -> Void) { - guard let ciImage = CIImage(image: image) else { - error("Unable to create CIImage") - completion(nil) - return - } - - let orientation = CGImagePropertyOrientation(image.imageOrientation) - let handler = VNImageRequestHandler(ciImage: ciImage, orientation: orientation) + func recognize(image: CGImage, completion: @escaping (_ matches: [Int: Float]?) -> Void) { + let image = CIImage(cgImage: image) + let handler = VNImageRequestHandler(ciImage: image, orientation: .up) let request = VNCoreMLRequest(model: model) { request, error in let matches = self.process(request: request, error: error) completion(matches) @@ -46,7 +34,7 @@ class Classifier: Logger { self.error("Failed to perform classification: \(error)") } } - + private func process(request: VNRequest, error: Error?) -> [Int : Float]? { if let e = error { self.error("Unable to classify image: \(e.localizedDescription)") @@ -57,7 +45,7 @@ class Classifier: Logger { return nil } let matches = result.reduce(into: [:]) { $0[Int($1.identifier)!] = $1.confidence } - + log("Classifed image with \(matches.count) classes") return matches } diff --git a/Caps/Data/Colors.swift b/Caps/Data/Colors.swift deleted file mode 100644 index 4d7d0e6..0000000 --- a/Caps/Data/Colors.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// Colors.swift -// CapCollector -// -// Created by Christoph on 26.05.20. -// Copyright © 2020 CH. All rights reserved. -// - -import UIKit -import SQLite - -extension Database { - - enum Colors { - - static let table = Table("colors") - - static let columnRed = Expression("red") - - static let columnGreen = Expression("green") - - static let columnBlue = Expression("blue") - - static var createQuery: String { - table.create(ifNotExists: true) { t in - t.column(Cap.columnId, primaryKey: true) - t.column(columnRed) - t.column(columnGreen) - t.column(columnBlue) - } - } - } - - var colors: [Int : UIColor] { - do { - let rows = try db.prepare(Database.Colors.table) - return rows.reduce(into: [:]) { dict, row in - let id = row[Cap.columnId] - let r = CGFloat(row[Database.Colors.columnRed]) - let g = CGFloat(row[Database.Colors.columnGreen]) - let b = CGFloat(row[Database.Colors.columnBlue]) - dict[id] = UIColor(red: r, green: g, blue: b, alpha: 1.0) - } - } catch { - log("Failed to load cap colors: \(error)") - return [:] - } - } - - var capsWithColors: Set { - do { - let rows = try db.prepare(Database.Colors.table.select(Cap.columnId)) - return Set(rows.map { $0[Cap.columnId]}) - } catch { - log("Failed to load caps with colors: \(error)") - return [] - } - } - - var capsWithoutColors: Set { - Set(1...capCount).subtracting(capsWithColors) - } - - func removeColor(for cap: Int) -> Bool { - do { - try db.run(Colors.table.filter(Cap.columnId == cap).delete()) - return true - } catch { - log("Failed to delete cap color \(cap): \(error)") - return false - } - } - - func set(color: UIColor, for cap: Int) -> Bool { - guard let _ = row(for: cap) else { - return insert(color: color, for: cap) - } - return update(color: color, for: cap) - } - - private func insert(color: UIColor, for cap: Int) -> Bool { - let (red, green, blue) = color.rgb - let query = Database.Colors.table.insert( - Cap.columnId <- cap, - Database.Colors.columnRed <- red, - Database.Colors.columnGreen <- green, - Database.Colors.columnBlue <- blue) - - do { - try db.run(query) - return true - } catch { - log("Failed to insert color for cap \(cap): \(error)") - return false - } - } - - private func update(color: UIColor, for cap: Int) -> Bool { - let (red, green, blue) = color.rgb - let query = Database.Colors.table.filter(Cap.columnId == cap).update( - Database.Colors.columnRed <- red, - Database.Colors.columnGreen <- green, - Database.Colors.columnBlue <- blue) - - do { - try db.run(query) - return true - } catch { - log("Failed to update color for cap \(cap): \(error)") - return false - } - } - - private func row(for cap: Int) -> Row? { - do { - return try db.pluck(Database.Colors.table.filter(Cap.columnId == cap)) - } catch { - log("Failed to get color for cap \(cap): \(error)") - return nil - } - } - - func color(for cap: Int) -> UIColor? { - guard let row = self.row(for: cap) else { - return nil - } - let r = CGFloat(row[Database.Colors.columnRed]) - let g = CGFloat(row[Database.Colors.columnGreen]) - let b = CGFloat(row[Database.Colors.columnBlue]) - return UIColor(red: r, green: g, blue: b, alpha: 1.0) - } -} diff --git a/Caps/Data/Database.swift b/Caps/Data/Database.swift index 29a4f24..e699b5a 100644 --- a/Caps/Data/Database.swift +++ b/Caps/Data/Database.swift @@ -1,1042 +1,636 @@ -// -// Database.swift -// CapCollector -// -// Created by Christoph on 14.04.20. -// Copyright © 2020 CH. All rights reserved. -// - import Foundation -import UIKit -import CoreML -import SQLite +import SwiftUI +import Vision +import CryptoKit -protocol DatabaseDelegate: AnyObject { - - func database(didAddCap cap: Cap) - - func database(didChangeCap cap: Int) - - func database(didLoadImageForCap cap: Int) - - func database(completedBackgroundWorkItem title: String, subtitle: String) - - func database(needsUserConfirmation title: String, body: String, shouldProceed: @escaping (Bool) -> Void) - - func database(didFailBackgroundWork title: String, subtitle: String) - - func databaseHasNewClassifier() - - func databaseDidFinishBackgroundWork() - - func databaseNeedsFullRefresh() -} +final class Database: ObservableObject { -private enum BackgroundWorkTaskType: Int, CustomStringConvertible, Comparable { - - case downloadCapNames = 9 - case downloadCounts = 8 - case downloadClassifier = 7 - case uploadingCaps = 6 - case uploadingImages = 5 - case downloadMainImages = 4 - case creatingThumbnails = 3 - case creatingColors = 2 - - var description: String { - switch self { - case .downloadCapNames: - return "Downloading names" - case .downloadCounts: - return "Downloading counts" - case .downloadClassifier: - return "Downloading classifier" - case .uploadingCaps: - return "Uploading caps" - case .uploadingImages: - return "Uploading images" - case .downloadMainImages: - return "Downloading images" - case .creatingThumbnails: - return "Creating thumbnails" - case .creatingColors: - return "Creating colors" - } - } - - - var maximumNumberOfSimultaneousItems: Int { - switch self { - case .downloadMainImages: - return 50 - case .creatingThumbnails: - return 10 - case .creatingColors: - return 10 - default: - return 1 - } - } - - var nextType: BackgroundWorkTaskType? { - BackgroundWorkTaskType(rawValue: rawValue - 1) - } - - static func < (lhs: BackgroundWorkTaskType, rhs: BackgroundWorkTaskType) -> Bool { - lhs.rawValue < rhs.rawValue - } - -} + static let imageCacheMemory = 10_000_000 + static let imageCacheStorage = 200_000_000 -final class Database { - - // MARK: Variables - - let db: Connection - - private let upload: Upload - - private let download: Download - - let storage: Storage - - weak var delegate: DatabaseDelegate? + private let imageCompressionQuality: CGFloat = 0.3 - init?(url: URL, server: URL, storageFolder: URL) { - guard let db = try? Connection(url.path) else { - return nil - } - - let upload = Upload(server: server) - let download = Download(server: server) - - do { - try db.run(Cap.createQuery) - try db.run(upload.createQuery) - try db.run(Database.Colors.createQuery) - try db.run(Database.TileImage.createQuery) - } catch { - return nil - } + private static var documentDirectory: URL { + try! FileManager.default.url( + for: .documentDirectory, + in: .userDomainMask, + appropriateFor: nil, create: true) + } - self.db = db - self.upload = upload - self.download = download - self.storage = Storage(in: storageFolder) - log("Database loaded with \(capCount) caps") + private var fm: FileManager { + .default } - - // MARK: Computed properties - /// All caps currently in the database - var caps: [Cap] { - (try? db.prepare(Cap.table))?.map(Cap.init) ?? [] + private var localDbUrl: URL { + Database.documentDirectory.appendingPathComponent("db.json") } - - /// The ids of all caps - var capIds: Set { - Set(caps.map { $0.id }) + + private var localClassifierUrl: URL { + Database.documentDirectory.appendingPathComponent("classifier.mlmodel") } - - /// A dictionary of all caps, indexed by their ids - var capDict: [Int : Cap] { - caps.reduce(into: [:]) { $0[$1.id] = $1 } + + private var imageUploadFolderUrl: URL { + Database.documentDirectory.appendingPathComponent("uploads") } - - /// The ids of the caps which weren't included in the last classification - var unmatchedCaps: [Int] { - let query = Cap.table.select(Cap.columnId).filter(Cap.columnMatched == false) - return (try? db.prepare(query).map { $0[Cap.columnId] }) ?? [] + + private var serverDbUrl: URL { + serverUrl.appendingPathComponent("caps.json") } - - /// The number of caps which could be recognized during the last classification - var recognizedCapCount: Int { - (try? db.scalar(Cap.table.filter(Cap.columnMatched == true).count)) ?? 0 + + private var serverClassifierUrl: URL { + serverUrl.appendingPathComponent("classifier.mlmodel") } - - /// The number of caps currently in the database - var capCount: Int { - (try? db.scalar(Cap.table.count)) ?? 0 + + private var serverClassifierVersionUrl: URL { + serverUrl.appendingPathComponent("classifier.version") } - - /// The total number of images for all caps - var imageCount: Int { - (try? db.prepare(Cap.table).reduce(0) { $0 + $1[Cap.columnCount] }) ?? 0 + + private let encoder = JSONEncoder() + private let decoder = JSONDecoder() + + let serverUrl: URL + + @AppStorage("authKey") + private var serverAuthenticationKey: String? + + var hasServerAuthentication: Bool { + serverAuthenticationKey != nil } - - var nextPendingCapUpload: Cap? { - do { - guard let row = try db.pluck(Cap.table.filter(Cap.columnUploaded == false).order(Cap.columnId.asc)) else { - return nil - } - return Cap(row: row) - } catch { - log("Failed to get next pending cap upload") - return nil - } + + @Published + private(set) var caps: [Int : Cap] { + didSet { scheduleSave() } } - - var pendingCapUploadCount: Int { - do { - let query = Cap.table.filter(Cap.columnUploaded == false).count - return try db.scalar(query) - } catch { - log("Failed to get pending cap upload count") - return 0 - } + + var nextCapId: Int { + (caps.values.max()?.id ?? 0) + 1 } - - var nextPendingImageUpload: (id: Int, version: Int)? { - do { - guard let row = try db.pluck(upload.table) else { - return nil - } - return (id: row[upload.rowCapId], version: row[upload.rowCapVersion]) - } catch { - log("Failed to get pending image uploads") - return nil - } - } - - var capsWithImages: Set { - capIds.filter { storage.hasImage(for: $0) } - } - - var capsWithThumbnails: Set { - capIds.filter { storage.hasThumbnail(for: $0) } - } - - var pendingImageUploadCount: Int { - ((try? db.scalar(upload.table.count)) ?? 0) - } - - /// The number of caps without a thumbnail on disk - var pendingCapForThumbnailCreation: Int { - caps.reduce(0) { $0 + (storage.hasThumbnail(for: $1.id) ? 0 : 1) } - } - - var pendingCapsForColorCreation: Int { - do { - return try capCount - db.scalar(Colors.table.count) - } catch { - log("Failed to get count of caps without color: \(error)") - return 0 - } - } - - - - var classifierVersion: Int { - set { - UserDefaults.standard.set(newValue, forKey: Classifier.userDefaultsKey) - log("Classifier version set to \(newValue)") - } + + @AppStorage("changed") + private var changedCapStorage: String = "" + + private(set) var changedCaps: Set { get { - UserDefaults.standard.integer(forKey: Classifier.userDefaultsKey) + Set(changedCapStorage.components(separatedBy: ",").compactMap(Int.init)) } - } - - var isInOfflineMode: Bool { set { - UserDefaults.standard.set(newValue, forKey: Upload.offlineKey) - log("Offline mode set to \(newValue)") + changedCapStorage = newValue.map { "\($0)" }.joined(separator: ",") } - get { - UserDefaults.standard.bool(forKey: Upload.offlineKey) - } - } - - // MARK: Data updates - - /** - Create a new cap with an image. - - The cap is inserted into the database, and the name and image will be uploaded to the server. - - - parameter image: The main image of the cap - - parameter name: The name of the cap - - note: Must be called on the main queue. - - note: The registered delegates will be informed about the added cap through `database(didAddCap:)` - - returns: `true`, if the cap was created. - */ - func createCap(image: UIImage, name: String) -> Bool { - let cap = Cap(name: name, id: capCount + 1) - guard insert(cap: cap) else { - log("Cap not inserted") - return false - } - guard storage.save(image: image, for: cap.id) else { - log("Cap image not saved") - return false - } - addPendingUpload(for: cap.id, version: 0) - startBackgroundWork() - return true - } - - /** - Insert a new cap. - - Only inserts the cap into the database, and optionally notifies the delegates. - - note: When a new cap is created, use `createCap(image:name:)` instead - */ - @discardableResult - private func insert(cap: Cap, notify: Bool = true) -> Bool { - do { - try db.run(cap.insertQuery) - if notify { - DispatchQueue.main.async { - self.delegate?.database(didAddCap: cap) - } - } - return true - } catch { - log("Failed to insert cap \(cap.id): \(error)") - return false - } - } - - func add(image: UIImage, for cap: Int) -> Bool { - guard let version = count(for: cap) else { - log("Failed to get count for cap \(cap)") - return false - } - guard storage.save(image: image, for: cap, version: version) else { - log("Failed to save image \(version) for cap \(cap) to disk") - return false - } - guard update(count: version + 1, for: cap) else { - log("Failed update count \(version) for cap \(cap)") - return false - } - guard addPendingUpload(for: cap, version: version) else { - log("Failed to add cap \(cap) version \(version) to upload queue") - return false - } - startBackgroundWork() - return true - } - - // MARK: Updating cap properties - - private func update(_ property: String, for cap: Int, notify: Bool = true, setter: Setter...) -> Bool { - do { - let query = updateQuery(for: cap).update(setter) - try db.run(query) - if notify { - DispatchQueue.main.async { - self.delegate?.database(didChangeCap: cap) - } - } - return true - } catch { - log("Failed to update \(property) for cap \(cap): \(error)") - return false - } - } - - @discardableResult - private func update(uploaded: Bool, for cap: Int) -> Bool { - update("uploaded", for: cap, setter: Cap.columnUploaded <- uploaded) } - @discardableResult - private func update(count: Int, for cap: Int) -> Bool { - update("count", for: cap, setter: Cap.columnCount <- count) + private lazy var imageUploads: [Int: Int] = loadImageUploadCounts() + + private var uploadTimer: Timer? + + /// The classifications for all caps from the classifier + @Published + var matches = [Int : Float]() + + @Published + var image: UIImage? = nil { + didSet { classifyImage() } } - - @discardableResult - private func update(matched: Bool, for cap: Int) -> Bool { - update("matched", for: cap, setter: Cap.columnMatched <- matched) - } - - // MARK: External editing - + + private var classifier: Classifier? + /** - Update the `name` of a cap. + The time to wait for changes to be written to disk. + + This delay is used to prevent file writes for each small update to the caps. */ - @discardableResult - func update(name: String, for cap: Int) -> Bool { - guard update("name", for: cap, setter: Cap.columnName <- name, Cap.columnUploaded <- false) else { - return false - } - startBackgroundWork() - return true + private let saveDelay: TimeInterval = 1 + + /** + The time when a save should occur. + + No save is necessary if this property is `nil`. + */ + private var nextSaveTime: Date? + + let imageCache: URLCache + + init(server: URL) { + self.serverUrl = server + self.caps = [:] + + let cacheDirectory = Database.documentDirectory.appendingPathComponent("images") + self.imageCache = URLCache( + memoryCapacity: Database.imageCacheMemory, + diskCapacity: Database.imageCacheStorage, + directory: cacheDirectory) + loadCaps() + } - - @discardableResult - private func updateWithoutUpload(name: String, for cap: Int) -> Bool { - update("name", for: cap, notify: false, setter: Cap.columnName <- name) - } - - func update(recognizedCaps: Set) { - let unrecognized = self.unmatchedCaps - // Update caps which haven't been recognized before - let newlyRecognized = recognizedCaps.intersection(unrecognized) - let logIndividualMessages = newlyRecognized.count < 10 - if !logIndividualMessages { - log("Marking \(newlyRecognized.count) caps as matched") + + @Published + var isUploading = false + + // MARK: Disk storage + + private func loadCaps() { + guard fm.fileExists(atPath: localDbUrl.path) else { + return } - for cap in newlyRecognized { - if logIndividualMessages { - log("Marking cap \(cap) as matched") - } - update(matched: true, for: cap) - } - // Update caps which are no longer recognized - let missing = Set(1...capCount).subtracting(recognizedCaps).subtracting(unrecognized) - for cap in missing { - log("Marking cap \(cap) as not matched") - update(matched: false, for: cap) - } - } - - // MARK: Uploads - - @discardableResult - private func addPendingUpload(for cap: Int, version: Int) -> Bool { + let data: Data do { - guard try db.scalar(upload.existsQuery(for: cap, version: version)) == 0 else { - return true - } - try db.run(upload.insertQuery(for: cap, version: version)) + data = try Data(contentsOf: localDbUrl) + } catch { + print("Failed to read database file: \(error)") + return + } + do { + let array = try JSONDecoder().decode([Cap].self, from: data) + self.caps = array.reduce(into: [:]) { $0[$1.id] = $1 } + // Prevent immediate save after modifying caps + nextSaveTime = nil + } catch { + print("Failed to decode database file: \(error)") + return + } + } + + private func scheduleSave() { + nextSaveTime = Date.now.addingTimeInterval(saveDelay) + DispatchQueue.main.asyncAfter(deadline: .now() + saveDelay) { + self.performScheduledSave() + } + } + + private func performScheduledSave() { + guard let date = nextSaveTime else { + // No save necessary, or already saved + return + } + guard date < .now else { + // Save pushed to future + return + } + save() + nextSaveTime = nil + } + + private func save() { + let data: Data + do { + data = try encoder.encode(caps.values.sorted()) + } catch { + print("Failed to encode database: \(error)") + return + } + do { + try data.write(to: localDbUrl) + } catch { + print("Failed to save database: \(error)") + } + print("Database saved") + } + + private func ensureFolderExistence(_ url: URL) -> Bool { + guard !fm.fileExists(atPath: url.path) else { + return true + } + do { + try fm.createDirectory(at: url, withIntermediateDirectories: true) return true } catch { - log("Failed to add pending upload of cap \(cap) version \(version): \(error)") + log("Failed to create folder \(url.path): \(error)") return false } } - - @discardableResult - private func removePendingUpload(for cap: Int, version: Int) -> Bool { - do { - try db.run(upload.deleteQuery(for: cap, version: version)) - return true - } catch { - log("Failed to remove pending upload of cap \(cap) version \(version): \(error)") - return false - } - } - - // MARK: Information retrieval - - func cap(for id: Int) -> Cap? { - do { - guard let row = try db.pluck(updateQuery(for: id)) else { - log("No cap with id \(id) in database") - return nil - } - return Cap(row: row) - } catch { - log("Failed to get cap \(id): \(error)") - return nil - } - } - - private func count(for cap: Int) -> Int? { - do { - let row = try db.pluck(updateQuery(for: cap).select(Cap.columnCount)) - return row?[Cap.columnCount] - } catch { - log("Failed to get count for cap \(cap)") - return nil - } - } - - func countOfCaps(withImageCountLessThan limit: Int) -> Int { - do { - return try db.scalar(Cap.table.filter(Cap.columnCount < limit).count) - } catch { - log("Failed to get caps with less than \(limit) images") - return 0 - } - } - - func lowestImageCountForCaps(startingAt start: Int) -> (count: Int, numberOfCaps: Int) { - do { - var currentCount = start - 1 - var capsFound = 0 - repeat { - currentCount += 1 - capsFound = try db.scalar(Cap.table.filter(Cap.columnCount == currentCount).count) - } while capsFound == 0 - - return (currentCount, capsFound) - } catch { - return (0,0) - } - } - - func updateQuery(for cap: Int) -> Table { - Cap.table.filter(Cap.columnId == cap) - } - + // MARK: Downloads - + @discardableResult - func downloadImage(for cap: Int, version: Int = 0, completion: @escaping (_ image: UIImage?) -> Void) -> Bool { - let url = storage.localImageUrl(for: cap, version: version) - return download.image(for: cap, version: version, to: url) { success in - if version == 0 && success { + func downloadCaps() async -> Bool { + print("Downloading cap data") + let data: Data + let response: URLResponse + do { + (data, response) = try await URLSession.shared.data(from: serverDbUrl) + } catch { + print("Failed to download classifier version: \(error)") + return false + } + guard (response as? HTTPURLResponse)?.statusCode == 200 else { + return false + } + + let capData: [CapData] + do { + capData = try decoder.decode([CapData].self, from: data) + } catch { + print("Failed to decode server database: \(error)") + return false + } + var inserts = 0 + var updates = 0 + for cap in capData { + guard var oldCap = caps[cap.id] else { + caps[cap.id] = Cap(data: cap) + inserts += 1 + continue + } + guard oldCap != cap else { + continue + } + if changedCaps.contains(oldCap.id) { +#warning("Merge changed caps with server updates") + } else { + oldCap.update(with: cap) + caps[cap.id] = oldCap + updates += 1 + } + } + print("Updated database from server (\(inserts) added, \(updates) updated)") + return true + } + + @discardableResult + func serverHasNewClassifier() async -> Bool { + let data: Data + let response: URLResponse + do { + (data, response) = try await URLSession.shared.data(from: serverClassifierVersionUrl) + } catch { + print("Failed to download classifier version: \(error)") + return false + } + guard (response as? HTTPURLResponse)?.statusCode == 200 else { + return false + } + + guard let string = String(data: data, encoding: .utf8) else { + log("Classifier version is invalid data (not a string)") + return false + } + guard let serverVersion = Int(string.trimmingCharacters(in: .whitespacesAndNewlines)) else { + log("Classifier version has an invalid value '\(string)'") + return false + } + DispatchQueue.main.async { + self.serverClassifierVersion = serverVersion + } + guard serverVersion > self.classifierVersion else { + print("No new classifier available") + return false + } + print("New classifier \(serverVersion) available") + return true + } + + @discardableResult + func downloadClassifier() async -> Bool { + print("Downloading classifier") + let tempUrl: URL + let response: URLResponse + do { + (tempUrl, response) = try await URLSession.shared.download(from: serverClassifierUrl) + } catch { + print("Failed to download classifier version: \(error)") + return false + } + guard (response as? HTTPURLResponse)?.statusCode == 200 else { + return false + } + do { + let url = self.localClassifierUrl + if fm.fileExists(atPath: url.path) { + try self.fm.removeItem(at: url) + } + try self.fm.moveItem(at: tempUrl, to: url) + } catch { + print("Failed to replace classifier: \(error)") + return false + } + DispatchQueue.main.async { + self.classifierVersion = self.serverClassifierVersion + self.classifier = nil + } + print("Downloaded classifier \(classifierVersion)") + return true + } + + /** + Indicate that the cap has pending operations, such as determining the color or a thumbnail + */ + func hasPendingOperations(for cap: Int) -> Bool { + return false + } + + // MARK: Adding new data + + func save(newCap name: String) -> Cap { + let cap = Cap(id: nextCapId, name: name, classifier: serverClassifierVersion) + caps[cap.id] = cap + #warning("Upload new cap") + return cap + } + + @discardableResult + func save(_ image: UIImage, for capId: Int) -> Bool { + guard caps[capId] != nil else { + log("Failed to save image for missing cap \(capId)") + return false + } + guard ensureFolderExistence(imageUploadFolderUrl) else { + return false + } + guard let data = image.jpegData(compressionQuality: imageCompressionQuality) else { + log("Failed to compress image for cap: \(capId)") + return false + } + let hash = Data(SHA256.hash(data: data)).hexEncoded.prefix(16) + let url = imageUploadFolderUrl.appendingPathComponent("\(capId)-\(hash).jpg") + do { + try data.write(to: url) + } catch { + log("Failed to save \(url.lastPathComponent): \(error)") + return false + } + log("Saved \(url.lastPathComponent) for upload") + caps[capId]?.imageCount += 1 + updateImageUploadCounts() + return true + } + + private func updateImageUploadCounts() { + + } + + private func loadImageUploadCounts() -> [Int : Int] { + var result = [Int : Int]() + pendingImageUploads.forEach { url in + guard let capId = capId(from: url) else { + return + } + if let old = result[capId] { + result[capId] = old + 1 + } else { + result[capId] = 1 + } + } + return result + } + + // MARK: Uploads + + func startRegularUploads() { + guard uploadTimer != nil else { + return + } + DispatchQueue.main.async { + self.uploadTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: self.uploadTimerElapsed) + } + } + + private func uploadTimerElapsed(timer: Timer) { + Task { + await uploadAll() + } + } + + private func uploadAll() async { + guard !isUploading else { + return + } + DispatchQueue.main.async { + self.isUploading = true + } + await uploadAllChangedCaps() + await uploadAllImages() + DispatchQueue.main.async { + self.isUploading = false + } + } + + /** + Indicate that the cap has pending uploads, either changes or images + */ + func hasPendingUpdates(for cap: Int) -> Bool { + changedCaps.contains(cap) || imageUploads[cap] != nil + } + + private var pendingImageUploads: [URL] { + (try? fm.contentsOfDirectory(at: imageUploadFolderUrl, includingPropertiesForKeys: nil)) ?? [] + } + + var pendingImageUploadCount: Int { + pendingImageUploads.count + } + + private func capId(from url: URL) -> Int? { + Int(url.lastPathComponent.components(separatedBy: "-").first!) + } + + private func uploadAllImages() async { + guard hasServerAuthentication else { + log("No server authentication to upload to server") + return + } + updateImageUploadCounts() + for url in pendingImageUploads { + guard let capId = capId(from: url) else { + log("Unexpected image \(url.lastPathComponent) in upload folder") + continue + } + guard await upload(imageAt: url, for: capId) else { + continue + } + do { + try fm.removeItem(at: url) + updateImageUploadCounts() + } catch { + log("Failed to remove uploaded image \(url.lastPathComponent): \(error)") + } + } + } + + @discardableResult + private func upload(imageAt url: URL, for cap: Int) async -> Bool { + guard let key = serverAuthenticationKey else { + return false + } + let url = serverUrl + .appendingPathComponent("images") + .appendingPathComponent("\(cap)?key=\(key)") + var request = URLRequest(url: url) + request.httpMethod = "POST" + do { + let (_, response) = try await URLSession.shared.upload(for: request, fromFile: url) + guard let httpResponse = response as? HTTPURLResponse else { + log("Unexpected response for upload of image \(url.lastPathComponent): \(response)") + return false + } + guard httpResponse.statusCode == 200 else { + log("Failed to upload image \(url.lastPathComponent): Response \(httpResponse.statusCode)") + return false + } + return true + } catch { + log("Failed to upload image \(url.lastPathComponent): \(error)") + return false + } + } + + var pendingCapUploadCount: Int { + changedCaps.count + } + + private func uploadAllChangedCaps() async { + guard hasServerAuthentication else { + log("No server authentication to upload to server") + return + } + var uploaded = Set() + for capId in changedCaps { + guard let cap = caps[capId] else { + uploaded.insert(capId) + continue + } + guard await upload(cap: cap) else { + continue + } + uploaded.insert(capId) + } + changedCaps.subtract(uploaded) + } + + @discardableResult + private func upload(cap: Cap) async -> Bool { + guard let key = serverAuthenticationKey else { + return false + } + let data: Data + do { + /// `Cap` and `CapData` have equivalent JSON layout + data = try encoder.encode(cap) + } catch { + log("Failed to encode cap \(cap.id) for upload: \(error)") + return false + } + let url = serverUrl + .appendingPathComponent("images") + .appendingPathComponent("\(cap)?key=\(key)") + var request = URLRequest(url: url) + request.httpMethod = "POST" + do { + let (_, response) = try await URLSession.shared.upload(for: request, from: data) + guard let httpResponse = response as? HTTPURLResponse else { + log("Unexpected response for upload of cap \(cap.id): \(response)") + return false + } + guard httpResponse.statusCode == 200 else { + log("Failed to upload cap \(cap.id): Response \(httpResponse.statusCode)") + return false + } + changedCaps.remove(cap.id) + return true + } catch { + log("Failed to upload cap \(cap.id): \(error)") + return false + } + } + + // MARK: Classification + + /// The compiled recognition model on disk + private var recognitionModel: VNCoreMLModel? { + guard fm.fileExists(atPath: localClassifierUrl.path) else { + log("No recognition model to load from disk") + return nil + } + do { + log("Loading model from disk") + let newUrl = try MLModel.compileModel(at: localClassifierUrl) + let model = try MLModel(contentsOf: newUrl) + return try VNCoreMLModel(for: model) + } catch { + log("Failed to load recognition model: \(error)") + return nil + } + } + + private func classifyImage() { + guard let image = image?.cgImage else { + matches.removeAll() + log("Image removed") + return + } + DispatchQueue.global().async { + guard let classifier = self.getClassifier() else { + return + } + log("Image classification started") + classifier.recognize(image: image) { matches in DispatchQueue.main.async { - self.delegate?.database(didLoadImageForCap: cap) - } - } - let image = self.storage.image(for: cap, version: version) - completion(image) - } - } - - private func update(names: [String]) { - let notify = capCount > 0 - log("Downloaded cap names (initialDownload: \(!notify))") - let caps = self.capDict - let changed: [Int] = names.enumerated().compactMap { id, name in - let id = id + 1 - guard let existingName = caps[id]?.name else { - // Insert cap - let cap = Cap(id: id, name: name, count: 0) - guard insert(cap: cap, notify: notify) else { - return nil - } - return id - } - guard existingName != name else { - // Name unchanged - return nil - } - guard updateWithoutUpload(name: name, for: id) else { - return nil - } - return id - } - if !notify { - log("Added \(changed.count) new caps after initial download") - delegate?.databaseNeedsFullRefresh() - } - } - - var isDoingWorkInBackgound: Bool { - backgroundTaskStatus != nil - } - - private var didUpdateBackgroundItems = false - private var backgroundTaskStatus: BackgroundWorkTaskType? = nil - private var expectedBackgroundWorkStatus: BackgroundWorkTaskType? = nil - - private var nextBackgroundWorkStatus: BackgroundWorkTaskType? { - guard let oldType = backgroundTaskStatus else { - return expectedBackgroundWorkStatus - } - guard let type = expectedBackgroundWorkStatus else { - return backgroundTaskStatus?.nextType - } - guard oldType > type else { - return type - } - return oldType.nextType - } - - private func setNextBackgroundWorkStatus() -> BackgroundWorkTaskType? { - backgroundTaskStatus = nextBackgroundWorkStatus - expectedBackgroundWorkStatus = nil - return backgroundTaskStatus - } - - private let context = CIContext(options: [.workingColorSpace: kCFNull!]) - - - func startInitialDownload() { - startBackgroundWork(startingWith: .downloadCapNames) - } - - func scheduleClassifierDownload() { - startBackgroundWork(startingWith: .downloadClassifier) - } - - func startBackgroundWork() { - startBackgroundWork(startingWith: .uploadingCaps) - } - - private func startBackgroundWork(startingWith type: BackgroundWorkTaskType) { - guard !isDoingWorkInBackgound else { - if expectedBackgroundWorkStatus?.rawValue ?? 0 < type.rawValue { - log("Background work scheduled: \(type)") - expectedBackgroundWorkStatus = type - } - return - } - DispatchQueue.global(qos: .utility).async { - self.performAllBackgroundWorkItems(allItemsStartingAt: type) - } - } - - private func performAllBackgroundWorkItems(allItemsStartingAt type: BackgroundWorkTaskType) { - didUpdateBackgroundItems = false - expectedBackgroundWorkStatus = type - log("Starting background task") - while let type = setNextBackgroundWorkStatus() { - log("Handling background task: \(type)") - guard performAllItems(for: type) else { - // If an error occurs, stop the background tasks - backgroundTaskStatus = nil - expectedBackgroundWorkStatus = nil - break - } - } - log("Background work completed") - delegate?.databaseDidFinishBackgroundWork() - } - - private func performAllItems(for type: BackgroundWorkTaskType) -> Bool { - switch type { - case .downloadCapNames: - return downloadCapNames() - case .downloadCounts: - return downloadImageCounts() - case .downloadClassifier: - return downloadClassifier() - case .uploadingCaps: - return uploadCaps() - case .uploadingImages: - return uploadImages() - case .downloadMainImages: - return downloadMainImages() - case .creatingThumbnails: - return createThumbnails() - case .creatingColors: - return createColors() - } - } - - private func downloadCapNames() -> Bool { - log("Downloading cap names") - let result = DispatchGroup.singleTask { callback in - download.names { names in - guard let names = names else { - callback(false) - return - } - self.update(names: names) - callback(true) - } - } - log("Completed download of cap names") - return result - } - - private func downloadImageCounts() -> Bool { - log("Downloading cap image counts") - let result = DispatchGroup.singleTask { callback in - download.imageCounts { counts in - guard let counts = counts else { - self.log("Failed to download server image counts") - callback(false) - return - } - let newCaps = self.didDownload(imageCounts: counts) - - guard newCaps.count > 0 else { - callback(true) - return - } - self.log("Found \(newCaps.count) new caps on the server.") - self.downloadInfo(for: newCaps) { success in - callback(success) + self.matches = matches ?? [:] } } } - guard result else { - log("Failed download of cap image counts") - return false - } - log("Completed download of cap image counts") - return true } - - private func downloadClassifier() -> Bool { - log("Downloading classifier (if needed)") - let result = DispatchGroup.singleTask { callback in - download.classifierVersion { version in - guard let version = version else { - self.log("Failed to download server model version") - callback(false) - return - } - let ownVersion = self.classifierVersion - guard ownVersion < version else { - self.log("Not updating classifier: Own version \(ownVersion), server version \(version)") - callback(true) - return - } - let title = "Download classifier" - let detail = ownVersion == 0 ? - "A classifier to match caps is available for download (version \(version)). Would you like to download it now?" : - "Version \(version) of the classifier is available for download (You have version \(ownVersion)). Would you like to download it now?" - self.delegate!.database(needsUserConfirmation: title, body: detail) { proceed in - guard proceed else { - self.log("User skipped classifier download") - callback(true) - return - } - self.download.classifier { progress, received, total in - let t = ByteCountFormatter.string(fromByteCount: total, countStyle: .file) - let r = ByteCountFormatter.string(fromByteCount: received, countStyle: .file) - let title = String(format: "%.0f", progress * 100) + " % (\(r) / \(t))" - self.delegate?.database(completedBackgroundWorkItem: "Downloading classifier", subtitle: title) - } completion: { url in - guard let url = url else { - self.log("Failed to download classifier") - callback(false) - return - } - let compiledUrl: URL - do { - compiledUrl = try MLModel.compileModel(at: url) - } catch { - self.log("Failed to compile downloaded classifier: \(error)") - callback(false) - return - } - - guard self.storage.save(recognitionModelAt: compiledUrl) else { - self.log("Failed to save compiled classifier") - callback(false) - return - } - callback(true) - self.classifierVersion = version - } - } - } + + private func getClassifier() -> Classifier? { + if let classifier = classifier { + return classifier } - log("Downloaded classifier (if new version existed)") - return result + guard let model = recognitionModel else { + return nil + } + return Classifier(model: model) } - - private func uploadCaps() -> Bool { - var completed = 0 - while let cap = nextPendingCapUpload { - guard upload.upload(cap) else { - delegate?.database(didFailBackgroundWork: "Upload failed", - subtitle: "Cap \(cap.id) not uploaded") - return false - } - update(uploaded: true, for: cap.id) - completed += 1 - let total = completed + pendingCapUploadCount - delegate?.database(completedBackgroundWorkItem: "Uploading caps", subtitle: "\(completed) of \(total)") - } - return true + + // MARK: Statistics + + var numberOfCaps: Int { + caps.count } - - private func uploadImages() -> Bool { - var completed = 0 - while let (id, version) = nextPendingImageUpload { - guard let cap = self.cap(for: id) else { - log("No cap \(id) to upload image \(version)") - removePendingUpload(for: id, version: version) - continue - } - guard let url = storage.existingImageUrl(for: cap.id, version: version) else { - log("No image \(version) of cap \(id) to upload") - removePendingUpload(for: id, version: version) - continue - } - guard let count = upload.upload(imageAt: url, of: cap.id) else { - delegate?.database(didFailBackgroundWork: "Upload failed", subtitle: "Image \(version) of cap \(id)") - return false - } - if count > cap.count { - update(count: count, for: cap.id) - } - removePendingUpload(for: id, version: version) - - completed += 1 - let total = completed + pendingImageUploadCount - delegate?.database(completedBackgroundWorkItem: "Uploading images", subtitle: "\(completed + 1) of \(total)") - } - return true + + var numberOfImages: Int { + caps.values.reduce(0) { $0 + $1.imageCount } } - - private func downloadMainImages() -> Bool { - let missing = caps.map { $0.id }.filter { !storage.hasImage(for: $0) } - let count = missing.count - guard count > 0 else { - log("No images to download") - return true - } - log("Starting image downloads") - - let group = DispatchGroup() - group.enter() - - var shouldDownload = true - let title = "Download images" - let detail = "\(count) caps have no image. Would you like to download them now? (~ \(ByteCountFormatter.string(fromByteCount: Int64(count * 10000), countStyle: .file))). Grid view is not available until all images are downloaded." - delegate?.database(needsUserConfirmation: title, body: detail) { proceed in - shouldDownload = proceed - group.leave() - } - group.wait() - guard shouldDownload else { - log("User skipped image download") - return false - } - - group.enter() - let queue = DispatchQueue(label: "images") - let semaphore = DispatchSemaphore(value: 5) - - var downloadsAreSuccessful = true - var completed = 0 - for cap in missing { - queue.async { - guard downloadsAreSuccessful else { - return - } - semaphore.wait() - let url = self.storage.localImageUrl(for: cap) - self.download.image(for: cap, to: url, queue: queue) { success in - defer { semaphore.signal() } - guard success else { - self.delegate?.database(didFailBackgroundWork: "Download failed", subtitle: "Image of cap \(cap)") - downloadsAreSuccessful = false - group.leave() - return - } - completed += 1 - self.delegate?.database(completedBackgroundWorkItem: "Downloading images", subtitle: "\(completed) of \(missing.count)") - if completed == missing.count { - group.leave() - } - } - } - } - guard group.wait(timeout: .now() + TimeInterval(missing.count * 2)) == .success else { - log("Timed out downloading images") - return false - } - log("Finished all image downloads") - return true + + var averageImageCount: Float { + Float(numberOfImages) / Float(numberOfCaps) } - - private func createThumbnails() -> Bool { - let missing = caps.map { $0.id }.filter { !storage.hasThumbnail(for: $0) } - guard missing.count > 0 else { - log("No thumbnails to create") - return true - } - log("Creating thumbnails") - let queue = DispatchQueue(label: "thumbnails") - let semaphore = DispatchSemaphore(value: 5) - - let group = DispatchGroup() - group.enter() - var thumbnailsAreSuccessful = true - var completed = 0 - for cap in missing { - queue.async { - guard thumbnailsAreSuccessful else { - return - } - semaphore.wait() - defer { semaphore.signal() } - guard let image = self.storage.image(for: cap) else { - self.log("No image for cap \(cap) to create thumbnail") - self.delegate?.database(didFailBackgroundWork: "Creation failed", subtitle: "Thumbnail of cap \(cap)") - thumbnailsAreSuccessful = false - group.leave() - return - } - let thumb = Cap.thumbnail(for: image) - guard self.storage.save(thumbnail: thumb, for: cap) else { - self.log("Failed to save thumbnail for cap \(cap)") - self.delegate?.database(didFailBackgroundWork: "Image not saved", subtitle: "Thumbnail of cap \(cap)") - thumbnailsAreSuccessful = false - group.leave() - return - } - completed += 1 - self.delegate?.database(completedBackgroundWorkItem: "Creating thumbnails", subtitle: "\(completed) of \(missing.count)") - if completed == missing.count { - group.leave() - } - } - } - guard group.wait(timeout: .now() + TimeInterval(missing.count * 2)) == .success else { - log("Timed out creating thumbnails") - return false - } - log("Finished all thumbnails") - return true + + @AppStorage("classifier") + private(set) var classifierVersion = 0 + + @AppStorage("serverClassifier") + private(set) var serverClassifierVersion = 0 + + var classifierClassCount: Int { + let version = classifierVersion + return caps.values.filter { $0.classifiable(by: version) }.count } - - private func createColors() -> Bool { - let missing = capIds.subtracting(capsWithColors) - guard missing.count > 0 else { - log("No colors to create") - return true - } - log("Creating colors") - let queue = DispatchQueue(label: "colors") - let semaphore = DispatchSemaphore(value: 5) - - let group = DispatchGroup() - group.enter() - var colorsAreSuccessful = true - var completed = 0 - for cap in missing { - queue.async { - guard colorsAreSuccessful else { - return - } - semaphore.wait() - defer { semaphore.signal() } - guard let image = self.storage.ciImage(for: cap) else { - self.log("No image for cap \(cap) to create color") - self.delegate?.database(didFailBackgroundWork: "No thumbnail found", subtitle: "Color of cap \(cap)") - colorsAreSuccessful = false - group.leave() - return - } - defer { self.context.clearCaches() } - guard let color = image.averageColor(context: self.context) else { - self.log("Failed to create color for cap \(cap)") - self.delegate?.database(didFailBackgroundWork: "Calculation failed", subtitle: "Color of cap \(cap)") - colorsAreSuccessful = false - group.leave() - return - } - guard self.set(color: color, for: cap) else { - self.log("Failed to save color for cap \(cap)") - self.delegate?.database(didFailBackgroundWork: "Color not saved", subtitle: "Color of cap \(cap)") - colorsAreSuccessful = false - group.leave() - return - } - completed += 1 - self.delegate?.database(completedBackgroundWorkItem: "Creating colors", subtitle: "\(completed) of \(missing.count)") - if completed == missing.count { - group.leave() - } - } - } - guard group.wait(timeout: .now() + TimeInterval(missing.count * 2)) == .success else { - log("Timed out creating colors") - return false - } - log("Finished all colors") - return true + + var imageCacheSize: Int { + imageCache.currentDiskUsage } - - func hasNewClassifier(completion: @escaping (_ version: Int?, _ size: Int64?) -> Void) { - download.classifierVersion { version in - guard let version = version else { - self.log("Failed to download server model version") - completion(nil, nil) - return - } - let ownVersion = self.classifierVersion - guard ownVersion < version else { - self.log("Not updating classifier: Own version \(ownVersion), server version \(version)") - completion(nil, nil) - return - } - self.log("Getting size of classifier \(version)") - self.download.classifierSize { size in - completion(version, size) - } - } + + var databaseSize: Int { + localDbUrl.fileSize } - - private func didDownload(imageCounts newCounts: [Int]) -> [Int : Int] { - let capsCounts = capDict - if newCounts.count != capsCounts.count { - log("Downloaded \(newCounts.count) image counts, but \(capsCounts.count) caps stored locally") - } - var newCaps = [Int : Int]() - let changed = newCounts.enumerated().compactMap { id, newCount -> Int? in - let id = id + 1 - guard let oldCount = capsCounts[id]?.count else { - log("Received count \(newCount) for unknown cap \(id)") - newCaps[id] = newCount - return nil - } - guard oldCount != newCount else { - return nil - } - self.update(count: newCount, for: id) - return id - } - switch changed.count { - case 0: - log("Refreshed image counts for all caps without changes") - case 1: - log("Refreshed image counts for caps, changed cap \(changed[0])") - case 2...10: - log("Refreshed image counts for caps \(changed.map(String.init).joined(separator: ", ")).") - default: - log("Refreshed image counts for all caps (\(changed.count) changed)") - } - - return newCaps - } - - private func downloadInfo(for newCaps: [Int : Int], completion: @escaping (_ success: Bool) -> Void) { - var success = true - let group = DispatchGroup() - for (id, count) in newCaps { - group.enter() - download.name(for: id) { name in - guard let name = name else { - self.log("Failed to get name for new cap \(id)") - success = false - group.leave() - return - } - let cap = Cap(id: id, name: name, count: count) - self.insert(cap: cap) - group.leave() - } - } - - if group.wait(timeout: .now() + .seconds(30)) != .success { - self.log("Timed out waiting for images to be downloaded") - } - completion(success) - } - - func downloadImageCount(for cap: Int) { - download.imageCount(for: cap) { count in - guard let count = count else { - return - } - self.update(count: count, for: cap) - } - } - - func setMainImage(of cap: Int, to version: Int) { - guard version != 0 else { - log("No need to switch main image with itself for cap \(cap)") - return - } - upload.setMainImage(for: cap, to: version) { success in - guard success else { - self.log("Could not make \(version) the main image for cap \(cap)") - return - } - guard self.storage.switchMainImage(to: version, for: cap) else { - self.log("Could not switch \(version) to main image for cap \(cap)") - return - } - DispatchQueue.main.async { - self.delegate?.database(didLoadImageForCap: cap) - } - - } + + var classifierSize: Int { + localClassifierUrl.fileSize } } -extension Database: Logger { } +extension Database { + + static var mock: Database { + let db = Database(server: URL(string: "https://christophhagen.de/caps")!) + db.caps = [ + Cap(id: 123, name: "My new cap"), + Cap(id: 234, name: "My favorite cap"), + Cap(id: 345, name: "My oldest cap"), + Cap(id: 456, name: "My new cap"), + Cap(id: 567, name: "My favorite cap"), + Cap(id: 678, name: "My oldest cap"), + ].reduce(into: [:]) { $0[$1.id] = $1 } + db.image = UIImage(systemSymbol: .photo) + return db + } +} diff --git a/Caps/Data/Download.swift b/Caps/Data/Download.swift deleted file mode 100644 index a961c1f..0000000 --- a/Caps/Data/Download.swift +++ /dev/null @@ -1,358 +0,0 @@ -// -// Download.swift -// CapCollector -// -// Created by Christoph on 26.04.20. -// Copyright © 2020 CH. All rights reserved. -// - -import Foundation -import UIKit - -final class Download { - - let serverUrl: URL - - let session: URLSession - - let delegate: Delegate - - private var downloadingMainImages = Set() - - init(server: URL) { - let delegate = Delegate() - - self.serverUrl = server - self.session = URLSession(configuration: .ephemeral, delegate: delegate, delegateQueue: nil) - self.delegate = delegate - } - - // MARK: Paths - - var serverNameListUrl: URL { - Download.serverNameListUrl(server: serverUrl) - } - - private static func serverNameListUrl(server: URL) -> URL { - server.appendingPathComponent("names.txt") - } - - private var serverClassifierVersionUrl: URL { - serverUrl.appendingPathComponent("classifier.version") - } - - private var serverRecognitionModelUrl: URL { - serverUrl.appendingPathComponent("classifier.mlmodel") - } - - private var serverAllCountsUrl: URL { - serverUrl.appendingPathComponent("counts") - } - - var serverImageUrl: URL { - serverUrl.appendingPathComponent("images") - } - - private func serverImageUrl(for cap: Int, version: Int = 0) -> URL { - serverImageUrl.appendingPathComponent(String(format: "%04d/%04d-%02d.jpg", cap, cap, version)) - } - - private func serverNameUrl(for cap: Int) -> URL { - serverUrl.appendingPathComponent("name/\(cap)") - } - - private func serverImageCountUrl(for cap: Int) -> URL { - serverUrl.appendingPathComponent("count/\(cap)") - } - - // MARK: Delegate - - final class Delegate: NSObject, URLSessionDownloadDelegate { - - typealias ProgressHandler = (_ progress: Float, _ bytesWritten: Int64, _ totalBytes: Int64) -> Void - - typealias CompletionHandler = (_ url: URL?) -> Void - - private var progress = [URLSessionDownloadTask : Float]() - - private var callbacks = [URLSessionDownloadTask : ProgressHandler]() - - private var completions = [URLSessionDownloadTask : CompletionHandler]() - - func registerForProgress(_ downloadTask: URLSessionDownloadTask, callback: ProgressHandler?, completion: @escaping CompletionHandler) { - progress[downloadTask] = 0 - callbacks[downloadTask] = callback - completions[downloadTask] = completion - } - - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { - completions[downloadTask]?(location) - callbacks[downloadTask] = nil - progress[downloadTask] = nil - completions[downloadTask] = nil - } - - func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { - let ratio = totalBytesExpectedToWrite > 0 ? Float(totalBytesWritten) / Float(totalBytesExpectedToWrite) : 0 - progress[downloadTask] = ratio - callbacks[downloadTask]?(ratio, totalBytesWritten, totalBytesExpectedToWrite) - } - - func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { - guard let downloadTask = task as? URLSessionDownloadTask else { - return - } - completions[downloadTask]?(nil) - callbacks[downloadTask] = nil - progress[downloadTask] = nil - completions[downloadTask] = nil - } - } - - // MARK: Downloading data - - func image(for cap: Int, to url: URL, timeout: TimeInterval = 30) -> Bool { - let group = DispatchGroup() - group.enter() - var result = true - let success = image(for: cap, version: 0, to: url) { success in - result = success - group.leave() - } - guard success else { - log("Already downloading image for cap \(cap)") - return false - } - guard group.wait(timeout: .now() + timeout) == .success else { - log("Timed out downloading image for cap \(cap)") - return false - } - return result - } - - /** - Download an image for a cap. - - Parameter cap: The id of the cap. - - Parameter version: The image version to download. - - Parameter completion: A closure with the resulting image - - Returns: `true`, of the file download was started, `false`, if the image is already downloading. - */ - @discardableResult - func image(for cap: Int, version: Int = 0, to url: URL, queue: DispatchQueue = .main, completion: @escaping (Bool) -> Void) -> Bool { - // Check if main image, and already being downloaded - if version == 0 { - guard !downloadingMainImages.contains(cap) else { - return false - } - downloadingMainImages.insert(cap) - } - let serverUrl = serverImageUrl(for: cap, version: version) - let query = "Image of cap \(cap) version \(version)" - let task = session.downloadTask(with: serverUrl) { fileUrl, response, error in - if version == 0 { - queue.async { - self.downloadingMainImages.remove(cap) - } - } - guard let fileUrl = self.convertResponse(to: query, fileUrl, response, error) else { - completion(false) - return - } - do { - if FileManager.default.fileExists(atPath: url.path) { - try FileManager.default.removeItem(at: url) - } - try FileManager.default.moveItem(at: fileUrl, to: url) - } catch { - self.log("Failed to move downloaded image for cap \(cap): \(error)") - completion(false) - } - completion(true) - } - task.resume() - return true - } - - func imageCount(for cap: Int, completion: @escaping (_ count: Int?) -> Void) { - let url = serverImageCountUrl(for: cap) - let query = "Image count for cap \(cap)" - session.startTaskExpectingInt(with: url, query: query, completion: completion) - } - - func name(for cap: Int, completion: @escaping (_ name: String?) -> Void) { - let url = serverNameUrl(for: cap) - let query = "Name for cap \(cap)" - session.startTaskExpectingString(with: url, query: query, completion: completion) - } - - func imageCounts(completion: @escaping ([Int]?) -> Void) { - let query = "Image count of all caps" - session.startTaskExpectingData(with: serverAllCountsUrl, query: query) { data in - guard let data = data else { - completion(nil) - return - } - completion(data.map(Int.init)) - } - } - - func names(completion: @escaping ([String]?) -> Void) { - let query = "Download of server database" - session.startTaskExpectingString(with: serverNameListUrl, query: query) { string in - completion(string?.trimmingCharacters(in: .whitespacesAndNewlines).components(separatedBy: "\n")) - } - } - - func databaseSize(completion: @escaping (_ size: Int64?) -> Void) { - size(of: "database size", to: serverNameListUrl, completion: completion) - } - - func classifierVersion(completion: @escaping (Int?) -> Void) { - let query = "Server classifier version" - session.startTaskExpectingInt(with: serverClassifierVersionUrl, query: query, completion: completion) - } - - func classifierSize(completion: @escaping (Int64?) -> Void) { - size(of: "classifier size", to: serverRecognitionModelUrl, completion: completion) - } - - func classifier(progress: Delegate.ProgressHandler? = nil, completion: @escaping (URL?) -> Void) { - let task = session.downloadTask(with: serverRecognitionModelUrl) - delegate.registerForProgress(task, callback: progress) { url in - self.log("Classifier download complete") - completion(url) - } - task.resume() - } - - // MARK: Requests - - private func size(of query: String, to url: URL, completion: @escaping (_ size: Int64?) -> Void) { - var request = URLRequest(url: url) - request.httpMethod = "HEAD" - let task = session.dataTask(with: request) { _, response, _ in - guard let r = response else { - self.log("Request '\(query)' received no response") - completion(nil) - return - } - completion(r.expectedContentLength) - } - task.resume() - } - - private func convertIntResponse(to query: String, _ data: Data?, _ response: URLResponse?, _ error: Error?) -> Int? { - guard let string = self.convertStringResponse(to: query, data, response, error) else { - return nil - } - guard let int = Int(string.trimmingCharacters(in: .whitespacesAndNewlines)) else { - self.log("Request '\(query)' received an invalid value '\(string)'") - return nil - } - return int - } - - private func convertStringResponse(to query: String, _ data: Data?, _ response: URLResponse?, _ error: Error?) -> String? { - guard let data = self.convertResponse(to: query, data, response, error) else { - return nil - } - guard let string = String(data: data, encoding: .utf8) else { - self.log("Request '\(query)' received invalid data (not a string)") - return nil - } - return string - } - - private func convertResponse(to query: String, _ result: T?, _ response: URLResponse?, _ error: Error?) -> T? { - if let error = error { - log("Request '\(query)' produced an error: \(error)") - return nil - } - guard let response = response else { - log("Request '\(query)' received no response") - return nil - } - guard let urlResponse = response as? HTTPURLResponse else { - log("Request '\(query)' received an invalid response: \(response)") - return nil - } - guard urlResponse.statusCode == 200 else { - log("Request '\(query)' failed with status code \(urlResponse.statusCode)") - return nil - } - guard let r = result else { - log("Request '\(query)' received no item") - return nil - } - return r - } - - -} - -extension Download: Logger { } - -extension URLSession { - - func startTaskExpectingData(with url: URL, query: String, completion: @escaping (Data?) -> Void) { - let task = dataTask(with: url) { data, response, error in - if let error = error { - log("Request '\(query)' produced an error: \(error)") - completion(nil) - return - } - guard let response = response else { - log("Request '\(query)' received no response") - completion(nil) - return - } - guard let urlResponse = response as? HTTPURLResponse else { - log("Request '\(query)' received an invalid response: \(response)") - completion(nil) - return - } - guard urlResponse.statusCode == 200 else { - log("Request '\(query)' failed with status code \(urlResponse.statusCode)") - completion(nil) - return - } - guard let d = data else { - log("Request '\(query)' received no data") - completion(nil) - return - } - completion(d) - } - task.resume() - } - - func startTaskExpectingString(with url: URL, query: String, completion: @escaping (String?) -> Void) { - startTaskExpectingData(with: url, query: query) { data in - guard let data = data else { - completion(nil) - return - } - guard let string = String(data: data, encoding: .utf8) else { - log("Request '\(query)' received invalid data (not a string)") - completion(nil) - return - } - completion(string) - } - } - - func startTaskExpectingInt(with url: URL, query: String, completion: @escaping (Int?) -> Void) { - startTaskExpectingString(with: url, query: query) { string in - guard let string = string else { - completion(nil) - return - } - guard let int = Int(string.trimmingCharacters(in: .whitespacesAndNewlines)) else { - log("Request '\(query)' received an invalid value '\(string)'") - completion(nil) - return - } - completion(int) - } - } -} diff --git a/Caps/Data/SortCriteria.swift b/Caps/Data/SortCriteria.swift new file mode 100644 index 0000000..214f524 --- /dev/null +++ b/Caps/Data/SortCriteria.swift @@ -0,0 +1,28 @@ +import Foundation + +enum SortCriteria: Int, CaseIterable { + case id = 0 + case name = 1 + case count = 2 + case match = 3 + + var text: String { + switch self { + case .id: + return "Id" + case .name: + return "Name" + case .count: + return "Count" + case .match: + return "Match" + } + } +} + +extension SortCriteria: Identifiable { + + var id: Int { + rawValue + } +} diff --git a/Caps/Data/Storage.swift b/Caps/Data/Storage.swift deleted file mode 100644 index 2ca0371..0000000 --- a/Caps/Data/Storage.swift +++ /dev/null @@ -1,374 +0,0 @@ -// -// DiskManager.swift -// CapFinder -// -// Created by User on 23.04.18. -// Copyright © 2018 User. All rights reserved. -// - -import Foundation -import UIKit -import CoreML -import Vision - - - -protocol ImageProvider: AnyObject { - - func image(for cap: Int) -> UIImage? - - func image(for cap: Int, version: Int) -> UIImage? - - func ciImage(for cap: Int) -> CIImage? -} - -protocol ThumbnailCreationDelegate { - - func thumbnailCreation(progress: Int, total: Int) - - func thumbnailCreationFailed() - - func thumbnailCreationIsMissingImages() - - func thumbnailCreationCompleted() -} - - -final class Storage: ImageProvider { - - // MARK: Paths - - let fm = FileManager.default - - let baseUrl: URL - - // MARK: INIT - - init(in folder: URL) { - self.baseUrl = folder - } - - // MARK: File/folder urls - - var dbUrl: URL { - baseUrl.appendingPathComponent("db.sqlite3") - } - - var modelUrl: URL { - baseUrl.appendingPathComponent("model.mlmodel") - } - - func localImageUrl(for cap: Int, version: Int = 0) -> URL { - baseUrl.appendingPathComponent("\(cap)-\(version).jpg") - } - - private func thumbnailUrl(for cap: Int) -> URL { - baseUrl.appendingPathComponent("\(cap)-thumb.jpg") - } - - private func tileImageUrl(for image: String) -> URL { - baseUrl.appendingPathComponent(image.clean + ".tile") - } - - // MARK: Storage - - /** - Save an image to disk - - parameter url: The url where the downloaded image is stored - - parameter cap: The cap id - - parameter version: The version of the image to get - - returns: True, if the image was saved - */ - func saveImage(at url: URL, for cap: Int, version: Int = 0) -> UIImage? { - let targetUrl = localImageUrl(for: cap, version: version) - do { - if fm.fileExists(atPath: targetUrl.path) { - try fm.removeItem(at: targetUrl) - } - try fm.moveItem(at: url, to: targetUrl) - return UIImage(contentsOfFile: targetUrl.path) - } catch { - log("Failed to delete or move image \(version) for cap \(cap)") - return nil - } - } - - /** - Save an image to disk - - parameter image: The image - - parameter cap: The cap id - - parameter version: The version of the image - - returns: True, if the image was saved - */ - func save(image: UIImage, for cap: Int, version: Int = 0) -> Bool { - guard let data = image.jpegData(compressionQuality: Cap.jpgQuality) else { - return false - } - return save(imageData: data, for: cap, version: version) - } - - /** - Save image data to disk - - parameter image: The data of the image - - parameter cap: The cap id - - parameter version: The version of the image - - returns: True, if the image was saved - */ - func save(imageData: Data, for cap: Int, version: Int = 0) -> Bool { - write(imageData, to: localImageUrl(for: cap, version: version)) - } - - /** - Save a thumbnail. - - parameter thumbnail: The image - - parameter cap: The cap id - - returns: True, if the image was saved - */ - func save(thumbnail: UIImage, for cap: Int) -> Bool { - guard let data = thumbnail.jpegData(compressionQuality: Cap.jpgQuality) else { - return false - } - return save(thumbnailData: data, for: cap) - } - - /** - Save a thumbnail to the download folder - - parameter thumbnailData: The data of the image - - parameter cap: The cap id - - returns: True, if the image was saved - */ - private func save(thumbnailData: Data, for cap: Int) -> Bool { - write(thumbnailData, to: thumbnailUrl(for: cap)) - } - - /** - Save the downloaded and compiled recognition model. - - Parameter url: The temporary location to which the model was compiled. - - Returns: `true`, if the model was moved. - */ - func save(recognitionModelAt url: URL) -> Bool { - move(url, to: modelUrl) - } - - /** - Save the downloaded and database. - - Parameter url: The temporary location to which the database was downloaded. - - Returns: `true`, if the database was moved. - */ - func save(databaseAt url: URL) -> Bool { - move(url, to: dbUrl) - } - - private func move(_ url: URL, to destination: URL) -> Bool { - if fm.fileExists(atPath: destination.path) { - do { - try fm.removeItem(at: destination) - } catch { - log("Failed to remove file \(destination.lastPathComponent) before writing new version: \(error)") - return false - } - } - do { - try fm.moveItem(at: url, to: destination) - return true - } catch { - self.error("Failed to move file \(destination.lastPathComponent) to permanent location: \(error)") - return false - } - } - - private func write(_ data: Data, to url: URL) -> Bool { - do { - try data.write(to: url) - } catch { - self.error("Could not write data to \(url): \(error)") - return false - } - return true - } - - // MARK: High-level functions - - func switchMainImage(to version: Int, for cap: Int) -> Bool { - guard deleteThumbnail(for: cap) else { - return false - } - let newImagePath = localImageUrl(for: cap, version: version) - guard fm.fileExists(atPath: newImagePath.path) else { - return deleteImage(for: cap, version: version) - } - let oldImagePath = localImageUrl(for: cap, version: 0) - return move(newImagePath, to: oldImagePath) - } - - // MARK: Status - - /** - Check if an image exists for a cap - - parameter cap: The id of the cap - - returns: True, if an image exists - */ - func hasImage(for cap: Int) -> Bool { - fm.fileExists(atPath: localImageUrl(for: cap, version: 0).path) - } - - /** - Check if a thumbnail exists for a cap - - parameter cap: The id of the cap - - returns: True, if a thumbnail exists - */ - func hasThumbnail(for cap: Int) -> Bool { - fm.fileExists(atPath: thumbnailUrl(for: cap).path) - } - - func existingImageUrl(for cap: Int, version: Int = 0) -> URL? { - let url = localImageUrl(for: cap, version: version) - return fm.fileExists(atPath: url.path) ? url : nil - } - - // MARK: Retrieval - - /** - Get the image data for a cap. - If the image exists on disk, it is returned. - If no image exists locally, then this function returns nil. - - parameter cap: The id of the cap - - parameter version: The image version - - returns: The image data, or `nil` - */ - func imageData(for cap: Int, version: Int = 0) -> Data? { - readData(from: localImageUrl(for: cap, version: version)) - } - - /** - Get the image for a cap. - If the image exists on disk, it is returned. - If no image exists locally, then this function returns nil. - - parameter cap: The id of the cap - - parameter version: The image version - - returns: The image, or `nil` - - note: Removes invalid image data on disk, if the data is not a valid image - - note: Must be called on the main thread - */ - func image(for cap: Int, version: Int) -> UIImage? { - guard let data = imageData(for: cap, version: version) else { - return nil - } - guard let image = UIImage(data: data) else { - log("Removing invalid image \(version) of cap \(cap) from disk") - deleteImage(for: cap, version: version) - return nil - } - return image - } - - func image(for cap: Int) -> UIImage? { - image(for: cap, version: 0) - } - - /** - Get the thumbnail data for a cap. - If the image exists on disk, it is returned. - If no image exists locally, then this function returns nil. - - parameter cap: The id of the cap - - returns: The image data, or `nil` - */ - func thumbnailData(for cap: Int) -> Data? { - readData(from: thumbnailUrl(for: cap)) - } - - /** - Get the thumbnail for a cap. - If the image exists on disk, it is returned. - If no image exists locally, then this function returns nil. - - parameter cap: The id of the cap - - returns: The image, or `nil` - */ - func thumbnail(for cap: Int) -> UIImage? { - guard let data = thumbnailData(for: cap) else { - return nil - } - return UIImage(data: data) - } - - /// The compiled recognition model on disk - var recognitionModel: VNCoreMLModel? { - guard fm.fileExists(atPath: modelUrl.path) else { - log("No recognition model to load") - return nil - } - do { - let model = try MLModel(contentsOf: modelUrl) - - return try VNCoreMLModel(for: model) - } catch { - self.error("Failed to load recognition model: \(error)") - return nil - } - } - - func ciImage(for cap: Int) -> CIImage? { - let url = thumbnailUrl(for: cap) - guard fm.fileExists(atPath: url.path) else { - return nil - } - guard let image = CIImage(contentsOf: url) else { - error("Failed to read CIImage for main image of cap \(cap)") - return nil - } - return image - } - - private func readData(from url: URL) -> Data? { - guard fm.fileExists(atPath: url.path) else { - return nil - } - do { - return try Data(contentsOf: url) - } catch { - self.error("Could not read data from \(url): \(error)") - return nil - } - } - - // MARK: Deleting data - - @discardableResult - func deleteDatabase() -> Bool { - do { - try fm.removeItem(at: dbUrl) - return true - } catch { - log("Failed to delete database: \(error)") - return false - } - } - - @discardableResult - func deleteImage(for cap: Int, version: Int) -> Bool { - let url = localImageUrl(for: cap, version: version) - return delete(at: url) - } - - @discardableResult - func deleteThumbnail(for cap: Int) -> Bool { - let url = thumbnailUrl(for: cap) - return delete(at: url) - } - - private func delete(at url: URL) -> Bool { - guard fm.fileExists(atPath: url.path) else { - return true - } - do { - try fm.removeItem(at: url) - return true - } catch { - log("Failed to delete file \(url.lastPathComponent): \(error)") - return false - } - } -} - -extension Storage: Logger { } - diff --git a/Caps/Data/TileImage.swift b/Caps/Data/TileImage.swift deleted file mode 100644 index 8ae0c68..0000000 --- a/Caps/Data/TileImage.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// TileImage.swift -// CapCollector -// -// Created by Christoph on 20.05.20. -// Copyright © 2020 CH. All rights reserved. -// - -import Foundation -import SQLite - -extension Database { - - struct TileImage { - - let name: String - - let width: Int - - /// The tiles of each cap, with the index being the tile, and the value being the cap id. - let caps: [Int] - - var encodedCaps: Data { - caps.map(UInt16.init).withUnsafeBytes { (p) in - Data(buffer: p.bindMemory(to: UInt8.self)) - } - } - - init(name: String, width: Int, caps: [Int]) { - self.name = name - self.width = width - self.caps = caps - } - - init(row: Row) { - self.name = row[TileImage.columnName] - self.width = row[TileImage.columnWidth] - self.caps = row[TileImage.columnCaps].withUnsafeBytes { p in - p.bindMemory(to: UInt16.self).map(Int.init) - } - } - - var insertQuery: Insert { - TileImage.table.insert( - TileImage.columnName <- name, - TileImage.columnWidth <- width, - TileImage.columnCaps <- encodedCaps) - } - - var updateQuery: Update { - TileImage.table.update( - TileImage.columnWidth <- width, - TileImage.columnCaps <- encodedCaps) - } - - static let columnName = Expression("name") - - static let columnWidth = Expression("width") - - static let columnCaps = Expression("caps") - - static let table = Table("images") - - - static func named(_ name: String) -> Table { - table.filter(columnName == name) - } - static func exists(_ name: String) -> Table { - named(name).select(columnName) - } - - static var createQuery: String { - table.create(ifNotExists: true) { t in - t.column(Cap.columnId, primaryKey: true) - t.column(columnName) - t.column(columnWidth) - t.column(columnCaps) - } - } - } - - - func save(tileImage: TileImage) -> Bool { - guard exists(tileImage.name) else { - return insert(tileImage) - } - return update(tileImage) - } - - var tileImages: [TileImage] { - (try? db.prepare(TileImage.table).map(TileImage.init)) ?? [] - } - - func tileImage(named name: String) -> TileImage? { - do { - guard let row = try db.pluck(TileImage.named(name)) else { - return nil - } - return TileImage(row: row) - } catch { - log("Failed to get tile image \(name): \(error)") - return nil - } - } - - private func exists(_ tileImage: String) -> Bool { - do { - return try db.pluck(TileImage.exists(tileImage)) != nil - } catch { - log("Failed to check tile image \(tileImage): \(error)") - return false - } - } - - private func insert(_ tileImage: TileImage) -> Bool { - do { - try db.run(tileImage.insertQuery) - return true - } catch { - log("Failed to insert tile image \(tileImage): \(error)") - return false - } - } - - private func update(_ tileImage: TileImage) -> Bool { - do { - try db.run(tileImage.updateQuery) - return true - } catch { - log("Failed to update tile image \(tileImage): \(error)") - return false - } - } -} diff --git a/Caps/Data/Upload.swift b/Caps/Data/Upload.swift deleted file mode 100644 index 170e922..0000000 --- a/Caps/Data/Upload.swift +++ /dev/null @@ -1,212 +0,0 @@ -// -// Upload.swift -// CapCollector -// -// Created by Christoph on 26.04.20. -// Copyright © 2020 CH. All rights reserved. -// - -import Foundation -import UIKit -import SQLite - -struct Upload { - - static let offlineKey = "offline" - - let serverUrl: URL - - let table = Table("uploads") - - let rowCapId = Expression("cap") - - let rowCapVersion = Expression("version") - - init(server: URL) { - self.serverUrl = server - } - - // MARK: Paths - - var serverImageUrl: URL { - serverUrl.appendingPathComponent("images") - } - - private func serverImageUrl(for cap: Int, version: Int = 0) -> URL { - serverImageUrl.appendingPathComponent("\(cap)/\(cap)-\(version).jpg") - } - - private func serverImageUploadUrl(for cap: Int) -> URL { - serverImageUrl.appendingPathComponent("\(cap)") - } - - private func serverNameUploadUrl(for cap: Int) -> URL { - serverUrl.appendingPathComponent("name/\(cap)") - } - - private func serverChangeMainImageUrl(for cap: Int, to newValue: Int) -> URL { - serverUrl.appendingPathComponent("switch/\(cap)/\(newValue)") - } - - // MARK: SQLite - - var createQuery: String { - table.create(ifNotExists: true) { t in - t.column(rowCapId) - t.column(rowCapVersion) - } - } - - func existsQuery(for cap: Int, version: Int) -> ScalarQuery { - table.filter(rowCapId == cap && rowCapVersion == version).count - } - - func insertQuery(for cap: Int, version: Int) -> Insert { - table.insert(rowCapId <- cap, rowCapVersion <- version) - } - - func deleteQuery(for cap: Int, version: Int) -> Delete { - table.filter(rowCapId == cap && rowCapVersion == version).delete() - } - - // MARK: Uploading data - - func upload(name: String, for cap: Int, completion: @escaping (_ success: Bool) -> Void) { - var request = URLRequest(url: serverNameUploadUrl(for: cap)) - request.httpMethod = "POST" - request.httpBody = name.data(using: .utf8) - let task = URLSession.shared.dataTask(with: request) { data, response, error in - if let error = error { - self.log("Failed to upload name of cap \(cap): \(error)") - completion(false) - return - } - guard let response = response else { - self.log("Failed to upload name of cap \(cap): No response") - completion(false) - return - } - guard let urlResponse = response as? HTTPURLResponse else { - self.log("Failed to upload name of cap \(cap): \(response)") - completion(false) - return - } - guard urlResponse.statusCode == 200 else { - self.log("Failed to upload name of cap \(cap): Response \(urlResponse.statusCode)") - completion(false) - return - } - completion(true) - } - task.resume() - } - - func upload(_ cap: Cap, timeout: TimeInterval = 30) -> Bool { - upload(name: cap.name, for: cap.id, timeout: timeout) - } - - func upload(name: String, for cap: Int, timeout: TimeInterval = 30) -> Bool { - let group = DispatchGroup() - group.enter() - var result = true - upload(name: name, for: cap) { success in - if success { - self.log("Uploaded cap \(cap)") - } else { - result = false - } - group.leave() - } - guard group.wait(timeout: .now() + timeout) == .success else { - log("Timed out uploading cap \(cap)") - return false - } - return result - } - - func upload(imageAt url: URL, for cap: Int, completion: @escaping (_ count: Int?) -> Void) { - var request = URLRequest(url: serverImageUploadUrl(for: cap)) - request.httpMethod = "POST" - let task = URLSession.shared.uploadTask(with: request, fromFile: url) { data, response, error in - if let error = error { - self.log("Failed to upload image of cap \(cap): \(error)") - completion(nil) - return - } - guard let response = response else { - self.log("Failed to upload image of cap \(cap): No response") - completion(nil) - return - } - guard let urlResponse = response as? HTTPURLResponse else { - self.log("Failed to upload image of cap \(cap): \(response)") - completion(nil) - return - } - guard urlResponse.statusCode == 200 else { - self.log("Failed to upload image of cap \(cap): Response \(urlResponse.statusCode)") - completion(nil) - return - } - guard let d = data, let string = String(data: d, encoding: .utf8), let int = Int(string) else { - self.log("Failed to upload image of cap \(cap): Invalid response") - completion(nil) - return - } - completion(int) - } - task.resume() - } - - func upload(imageAt url: URL, of cap: Int, timeout: TimeInterval = 30) -> Int? { - let group = DispatchGroup() - group.enter() - var result: Int? = nil - upload(imageAt: url, for: cap) { count in - result = count - group.leave() - } - guard group.wait(timeout: .now() + timeout) == .success else { - log("Timed out uploading image of \(cap)") - return nil - } - return result - } - - /** - Sets the main image for a cap to a different version. - - - Parameter cap: The id of the cap - - Parameter version: The version to set as the main version. - - Parameter completion: A callback with the result on completion. - */ - func setMainImage(for cap: Int, to version: Int, completion: @escaping (_ success: Bool) -> Void) { - let url = serverChangeMainImageUrl(for: cap, to: version) - let task = URLSession.shared.dataTask(with: url) { data, response, error in - if let error = error { - self.log("Failed to set main image of cap \(cap) to \(version): \(error)") - completion(false) - return - } - guard let response = response else { - self.log("Failed to set main image of cap \(cap) to \(version): No response") - completion(false) - return - } - guard let urlResponse = response as? HTTPURLResponse else { - self.log("Failed to set main image of cap \(cap) to \(version): \(response)") - completion(false) - return - } - guard urlResponse.statusCode == 200 else { - self.log("Failed to set main image of cap \(cap) to \(version): Response \(urlResponse.statusCode)") - completion(false) - return - } - completion(true) - } - task.resume() - } -} - -extension Upload: Logger { } diff --git a/Caps/Extensions/Array+Extensions.swift b/Caps/Extensions/Array+Extensions.swift deleted file mode 100644 index 4514c4e..0000000 --- a/Caps/Extensions/Array+Extensions.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// Array+Extensions.swift -// CapCollector -// -// Created by Christoph on 12.05.20. -// Copyright © 2020 CH. All rights reserved. -// - -import Foundation - -extension Array { - - func split(intoPartsOf maxElements: Int) -> [ArraySlice] { - guard !isEmpty, maxElements > 0 else { - return [] - } - var result = [ArraySlice]() - var currentIndex = 0 - while true { - let nextIndex = currentIndex + maxElements - if nextIndex >= count { - result.append(self[currentIndex.. CGImage? { + guard let pixelBuffer = cvPixelBuffer else { + return nil + } + + var image: CGImage? + VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &image) + return image + } + + /** + Crop an image to a square, centered around the middle of the frame + - parameter size: The height and width of the resulting image + - returns: The cropped image + */ + func crop(to size: CGFloat) -> CGImage? { + let rect = CGRect( + x: (CGFloat(height) - size) / 2, + y: (CGFloat(width) - size) / 2, + width: size, + height: size) + + return cropping(to: rect) + } +} diff --git a/Caps/Extensions/CGImagePropertyOrientation+Extensions.swift b/Caps/Extensions/CGImagePropertyOrientation+Extensions.swift index efcd191..963812c 100644 --- a/Caps/Extensions/CGImagePropertyOrientation+Extensions.swift +++ b/Caps/Extensions/CGImagePropertyOrientation+Extensions.swift @@ -1,11 +1,3 @@ -// -// CGImagePropertyOrientation+Extensions.swift -// CapCollector -// -// Created by Christoph on 13.05.20. -// Copyright © 2020 CH. All rights reserved. -// - import UIKit extension CGImagePropertyOrientation { diff --git a/Caps/Extensions/Data+Extensions.swift b/Caps/Extensions/Data+Extensions.swift new file mode 100644 index 0000000..159efeb --- /dev/null +++ b/Caps/Extensions/Data+Extensions.swift @@ -0,0 +1,59 @@ +import Foundation + +extension Data { + + public var hexEncoded: String { + return map { String(format: "%02hhx", $0) }.joined() + } + + // Convert 0 ... 9, a ... f, A ...F to their decimal value, + // return nil for all other input characters + private func decodeNibble(_ u: UInt16) -> UInt8? { + switch(u) { + case 0x30 ... 0x39: + return UInt8(u - 0x30) + case 0x41 ... 0x46: + return UInt8(u - 0x41 + 10) + case 0x61 ... 0x66: + return UInt8(u - 0x61 + 10) + default: + return nil + } + } + + public init?(fromHexEncodedString string: String) { + let utf16 = string.utf16 + self.init(capacity: utf16.count/2) + + var i = utf16.startIndex + guard utf16.count % 2 == 0 else { + return nil + } + while i != utf16.endIndex { + guard let hi = decodeNibble(utf16[i]), + let lo = decodeNibble(utf16[utf16.index(i, offsetBy: 1, limitedBy: utf16.endIndex)!]) else { + return nil + } + var value = hi << 4 + lo + self.append(&value, count: 1) + i = utf16.index(i, offsetBy: 2, limitedBy: utf16.endIndex)! + } + } +} + +extension Data { + + + func convert(into value: T) -> T { + withUnsafeBytes { + $0.baseAddress!.load(as: T.self) + } + } + + init(from value: T) { + var target = value + self = Swift.withUnsafeBytes(of: &target) { + Data($0) + } + } +} diff --git a/Caps/Extensions/DispatchGroup+Extensions.swift b/Caps/Extensions/DispatchGroup+Extensions.swift deleted file mode 100644 index 7b5dad0..0000000 --- a/Caps/Extensions/DispatchGroup+Extensions.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// DispatchGroup+Extensions.swift -// CapCollector -// -// Created by iMac on 13.01.21. -// Copyright © 2021 CH. All rights reserved. -// - -import Foundation - -extension DispatchGroup { - - typealias AsyncSuccessCallback = (Bool) -> Void - - static func singleTask(timeout: TimeInterval = 30, _ block: (@escaping AsyncSuccessCallback) -> Void) -> Bool { - let group = DispatchGroup() - group.enter() - var result = true - block { success in - result = success - group.leave() - } - guard group.wait(timeout: .now() + timeout) == .success else { - return false - } - return result - } -} diff --git a/Caps/Extensions/UIAlertControllerExtensions.swift b/Caps/Extensions/UIAlertControllerExtensions.swift deleted file mode 100644 index 97b65ad..0000000 --- a/Caps/Extensions/UIAlertControllerExtensions.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// UIAlertControllerExtensions.swift -// CapFinder -// -// Created by User on 23.03.18. -// Copyright © 2018 User. All rights reserved. -// - -import Foundation -import UIKit - -extension UIAlertController { - - private struct AssociatedKeys { - static var blurStyleKey = "UIAlertController.blurStyleKey" - } - - public var blurStyle: UIBlurEffect.Style { - get { - return objc_getAssociatedObject(self, &AssociatedKeys.blurStyleKey) as? UIBlurEffect.Style ?? .extraLight - } set (style) { - objc_setAssociatedObject(self, &AssociatedKeys.blurStyleKey, style, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) - - view.setNeedsLayout() - view.layoutIfNeeded() - } - } - - public var cancelButtonColor: UIColor? { - return blurStyle == .dark ? UIColor(red: 28.0/255.0, green: 28.0/255.0, blue: 28.0/255.0, alpha: 1.0) : nil - } - - private var visualEffectView: UIVisualEffectView? { - if let presentationController = presentationController, presentationController.responds(to: Selector(("popoverView"))), let view = presentationController.value(forKey: "popoverView") as? UIView // We're on an iPad and visual effect view is in a different place. - { - return view.recursiveSubviews.compactMap({$0 as? UIVisualEffectView}).first - } - - return view.recursiveSubviews.compactMap({$0 as? UIVisualEffectView}).first - } - - private var cancelActionView: UIView? { - return view.recursiveSubviews.compactMap({ - $0 as? UILabel} - ).first(where: { - $0.text == actions.first(where: { $0.style == .cancel })?.title - })?.superview?.superview - } - - public convenience init(title: String?, message: String?, preferredStyle: UIAlertController.Style, blurStyle: UIBlurEffect.Style) { - self.init(title: title, message: message, preferredStyle: preferredStyle) - self.blurStyle = blurStyle - } - - open override func viewWillLayoutSubviews() { - super.viewWillLayoutSubviews() - - visualEffectView?.effect = UIBlurEffect(style: blurStyle) - cancelActionView?.backgroundColor = cancelButtonColor - } -} diff --git a/Caps/Extensions/UIColor+Extensions.swift b/Caps/Extensions/UIColor+Extensions.swift deleted file mode 100644 index 14d6f7f..0000000 --- a/Caps/Extensions/UIColor+Extensions.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// UIColor+Extensions.swift -// CapCollector -// -// Created by Christoph on 14.04.20. -// Copyright © 2020 CH. All rights reserved. -// - -import UIKit - -extension UIColor { - - var rgb: (red: Double, green: Double, blue: Double) { - var fRed: CGFloat = 0 - var fGreen: CGFloat = 0 - var fBlue: CGFloat = 0 - var fAlpha: CGFloat = 0 - getRed(&fRed, green: &fGreen, blue: &fBlue, alpha: &fAlpha) - return (Double(fRed), Double(fGreen), Double(fBlue)) - } -} - diff --git a/Caps/Extensions/UIImage+Extensions.swift b/Caps/Extensions/UIImage+Extensions.swift index 74e1aa1..0bf66e2 100644 --- a/Caps/Extensions/UIImage+Extensions.swift +++ b/Caps/Extensions/UIImage+Extensions.swift @@ -1,11 +1,3 @@ -// -// UIImageExtensions.swift -// CapFinder -// -// Created by User on 13.02.18. -// Copyright © 2018 User. All rights reserved. -// - import Foundation import UIKit @@ -22,7 +14,7 @@ extension UIImage { func resize(to targetSize: CGSize) -> UIImage { let rect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height) - UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0) + UIGraphicsBeginImageContextWithOptions(targetSize, false, scale) self.draw(in: rect) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() @@ -35,7 +27,7 @@ extension UIImage { - returns: The cropped image */ func crop(factor: CGFloat) -> UIImage { - let width = self.size.width * factor + let width = size.width * scale * factor return crop(to: width) } @@ -45,15 +37,11 @@ extension UIImage { - returns: The cropped image */ func crop(to size: CGFloat) -> UIImage { - var rect = CGRect( - x: (self.size.height - size) / 2, - y: (self.size.width - size) / 2, - width: size, - height: size) - rect.origin.x *= scale - rect.origin.y *= scale - rect.size.width *= scale - rect.size.height *= scale + let rect = CGRect( + x: (self.size.height * scale - size) / 2, + y: (self.size.width * scale - size) / 2, + width: size * scale, + height: size * scale) let imageRef = cgImage!.cropping(to: rect) return UIImage(cgImage: imageRef!, scale: scale, orientation: imageOrientation) @@ -77,10 +65,10 @@ extension UIImage { return nil } UIBezierPath(ovalIn: breadthRect).addClip() - UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation).draw(in: breadthRect) + UIImage(cgImage: cgImage, scale: scale, orientation: imageOrientation).draw(in: breadthRect) return UIGraphicsGetImageFromCurrentImageContext() } - + var averageColor: UIColor? { let image = ciImage ?? CIImage(cgImage: cgImage!) return image.averageColor @@ -88,14 +76,14 @@ extension UIImage { } extension CIImage { - + func averageColor(context: CIContext) -> UIColor? { let extentVector = CIVector( x: extent.origin.x, y: extent.origin.y, z: extent.size.width, w: extent.size.height) - + guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: self, kCIInputExtentKey: extentVector]) else { log("Failed to create filter") return nil @@ -104,27 +92,27 @@ extension CIImage { log("Failed get filter output") return nil } - + var bitmap = [UInt8](repeating: 0, count: 4) - + context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) - + return UIColor( red: saturate(bitmap[0]), green: saturate(bitmap[1]), blue: saturate(bitmap[2]), alpha: CGFloat(bitmap[3]) / 255) } - + var averageColor: UIColor? { let extentVector = CIVector( x: extent.origin.x, y: extent.origin.y, z: extent.size.width, w: extent.size.height) - + guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: self, kCIInputExtentKey: extentVector]) else { log("Failed to create filter") return nil @@ -133,7 +121,7 @@ extension CIImage { log("Failed get filter output") return nil } - + var bitmap = [UInt8](repeating: 0, count: 4) guard let null = kCFNull else { return nil @@ -142,13 +130,13 @@ extension CIImage { context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) - + let color = UIColor( red: saturate(bitmap[0]), green: saturate(bitmap[1]), blue: saturate(bitmap[2]), alpha: CGFloat(bitmap[3]) / 255) - + return color } } diff --git a/Caps/Extensions/UINavigationItem+Extensions.swift b/Caps/Extensions/UINavigationItem+Extensions.swift deleted file mode 100644 index 7ac106f..0000000 --- a/Caps/Extensions/UINavigationItem+Extensions.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// UINavigationItem+Extensions.swift -// CapCollector -// -// Created by Christoph on 12.05.20. -// Copyright © 2020 CH. All rights reserved. -// - -import UIKit - -extension UINavigationItem { - - func setTitle(_ title: String, subtitle: String) { - let titleLabel = UILabel() - titleLabel.text = title - titleLabel.font = .systemFont(ofSize: 17.0) - titleLabel.textColor = .black - - let subtitleLabel = UILabel() - subtitleLabel.text = subtitle - subtitleLabel.font = .systemFont(ofSize: 12.0) - subtitleLabel.textColor = .gray - - let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) - stackView.distribution = .equalCentering - stackView.alignment = .center - stackView.axis = .vertical - - self.titleView = stackView - } -} diff --git a/Caps/Extensions/UIViewExtensions.swift b/Caps/Extensions/UIViewExtensions.swift deleted file mode 100644 index 4619a0a..0000000 --- a/Caps/Extensions/UIViewExtensions.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// UIViewExtensions.swift -// CapFinder -// -// Created by User on 23.03.18. -// Copyright © 2018 User. All rights reserved. -// - -import Foundation -import UIKit - -extension UIView { - - var recursiveSubviews: [UIView] { - var subviews = self.subviews.compactMap{ $0 } - subviews.forEach { subviews.append(contentsOf: $0.recursiveSubviews) } - return subviews - } - - func fromNib() -> T { // 2 - return Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)!.first! as! T - } -} diff --git a/Caps/Extensions/URL+Extensions.swift b/Caps/Extensions/URL+Extensions.swift new file mode 100644 index 0000000..eb550a6 --- /dev/null +++ b/Caps/Extensions/URL+Extensions.swift @@ -0,0 +1,25 @@ +import Foundation + +extension URL { + + var attributes: [FileAttributeKey : Any]? { + do { + return try FileManager.default.attributesOfItem(atPath: path) + } catch let error as NSError { + print("FileAttribute error: \(error)") + } + return nil + } + + var fileSize: Int { + return Int(attributes?[.size] as? UInt64 ?? 0) + } + + var fileSizeString: String { + return ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file) + } + + var creationDate: Date? { + return attributes?[.creationDate] as? Date + } +} diff --git a/Caps/Extensions/ViewControllerExtensions.swift b/Caps/Extensions/ViewControllerExtensions.swift deleted file mode 100644 index a0fb98e..0000000 --- a/Caps/Extensions/ViewControllerExtensions.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// ViewControllerExtensions.swift -// CapFinder -// -// Created by User on 18.03.18. -// Copyright © 2018 User. All rights reserved. -// - -import Foundation -import UIKit - -extension UIViewController { - - // MARK: Alerts - - /// Present an alert with a message to the user - func showAlert(_ message: String, title: String = "Error") { - let alertController = UIAlertController( - title: title, - message: message, - preferredStyle: .alert)//, - //blurStyle: .dark) - - alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil)) - - self.present(alertController, animated: true, completion: nil) - } -} diff --git a/Caps/Info.plist b/Caps/Info.plist deleted file mode 100644 index c0cb3d1..0000000 --- a/Caps/Info.plist +++ /dev/null @@ -1,76 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Caps - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleVersion - 1 - LSApplicationQueriesSchemes - - dbapi-8-emm - dbapi-2 - - LSRequiresIPhoneOS - - NSCameraUsageDescription - Take images to identify matching caps and register new ones - UIApplicationShortcutItems - - - UIApplicationShortcutItemIconType - UIApplicationShortcutIconTypeCapturePhoto - UIApplicationShortcutItemSubtitle - Compare a new image - UIApplicationShortcutItemTitle - Take image - UIApplicationShortcutItemType - firstShortcut - UIApplicationShortcutItemUserInfo - - firstShortcutKey1 - firstShortcutKeyValue1 - - - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarStyle - UIStatusBarStyleDefault - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationLandscapeLeft - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/Caps/Logger.swift b/Caps/Logger.swift index 23e4478..93f66cd 100644 --- a/Caps/Logger.swift +++ b/Caps/Logger.swift @@ -1,11 +1,3 @@ -// -// Logger.swift -// CapFinder -// -// Created by User on 11.04.18. -// Copyright © 2018 User. All rights reserved. -// - import Foundation protocol Logger { @@ -27,7 +19,7 @@ func log(_ message: String, file: String = #file, line: Int = #line) { } extension Logger { - + static var logToken: String { "[" + String(describing: self) + "] " } @@ -47,7 +39,7 @@ extension Logger { static func log(_ message: String) { addToFile(logToken + message) } - + private static func addToFile(_ message: String) { Log.write("\n" + message) print(message) @@ -55,7 +47,7 @@ extension Logger { } enum Log { - + static func set(logFile: String) throws { let url = URL(fileURLWithPath: logFile) if !FileManager.default.fileExists(atPath: logFile) { @@ -63,14 +55,14 @@ enum Log { } file = FileHandle(forWritingAtPath: logFile) } - + static func write(_ message: String) { guard let f = file else { return } f.write(message.data(using: .utf8)!) } - + private static var file: FileHandle? } diff --git a/Caps/Presentation/CapCell.swift b/Caps/Presentation/CapCell.swift deleted file mode 100644 index 5d09794..0000000 --- a/Caps/Presentation/CapCell.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// CapCell.swift -// CapFinder -// -// Created by User on 22.04.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - - -class CapCell: UITableViewCell { - - @IBOutlet private weak var capImage: RoundedImageView! - - @IBOutlet private weak var matchLabel: UILabel! - - @IBOutlet private weak var nameLabel: UILabel! - - @IBOutlet private weak var countLabel: UILabel! - - var id: Int = 0 - - func set(image: UIImage?) { - capImage.image = image ?? UIImage(named: "launch") - } - - func set(name: String) { - self.nameLabel.text = name - } - - func set(matchLabel: String) { - self.matchLabel.text = matchLabel - } - - func set(countLabel: String) { - self.countLabel.text = countLabel - } -} diff --git a/Caps/Presentation/GridViewController.swift b/Caps/Presentation/GridViewController.swift deleted file mode 100644 index d7bf2f7..0000000 --- a/Caps/Presentation/GridViewController.swift +++ /dev/null @@ -1,360 +0,0 @@ -// -// GridViewController.swift -// CapCollector -// -// Created by Christoph on 07.01.19. -// Copyright © 2019 CH. All rights reserved. -// - -import UIKit - -class GridViewController: UIViewController { - - /// The number of horizontal pixels for each cap. - static let len: CGFloat = 60 - - private lazy var rowHeight = GridViewController.len * 0.866 - - private lazy var margin = GridViewController.len - rowHeight - - private var myView: UIView! - - private var canvasSize: CGSize = .zero - - @IBOutlet weak var scrollView: UIScrollView! - - /// A dictionary of the caps for the tiles - private var tiles = [Int]() - - /// The name of the tile image - private var name: String = "default" - - /// The number of caps horizontally. - private var columns = 40 - - /// A dictionary for the colors of the caps - private var colors = [Int : UIColor]() - - /// The currently displaxed image views indexed by their tile ids - private var installedTiles = [Int : RoundedImageView]() - - private var selectedTile: Int? = nil - - private weak var selectionView: RoundedButton! - - override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - return .portrait - } - - override var shouldAutorotate: Bool { - return true - } - - private var isShowingColors = false - - @IBAction func toggleAverageColor(_ sender: Any) { - isShowingColors = !isShowingColors - for (tile, view) in installedTiles { - if isShowingColors { - view.image = nil - view.backgroundColor = tileColor(tile: tile) - } else { - let id = tiles[tile] - if let image = app.database.storage.thumbnail(for: id) { - view.image = image - continue - } - self.downloadImage(cap: id, tile: tile) - } - } - } - - func load(tileImage: Database.TileImage) { - let totalCount = app.database.capCount - let firstNewId = tileImage.caps.count + 1 - if totalCount >= firstNewId { - self.tiles = tileImage.caps + (firstNewId...totalCount) - } else { - self.tiles = tileImage.caps - } - self.columns = tileImage.width - self.name = tileImage.name - } - - private func saveTileImage() { - let tileImage = Database.TileImage(name: name, width: columns, caps: tiles) - guard app.database.save(tileImage: tileImage) else { - log("Failed to save tile image") - return - } - log("Tile image saved") - } - - override func viewDidLoad() { - super.viewDidLoad() - - colors = app.database.colors - - let width = CGFloat(columns) * GridViewController.len + GridViewController.len / 2 - let height = (CGFloat(tiles.count) / CGFloat(columns)).rounded(.up) * rowHeight + margin - canvasSize = CGSize(width: width, height: height) - myView = UIView(frame: CGRect(origin: .zero, size: canvasSize)) - - scrollView.addSubview(myView) - scrollView.contentSize = canvasSize - scrollView.delegate = self - scrollView.zoomScale = 0.5 - scrollView.maximumZoomScale = 1 - setZoomRange() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - updateTiles() - - let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) - myView.addGestureRecognizer(tapRecognizer) - } - - override func viewDidLayoutSubviews() { - setZoomRange() - updateTiles() - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - saveTileImage() - } - - // MARK: Tiles - - private func tileColor(tile: Int) -> UIColor? { - let id = tiles[tile] - return colors[id] - } - - /** - Switch two tiles. - */ - private func switchTiles(_ lhs: Int, _ rhs: Int) -> Bool { - let temp = tiles[rhs] - tiles[rhs] = tiles[lhs] - tiles[lhs] = temp - return true - } - - - private func setZoomRange() { - let size = scrollView.frame.size - let a = size.width / canvasSize.width - let b = size.height / canvasSize.height - let scale = min(a,b) - scrollView.minimumZoomScale = min(a,b) - if scrollView.zoomScale < scale { - scrollView.setZoomScale(scale, animated: true) - } - } - - @objc func handleTap(_ sender: UITapGestureRecognizer) { - - let loc = sender.location(in: myView) - let y = loc.y - let s = y.truncatingRemainder(dividingBy: rowHeight) - let row = Int(y / rowHeight) - guard s > margin else { - return - } - let column: Int - if row.isEven { - column = Int(loc.x / GridViewController.len) - // Abort, if user tapped outside of the grid - if column >= columns { - clearTileSelection() - return - } - } else { - column = Int((loc.x - GridViewController.len / 2) / GridViewController.len) - } - handleTileTapped(tile: row * columns + Int(column)) - } - - private func handleTileTapped(tile: Int) { - if let selected = selectedTile { - switchTiles(oldTile: selected, newTile: tile) - } else { - showSelection(tile: tile) - } - } - - private func showSelection(tile: Int) { - clearTileSelection() - - if let view = installedTiles[tile] { - view.borderWidth = 3 - view.borderColor = AppDelegate.tintColor - selectedTile = tile - } else { - selectedTile = nil - } - } - - private func tileIsVisible(tile: Int, in rect: CGRect) -> Bool { - return rect.intersects(frame(for: tile)) - } - - private func makeTile(_ tile: Int) { - let view = RoundedImageView(frame: frame(for: tile)) - myView.addSubview(view) - defer { - installedTiles[tile] = view - } - // Only set image if images are shown - guard !isShowingColors else { - view.backgroundColor = tileColor(tile: tile) - return - - } - if let image = app.database.storage.thumbnail(for: tiles[tile]) { - view.image = image - return - } - - downloadImage(tile: tile) - } - - private func downloadImage(tile: Int) { - let id = tiles[tile] - downloadImage(cap: id, tile: tile) - } - - private func downloadImage(cap id: Int, tile: Int) { - app.database.downloadImage(for: id) { img in - guard img != nil else { - return - } - guard let view = self.installedTiles[tile] else { - self.log("No installed tile for downloaded image \(id)") - return - } - guard let image = app.database.storage.thumbnail(for: id) else { - self.log("Failed to load image for cap \(id) after successful download") - return - } - DispatchQueue.main.async { - guard self.isShowingColors else { - view.image = image - return - } - guard let color = image.averageColor else { - self.log("Failed to get average color from image for cap \(id)") - return - } - view.backgroundColor = color - self.colors[id] = color - } - } - } - - private func frame(for tile: Int) -> CGRect { - let row = tile / columns - let column = tile - row * columns - let x = CGFloat(column) * GridViewController.len + (row.isEven ? 0 : GridViewController.len / 2) - let y = CGFloat(row) * rowHeight - return CGRect(x: x, y: y, width: GridViewController.len, height: GridViewController.len) - } - - private func switchTiles(oldTile: Int, newTile: Int) { - guard oldTile != newTile else { - clearTileSelection() - return - } - guard switchTiles(oldTile, newTile) else { - clearTileSelection() - return - } - // Switch cap colors - let temp = installedTiles[oldTile]?.backgroundColor - installedTiles[oldTile]?.backgroundColor = installedTiles[newTile]?.backgroundColor - installedTiles[newTile]?.backgroundColor = temp - if !isShowingColors { - let temp = installedTiles[oldTile]?.image - installedTiles[oldTile]?.image = installedTiles[newTile]?.image - installedTiles[newTile]?.image = temp - } - clearTileSelection() - - } - - private func clearTileSelection() { - guard let tile = selectedTile else { - return - } - installedTiles[tile]?.borderWidth = 0 - selectedTile = nil - } - - private func showTiles(in rect: CGRect) { - for tile in 0.. UIView? { - return myView - } - - func scrollViewDidScroll(_ scrollView: UIScrollView) { - updateTiles() - } -} - -private extension Int { - - var isEven: Bool { - return self % 2 == 0 - } -} - -extension GridViewController: Logger { } diff --git a/Caps/Presentation/ImageCell.swift b/Caps/Presentation/ImageCell.swift deleted file mode 100644 index d8e6a30..0000000 --- a/Caps/Presentation/ImageCell.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// ImageCell.swift -// CapFinder -// -// Created by User on 07.02.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - -class ImageCell: UICollectionViewCell { - - @IBOutlet weak var capView: UIImageView! - -} diff --git a/Caps/Presentation/ImageSelector.swift b/Caps/Presentation/ImageSelector.swift deleted file mode 100644 index 198d7bb..0000000 --- a/Caps/Presentation/ImageSelector.swift +++ /dev/null @@ -1,186 +0,0 @@ -// -// ListViewController.swift -// CapFinder -// -// Created by User on 22.02.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - -class ImageSelector: UIViewController { - - // MARK: - Constants - - /// The number of items per row - private let itemsPerRow: CGFloat = 3 - - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return .portrait - } - - override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - return .portrait - } - - override var shouldAutorotate: Bool { - return false - } - - // MARK: - Variables - - private var titleLabel: UILabel! - - private var subtitleLabel: UILabel! - - private var images = [UIImage?]() - - var cap: Cap! - - weak var imageProvider: ImageProvider? - - @IBOutlet weak var collection: UICollectionView! - - private var titleText: String { - "Cap \(cap.id) (\(cap.count) images)" - } - - private var subtitleText: String { - cap.name - } - - // MARK: - Life cycle - - override func viewDidLoad() { - super.viewDidLoad() - - collection.dataSource = self - collection.delegate = self - - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - downloadImages() - } - - override func didMove(toParent parent: UIViewController?) { - super.didMove(toParent: parent) - - guard parent != nil && self.navigationItem.titleView == nil else { - return - } - initNavigationItemTitleView() - } - - private func initNavigationItemTitleView() { - self.titleLabel = UILabel() - titleLabel.text = titleText - titleLabel.font = .preferredFont(forTextStyle: .headline) - titleLabel.textColor = .label - - self.subtitleLabel = UILabel() - subtitleLabel.text = subtitleText - subtitleLabel.font = .preferredFont(forTextStyle: .footnote) - subtitleLabel.textColor = .secondaryLabel - - let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) - stackView.distribution = .equalCentering - stackView.alignment = .center - stackView.axis = .vertical - - self.navigationItem.titleView = stackView - } - - // MARK: Image download - - private func downloadImages() { - images = [UIImage?](repeating: nil, count: cap.count) - log("\(cap.count) images for cap \(cap.id)") - for version in 0.. Int { - return 1 - } - - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return images.count - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCell( - withReuseIdentifier: "Image", - for: indexPath) as! ImageCell - - cell.capView.image = images[indexPath.row] ?? UIImage(named: "launch") - return cell - } - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - selectedImage(nr: indexPath.row) - navigationController?.popViewController(animated: true) - } -} - -// MARK: - UICollectionViewDelegateFlowLayout - -extension ImageSelector : UICollectionViewDelegateFlowLayout { - - func collectionView(_ collectionView: UICollectionView, - layout collectionViewLayout: UICollectionViewLayout, - sizeForItemAt indexPath: IndexPath) -> CGSize { - let widthPerItem = collectionView.frame.width / itemsPerRow - return CGSize(width: widthPerItem, height: widthPerItem) - } - - func collectionView(_ collectionView: UICollectionView, - layout collectionViewLayout: UICollectionViewLayout, - insetForSectionAt section: Int) -> UIEdgeInsets { - return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - } - - func collectionView(_ collectionView: UICollectionView, - layout collectionViewLayout: UICollectionViewLayout, - minimumLineSpacingForSectionAt section: Int) -> CGFloat { - return 0 - } -} - -extension ImageSelector: Logger { } - - diff --git a/Caps/Presentation/NavigationController.swift b/Caps/Presentation/NavigationController.swift deleted file mode 100644 index 873ef7a..0000000 --- a/Caps/Presentation/NavigationController.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// NavigationController.swift -// CapCollector -// -// Created by Christoph on 08.01.19. -// Copyright © 2019 CH. All rights reserved. -// - -import UIKit - -class NavigationController: UINavigationController { - - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return allowLandscape ? .allButUpsideDown : .portrait - } - - override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - return .portrait - } - - override var shouldAutorotate: Bool { - return allowLandscape - } - - var allowLandscape: Bool = false - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - -} diff --git a/Caps/Presentation/SearchAndDisplayAccessory.swift b/Caps/Presentation/SearchAndDisplayAccessory.swift deleted file mode 100644 index 97535c0..0000000 --- a/Caps/Presentation/SearchAndDisplayAccessory.swift +++ /dev/null @@ -1,161 +0,0 @@ -// -// SearchAndDisplayAccessory.swift -// CapCollector -// -// Created by Christoph on 09.10.19. -// Copyright © 2019 CH. All rights reserved. -// - -import UIKit - -class PassthroughView: UIView { - - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - let view = super.hitTest(point, with: event) - return view == self ? nil : view - } -} - -protocol CapAccessoryDelegate: AnyObject { - - func capSearchWasDismissed() - - func capSearch(didChange text: String) - - func capAccessoryDidDiscardImage() - - func capAccessory(shouldSave image: UIImage) - - func capAccessoryCameraButtonPressed() -} - -class SearchAndDisplayAccessory: PassthroughView { - - // MARK: - Outlets - - @IBOutlet weak var capImage: RoundedImageView! - - @IBOutlet weak var saveButton: UIButton! - - @IBOutlet weak var cameraButton: UIButton! - - @IBOutlet weak var searchBar: UISearchBar! - - @IBOutlet weak var imageHeightContraint: NSLayoutConstraint! - - // MARK: - Actions - - @IBAction func cameraButtonPressed() { - if isShowingCapImage { - discardImage() - } else { - delegate?.capAccessoryCameraButtonPressed() - } - } - - @IBAction func saveButtonPressed() { - if let image = capImage.image { - delegate?.capAccessory(shouldSave: image) - } - } - - // MARK: - Variables - - var view: UIView? - - weak var delegate: CapAccessoryDelegate? - - var currentImage: UIImage? { - capImage.image - } - - var isShowingCapImage: Bool { - capImage.image != nil - } - - // MARK: - Setup - - convenience init(width: CGFloat) { - let frame = CGRect(origin: .zero, size: CGSize(width: width, height: 145)) - self.init(frame: frame) - } - - override init(frame: CGRect) { - super.init(frame: frame) - setup() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setup() - } - - private func setup() { - view = fromNib() - view!.frame = bounds - //view!.autoresizingMask = .flexibleHeight - addSubview(view!) - - hideImageView() - - searchBar.text = nil - searchBar.setShowsCancelButton(false, animated: false) - searchBar.delegate = self - } - - // MARK: Search bar - - func dismissAndClearSearchBar() { - searchBar.resignFirstResponder() - searchBar.text = nil - } - - // MARK: Cap image - - func showImageView(with image: UIImage) { - capImage.image = image - cameraButton.setImage(UIImage(systemName: "xmark"), for: .normal) - - imageHeightContraint.constant = 90 - capImage.alpha = 1 - capImage.isHidden = false - saveButton.isHidden = false - } - - func discardImage() { - DispatchQueue.main.async { - self.dismissAndClearSearchBar() - self.hideImageView() - } - delegate?.capAccessoryDidDiscardImage() - } - - func hideImageView() { - capImage.image = nil - cameraButton.setImage(UIImage(systemName: "camera"), for: .normal) - - //imageHeightContraint.constant = 0 - capImage.alpha = 0 - capImage.isHidden = true - saveButton.isHidden = true - } -} - -// MARK: - UISearchBarDelegate - -extension SearchAndDisplayAccessory: UISearchBarDelegate { - - func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { - searchBar.resignFirstResponder() - searchBar.text = nil - delegate?.capSearchWasDismissed() - } - - func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { - searchBar.resignFirstResponder() - } - - func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { - delegate?.capSearch(didChange: searchText) - } -} diff --git a/Caps/Presentation/SearchAndDisplayAccessory.xib b/Caps/Presentation/SearchAndDisplayAccessory.xib deleted file mode 100644 index 60b535f..0000000 --- a/Caps/Presentation/SearchAndDisplayAccessory.xib +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Title - Title - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Caps/Presentation/SortController.swift b/Caps/Presentation/SortController.swift deleted file mode 100644 index fa53586..0000000 --- a/Caps/Presentation/SortController.swift +++ /dev/null @@ -1,113 +0,0 @@ -// -// SortController.swift -// CapCollector -// -// Created by Christoph on 12.11.18. -// Copyright © 2018 CH. All rights reserved. -// - -import UIKit - -enum SortCriteria: Int { - case id = 0 - case name = 1 - case count = 2 - case match = 3 - - var text: String { - switch self { - case .id: - return "Id" - case .name: - return "Name" - case .count: - return "Count" - case .match: - return "Match" - } - } -} - -protocol SortControllerDelegate: AnyObject { - - func sortController(didSelect sortType: SortCriteria, ascending: Bool) -} - -class SortController: UITableViewController { - - @IBOutlet weak var thirdRowLabel: UILabel! - - var selected: SortCriteria = .id - - var ascending: Bool = false - - weak var delegate: SortControllerDelegate? - - var options = [SortCriteria]() - - override func viewDidLoad() { - super.viewDidLoad() - - preferredContentSize = CGSize(width: 200, height: 139 + options.count * 40) - } - - private func giveFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle) { - UIImpactFeedbackGenerator(style: style).impactOccurred() - } - - private func sortCriteria(for index: Int) -> SortCriteria { - index < options.count ? options[index] : .match - } - - // MARK: - Table view data source - - override func numberOfSections(in tableView: UITableView) -> Int { - return 2 - } - - override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - section == 0 ? "Sort order" : "Sort by" - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - section == 0 ? 1 : options.count - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "SortCell")! - - guard indexPath.section != 0 else { - cell.accessoryType = ascending ? .checkmark : .none - cell.textLabel?.text = "Ascending" - return cell - } - let select = sortCriteria(for: indexPath.row) - cell.textLabel?.text = select.text - guard select == selected else { - cell.accessoryType = .none - return cell - } - cell.accessoryType = .checkmark - return cell - } - - override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - 40 - } - - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - guard indexPath.section == 1 else { - ascending = !ascending - tableView.reloadRows(at: [indexPath], with: .automatic) - delegate?.sortController(didSelect: selected, ascending: ascending) - giveFeedback(.light) - return - } - giveFeedback(.medium) - selected = sortCriteria(for: indexPath.row) - tableView.reloadRows(at: [indexPath], with: .automatic) - delegate?.sortController(didSelect: selected, ascending: ascending) - self.dismiss(animated: true) - } -} diff --git a/Caps/Preview Content/Preview Assets.xcassets/Contents.json b/Caps/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Caps/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Caps/TableView.swift b/Caps/TableView.swift deleted file mode 100644 index f7b30f7..0000000 --- a/Caps/TableView.swift +++ /dev/null @@ -1,885 +0,0 @@ -// -// TableView.swift -// CapFinder -// -// Created by User on 22.04.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - -enum NavigationBarDataType { - - case appInfo - case upload - case thumbnails -} - -protocol NavigationBarDataSource { - - var title: String { get } - - var subtitle: String { get } - - var id: NavigationBarDataType { get } -} - -class TableView: UITableViewController { - - @IBOutlet weak var infoButton: UIBarButtonItem! - - private lazy var classifier: Classifier? = loadClassifier() - - private var accessory: SearchAndDisplayAccessory? - - private var titleLabel: UILabel! - - private var subtitleLabel: UILabel! - - private var caps = [Cap]() - - private var shownCaps = [Cap]() - - private var matches: [Int : Float]? - - private var sortType: SortCriteria = .id - - private var searchText: String? = nil - - private var sortAscending: Bool = false - - /// This will be set to a cap id when adding a cap to it - private var capToAddImageTo: Int? - - private var isUnlocked = false - - var imageProvider: ImageProvider { - app.database.storage - } - - // MARK: Computed properties - - private var titleText: String { - let recognized = app.database.recognizedCapCount - let all = app.database.capCount - switch all { - case 0: - return "No caps" - case 1: - return "1 cap" - case recognized: - return "\(all) caps" - default: - return "\(all) caps (\(all - recognized) new)" - } - } - - private var subtitleText: String { - let capCount = app.database.capCount - guard capCount > 0, isUnlocked else { - return "" - } - let allImages = app.database.imageCount - - let ratio = Float(allImages) / Float(capCount) - return String(format: "%d images (%.2f per cap)", allImages, ratio) - } - - // MARK: Overrides - - override var inputAccessoryView: UIView? { - get { return accessory } - } - - override var canBecomeFirstResponder: Bool { - return true - } - - // MARK: - Actions - - @IBAction func updateInfo(_ sender: UIBarButtonItem, forEvent event: UIEvent) { - guard let touch = event.allTouches?.first, touch.tapCount > 0 else { - return - } - guard !app.database.isInOfflineMode else { - showOfflineDialog() - return - } - app.database.startInitialDownload() - } - - @IBAction func showMosaic(_ sender: UIBarButtonItem) { - checkThumbnailsAndColorsBeforShowingGrid() - } - - func showCameraView() { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - let controller = storyboard.instantiateViewController(withIdentifier: "NewImageController") as! CameraController - controller.delegate = self - self.present(controller, animated: true) - } - - @objc private func titleWasTapped() { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - let controller = storyboard.instantiateViewController(withIdentifier: "SortController") as! SortController - controller.selected = sortType - controller.ascending = sortAscending - controller.delegate = self - - controller.options = [.id, .name] - if isUnlocked { controller.options.append(.count) } - if matches != nil { controller.options.append(.match) } - - let presentationController = AlwaysPresentAsPopover.configurePresentation(forController: controller) - - presentationController.sourceView = navigationItem.titleView! - presentationController.permittedArrowDirections = [.up] - self.present(controller, animated: true) - } - - // MARK: - Life cycle - - override func viewDidLoad() { - super.viewDidLoad() - - tableView.rowHeight = 100 - - accessory = SearchAndDisplayAccessory(width: self.view.frame.width) - accessory?.delegate = self - - initInfoButton() - - app.database.delegate = self - let count = app.database.capCount - if count == 0 { - log("No caps found, downloading names") - app.database.startInitialDownload() - } else { - log("Loaded \(count) caps") - reloadCapsFromDatabase() - } - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - (navigationController as? NavigationController)?.allowLandscape = false - isUnlocked = app.isUnlocked - log(isUnlocked ? "App is unlocked" : "App is locked") - app.database.startBackgroundWork() - } - - override func didMove(toParent parent: UIViewController?) { - super.didMove(toParent: parent) - - guard parent != nil && self.navigationItem.titleView == nil else { - return - } - initNavigationItemTitleView() - } - - private func initInfoButton() { - let offline = app.database.isInOfflineMode - setInfoButtonIcon(offline: offline) - } - - private func setInfoButtonIcon(offline: Bool) { - let symbol = offline ? "icloud.slash" : "arrow.clockwise.icloud" - infoButton.image = UIImage(systemName: symbol) - } - - private func initNavigationItemTitleView() { - self.titleLabel = UILabel() - titleLabel.text = titleText - titleLabel.font = .preferredFont(forTextStyle: .headline) - titleLabel.textColor = .label - - self.subtitleLabel = UILabel() - subtitleLabel.text = subtitleText - subtitleLabel.font = .preferredFont(forTextStyle: .footnote) - subtitleLabel.textColor = .secondaryLabel - - let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) - stackView.distribution = .equalCentering - stackView.alignment = .center - stackView.axis = .vertical - - self.navigationItem.titleView = stackView - - let recognizer = UITapGestureRecognizer(target: self, action: #selector(titleWasTapped)) - stackView.isUserInteractionEnabled = true - stackView.addGestureRecognizer(recognizer) - - let longPress = UILongPressGestureRecognizer(target: self, action: #selector(attemptChangeOfUserPermissions)) - stackView.addGestureRecognizer(longPress) - } - - private func set(title: String, subtitle: String) { - DispatchQueue.main.async { - self.titleLabel?.text = title - self.subtitleLabel?.text = subtitle - } - } - - private func updateNavigationItemTitleView() { - DispatchQueue.main.async { - self.titleLabel?.text = self.titleText - self.subtitleLabel?.text = self.subtitleText - } - } - - // MARK: Starting updates - - private func checkThumbnailsAndColorsBeforShowingGrid() { - let colors = app.database.pendingCapsForColorCreation - let thumbs = app.database.pendingCapForThumbnailCreation - guard colors == 0 && thumbs == 0 else { - app.database.startBackgroundWork() - showAlert("Please wait until all background work is completed. \(colors) colors and \(thumbs) thumbnails need to be created.", title: "Mosaic not ready") - return - } - showGrid() - } - - private func showGrid() { - let vc = app.mainStoryboard.instantiateViewController(withIdentifier: "GridView") as! GridViewController - guard let nav = navigationController as? NavigationController else { - return - } - if let tileImage = app.database.tileImage(named: "default") { - log("Showing existing tile image") - vc.load(tileImage: tileImage) - } else { - let tileImage = Database.TileImage(name: "default", width: 40, caps: []) - log("Showing default tile image") - vc.load(tileImage: tileImage) - } - nav.pushViewController(vc, animated: true) - nav.allowLandscape = true - } - - private func showOfflineDialog() { - let offline = app.database.isInOfflineMode - if offline { - print("Marking as online") - app.database.isInOfflineMode = false - app.database.startBackgroundWork() - self.showAlert("Offline mode was disabled", title: "Online") - } else { - print("Marking as offline") - app.database.isInOfflineMode = true - self.showAlert("Offline mode was enabled", title: "Offline") - } - } - - private func rename(cap: Cap, at indexPath: IndexPath) { - let detail = "Choose a new name for the cap" - askUserForText("Enter new name", detail: detail, existingText: cap.name, yesText: "Save") { text in - guard app.database.update(name: text, for: cap.id) else { - self.showAlert("Name could not be set.", title: "Update failed") - return - } - } - } - - private func saveNewCap(for image: UIImage) { - let detail = "Choose a name for the image" - askUserForText("Enter name", detail: detail, existingText: accessory!.searchBar.text, yesText: "Save") { text in - DispatchQueue.global(qos: .userInitiated).async { - guard app.database.createCap(image: image, name: text) else { - self.showAlert("Cap not added", title: "Database error") - return - } - self.accessory!.discardImage() - } - } - } - - private func updateShownCaps(_ newList: [Cap], insertedId id: Int) { - // Main queue - guard shownCaps.count == newList.count - 1 else { - log("Cap list refresh mismatch: was \(shownCaps.count), is \(newList.count)") - show(sortedCaps: newList) - return - } - guard let index = newList.firstIndex(where: { $0.id == id}) else { - log("Cap list refresh without new cap \(id)") - show(sortedCaps: newList) - return - } - - self.tableView.beginUpdates() - self.shownCaps = newList - let indexPath = IndexPath(row: index, section: 0) - self.tableView.insertRows(at: [indexPath], with: .automatic) - self.tableView.endUpdates() - } - - - // MARK: User interaction - - @objc private func attemptChangeOfUserPermissions() { - guard isUnlocked else { - attemptAppUnlock() - return - } - log("Locking app.") - app.lock() - isUnlocked = false - showAllCapsAndScrollToTop() - updateNavigationItemTitleView() - showAlert("The app was locked to prevent modifications.", title: "Locked") - } - - private func attemptAppUnlock() { - log("Presenting unlock dialog to user") - askUserForText("Enter pin", detail: "Enter the correct pin to unlock write permissions for the app.", placeholder: "Pin", yesText: "Unlock") { text in - guard let pin = Int(text), app.checkUnlock(with: pin) else { - self.unlockFailed() - return - } - self.unlockDidSucceed() - } - } - - private func unlockFailed() { - showAlert("The pin you entered is incorrect.", title: "Invalid pin") - } - - private func unlockDidSucceed() { - showAlert("The app was successfully unlocked.", title: "Unlocked") - isUnlocked = true - - showAllCapsAndScrollToTop() - updateNavigationItemTitleView() - } - - private func loadClassifier() -> Classifier? { - guard let model = app.database.storage.recognitionModel else { - return nil - } - return Classifier(model: model) - } - - private func askUserForText(_ title: String, detail: String, existingText: String? = nil, placeholder: String? = "Cap name", yesText: String, noText: String = "Cancel", confirmed: @escaping (_ text: String) -> Void) { - DispatchQueue.main.async { - let alertController = UIAlertController( - title: title, - message: detail, - preferredStyle: .alert) - - alertController.addTextField { textField in - textField.placeholder = placeholder - textField.keyboardType = .default - textField.text = existingText - } - - let action = UIAlertAction(title: yesText, style: .default) { _ in - guard let name = alertController.textFields?.first?.text else { - return - } - confirmed(name) - } - - let cancel = UIAlertAction(title: noText, style: .cancel) - - alertController.addAction(action) - alertController.addAction(cancel) - self.present(alertController, animated: true) - } - } - - private func presentUserBinaryChoice(_ title: String, detail: String, yesText: String, noText: String = "Cancel", dismissed: (() -> Void)? = nil, confirmed: @escaping () -> Void) { - let alert = UIAlertController(title: title, message: detail, preferredStyle: .alert) - - let confirm = UIAlertAction(title: yesText, style: .default) { _ in - confirmed() - } - let cancel = UIAlertAction(title: noText, style: .cancel) { _ in - dismissed?() - } - alert.addAction(confirm) - alert.addAction(cancel) - DispatchQueue.main.async { - self.present(alert, animated: true) - } - } - - // MARK: Classification - - /// The similarity of the cap to the currently processed image - private func match(for cap: Int) -> Float? { - matches?[cap] - } - - private func clearClassifierMatches() { - matches = nil - } - - private func classify(image: UIImage) { - guard let classifier = self.classifier else { - return - } - DispatchQueue.global(qos: .userInitiated).async { - self.log("Classification starting...") - classifier.recognize(image: image) { matches in - guard let matches = matches else { - self.log("Failed to classify image") - self.matches = nil - return - } - self.log("Classification finished") - self.matches = matches - self.sortType = .match - self.sortAscending = false - self.showAllCapsAndScrollToTop() - DispatchQueue.global(qos: .background).async { - app.database.update(recognizedCaps: Set(matches.keys)) - } - } - } - } - - private func classifyDummyImage() { - guard let classifier = self.classifier else { - return - } - DispatchQueue.global(qos: .userInitiated).async { - classifier.recognize(image: UIImage(named: "launch")!) { matches in - guard let matches = matches else { - self.log("Failed to classify dummy image") - self.matches = nil - return - } - self.log("Dummy classification finished") - DispatchQueue.global(qos: .background).async { - app.database.update(recognizedCaps: Set(matches.keys)) - } - } - } - } - - // MARK: Finishing downloads - - private func didDownloadClassifier() { - guard let model = app.database.storage.recognitionModel else { - classifier = nil - return - } - classifier = Classifier(model: model) - guard let image = accessory!.currentImage else { - classifyDummyImage() - return - } - classify(image: image) - } - - // MARK: - Showing caps - - private func reloadCapsFromDatabase() { - caps = app.database?.caps ?? [] - showCaps() - } - - /** - Match all cap names against the given string and return matches. - - note: Each space-separated part of the string is matched individually - */ - private func showCaps(matching text: String? = nil) { - DispatchQueue.global(qos: .userInteractive).async { - self.searchText = text - guard let t = text else { - self.show(caps: self.caps) - return - } - let found = self.filter(caps: self.caps, matching: t) - self.show(caps: found) - } - } - - private func show(caps: [Cap]) { - show(sortedCaps: sorted(caps: caps)) - } - - private func show(sortedCaps caps: [Cap]) { - shownCaps = caps - DispatchQueue.main.async { - self.tableView.reloadData() - } - } - - private func filter(caps: [Cap], matching text: String) -> [Cap] { - let textParts = text.components(separatedBy: " ").filter { $0 != "" } - return caps.compactMap { cap -> Cap? in - // For each part of text, check if name contains it - for textItem in textParts { - if !cap.cleanName.contains(textItem) { - return nil - } - } - return cap - } - } - - private func sorted(caps: [Cap]) -> [Cap] { - if sortAscending { - switch sortType { - case .id: return caps.sorted { $0.id < $1.id } - case .count: return caps.sorted { $0.count < $1.count } - case .name: return caps.sorted { $0.name < $1.name } - case .match: return caps.sorted { match(for: $0.id) ?? 0 < match(for: $1.id) ?? 0 } - } - } else { - switch sortType { - case .id: return caps.sorted { $0.id > $1.id } - case .count: return caps.sorted { $0.count > $1.count } - case .name: return caps.sorted { $0.name > $1.name } - case .match: return caps.sorted { match(for: $0.id) ?? 0 > match(for: $1.id) ?? 0 } - } - } - } - - /// Resets the cap list to its original state, discarding any previous sorting. - private func showAllCapsByDescendingId() { - sortType = .id - sortAscending = false - showAllCapsAndScrollToTop() - } - - /// Display all caps in the table, and scrolls to the top - private func showAllCapsAndScrollToTop() { - showCaps() - tableViewScrollToTop() - } - - // MARK: - TableView - - /** - Scroll the table view to the top - */ - private func tableViewScrollToTop() { - guard shownCaps.count > 0 else { return } - let path = IndexPath(row: 0, section: 0) - DispatchQueue.main.async { - self.tableView.scrollToRow(at: path, at: .top, animated: true) - } - } -} - -// MARK: - SortControllerDelegate - -extension TableView: SortControllerDelegate { - - func sortController(didSelect sortType: SortCriteria, ascending: Bool) { - self.sortType = sortType - self.sortAscending = ascending - if sortType != .match { - clearClassifierMatches() - } - showAllCapsAndScrollToTop() - } -} - -// MARK: - CameraControllerDelegate - -extension TableView: CameraControllerDelegate { - - func didCapture(image: UIImage) { - guard let cap = capToAddImageTo else { - accessory!.showImageView(with: image) - classify(image: image) - return - } - - guard app.database.add(image: image, for: cap) else { - self.error("Could not save image") - return - } - log("Added image for cap \(cap)") - self.capToAddImageTo = nil - } - - func didCancel() { - capToAddImageTo = nil - } -} - -// MARK: - UITableViewDataSource - -extension TableView { - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "cap") as! CapCell - let cap = shownCaps[indexPath.row] - - configure(cell: cell, for: cap) - return cell - } - - private func configure(cell: CapCell, for cap: Cap) { - let matchText = cap.matchLabelText(match: match(for: cap.id), appIsUnlocked: self.isUnlocked) - let countText = cap.countLabelText(appIsUnlocked: self.isUnlocked) - - cell.id = cap.id - cell.set(name: cap.name) - cell.set(matchLabel: matchText) - cell.set(countLabel: countText) - - if let image = imageProvider.image(for: cap.id) { - cell.set(image: image) - } else { - cell.set(image: nil) - app.database.downloadImage(for: cap.id) { _ in - // Delegate call will update image - } - } - } - - override func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return shownCaps.count - } -} - -// MARK: - UITableViewDelegate - -extension TableView { - - private func takeImage(for cap: Int) { - self.capToAddImageTo = cap - showCameraView() - } - - override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { - // Prevent unauthorized users from selecting caps - isUnlocked ? indexPath : nil - } - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - defer { - tableView.deselectRow(at: indexPath, animated: true) - } - // Prevent unauthorized users from making changes - guard isUnlocked else { - return - } - let cap = shownCaps[indexPath.row] - guard let image = accessory?.capImage.image else { - self.giveFeedback(.medium) - takeImage(for: cap.id) - return - } - guard app.database.add(image: image, for: cap.id) else { - self.giveFeedback(.heavy) - self.error("Could not save image") - return - } - self.giveFeedback(.medium) - // Delegate call will update cell - self.accessory?.discardImage() - } - - private func giveFeedback(_ style: UIImpactFeedbackGenerator.FeedbackStyle) { - UIImpactFeedbackGenerator(style: style).impactOccurred() - } - - override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { - // Prevent unauthorized users from making changes - guard isUnlocked else { - return nil - } - - let cap = shownCaps[indexPath.row] - - let rename = UIContextualAction(style: .normal, title: "Rename\ncap") { (_, _, success) in - success(true) - self.rename(cap: cap, at: indexPath) - self.giveFeedback(.medium) - } - rename.backgroundColor = .blue - - let image = UIContextualAction(style: .normal, title: "Change\nimage") { (_, _, success) in - self.giveFeedback(.medium) - let storyboard = UIStoryboard(name: "Main", bundle: nil) - let controller = storyboard.instantiateViewController(withIdentifier: "ImageSelector") as! ImageSelector - controller.cap = cap - controller.imageProvider = self.imageProvider - self.navigationController?.pushViewController(controller, animated: true) - success(true) - } - image.backgroundColor = .red - - return UISwipeActionsConfiguration(actions: [rename, image]) - } - - override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { - let cap = shownCaps[indexPath.row] - - var actions = [UIContextualAction]() - // Prevent unauthorized users from making changes - if isUnlocked { - let count = UIContextualAction(style: .normal, title: "Update\ncount") { (_, _, success) in - self.giveFeedback(.medium) - success(true) - DispatchQueue.global(qos: .userInitiated).async { - app.database.downloadImageCount(for: cap.id) - } - } - count.backgroundColor = .orange - actions.append(count) - } - - let similar = UIContextualAction(style: .normal, title: "Similar\ncaps") { (_, _, success) in - self.giveFeedback(.medium) - self.accessory?.hideImageView() - guard let image = self.imageProvider.image(for: cap.id, version: 0) else { - success(false) - return - } - self.classify(image: image) - success(true) - } - similar.backgroundColor = .blue - actions.append(similar) - - return UISwipeActionsConfiguration(actions: actions) - } -} - -// MARK: - Logging - -extension TableView: Logger { } - -// MARK: - Protocol DatabaseDelegate - -extension TableView: DatabaseDelegate { - - func database(needsUserConfirmation title: String, body: String, shouldProceed: @escaping (Bool) -> Void) { - presentUserBinaryChoice(title, detail: body, yesText: "Download", noText: "Later", dismissed: { - shouldProceed(false) - }) { - shouldProceed(true) - } - } - - func databaseHasNewClassifier() { - didDownloadClassifier() - } - - func database(completedBackgroundWorkItem title: String, subtitle: String) { - set(title: title, subtitle: subtitle) - } - - func database(didFailBackgroundWork title: String, subtitle: String) { - set(title: title, subtitle: subtitle) - DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10)) { - self.updateNavigationItemTitleView() - } - } - - func databaseDidFinishBackgroundWork() { -// set(title: "All tasks completed", subtitle: titleText) - self.updateNavigationItemTitleView() -// DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) { -// self.updateNavigationItemTitleView() -// } - } - - func database(didAddCap cap: Cap) { - caps.append(cap) - updateNavigationItemTitleView() - guard let text = searchText else { - // All caps are shown - let newList = sorted(caps: caps) - updateShownCaps(newList, insertedId: cap.id) - return - } - guard filter(caps: [cap], matching: text) != [] else { - // Cap is not shown, so don't reload - return - } - let newList = sorted(caps: filter(caps: caps, matching: text)) - updateShownCaps(newList, insertedId: cap.id) - } - - func database(didChangeCap id: Int) { - updateNavigationItemTitleView() - guard let cap = app.database.cap(for: id) else { - log("Changed cap \(id) not found in database") - return - } - if let index = caps.firstIndex(where: { $0.id == id}) { - caps[index] = cap - } else { - log("Cap not found in full list") - } - if let index = shownCaps.firstIndex(where: { $0.id == id}) { - shownCaps[index] = cap - } - guard let cell = visibleCell(for: id) else { - return - } - configure(cell: cell, for: cap) - } - - func database(didLoadImageForCap cap: Int) { - DispatchQueue.main.async { - guard let cell = self.visibleCell(for: cap) else { - return - } - guard let image = self.imageProvider.image(for: cap) else { - self.log("No image for cap \(cap), although it should be loaded") - return - } - cell.set(image: image) - } - - } - - func databaseNeedsFullRefresh() { - reloadCapsFromDatabase() - } - - private func visibleCell(for cap: Int) -> CapCell? { - tableView.visibleCells - .map { $0 as! CapCell } - .first { $0.id == cap } - } -} - -// MARK: - Protocol CapSearchDelegate - -extension TableView: CapAccessoryDelegate { - - func capSearchWasDismissed() { - showAllCapsAndScrollToTop() - } - - func capSearch(didChange text: String) { - let cleaned = text.clean - guard cleaned != "" else { - self.showCaps(matching: nil) - return - } - self.showCaps(matching: cleaned) - } - - func capAccessoryDidDiscardImage() { - matches = nil - showAllCapsByDescendingId() - } - - func capAccessory(shouldSave image: UIImage) { - guard isUnlocked else { - return - } - saveNewCap(for: image) - } - - func capAccessoryCameraButtonPressed() { - showCameraView() - } - -} diff --git a/Caps/View Components/AlwaysShowPopup.swift b/Caps/View Components/AlwaysShowPopup.swift deleted file mode 100644 index aeb4f15..0000000 --- a/Caps/View Components/AlwaysShowPopup.swift +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018, Ralf Ebert -// License https://opensource.org/licenses/MIT -// License https://creativecommons.org/publicdomain/zero/1.0/ -// Source https://www.ralfebert.de/ios-examples/uikit/choicepopover/ - -import UIKit - -/** - By default, when you use: - - ``` - controller.modalPresentationStyle = .popover - ``` - - in a horizontally compact environment (iPhone in portrait mode), this option behaves the same as fullScreen. - You can make it to always show a popover by using: - - ``` - let presentationController = AlwaysPresentAsPopover.configurePresentation(forController: controller) - ``` - */ -class AlwaysPresentAsPopover : NSObject, UIPopoverPresentationControllerDelegate { - - // `sharedInstance` because the delegate property is weak - the delegate instance needs to be retained. - private static let sharedInstance = AlwaysPresentAsPopover() - - private override init() { - super.init() - } - - func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { - return .none - } - - static func configurePresentation(forController controller : UIViewController) -> UIPopoverPresentationController { - controller.modalPresentationStyle = .popover - let presentationController = controller.presentationController as! UIPopoverPresentationController - presentationController.delegate = AlwaysPresentAsPopover.sharedInstance - return presentationController - } - -} diff --git a/Caps/View Components/CropView.swift b/Caps/View Components/CropView.swift deleted file mode 100644 index 27525e9..0000000 --- a/Caps/View Components/CropView.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// CropView.swift -// CapFinder -// -// Created by User on 31.01.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - -//@IBDesignable -class CropView: UIView { - - @IBInspectable var lineColor: UIColor = UIColor.black - - @IBInspectable var lineWidth: Float = 2 - - @IBInspectable var relativeSize: Float = 0.6 { - didSet { size = CGFloat(relativeSize) / 2 } - } - - private var size: CGFloat = 0.3 - - override init(frame: CGRect) { - super.init(frame: frame) - } - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - override func draw(_ rect: CGRect) { - let height = rect.height - let width = rect.width - - let length = height > width ? width : height - - let center = CGPoint(x: width / 2, y: height / 2) - let path = UIBezierPath() - - path.lineWidth = CGFloat(self.lineWidth) - lineColor.setStroke() - - path.addArc( - withCenter: center, - radius: length * size, - startAngle: 0, - endAngle: .pi * 2, - clockwise: true) - - path.stroke() - } -} diff --git a/Caps/View Components/RoundedButton.swift b/Caps/View Components/RoundedButton.swift deleted file mode 100644 index 240c3bd..0000000 --- a/Caps/View Components/RoundedButton.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// RoundedButton.swift -// CapFinder -// -// Created by User on 01.02.18. -// Copyright © 2018 User. All rights reserved. -// - -import Foundation -import UIKit - -@IBDesignable -class RoundedButton: UIButton { - - @IBInspectable var borderColor: UIColor = UIColor.black { - didSet { - layer.borderColor = borderColor.cgColor - } - } - - @IBInspectable var borderWidth: CGFloat = 0 { - didSet { - layer.borderWidth = borderWidth - } - } - //Normal state bg and border - @IBInspectable var normalBorderColor: UIColor? { - didSet { - layer.borderColor = normalBorderColor?.cgColor - } - } - - @IBInspectable var normalBackgroundColor: UIColor? { - didSet { - setBgColorForState(color: normalBackgroundColor, forState: []) - } - } - - - //Highlighted state bg and border - @IBInspectable var highlightedBorderColor: UIColor? - - @IBInspectable var highlightedBackgroundColor: UIColor? { - didSet { - setBgColorForState(color: highlightedBackgroundColor, forState: .highlighted) - } - } - - - private func setBgColorForState(color: UIColor?, forState: UIControl.State){ - self.backgroundColor = color -// if color != nil { -// self.backgroundColor = color! -// setBackgroundImage(UIImage.imageWithColor(color: color!), for: forState) -// } else { -// setBackgroundImage(nil, for: forState) -// } - } - - override func layoutSubviews() { - super.layoutSubviews() - - layer.cornerRadius = layer.frame.height / 2 - // layer.cornerRadius = min(layer.frame.height, layer.frame.width) / 2 - clipsToBounds = true - - if borderWidth > 0 { - if state == [] && layer.borderColor == normalBorderColor?.cgColor { - layer.borderColor = normalBorderColor?.cgColor - } else if state == .highlighted && highlightedBorderColor != nil { - layer.borderColor = highlightedBorderColor!.cgColor - } - } - } - -} - -extension RoundedButton { - - func set(template: String, with tint: UIColor) { - self.setImage(UIImage.templateImage(named: template), for: .normal) - self.tintColor = tint - self.borderColor = tint - } -} - -//Extension Required by RoundedButton to create UIImage from UIColor -extension UIImage { - class func imageWithColor(color: UIColor) -> UIImage { - let rect: CGRect = CGRect(x: 0, y: 0, width: 1, height: 1) - UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), false, 1.0) - color.setFill() - UIRectFill(rect) - let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()! - UIGraphicsEndImageContext() - return image - } -} - diff --git a/Caps/View Components/RoundedImageView.swift b/Caps/View Components/RoundedImageView.swift deleted file mode 100644 index 4d70fbd..0000000 --- a/Caps/View Components/RoundedImageView.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// RoundedImageView.swift -// CapFinder -// -// Created by User on 22.04.18. -// Copyright © 2018 User. All rights reserved. -// - -import UIKit - -class RoundedImageView: UIImageView { - - @IBInspectable var borderColor: UIColor = UIColor.black { - didSet { - layer.borderColor = borderColor.cgColor - } - } - - @IBInspectable var borderWidth: CGFloat = 0 { - didSet { - layer.borderWidth = borderWidth - } - } - - override func layoutSubviews() { - super.layoutSubviews() - - layer.cornerRadius = layer.frame.height / 2 - clipsToBounds = true - } -} diff --git a/Caps/Views/CapNameEntryView.swift b/Caps/Views/CapNameEntryView.swift new file mode 100644 index 0000000..4cd35a3 --- /dev/null +++ b/Caps/Views/CapNameEntryView.swift @@ -0,0 +1,31 @@ +import SwiftUI +import SFSafeSymbols + +struct CapNameEntryView: View { + + @Binding + var name: String + + var body: some View { + TextField("Name", text: $name, prompt: Text("Enter name...")) + .padding(7) + .padding(.horizontal, 25) + .background(Color(.systemGray5)) + .cornerRadius(8) + .overlay( + HStack { + Image(systemSymbol: .squareAndPencil) + .foregroundColor(.gray) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) + .padding(.leading, 8) + } + ) + } +} + +struct CapNameEntryView_Previews: PreviewProvider { + static var previews: some View { + CapNameEntryView(name: .constant("")) + .previewLayout(.fixed(width: 375, height: 50)) + } +} diff --git a/Caps/Views/CapRowView.swift b/Caps/Views/CapRowView.swift new file mode 100644 index 0000000..3e66131 --- /dev/null +++ b/Caps/Views/CapRowView.swift @@ -0,0 +1,77 @@ +import SwiftUI +import CachedAsyncImage + +struct CapRowView: View { + + private let imageSize: CGFloat = 70 + + private let sufficientImageCount = 10 + + let cap: Cap + + let match: Float? + + @EnvironmentObject + var database: Database + + var imageUrl: URL { + database.serverUrl.appendingPathComponent(cap.mainImagePath) + } + + var imageCountText: String { + guard cap.imageCount != 1 else { + return "\(cap.id) (1 image)" + } + return "\(cap.id) (\(cap.imageCount) images)" + } + + var body: some View { + HStack(alignment: .center) { + VStack(alignment: .leading, spacing: 0) { + + HStack(spacing: 8) { + Text(imageCountText) + .font(.footnote) + if !cap.classifiable(by: database.classifierVersion) { + Text("📵") + } + if cap.imageCount < sufficientImageCount { + Text("⚠️") + } + if database.hasPendingUpdates(for: cap.id) { + Text("⇅") + } + if database.hasPendingOperations(for: cap.id) { + ProgressView() + } + } + .padding(.top, 0) + .font(.footnote) + Text(cap.name) + .font(.headline) + .padding(.bottom, 3) + if let match = match { + Text("\(Int((match * 100).rounded())) % match") + .font(.footnote) + } + }//.padding(.vertical) + Spacer() + CachedAsyncImage(url: imageUrl, urlCache: database.imageCache) { image in + image.resizable() + } placeholder: { + ProgressView() + } + .frame(width: imageSize, height: imageSize) + .cornerRadius(imageSize / 2) + } + } +} + +struct CapRowView_Previews: PreviewProvider { + static var previews: some View { + CapRowView(cap: Cap(id: 123, name: "My new cap"), + match: 0.13) + .previewLayout(.fixed(width: 375, height: 80)) + .environmentObject(Database.mock) + } +} diff --git a/Caps/Views/GridView.swift b/Caps/Views/GridView.swift new file mode 100644 index 0000000..043e6bf --- /dev/null +++ b/Caps/Views/GridView.swift @@ -0,0 +1,13 @@ +import SwiftUI + +struct GridView: View { + var body: some View { + Text("Grid view") + } +} + +struct GridView_Previews: PreviewProvider { + static var previews: some View { + GridView() + } +} diff --git a/Caps/Views/SearchField.swift b/Caps/Views/SearchField.swift new file mode 100644 index 0000000..03e716c --- /dev/null +++ b/Caps/Views/SearchField.swift @@ -0,0 +1,40 @@ +import SwiftUI +import SFSafeSymbols + +struct SearchField: View { + + @Binding + var searchString: String + + var body: some View { + TextField("Search", text: $searchString, prompt: Text("Search...")) + .padding(7) + .padding(.horizontal, 25) + .background(Color(.systemGray5)) + .cornerRadius(8) + .overlay( + HStack { + Image(systemSymbol: .magnifyingglass) + .foregroundColor(.gray) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) + .padding(.leading, 8) + if searchString != "" { + Button(action: { + self.searchString = "" + }) { + Image(systemSymbol: .multiplyCircleFill) + .foregroundColor(.gray) + .padding(.trailing, 8) + } + } + } + ) + } +} + +struct SearchField_Previews: PreviewProvider { + static var previews: some View { + SearchField(searchString: .constant("")) + .previewLayout(.fixed(width: 375, height: 50)) + } +} diff --git a/Caps/Views/SettingsStatisticRow.swift b/Caps/Views/SettingsStatisticRow.swift new file mode 100644 index 0000000..07e5981 --- /dev/null +++ b/Caps/Views/SettingsStatisticRow.swift @@ -0,0 +1,30 @@ +// +// SettingsStatisticRow.swift +// Caps +// +// Created by CH on 26.05.22. +// + +import SwiftUI + +struct SettingsStatisticRow: View { + + let label: String + + let value: String + + var body: some View { + HStack { + Text(label) + Spacer() + Text(value) + } + } +} + +struct SettingsStatisticRow_Previews: PreviewProvider { + static var previews: some View { + SettingsStatisticRow(label: "Label", value: "Value") + .previewLayout(.fixed(width: 375, height: 40)) + } +} diff --git a/Caps/Views/SettingsView.swift b/Caps/Views/SettingsView.swift new file mode 100644 index 0000000..f0aec12 --- /dev/null +++ b/Caps/Views/SettingsView.swift @@ -0,0 +1,74 @@ +import SwiftUI + +struct SettingsView: View { + + @EnvironmentObject + var database: Database + + @Binding + var isPresented: Bool + + var body: some View { + VStack(alignment: .leading, spacing: 3) { + HStack { + Text("Settings") + .font(.title2) + .bold() + Spacer() + Button(action: hide) { + Image(systemSymbol: .xmarkCircleFill) + .foregroundColor(.gray) + .font(.system(size: 26)) + } + } + Text("Statistics") + .font(.footnote) + .textCase(.uppercase) + .foregroundColor(.secondary) + .padding(.top) + Group { + SettingsStatisticRow(label: "Caps", value: "\(database.numberOfCaps)") + SettingsStatisticRow(label: "Total images", value: "\(database.numberOfImages)") + SettingsStatisticRow(label: "Images per cap", value: String(format: "%.1f", database.averageImageCount)) + }.padding(.horizontal) + Text("Classifier") + .font(.footnote) + .textCase(.uppercase) + .foregroundColor(.secondary) + .padding(.top) + Group { + SettingsStatisticRow(label: "Version", value: "\(database.classifierVersion)") + SettingsStatisticRow(label: "Recognized caps", value: "\(database.classifierClassCount)") + }.padding(.horizontal) + Text("Storage") + .font(.footnote) + .textCase(.uppercase) + .foregroundColor(.secondary) + .padding(.top) + Group { + SettingsStatisticRow(label: "Image cache", value: byteString(database.imageCacheSize)) + SettingsStatisticRow(label: "Database", value: byteString(database.databaseSize)) + SettingsStatisticRow(label: "Classifier", value: byteString(database.classifierSize)) + }.padding(.horizontal) + + Spacer() + } + .padding(.horizontal) + } + + private func hide() { + isPresented = false + } + + private func byteString(_ count: Int) -> String { + ByteCountFormatter.string(fromByteCount: Int64(count), countStyle: .file) + } +} + +struct SettingsView_Previews: PreviewProvider { + static var previews: some View { + SettingsView(isPresented: .constant(true)) + .environmentObject(Database.mock) + .previewLayout(.fixed(width: 375, height: 330)) + } +} diff --git a/Caps/Views/SortCaseRowView.swift b/Caps/Views/SortCaseRowView.swift new file mode 100644 index 0000000..67dd879 --- /dev/null +++ b/Caps/Views/SortCaseRowView.swift @@ -0,0 +1,33 @@ +import SwiftUI + +struct SortCaseRowView: View { + + @Binding + var selectedType: SortCriteria + + let type: SortCriteria + + var body: some View { + Button(action: { selectedType = type}) { + HStack { + Text(type.text) + .foregroundColor(.primary) + Spacer() + if selectedType == type { + Image(systemSymbol: .checkmark) + } + } + .padding(.horizontal) + .padding(.vertical, 8) + .background(Color(UIColor.systemGroupedBackground)) + .cornerRadius(8) + } + } +} + +struct SortCaseRowView_Previews: PreviewProvider { + static var previews: some View { + SortCaseRowView(selectedType: .constant(.id), type: .id) + .previewLayout(.fixed(width: 375, height: 50)) + } +} diff --git a/Caps/Views/SortSelectionView.swift b/Caps/Views/SortSelectionView.swift new file mode 100644 index 0000000..b4ac5dd --- /dev/null +++ b/Caps/Views/SortSelectionView.swift @@ -0,0 +1,95 @@ +import SwiftUI + +private extension Binding where Value == SortCriteria { + + func value() -> Binding { + return Binding(get:{ self.wrappedValue.rawValue }, + set: { self.wrappedValue = .init(rawValue: $0)!}) + } +} + + +struct SortSelectionView: View { + + let hasMatches: Bool + + @Binding + var isPresented: Bool + + @Binding + var sortType: SortCriteria + + @Binding + var sortAscending: Bool + + @Binding + var showGridView: Bool + + var body: some View { + VStack(alignment: .leading, spacing: 3) { + HStack { + Text("List Settings").font(.title2).bold() + Spacer() + Button(action: { isPresented = false }) { + Image(systemSymbol: .xmarkCircleFill) + .foregroundColor(.gray) + .font(.system(size: 26)) + } + } + .padding(.bottom) + Text("Sort by") + .font(.footnote) + .textCase(.uppercase) + .foregroundColor(.secondary) + Picker("Sort type", selection: $sortType.value()) { + Text(SortCriteria.id.text).tag(SortCriteria.id.rawValue) + Text(SortCriteria.name.text).tag(SortCriteria.name.rawValue) + Text(SortCriteria.count.text).tag(SortCriteria.count.rawValue) + if hasMatches { + Text(SortCriteria.match.text).tag(SortCriteria.match.rawValue) + } + } + .pickerStyle(SegmentedPickerStyle()) + .padding(.bottom) + Text("Sort order") + .font(.footnote) + .textCase(.uppercase) + .foregroundColor(.secondary) + Picker("Sort order", selection: $sortAscending) { + Text("Ascending").tag(true) + Text("Descending").tag(false) + } + .pickerStyle(SegmentedPickerStyle()) + .padding(.bottom) + HStack { + Spacer() + Button(action: showGrid) { + HStack { + Image(systemSymbol: .circleHexagongrid) + Text("Show grid") + } + }.padding() + Spacer() + } + Spacer() + } + .padding(.horizontal) + } + + private func showGrid() { + showGridView = true + isPresented = false + } +} + +struct SortSelectionView_Previews: PreviewProvider { + static var previews: some View { + SortSelectionView( + hasMatches: true, + isPresented: .constant(true), + sortType: .constant(.id), + sortAscending: .constant(false), + showGridView: .constant(false)) + .previewLayout(.fixed(width: 375, height: 250)) + } +}