From 24e9b90c1682138bf49e33fe68fb39dbdf97f5e9 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Sun, 18 Jun 2023 14:06:55 +0300 Subject: [PATCH] Adding new report sharing variant - copy report url (useful for catalyst) --- AutoCat.xcodeproj/project.pbxproj | 14 ++- .../xcdebugger/Breakpoints_v2.xcbkptlist | 50 +++++++- .../Extensions/UISegmentedControl.swift | 42 +++++++ AutoCat/ACUIKit/Extensions/UIStackView.swift | 43 +++++++ AutoCat/Controllers/NewNumberController.swift | 112 +++++++++++------- AutoCat/Controllers/ReportController.swift | 16 ++- AutoCat/ru.lproj/Localizable.strings | 2 + 7 files changed, 232 insertions(+), 47 deletions(-) create mode 100644 AutoCat/ACUIKit/Extensions/UISegmentedControl.swift create mode 100644 AutoCat/ACUIKit/Extensions/UIStackView.swift diff --git a/AutoCat.xcodeproj/project.pbxproj b/AutoCat.xcodeproj/project.pbxproj index e0cec14..b042c6c 100644 --- a/AutoCat.xcodeproj/project.pbxproj +++ b/AutoCat.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -25,6 +25,8 @@ 7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471523FDEB2A00B424AF /* MainSplitController.swift */; }; 7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471723FDEBFA00B424AF /* ReportController.swift */; }; 7A11471A23FE839000B424AF /* AuthController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471923FE839000B424AF /* AuthController.swift */; }; + 7A17CE4A2A2E820300626A6E /* UIStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A17CE492A2E820300626A6E /* UIStackView.swift */; }; + 7A17CE4C2A2E850200626A6E /* UISegmentedControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A17CE4B2A2E850200626A6E /* UISegmentedControl.swift */; }; 7A1CF80329A41C62007962DA /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A1CF80229A41C62007962DA /* Realm */; }; 7A1CF80529A41C66007962DA /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A1CF80429A41C66007962DA /* RealmSwift */; }; 7A1CF80829A41D58007962DA /* RxBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 7A1CF80729A41D58007962DA /* RxBlocking */; }; @@ -198,6 +200,8 @@ 7A11474A23FF368B00B424AF /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; 7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = ""; }; 7A15051124DB3E3000F39631 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = ""; }; + 7A17CE492A2E820300626A6E /* UIStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIStackView.swift; sourceTree = ""; }; + 7A17CE4B2A2E850200626A6E /* UISegmentedControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UISegmentedControl.swift; sourceTree = ""; }; 7A1CF81529A42117007962DA /* Realm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Realm.swift; sourceTree = ""; }; 7A1DC38D2517ED98002E9C99 /* BlockBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockBarButtonItem.swift; sourceTree = ""; }; 7A21112924FC3D7E003BBF6F /* AudioEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioEngine.swift; sourceTree = ""; }; @@ -611,6 +615,8 @@ 7AC355582969746600889457 /* UIControl.swift */, 7AC3555A296995B200889457 /* UIEdgeInsets.swift */, 7A91894E29A2BD8700519C74 /* GestureRecognizers.swift */, + 7A17CE492A2E820300626A6E /* UIStackView.swift */, + 7A17CE4B2A2E850200626A6E /* UISegmentedControl.swift */, ); path = Extensions; sourceTree = ""; @@ -865,6 +871,7 @@ 7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */, 7A0420B62568650C00034941 /* DkbmController.swift in Sources */, 7A27ADF5249FD2F90035F39E /* FileManagerExt.swift in Sources */, + 7A17CE4A2A2E820300626A6E /* UIStackView.swift in Sources */, 7A1DC38E2517ED98002E9C99 /* BlockBarButtonItem.swift in Sources */, 7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */, 7A27ADF3249F8B650035F39E /* RecordsController.swift in Sources */, @@ -916,6 +923,7 @@ 7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */, 7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */, 7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */, + 7A17CE4C2A2E850200626A6E /* UISegmentedControl.swift in Sources */, 6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1150,7 +1158,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 116; + CURRENT_PROJECT_VERSION = 117; DEVELOPMENT_TEAM = 46DTTB8X4S; INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = AutoCat; @@ -1178,7 +1186,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 116; + CURRENT_PROJECT_VERSION = 117; DEVELOPMENT_TEAM = 46DTTB8X4S; INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = AutoCat; diff --git a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 1359d48..4b18da9 100644 --- a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -8,7 +8,7 @@ BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint"> + + + + + + + + + + diff --git a/AutoCat/ACUIKit/Extensions/UISegmentedControl.swift b/AutoCat/ACUIKit/Extensions/UISegmentedControl.swift new file mode 100644 index 0000000..92826d7 --- /dev/null +++ b/AutoCat/ACUIKit/Extensions/UISegmentedControl.swift @@ -0,0 +1,42 @@ +// +// UISegmentedControl.swift +// AutoCat +// +// Created by Selim Mustafaev on 06.06.2023. +// Copyright © 2023 Selim Mustafaev. All rights reserved. +// + +import UIKit + +extension UISegmentedControl { + + static func segments(titles: [String]) -> UISegmentedControl { + let view = UISegmentedControl(items: titles) + view.translatesAutoresizingMaskIntoConstraints = false + return view + } + + static func segments(images: [UIImage?]) -> UISegmentedControl { + let view = UISegmentedControl(items: images.compactMap { $0 }) + view.translatesAutoresizingMaskIntoConstraints = false + return view + } + + func onValueChanged(_ closure: @escaping (Int) -> Void) -> UISegmentedControl { + addActionImpl(for: .valueChanged) { [weak self] in + guard let index = self?.selectedSegmentIndex else { + return + } + + closure(index) + } + + return self + } + + func select(index: Int) -> UISegmentedControl { + selectedSegmentIndex = index + return self + } +} + diff --git a/AutoCat/ACUIKit/Extensions/UIStackView.swift b/AutoCat/ACUIKit/Extensions/UIStackView.swift new file mode 100644 index 0000000..47a3b30 --- /dev/null +++ b/AutoCat/ACUIKit/Extensions/UIStackView.swift @@ -0,0 +1,43 @@ +// +// UIStackView.swift +// AutoCat +// +// Created by Selim Mustafaev on 05.06.2023. +// Copyright © 2023 Selim Mustafaev. All rights reserved. +// + +import UIKit + +extension UIStackView { + + static func horizontal(_ views: [UIView]) -> UIStackView { + let stack = UIStackView(arrangedSubviews: views) + stack.translatesAutoresizingMaskIntoConstraints = false + stack.axis = .horizontal + stack.spacing = 16 + return stack + } + + static func vertical(_ views: [UIView]) -> UIStackView { + let stack = UIStackView(arrangedSubviews: views) + stack.translatesAutoresizingMaskIntoConstraints = false + stack.axis = .vertical + stack.spacing = 16 + return stack + } + + func spacing(_ spacing: CGFloat) -> UIStackView { + self.spacing = spacing + return self + } + + func alignment(_ alignment: Alignment) -> UIStackView { + self.alignment = alignment + return self + } + + func distribution(_ distribution: Distribution) -> UIStackView { + self.distribution = distribution + return self + } +} diff --git a/AutoCat/Controllers/NewNumberController.swift b/AutoCat/Controllers/NewNumberController.swift index c004b97..53800d5 100644 --- a/AutoCat/Controllers/NewNumberController.swift +++ b/AutoCat/Controllers/NewNumberController.swift @@ -1,9 +1,24 @@ import UIKit import AutoCatCore +// MARK: - Types + +enum NumberType: Int, CaseIterable { + + case plateNumber = 0 + case vin = 1 + + var title: String { + switch self { + case .plateNumber: return "GRZ" + case .vin: return "VIN" + } + } +} + class NewNumberController: UIViewController { - public var onCheck: ((String) -> Void)? + // MARK: - Views private lazy var keyboardView: PNKeyboard = { let keyboard = PNKeyboard(target: self.plateView) @@ -20,6 +35,13 @@ class NewNumberController: UIViewController { view.accessibilityIdentifier = "plateView" return view }() + + private lazy var vinField: UITextField = { + let view = UITextField() + view.translatesAutoresizingMaskIntoConstraints = false + view.isHidden = true + return view + }() private lazy var checkButton: ACButton = { let button = ACButton(title: NSLocalizedString("Check", comment: ""), onTap: check) @@ -28,14 +50,10 @@ class NewNumberController: UIViewController { button.accessibilityIdentifier = "checkButton" return button }() - - private lazy var stackView: UIStackView = { - let stack = UIStackView(arrangedSubviews: [plateView, checkButton]) - stack.axis = .horizontal - stack.spacing = 16 - stack.translatesAutoresizingMaskIntoConstraints = false - return stack - }() + + private lazy var stackView: UIStackView = .horizontal([ + plateView, vinField, checkButton + ]) private let titleLabel: UILabel = { let label = UILabel() @@ -46,42 +64,35 @@ class NewNumberController: UIViewController { return label }() - private lazy var mainStackView: UIStackView = { - let stack = UIStackView(arrangedSubviews: [titleLabel, stackView, settingsStackView, keyboardView]) - stack.axis = .vertical - stack.spacing = 16 - stack.translatesAutoresizingMaskIntoConstraints = false - return stack - }() + private lazy var mainStackView: UIStackView = .vertical([ + titleLabel, + stackView, + //settingsStackView, + keyboardView + ]) - private lazy var locationSwitcherView: UISegmentedControl = { - let view = UISegmentedControl() - view.translatesAutoresizingMaskIntoConstraints = false - view.insertSegment(with: UIImage(systemName: "location.fill"), at: 0, animated: false) - view.insertSegment(with: UIImage(systemName: "location"), at: 1, animated: false) - view.insertSegment(with: UIImage(systemName: "location.slash"), at: 2, animated: false) - return view - }() + private let locationSwitcherView: UISegmentedControl = .segments(images: [ + UIImage(systemName: "location.fill"), + UIImage(systemName: "location"), + UIImage(systemName: "location.slash") + ]) - private lazy var numTypeSwitcherView: UISegmentedControl = { - let view = UISegmentedControl() - view.translatesAutoresizingMaskIntoConstraints = false - view.insertSegment(withTitle: "ГРЗ", at: 0, animated: false) - view.insertSegment(withTitle: "VIN", at: 1, animated: false) - view.selectedSegmentIndex = 0 - view.isEnabled = false - return view - }() + private lazy var numTypeSwitcherView: UISegmentedControl = .segments(titles: NumberType.allCases.map(\.title)) + .select(index: NumberType.plateNumber.rawValue) + .onValueChanged(onNumberTypeChanged) - private lazy var settingsStackView: UIStackView = { - let stack = UIStackView(arrangedSubviews: [numTypeSwitcherView, locationSwitcherView]) - stack.axis = .horizontal - stack.spacing = 16 - stack.distribution = .fillProportionally - stack.translatesAutoresizingMaskIntoConstraints = false - stack.isHidden = true - return stack - }() + private lazy var settingsStackView: UIStackView = .horizontal([ + numTypeSwitcherView, + locationSwitcherView + ]) + .distribution(.fillProportionally) + + // MARK: - Variables + + public var onCheck: ((String) -> Void)? + private var numberType: NumberType = .plateNumber + + // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() @@ -108,6 +119,23 @@ class NewNumberController: UIViewController { func onNumberChanged() { checkButton.isEnabled = plateView.number?.isValid ?? false } + + func onNumberTypeChanged(_ index: Int) { + guard let type = NumberType(rawValue: index) else { + return + } + + numberType = type + + switch type { + case .plateNumber: + plateView.isHidden = false + vinField.isHidden = true + case .vin: + plateView.isHidden = true + vinField.isHidden = false + } + } } extension NewNumberController: PNKeyboardDelegate { diff --git a/AutoCat/Controllers/ReportController.swift b/AutoCat/Controllers/ReportController.swift index 9caafc9..0b9bf09 100644 --- a/AutoCat/Controllers/ReportController.swift +++ b/AutoCat/Controllers/ReportController.swift @@ -5,6 +5,7 @@ import RealmSwift import Eureka import AutoCatCore import SwiftEntryKit +import MobileCoreServices class ReportController: FormViewController, MediaBrowserViewControllerDataSource, MediaBrowserViewControllerDelegate, UIActivityItemSource { @@ -348,16 +349,29 @@ class ReportController: FormViewController, MediaBrowserViewControllerDataSource let shareLink = UIAlertAction(title: NSLocalizedString("As link", comment: ""), style: .default) { _ in guard let vehicle = self.vehicle else { return } - if let jwt = try? JWT.generate(for: vehicle.getNumber()), let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) { + if let jwt = try? JWT.generate(for: vehicle.getNumber()), + let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) + { let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil) controller.popoverPresentationController?.barButtonItem = sender self.present(controller, animated: true) } } + let copyLink = UIAlertAction(title: NSLocalizedString("Copy link to report", comment: ""), style: .default) { _ in + guard let vehicle = self.vehicle else { return } + + if let jwt = try? JWT.generate(for: vehicle.getNumber()), + let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) + { + UIPasteboard.general.string = url.absoluteString + } + } + sheet.addAction(shareImage) sheet.addAction(shareTextAndImage) sheet.addAction(shareLink) + sheet.addAction(copyLink) sheet.addAction(cancel) self.present(sheet, animated: true, completion: nil) } diff --git a/AutoCat/ru.lproj/Localizable.strings b/AutoCat/ru.lproj/Localizable.strings index 7ca4cac..e04f531 100644 --- a/AutoCat/ru.lproj/Localizable.strings +++ b/AutoCat/ru.lproj/Localizable.strings @@ -403,3 +403,5 @@ /* No comment provided by engineer. */ "ZIP (or OKTMO) code" = "Индекс (или ОКТМО)"; +/* No comment provided by engineer. */ +"Copy link to report" = "Копировать ссылку на отчет";