├── Podfile
├── BarcodeScanner
├── Supporting Files
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-1024.png
│ │ │ ├── Icon-20.png
│ │ │ ├── Icon-29.png
│ │ │ ├── Icon-40.png
│ │ │ ├── Icon-76.png
│ │ │ ├── Icon-20@2x.png
│ │ │ ├── Icon-20@3x.png
│ │ │ ├── Icon-29@2x.png
│ │ │ ├── Icon-29@3x.png
│ │ │ ├── Icon-40@2x.png
│ │ │ ├── Icon-40@3x.png
│ │ │ ├── Icon-60@2x.png
│ │ │ ├── Icon-60@3x.png
│ │ │ ├── Icon-76@2x.png
│ │ │ ├── Icon-83.5@2x.png
│ │ │ └── Contents.json
│ ├── Font
│ │ ├── ProximaNovaExCn-Bold.ttf
│ │ ├── ProximaNovaExCn-Light.ttf
│ │ ├── ProximaNovaExCn-Thin.ttf
│ │ └── ProximaNovaExCn-Regular.ttf
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── AppDelegate.swift
│ ├── SceneDelegate.swift
│ └── Info.plist
├── Common
│ ├── Components
│ │ ├── STCamera
│ │ │ ├── FlashlightStatus.swift
│ │ │ ├── STScanArea.swift
│ │ │ └── STCamera.swift
│ │ ├── STAlert
│ │ │ └── STAlert.swift
│ │ └── STModal
│ │ │ └── STModal.swift
│ ├── Extensions
│ │ ├── UIView.swift
│ │ └── UIViewController.swift
│ └── Services
│ │ └── Network
│ │ └── NetworkService.swift
└── Modules
│ ├── Main
│ ├── Builder
│ │ └── MainBuilder.swift
│ ├── Router
│ │ └── MainRouter.swift
│ ├── Presenter
│ │ └── MainPresenter.swift
│ └── View
│ │ ├── MainViewController.swift
│ │ └── MainViewController.xib
│ ├── Error
│ ├── Builder
│ │ └── ErrorBuilder.swift
│ ├── Presenter
│ │ └── ErrorPresenter.swift
│ ├── Model
│ │ └── NetworkError.swift
│ └── View
│ │ ├── ErrorViewController.swift
│ │ └── ErrorViewController.xib
│ └── Product
│ ├── Builder
│ └── ProductBuilder.swift
│ ├── Model
│ └── Product.swift
│ ├── Presenter
│ └── ProductPresenter.swift
│ └── View
│ ├── ProductViewController.swift
│ └── ProductViewController.xib
├── .gitignore
├── BarcodeScanner.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── IDETemplateMacros.plist
├── Podfile.lock
├── LICENSE.txt
├── README.md
└── BarcodeScanner.xcodeproj
└── project.pbxproj
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '13.0'
2 |
3 | target 'BarcodeScanner' do
4 |
5 | pod 'SwiftEntryKit'
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pbxuser
3 | *.mode1v3
4 | *.mode2v3
5 | *.perspectivev3
6 | *.xcuserstate
7 | project.xcworkspace/
8 | xcuserdata/
9 | Pods/
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Bold.ttf
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Light.ttf
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Thin.ttf
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Font/ProximaNovaExCn-Regular.ttf
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-1024.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-20.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-29.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onl1ner/BarcodeScanner/HEAD/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/BarcodeScanner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BarcodeScanner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - QuickLayout (3.0.0)
3 | - SwiftEntryKit (1.2.3):
4 | - QuickLayout (= 3.0.0)
5 |
6 | DEPENDENCIES:
7 | - SwiftEntryKit
8 |
9 | SPEC REPOS:
10 | trunk:
11 | - QuickLayout
12 | - SwiftEntryKit
13 |
14 | SPEC CHECKSUMS:
15 | QuickLayout: 07b45a72b10083fee3f095990cfed1c1e7b27f0a
16 | SwiftEntryKit: 340713c2e4a6662c5149629990bf1088bf5f0389
17 |
18 | PODFILE CHECKSUM: 533cf2b58c9fd8d51c0fc541c894245268a17d8a
19 |
20 | COCOAPODS: 1.10.1
21 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Tamerlan Satualdypov
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included
12 | in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Components/STCamera/FlashlightStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import Foundation
25 |
26 | enum FlashlightStatus {
27 | case on
28 | case off
29 |
30 | case notFound
31 | case notInitialized
32 | }
33 |
--------------------------------------------------------------------------------
/BarcodeScanner.xcworkspace/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 |
7 | // MIT License
8 | //
9 | // Copyright (c) 2021 Tamerlan Satualdypov
10 | //
11 | // Permission is hereby granted, free of charge, to any person obtaining a copy
12 | // of this software and associated documentation files (the "Software"), to deal
13 | // in the Software without restriction, including without limitation the rights
14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | // copies of the Software, and to permit persons to whom the Software is
16 | // furnished to do so, subject to the following conditions:
17 | //
18 | // The above copyright notice and this permission notice shall be included in all
19 | // copies or substantial portions of the Software.
20 | //
21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | // SOFTWARE.
28 |
29 |
30 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Extensions/UIView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | extension UIView {
27 |
28 | public func setupShadow(withColor color : UIColor, opacity : Float, offset : CGSize) -> () {
29 | self.layer.shadowColor = color.cgColor
30 | self.layer.shadowOpacity = opacity
31 | self.layer.shadowOffset = offset
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Extensions/UIViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | extension UIViewController {
27 |
28 | public func showAlert(title: String, message: String) -> () {
29 | let alert = STAlert(title: title, message: message, preferredStyle: .alert)
30 | .addCancel(title: "Понятно")
31 | .prepared()
32 |
33 | self.present(alert, animated: true)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Main/Builder/MainBuilder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import Foundation
25 |
26 | final class MainBuilder {
27 |
28 | public static func build() -> MainViewController {
29 | let view = MainViewController()
30 | let router = MainRouter(view: view)
31 | let presenter = MainPresenter(view: view, router: router)
32 |
33 | view.presenter = presenter
34 |
35 | return view
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Error/Builder/ErrorBuilder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import Foundation
25 |
26 | final class ErrorBuilder {
27 |
28 | public static func build(with error: NetworkError, delegate: STModalDelegate?) -> STModal {
29 | let view = ErrorViewController()
30 | let presenter = ErrorPresenter(view: view, error: error)
31 |
32 | view.presenter = presenter
33 |
34 | return .init(view: view, delegate: delegate)
35 | .set(width: .offset(value: 16.0))
36 | .set(height: .intrinsic)
37 | .set(verticalOffset: 32.0)
38 | .set(position: .bottom)
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Product/Builder/ProductBuilder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import Foundation
25 |
26 | final class ProductBuilder {
27 |
28 | public static func build(with product: Product, delegate: STModalDelegate?) -> STModal {
29 | let view = ProductViewController()
30 | let presenter = ProductPresenter(view: view, product: product)
31 |
32 | view.presenter = presenter
33 |
34 | return .init(view: view, delegate: delegate)
35 | .set(width: .offset(value: 16.0))
36 | .set(height: .intrinsic)
37 | .set(verticalOffset: 32.0)
38 | .set(position: .bottom)
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | @UIApplicationMain
27 | class AppDelegate: UIResponder, UIApplicationDelegate {
28 |
29 | public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
30 | return true
31 | }
32 |
33 | public func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
34 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
35 | }
36 |
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
27 |
28 | public var window: UIWindow?
29 |
30 | public func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
31 | guard let windowScene = (scene as? UIWindowScene) else { return }
32 |
33 | self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
34 | self.window?.windowScene = windowScene
35 |
36 | self.window?.rootViewController = MainBuilder.build()
37 | self.window?.makeKeyAndVisible()
38 | }
39 |
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Error/Presenter/ErrorPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 | import Foundation
24 |
25 | protocol ErrorPresenterProtocol {
26 | func viewDidLoad() -> ()
27 | init(view : ErrorViewControllerProtocol, error : NetworkError)
28 | }
29 |
30 | final class ErrorPresenter : ErrorPresenterProtocol {
31 |
32 | private weak var view: ErrorViewControllerProtocol?
33 | private var error: NetworkError
34 |
35 | public func viewDidLoad() -> () {
36 | self.view?.set(image: self.error.image)
37 | self.view?.set(title: self.error.title)
38 | self.view?.set(message: self.error.message)
39 | }
40 |
41 | init(view: ErrorViewControllerProtocol, error: NetworkError) {
42 | self.view = view
43 | self.error = error
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Product/Model/Product.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | struct Product {
27 | let classification : String
28 | let name : String
29 | let barcode : String
30 |
31 | let image : UIImage?
32 |
33 | /// Структура для сериализации JSON-a возвращающий название продукта
34 | struct Name : Decodable {
35 | let status : Int
36 | let names : [String]
37 | }
38 |
39 | /// Структура для сериализации JSON-a возвращающий классификатор продукта
40 | struct Class : Decodable {
41 | let status : Int
42 | let classification : [String]
43 |
44 | enum CodingKeys : String, CodingKey {
45 | case status
46 | case classification = "class"
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Product/Presenter/ProductPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import Foundation
25 |
26 | protocol ProductPresenterProtocol {
27 | func viewDidLoad() -> ()
28 | init(view: ProductViewControllerProtocol, product: Product)
29 | }
30 |
31 | final class ProductPresenter : ProductPresenterProtocol {
32 |
33 | private weak var view: ProductViewControllerProtocol?
34 | private var product: Product
35 |
36 | public func viewDidLoad() -> () {
37 | self.view?.set(image: self.product.image)
38 | self.view?.set(classification: self.product.classification)
39 | self.view?.set(name: self.product.name)
40 | self.view?.set(barcode: self.product.barcode)
41 | }
42 |
43 | init(view: ProductViewControllerProtocol, product: Product) {
44 | self.view = view
45 | self.product = product
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ## What is it?
4 | **BarcodeScanner – simple & easy application that helps you to scan both EAN8 and EAN13 barcodes.**
5 |
6 | ## How the app works
7 | To scan a barcode simply point the camera at the code and you are done! No need to press a button or take a photo. Application will automaticaly recognise the code your camera pointing at.
8 |
9 | BarcodeScanner will give you information related to scanned product. Name of the product, it's class(if classified) and product's photo. To recognise the name and class application uses API of [OlegON's database](https://barcodes.olegon.ru "OlegON's database"). The photos are simply downloaded from Google via their [Google Custom Search API](https://developers.google.com/custom-search "Google Custom Search API").
10 |
11 | ## License
12 | This application is distributed under the terms and conditions of the MIT license.
13 | ```
14 | Copyright (c) 2021 Tamerlan Satualdypov
15 |
16 | Permission is hereby granted, free of charge, to any person obtaining
17 | a copy of this software and associated documentation files (the
18 | "Software"), to deal in the Software without restriction, including
19 | without limitation the rights to use, copy, modify, merge, publish,
20 | distribute, sublicense, and/or sell copies of the Software, and to
21 | permit persons to whom the Software is furnished to do so, subject to
22 | the following conditions:
23 |
24 | The above copyright notice and this permission notice shall be included
25 | in all copies or substantial portions of the Software.
26 |
27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
30 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
31 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
32 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
33 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Main/Router/MainRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import SwiftEntryKit
26 |
27 | protocol MainRouterProtocol {
28 | func show(product: Product) -> ()
29 | func show(error: NetworkError) -> ()
30 |
31 | init(view: MainViewController)
32 | }
33 |
34 | final class MainRouter: MainRouterProtocol {
35 |
36 | private weak var view : MainViewController?
37 |
38 | public func show(product: Product) -> () {
39 | let modal = ProductBuilder.build(with: product, delegate: self.view)
40 | SwiftEntryKit.display(entry: modal.view, using: modal.attributes)
41 | }
42 |
43 | public func show(error: NetworkError) -> () {
44 | let modal = ErrorBuilder.build(with: error, delegate: self.view)
45 | SwiftEntryKit.display(entry: modal.view, using: modal.attributes)
46 | }
47 |
48 | init(view: MainViewController) {
49 | self.view = view
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSCameraUsageDescription
24 | Разрешите доступ к камере, чтобы вы могли сканировать штрихкоды!
25 | UIApplicationSceneManifest
26 |
27 | UIApplicationSupportsMultipleScenes
28 |
29 | UISceneConfigurations
30 |
31 | UIWindowSceneSessionRoleApplication
32 |
33 |
34 | UISceneConfigurationName
35 | Default Configuration
36 | UISceneDelegateClassName
37 | $(PRODUCT_MODULE_NAME).SceneDelegate
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Error/Model/NetworkError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | enum NetworkError: Error {
27 | case notFound
28 | case transportError(Error)
29 | case badRequest
30 | case unexpected
31 |
32 | public var title: String {
33 | return "Произошла ошибка"
34 | }
35 |
36 | public var message: String {
37 | switch self {
38 | case .notFound: return "Похоже, что в базе данных не нашлось продуктов с подходящим штрихкодом."
39 | case .transportError(let error as NSError): return "Произошла ошибка при отправке данных на сервер. Код: \(error.code)"
40 | case .badRequest, .unexpected: return "Произошла непредвиденная ошибка."
41 | }
42 | }
43 |
44 | public var image: UIImage? {
45 | switch self {
46 | case .notFound: return .init(systemName: "tray.and.arrow.up")
47 | case .transportError(_): return .init(systemName: "wifi.exclamationmark")
48 | case .badRequest, .unexpected: return .init(systemName: "barcode.viewfinder")
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Main/Presenter/MainPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | protocol MainPresenterProtocol {
27 | func product(for barcode: String) -> ()
28 |
29 | init(view: MainViewControllerProtocol, router: MainRouterProtocol)
30 | }
31 |
32 | final class MainPresenter: MainPresenterProtocol {
33 |
34 | private weak var view: MainViewControllerProtocol?
35 | private var router: MainRouterProtocol
36 |
37 | public func product(for barcode: String) -> () {
38 | self.view?.stopInput()
39 | self.view?.startLoading()
40 |
41 | NetworkService.shared.product(for: barcode) { result in
42 | self.view?.stopLoading()
43 |
44 | switch result {
45 | case .success(let product): self.router.show(product: product)
46 | case .failure(let error): self.router.show(error: error)
47 | }
48 | }
49 | }
50 |
51 | init(view: MainViewControllerProtocol, router: MainRouterProtocol) {
52 | self.view = view
53 | self.router = router
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Error/View/ErrorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import SwiftEntryKit
26 |
27 | protocol ErrorViewControllerProtocol: AnyObject {
28 | func set(image : UIImage?)
29 | func set(title : String) -> ()
30 | func set(message : String) -> ()
31 | }
32 |
33 | final class ErrorViewController: UIViewController, ErrorViewControllerProtocol {
34 |
35 | @IBOutlet private weak var imageView: UIImageView!
36 |
37 | @IBOutlet private weak var titleLabel: UILabel!
38 | @IBOutlet private weak var messageLabel: UILabel!
39 |
40 | public var presenter : ErrorPresenterProtocol!
41 |
42 | @IBAction private func dismissPressed(_ sender: UIButton) -> () {
43 | SwiftEntryKit.dismiss()
44 | }
45 |
46 | public func set(image: UIImage?) -> () {
47 | self.imageView.image = image
48 | }
49 |
50 | public func set(title: String) -> () {
51 | self.titleLabel.text = title
52 | }
53 |
54 | public func set(message: String) -> () {
55 | self.messageLabel.text = message
56 | }
57 |
58 | override public func viewDidLoad() -> () {
59 | super.viewDidLoad()
60 |
61 | self.view.layer.cornerRadius = 16
62 | self.presenter.viewDidLoad()
63 | }
64 |
65 | }
66 |
67 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Components/STAlert/STAlert.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | final class STAlert {
27 |
28 | private var actionSheetController : UIAlertController
29 |
30 | public func prepared() -> UIAlertController {
31 | return self.actionSheetController
32 | }
33 |
34 | public func addAction(title: String, style: UIAlertAction.Style, actionHandler: ((UIAlertAction) -> ())?) -> Self {
35 | let action = UIAlertAction(title: title, style: style, handler: actionHandler)
36 | self.actionSheetController.addAction(action)
37 | return self
38 | }
39 |
40 | public func addCancel(title: String = "Cancel") -> Self {
41 | let cancelAction = UIAlertAction(title: title, style: .cancel, handler: nil)
42 | self.actionSheetController.addAction(cancelAction)
43 | return self
44 | }
45 |
46 | public convenience init(error: NSError) {
47 | self.init(title: "Error", message: "\(error.domain). Code: \(error.code)", preferredStyle: .alert)
48 |
49 | let action = UIAlertAction(title: "Ok", style: .cancel, handler: { _ in
50 | self.actionSheetController.dismiss(animated: true, completion: nil)
51 | })
52 |
53 | self.actionSheetController.addAction(action)
54 | }
55 |
56 | public init(title: String? = nil, message: String? = nil, preferredStyle: UIAlertController.Style) {
57 | self.actionSheetController = .init(title: title, message: message, preferredStyle: preferredStyle)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/BarcodeScanner/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom": "iphone",
6 | "filename" : "Icon-20@2x.png",
7 | "scale": "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom": "iphone",
12 | "filename" : "Icon-20@3x.png",
13 | "scale": "3x"
14 | },
15 | {
16 | "size" : "20x20",
17 | "idiom": "ipad",
18 | "filename" : "Icon-20.png",
19 | "scale": "1x"
20 | },
21 | {
22 | "size" : "20x20",
23 | "idiom": "ipad",
24 | "filename" : "Icon-20@2x.png",
25 | "scale": "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-29@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "29x29",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-29@3x.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-40@2x.png",
43 | "scale" : "2x"
44 | },
45 | {
46 | "size" : "40x40",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-40@3x.png",
49 | "scale" : "3x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-60@2x.png",
55 | "scale" : "2x"
56 | },
57 | {
58 | "size" : "60x60",
59 | "idiom" : "iphone",
60 | "filename" : "Icon-60@3x.png",
61 | "scale" : "3x"
62 | },
63 | {
64 | "size" : "29x29",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-29.png",
67 | "scale" : "1x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-29@2x.png",
73 | "scale" : "2x"
74 | },
75 | {
76 | "size" : "40x40",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-40.png",
79 | "scale" : "1x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-40@2x.png",
85 | "scale" : "2x"
86 | },
87 | {
88 | "size" : "76x76",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-76.png",
91 | "scale" : "1x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-76@2x.png",
97 | "scale" : "2x"
98 | },
99 | {
100 | "size" : "83.5x83.5",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-83.5@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "1024x1024",
107 | "idiom" : "ios-marketing",
108 | "filename" : "Icon-1024.png",
109 | "scale" : "1x"
110 | }
111 | ],
112 | "info" : {
113 | "version" : 1,
114 | "author" : "xcode"
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Components/STModal/STModal.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import SwiftEntryKit
26 |
27 | protocol STModalDelegate {
28 | func modalDidDisappear() -> ()
29 | }
30 |
31 | final class STModal {
32 |
33 | public private(set) var view: UIViewController
34 | public private(set) var attributes: EKAttributes
35 |
36 | private var delegate: STModalDelegate?
37 |
38 | private func setDefaultAttributes() -> () {
39 | self.attributes.screenBackground = .color(color: .black.with(alpha: 0.25))
40 | self.attributes.displayDuration = .infinity
41 |
42 | self.attributes.entryInteraction = .absorbTouches
43 | self.attributes.screenInteraction = .dismiss
44 |
45 | self.attributes.lifecycleEvents.didDisappear = self.delegate?.modalDidDisappear
46 | }
47 |
48 | public func set(position: EKAttributes.Position) -> Self {
49 | self.attributes.position = position
50 | return self
51 | }
52 |
53 | public func set(verticalOffset: CGFloat) -> Self {
54 | self.attributes.positionConstraints.verticalOffset = verticalOffset
55 | return self
56 | }
57 |
58 | public func set(width: EKAttributes.PositionConstraints.Edge) -> Self {
59 | self.attributes.positionConstraints.size.width = width
60 | return self
61 | }
62 |
63 | public func set(height: EKAttributes.PositionConstraints.Edge) -> Self {
64 | self.attributes.positionConstraints.size.height = height
65 | return self
66 | }
67 |
68 | public init(view: UIViewController, delegate: STModalDelegate? = nil) {
69 | self.view = view
70 | self.attributes = .init()
71 |
72 | self.delegate = delegate
73 |
74 | self.setDefaultAttributes()
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Product/View/ProductViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import SwiftEntryKit
26 |
27 | protocol ProductViewControllerProtocol: AnyObject {
28 | func set(image: UIImage?) -> ()
29 | func set(classification: String) -> ()
30 | func set(name: String) -> ()
31 | func set(barcode: String) -> ()
32 | }
33 |
34 | final class ProductViewController: UIViewController, ProductViewControllerProtocol {
35 |
36 | @IBOutlet private weak var imageBackView: UIView!
37 | @IBOutlet private weak var imageView: UIImageView!
38 |
39 | @IBOutlet private weak var classLabel: UILabel!
40 | @IBOutlet private weak var nameLabel: UILabel!
41 |
42 | @IBOutlet private weak var barcodeBackView: UIView!
43 | @IBOutlet private weak var barcodeLabel: UILabel!
44 |
45 | public var presenter: ProductPresenterProtocol!
46 |
47 | @IBAction private func dismissPressed(_ sender: UIButton) -> () {
48 | SwiftEntryKit.dismiss()
49 | }
50 |
51 | public func set(image: UIImage?) -> () {
52 | self.imageView.image = image
53 | }
54 |
55 | public func set(classification: String) -> () {
56 | self.classLabel.text = classification
57 | }
58 |
59 | public func set(name: String) -> () {
60 | self.nameLabel.text = name
61 | }
62 |
63 | public func set(barcode: String) -> () {
64 | self.barcodeLabel.text = barcode
65 | }
66 |
67 | override public func viewDidLoad() -> () {
68 | super.viewDidLoad()
69 |
70 | self.view.layer.cornerRadius = 16
71 |
72 | self.imageBackView.layer.cornerRadius = 20
73 |
74 | self.barcodeBackView.layer.cornerRadius = 16
75 | self.imageView.layer.cornerRadius = 16
76 |
77 | self.imageBackView.setupShadow(withColor: .black, opacity: 0.2, offset: .zero)
78 | self.barcodeBackView.setupShadow(withColor: .black, opacity: 0.2, offset: .zero)
79 |
80 | self.presenter.viewDidLoad()
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Components/STCamera/STScanArea.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import CoreGraphics
26 |
27 | final class STScanArea : UIView {
28 |
29 | public var sizeMultiplier : CGFloat = 0.2 {
30 | didSet{
31 | self.draw(self.bounds)
32 | }
33 | }
34 |
35 | public var lineWidth : CGFloat = 5 {
36 | didSet{
37 | self.draw(self.bounds)
38 | }
39 | }
40 |
41 | public var lineColor : UIColor = UIColor.white {
42 | didSet{
43 | self.draw(self.bounds)
44 | }
45 | }
46 |
47 | private func drawCorners() -> () {
48 | /// Углы прямоугольника рисуются по часовой стрелке начиная с левого верхнего угла
49 |
50 | let currentContext = UIGraphicsGetCurrentContext()
51 |
52 | currentContext?.setLineWidth(lineWidth)
53 | currentContext?.setStrokeColor(lineColor.cgColor)
54 |
55 | /// Первая часть левого верхнего угла
56 | currentContext?.beginPath()
57 | currentContext?.move(to: CGPoint(x: 0, y: 0))
58 | currentContext?.addLine(to: CGPoint(x: self.bounds.size.width * sizeMultiplier, y: 0))
59 | currentContext?.strokePath()
60 |
61 | /// Правый верхний угол
62 | currentContext?.beginPath()
63 | currentContext?.move(to: CGPoint(x: self.bounds.size.width - self.bounds.size.width * sizeMultiplier, y: 0))
64 | currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: 0))
65 | currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height * sizeMultiplier))
66 | currentContext?.strokePath()
67 |
68 | /// Правый нижний угол
69 | currentContext?.beginPath()
70 | currentContext?.move(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height - self.bounds.size.height * sizeMultiplier))
71 | currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height))
72 | currentContext?.addLine(to: CGPoint(x: self.bounds.size.width - self.bounds.size.width * sizeMultiplier, y: self.bounds.size.height))
73 | currentContext?.strokePath()
74 |
75 | /// Левый нижний угол
76 | currentContext?.beginPath()
77 | currentContext?.move(to: CGPoint(x: self.bounds.size.width * sizeMultiplier, y: self.bounds.size.height))
78 | currentContext?.addLine(to: CGPoint(x: 0, y: self.bounds.size.height))
79 | currentContext?.addLine(to: CGPoint(x: 0, y: self.bounds.size.height - self.bounds.size.height * sizeMultiplier))
80 | currentContext?.strokePath()
81 |
82 | /// Вторая часть левого верхнего угла
83 | currentContext?.beginPath()
84 | currentContext?.move(to: CGPoint(x: 0, y: self.bounds.size.height * sizeMultiplier))
85 | currentContext?.addLine(to: CGPoint(x: 0, y: 0))
86 | currentContext?.strokePath()
87 | }
88 |
89 | override public func draw(_ rect: CGRect) -> Void {
90 | super.draw(rect)
91 | self.drawCorners()
92 | }
93 |
94 | override init(frame: CGRect) {
95 | super.init(frame: frame)
96 | self.backgroundColor = UIColor.clear
97 | }
98 |
99 | required init?(coder: NSCoder) {
100 | super.init(coder: coder)
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Main/View/MainViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import SwiftEntryKit
26 |
27 | protocol MainViewControllerProtocol: AnyObject, STModalDelegate {
28 | func stopInput() -> ()
29 |
30 | func startLoading() -> ()
31 | func stopLoading() -> ()
32 | }
33 |
34 | final class MainViewController: UIViewController, MainViewControllerProtocol {
35 |
36 | @IBOutlet private weak var toggleFlashlightButton : UIButton!
37 |
38 | @IBOutlet private weak var blurEffectView : UIVisualEffectView!
39 | @IBOutlet private weak var activityIndicator : UIActivityIndicatorView!
40 |
41 | private lazy var camera : STCameraProtocol = STCamera(frame: self.view.layer.bounds, delegate: self)
42 |
43 | public var presenter : MainPresenterProtocol!
44 |
45 | @IBAction private func toggleFlashlight(_ sender: UIButton) -> () {
46 | let status = self.camera.toggleFlashlight()
47 |
48 | switch status {
49 | case .on: sender.setImage(UIImage(systemName: "bolt.slash.circle.fill"), for: .normal)
50 | case .off: sender.setImage(UIImage(systemName: "bolt.circle.fill"), for: .normal)
51 | case .notFound: self.showAlert(title: "Произошла ошибка", message: "Похоже, что на вашем устройстве нет фонарика.")
52 | case .notInitialized: self.showAlert(title: "Произошла ошибка", message: "Не удалось переключить фонарик. Попробуйте еще раз.")
53 | }
54 | }
55 |
56 | private func createCamera() -> () {
57 | guard let cameraLayer = self.camera.layer else { return }
58 | self.view.layer.addSublayer(cameraLayer)
59 |
60 | self.camera.start()
61 | }
62 |
63 | private func startInput() -> () {
64 | self.camera.start()
65 |
66 | UIView.animate(withDuration: 0.2) {
67 | self.blurEffectView.alpha = 0.0
68 | } completion: { _ in
69 | self.blurEffectView.isHidden = true
70 | }
71 | }
72 |
73 | public func startLoading() -> () {
74 | self.activityIndicator.startAnimating()
75 | }
76 |
77 | public func stopLoading() -> () {
78 | self.activityIndicator.stopAnimating()
79 | }
80 |
81 | public func stopInput() -> () {
82 | self.blurEffectView.isHidden = false
83 |
84 | UIView.animate(withDuration: 0.2) {
85 | self.blurEffectView.alpha = 1.0
86 | }
87 |
88 | self.camera.stop()
89 | }
90 |
91 | override public func viewDidLoad() -> () {
92 | super.viewDidLoad()
93 |
94 | self.createCamera()
95 |
96 | self.view.bringSubviewToFront(self.toggleFlashlightButton)
97 | self.view.bringSubviewToFront(self.blurEffectView)
98 | }
99 |
100 | override public func viewDidLayoutSubviews() -> () {
101 | super.viewDidLayoutSubviews()
102 | self.camera.frame = view.layer.bounds
103 | }
104 | }
105 |
106 | extension MainViewController: STCameraDelegate {
107 |
108 | public func scanned(barcode: String) -> () {
109 | self.presenter.product(for: barcode)
110 | }
111 |
112 | }
113 |
114 | extension MainViewController: STModalDelegate {
115 |
116 | public func modalDidDisappear() -> () {
117 | self.startInput()
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Main/View/MainViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Components/STCamera/STCamera.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 | import AVFoundation
26 |
27 | protocol STCameraDelegate {
28 | func scanned(barcode : String) -> ()
29 | }
30 |
31 | protocol STCameraProtocol : AnyObject {
32 | var layer : AVCaptureVideoPreviewLayer? { get }
33 | var frame : CGRect { get set }
34 |
35 | func start() -> ()
36 | func stop() -> ()
37 |
38 | func toggleFlashlight() -> FlashlightStatus
39 |
40 | init(frame : CGRect, delegate : STCameraDelegate?)
41 | }
42 |
43 | final class STCamera : NSObject, STCameraProtocol {
44 |
45 | private let codeTypes: [AVMetadataObject.ObjectType] = [.ean8, .ean13]
46 |
47 | private var captureSession: AVCaptureSession = .init()
48 | private var delegate: STCameraDelegate?
49 |
50 | private var scanArea: STScanArea = .init(frame: .init(x: 0, y: 0, width: 250.0, height: 100.0))
51 |
52 | public var layer: AVCaptureVideoPreviewLayer?
53 |
54 | public var frame: CGRect {
55 | didSet {
56 | self.layer?.frame = self.frame
57 | self.scanArea.center = self.center
58 | }
59 | }
60 |
61 | public var center: CGPoint {
62 | return .init(x: self.frame.width / 2, y: self.frame.height / 2)
63 | }
64 |
65 | private func configure() -> () {
66 | guard let captureDevice = AVCaptureDevice.default(for: .video) else { return }
67 |
68 | do {
69 | // Добавляем инпут как инстанс класса AVCaptureDeviceInput полученного девайса
70 | let input = try AVCaptureDeviceInput(device: captureDevice)
71 | self.captureSession.addInput(input)
72 |
73 | // Инициализируем оутпут, используя класс AVCaptureMetadataOutput и добавляем в нашу сессию
74 | let captureOutput = AVCaptureMetadataOutput()
75 | self.captureSession.addOutput(captureOutput)
76 |
77 | // Инициализуем наш делегат для получения всех сигналов
78 | captureOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
79 | captureOutput.metadataObjectTypes = self.codeTypes
80 | captureOutput.rectOfInterest = self.scanArea.bounds
81 |
82 | } catch { return }
83 |
84 | // Инициализируем слой с превью видео
85 | self.layer = .init(session: self.captureSession)
86 |
87 | self.layer?.videoGravity = .resizeAspectFill
88 | self.layer?.frame = self.frame
89 |
90 | self.layer?.addSublayer(self.scanArea.layer)
91 | }
92 |
93 | public func stop() -> () {
94 | self.captureSession.stopRunning()
95 | }
96 |
97 | public func start() -> () {
98 | self.captureSession.startRunning()
99 | }
100 |
101 | public func toggleFlashlight() -> FlashlightStatus {
102 | guard let captureDevice = AVCaptureDevice.default(for: .video) else { return .notInitialized }
103 |
104 | if captureDevice.hasTorch {
105 | do {
106 | try captureDevice.lockForConfiguration()
107 | captureDevice.torchMode = captureDevice.torchMode == .off ? .on : .off
108 | captureDevice.unlockForConfiguration()
109 |
110 | return captureDevice.torchMode == .on ? .on : .off
111 | } catch let error {
112 | print("Cannot toggle flashlight: \(error.localizedDescription)")
113 | return .notInitialized
114 | }
115 | } else { return .notFound }
116 | }
117 |
118 | init(frame: CGRect, delegate: STCameraDelegate?) {
119 | self.frame = frame
120 | self.delegate = delegate
121 |
122 | super.init()
123 |
124 | self.configure()
125 | }
126 | }
127 |
128 | extension STCamera : AVCaptureMetadataOutputObjectsDelegate {
129 | public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) -> () {
130 |
131 | guard !metadataObjects.isEmpty,
132 | let metadataObj = metadataObjects.first as? AVMetadataMachineReadableCodeObject
133 | else { return }
134 |
135 | if self.codeTypes.contains(metadataObj.type) {
136 | if let barcode = metadataObj.stringValue {
137 | self.delegate?.scanned(barcode: barcode)
138 | }
139 | }
140 |
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/BarcodeScanner/Common/Services/Network/NetworkService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MIT License
3 | //
4 | // Copyright (c) 2021 Tamerlan Satualdypov
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy
7 | // of this software and associated documentation files (the "Software"), to deal
8 | // in the Software without restriction, including without limitation the rights
9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | // copies of the Software, and to permit persons to whom the Software is
11 | // furnished to do so, subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | // SOFTWARE.
23 |
24 | import UIKit
25 |
26 | protocol NetworkServiceProtocol {
27 | func product(for barcode : String, completion: @escaping (Result) -> ()) -> ()
28 | }
29 |
30 | final class NetworkService : NetworkServiceProtocol {
31 |
32 | public static let shared : NetworkServiceProtocol = NetworkService()
33 |
34 | private let barcodeBase : String = "https://barcodes.olegon.ru/api/card/"
35 |
36 | private let imageBase : String = "https://www.googleapis.com/customsearch/v1"
37 | private let imageKey : String = "YOUR-API-KEY"
38 | private let imageEngineKey : String = "YOUR-SEARCH-ENGINE-KEY"
39 |
40 | private func deserialize(data : Data, as objectType : T.Type) -> T? {
41 | return try? JSONDecoder().decode(objectType, from: data)
42 | }
43 |
44 | private func createDataTask(with url: URL?, completion: @escaping (Data?, URLResponse?, Error?) -> ()) -> () {
45 | guard let url = url else { return }
46 | URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
47 | }
48 |
49 | private func processDataTask(data: Data?, response: URLResponse?, error: Error?) -> Result {
50 | if let error = error {
51 | return .failure(.transportError(error))
52 | }
53 |
54 | switch (response as! HTTPURLResponse).statusCode {
55 | case 400: return .failure(.badRequest)
56 | case 404: return .failure(.notFound)
57 | case 429: return .failure(.unexpected)
58 | default: break
59 | }
60 |
61 | if let data = data {
62 | if let deserialized = self.deserialize(data: data, as: T.self) {
63 | return .success(deserialized)
64 | }
65 | }
66 |
67 | return .failure(.unexpected)
68 | }
69 |
70 | private func image(from url: URL?, completion: @escaping (UIImage?) -> ()) -> () {
71 | self.createDataTask(with: url) { data, _, error in
72 | guard error == nil, let data = data else { return completion(nil) }
73 | completion(.init(data: data))
74 | }
75 | }
76 |
77 | private func productImage(for barcode : String, completion: @escaping (UIImage?) -> ()) -> () {
78 | let queryParameters = [URLQueryItem(name: "key", value: self.imageKey),
79 | URLQueryItem(name: "cx", value: self.imageEngineKey),
80 | URLQueryItem(name: "searchType", value: "image"),
81 | URLQueryItem(name: "q", value: barcode),
82 | URLQueryItem(name: "fields", value: "items(link)")]
83 |
84 | var components = URLComponents(string: self.imageBase)
85 | components?.queryItems = queryParameters
86 |
87 | self.createDataTask(with: components?.url) { data, response, error in
88 | if let data = data {
89 | guard let object = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
90 | let dictionary = object as? [String : Any],
91 | let items = dictionary["items"] as? NSArray,
92 | let item = items.firstObject as? [String : String],
93 | let link = item["link"]
94 | else { return completion(nil) }
95 |
96 | self.image(from: URL(string: link), completion: completion)
97 | }
98 | }
99 | }
100 |
101 | private func productName(for barcode: String, completion: @escaping (Result) -> ()) -> () {
102 | let url = URL(string: self.barcodeBase + "name/\(barcode)")
103 |
104 | self.createDataTask(with: url) { data, response, error in
105 | completion(self.processDataTask(data: data, response: response, error: error))
106 | }
107 | }
108 |
109 | private func productClass(for barcode: String, completion: @escaping (Result) -> ()) -> () {
110 | let url = URL(string: self.barcodeBase + "class/\(barcode)")
111 |
112 | self.createDataTask(with: url) { data, response, error in
113 | completion(self.processDataTask(data: data, response: response, error: error))
114 | }
115 | }
116 |
117 | public func product(for barcode : String, completion: @escaping (Result) -> ()) -> () {
118 | var classification : String = "Не классифицирован"
119 | var name : String = "Наименование продукта"
120 | var image : UIImage?
121 |
122 | var error : NetworkError?
123 |
124 | let group : DispatchGroup = .init()
125 |
126 | group.enter()
127 |
128 | self.productClass(for: barcode) { result in
129 | switch result {
130 | case .success(let response): classification = response
131 | case .failure(_): classification = "Не классифицирован"
132 | }
133 |
134 | group.leave()
135 | }
136 |
137 | group.enter()
138 |
139 | self.productName(for: barcode) { result in
140 | switch result {
141 | case .success(let response): name = response
142 | case .failure(let response): error = response
143 | }
144 |
145 | group.leave()
146 | }
147 |
148 | group.enter()
149 |
150 | self.productImage(for: barcode) { response in
151 | image = response
152 | group.leave()
153 | }
154 |
155 | group.notify(queue: .main) {
156 | if let error = error {
157 | completion(.failure(error))
158 | } else {
159 | let product : Product = .init(classification: classification, name: name, barcode: barcode, image: image)
160 | completion(.success(product))
161 | }
162 | }
163 | }
164 |
165 | private init() { }
166 | }
167 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Error/View/ErrorViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ProximaNovaExCn-Bold
13 |
14 |
15 | ProximaNovaExCn-Regular
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/BarcodeScanner/Modules/Product/View/ProductViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ProximaNovaExCn-Light
14 |
15 |
16 | ProximaNovaExCn-Regular
17 |
18 |
19 | ProximaNovaExCn-Thin
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
104 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/BarcodeScanner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0806B0B326A2B96400489884 /* FlashlightStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0B226A2B96400489884 /* FlashlightStatus.swift */; };
11 | 0806B0B726A2BBB600489884 /* MainRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0B626A2BBB600489884 /* MainRouter.swift */; };
12 | 0806B0BB26A2BD7B00489884 /* MainBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0BA26A2BD7B00489884 /* MainBuilder.swift */; };
13 | 0806B0BF26A2C14700489884 /* STModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0BE26A2C14700489884 /* STModal.swift */; };
14 | 0806B0C226A2C17000489884 /* STAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0C126A2C16F00489884 /* STAlert.swift */; };
15 | 0806B0C526A2C2F900489884 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0C426A2C2F900489884 /* ErrorPresenter.swift */; };
16 | 0806B0C826A2C3F700489884 /* ErrorBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0C726A2C3F700489884 /* ErrorBuilder.swift */; };
17 | 0806B0CB26A2C4B400489884 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0CA26A2C4B400489884 /* NetworkError.swift */; };
18 | 0806B0CE26A2CB8800489884 /* ProductPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0CD26A2CB8800489884 /* ProductPresenter.swift */; };
19 | 0806B0D126A2CC0D00489884 /* ProductBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0D026A2CC0D00489884 /* ProductBuilder.swift */; };
20 | 0806B0D526A2DE6D00489884 /* STScanArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0806B0D426A2DE6D00489884 /* STScanArea.swift */; };
21 | 9220A0F0250132D4000562F3 /* MainPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9220A0EA250132D4000562F3 /* MainPresenter.swift */; };
22 | 9220A0F1250132D4000562F3 /* Product.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9220A0EC250132D4000562F3 /* Product.swift */; };
23 | 9220A0F2250132D4000562F3 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9220A0EE250132D4000562F3 /* MainViewController.xib */; };
24 | 9220A0F3250132D4000562F3 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9220A0EF250132D4000562F3 /* MainViewController.swift */; };
25 | 9220A0F6250132EC000562F3 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9220A0F5250132EC000562F3 /* UIViewController.swift */; };
26 | 9220A0FC250132F7000562F3 /* STCamera.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9220A0F9250132F7000562F3 /* STCamera.swift */; };
27 | 9220A0FD250132F7000562F3 /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9220A0FB250132F7000562F3 /* NetworkService.swift */; };
28 | 924521202427CCB00050F4DD /* ProductViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9245211F2427CCB00050F4DD /* ProductViewController.xib */; };
29 | 924521222427CCDA0050F4DD /* ProductViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924521212427CCDA0050F4DD /* ProductViewController.swift */; };
30 | 9254558024265D65007F5FD4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9254557F24265D65007F5FD4 /* AppDelegate.swift */; };
31 | 9254558224265D65007F5FD4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9254558124265D65007F5FD4 /* SceneDelegate.swift */; };
32 | 9254558924265D66007F5FD4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9254558824265D66007F5FD4 /* Assets.xcassets */; };
33 | 9254558C24265D66007F5FD4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9254558A24265D66007F5FD4 /* LaunchScreen.storyboard */; };
34 | 92ECA710242920D000CCE0B7 /* ProximaNovaExCn-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 92ECA6E6242920D000CCE0B7 /* ProximaNovaExCn-Thin.ttf */; };
35 | 92ECA711242920D000CCE0B7 /* ProximaNovaExCn-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 92ECA6E7242920D000CCE0B7 /* ProximaNovaExCn-Light.ttf */; };
36 | 92ECA717242920D000CCE0B7 /* ProximaNovaExCn-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 92ECA6ED242920D000CCE0B7 /* ProximaNovaExCn-Regular.ttf */; };
37 | 92ECA71C242920D000CCE0B7 /* ProximaNovaExCn-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 92ECA6F2242920D000CCE0B7 /* ProximaNovaExCn-Bold.ttf */; };
38 | 92ECA7342429297E00CCE0B7 /* ErrorViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92ECA7332429297E00CCE0B7 /* ErrorViewController.xib */; };
39 | 92ECA73624292C7F00CCE0B7 /* ErrorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECA73524292C7F00CCE0B7 /* ErrorViewController.swift */; };
40 | 92ECA738242A347800CCE0B7 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECA737242A347800CCE0B7 /* UIView.swift */; };
41 | E9EF20C0E411E9E836F053D9 /* libPods-BarcodeScanner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F63026D1ABCF9F9F9E9B3E1D /* libPods-BarcodeScanner.a */; };
42 | /* End PBXBuildFile section */
43 |
44 | /* Begin PBXFileReference section */
45 | 0806B0B226A2B96400489884 /* FlashlightStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashlightStatus.swift; sourceTree = ""; };
46 | 0806B0B626A2BBB600489884 /* MainRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainRouter.swift; sourceTree = ""; };
47 | 0806B0BA26A2BD7B00489884 /* MainBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainBuilder.swift; sourceTree = ""; };
48 | 0806B0BE26A2C14700489884 /* STModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STModal.swift; sourceTree = ""; };
49 | 0806B0C126A2C16F00489884 /* STAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STAlert.swift; sourceTree = ""; };
50 | 0806B0C426A2C2F900489884 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = ""; };
51 | 0806B0C726A2C3F700489884 /* ErrorBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorBuilder.swift; sourceTree = ""; };
52 | 0806B0CA26A2C4B400489884 /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; };
53 | 0806B0CD26A2CB8800489884 /* ProductPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductPresenter.swift; sourceTree = ""; };
54 | 0806B0D026A2CC0D00489884 /* ProductBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductBuilder.swift; sourceTree = ""; };
55 | 0806B0D426A2DE6D00489884 /* STScanArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = STScanArea.swift; sourceTree = ""; };
56 | 79180CF1F92ACB640AF74021 /* Pods-BarcodeScanner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BarcodeScanner.debug.xcconfig"; path = "Target Support Files/Pods-BarcodeScanner/Pods-BarcodeScanner.debug.xcconfig"; sourceTree = ""; };
57 | 9220A0EA250132D4000562F3 /* MainPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainPresenter.swift; sourceTree = ""; };
58 | 9220A0EC250132D4000562F3 /* Product.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Product.swift; sourceTree = ""; };
59 | 9220A0EE250132D4000562F3 /* MainViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainViewController.xib; sourceTree = ""; };
60 | 9220A0EF250132D4000562F3 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; };
61 | 9220A0F5250132EC000562F3 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; };
62 | 9220A0F9250132F7000562F3 /* STCamera.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = STCamera.swift; sourceTree = ""; };
63 | 9220A0FB250132F7000562F3 /* NetworkService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkService.swift; sourceTree = ""; };
64 | 9245211F2427CCB00050F4DD /* ProductViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProductViewController.xib; sourceTree = ""; };
65 | 924521212427CCDA0050F4DD /* ProductViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductViewController.swift; sourceTree = ""; };
66 | 9254557C24265D65007F5FD4 /* BarcodeScanner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BarcodeScanner.app; sourceTree = BUILT_PRODUCTS_DIR; };
67 | 9254557F24265D65007F5FD4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
68 | 9254558124265D65007F5FD4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
69 | 9254558824265D66007F5FD4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
70 | 9254558B24265D66007F5FD4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
71 | 9254558D24265D66007F5FD4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
72 | 92ECA6E6242920D000CCE0B7 /* ProximaNovaExCn-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ProximaNovaExCn-Thin.ttf"; sourceTree = ""; };
73 | 92ECA6E7242920D000CCE0B7 /* ProximaNovaExCn-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ProximaNovaExCn-Light.ttf"; sourceTree = ""; };
74 | 92ECA6ED242920D000CCE0B7 /* ProximaNovaExCn-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ProximaNovaExCn-Regular.ttf"; sourceTree = ""; };
75 | 92ECA6F2242920D000CCE0B7 /* ProximaNovaExCn-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ProximaNovaExCn-Bold.ttf"; sourceTree = ""; };
76 | 92ECA7332429297E00CCE0B7 /* ErrorViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ErrorViewController.xib; sourceTree = ""; };
77 | 92ECA73524292C7F00CCE0B7 /* ErrorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorViewController.swift; sourceTree = ""; };
78 | 92ECA737242A347800CCE0B7 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; };
79 | EF879855EA857755783B90DA /* Pods-BarcodeScanner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BarcodeScanner.release.xcconfig"; path = "Target Support Files/Pods-BarcodeScanner/Pods-BarcodeScanner.release.xcconfig"; sourceTree = ""; };
80 | F63026D1ABCF9F9F9E9B3E1D /* libPods-BarcodeScanner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BarcodeScanner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
81 | /* End PBXFileReference section */
82 |
83 | /* Begin PBXFrameworksBuildPhase section */
84 | 9254557924265D65007F5FD4 /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | E9EF20C0E411E9E836F053D9 /* libPods-BarcodeScanner.a in Frameworks */,
89 | );
90 | runOnlyForDeploymentPostprocessing = 0;
91 | };
92 | /* End PBXFrameworksBuildPhase section */
93 |
94 | /* Begin PBXGroup section */
95 | 0806B0B026A2B95200489884 /* Components */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 0806B0C026A2C15900489884 /* STAlert */,
99 | 0806B0BD26A2C12E00489884 /* STModal */,
100 | 0806B0B126A2B95800489884 /* STCamera */,
101 | );
102 | path = Components;
103 | sourceTree = "";
104 | };
105 | 0806B0B126A2B95800489884 /* STCamera */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 9220A0F9250132F7000562F3 /* STCamera.swift */,
109 | 0806B0D426A2DE6D00489884 /* STScanArea.swift */,
110 | 0806B0B226A2B96400489884 /* FlashlightStatus.swift */,
111 | );
112 | path = STCamera;
113 | sourceTree = "";
114 | };
115 | 0806B0B526A2BBAD00489884 /* Router */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 0806B0B626A2BBB600489884 /* MainRouter.swift */,
119 | );
120 | path = Router;
121 | sourceTree = "";
122 | };
123 | 0806B0B926A2BD7400489884 /* Builder */ = {
124 | isa = PBXGroup;
125 | children = (
126 | 0806B0BA26A2BD7B00489884 /* MainBuilder.swift */,
127 | );
128 | path = Builder;
129 | sourceTree = "";
130 | };
131 | 0806B0BD26A2C12E00489884 /* STModal */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 0806B0BE26A2C14700489884 /* STModal.swift */,
135 | );
136 | path = STModal;
137 | sourceTree = "";
138 | };
139 | 0806B0C026A2C15900489884 /* STAlert */ = {
140 | isa = PBXGroup;
141 | children = (
142 | 0806B0C126A2C16F00489884 /* STAlert.swift */,
143 | );
144 | path = STAlert;
145 | sourceTree = "";
146 | };
147 | 0806B0C326A2C2EE00489884 /* Presenter */ = {
148 | isa = PBXGroup;
149 | children = (
150 | 0806B0C426A2C2F900489884 /* ErrorPresenter.swift */,
151 | );
152 | path = Presenter;
153 | sourceTree = "";
154 | };
155 | 0806B0C626A2C3E600489884 /* Builder */ = {
156 | isa = PBXGroup;
157 | children = (
158 | 0806B0C726A2C3F700489884 /* ErrorBuilder.swift */,
159 | );
160 | path = Builder;
161 | sourceTree = "";
162 | };
163 | 0806B0C926A2C48D00489884 /* Model */ = {
164 | isa = PBXGroup;
165 | children = (
166 | 0806B0CA26A2C4B400489884 /* NetworkError.swift */,
167 | );
168 | path = Model;
169 | sourceTree = "";
170 | };
171 | 0806B0CC26A2CB7C00489884 /* Presenter */ = {
172 | isa = PBXGroup;
173 | children = (
174 | 0806B0CD26A2CB8800489884 /* ProductPresenter.swift */,
175 | );
176 | path = Presenter;
177 | sourceTree = "";
178 | };
179 | 0806B0CF26A2CC0400489884 /* Builder */ = {
180 | isa = PBXGroup;
181 | children = (
182 | 0806B0D026A2CC0D00489884 /* ProductBuilder.swift */,
183 | );
184 | path = Builder;
185 | sourceTree = "";
186 | };
187 | 08FBAB7926A20BA000DF4592 /* Supporting Files */ = {
188 | isa = PBXGroup;
189 | children = (
190 | 92ECA6DE242920D000CCE0B7 /* Font */,
191 | 9254558D24265D66007F5FD4 /* Info.plist */,
192 | 9254557F24265D65007F5FD4 /* AppDelegate.swift */,
193 | 9254558124265D65007F5FD4 /* SceneDelegate.swift */,
194 | 9254558824265D66007F5FD4 /* Assets.xcassets */,
195 | 9254558A24265D66007F5FD4 /* LaunchScreen.storyboard */,
196 | );
197 | path = "Supporting Files";
198 | sourceTree = "";
199 | };
200 | 08FBAB7A26A20C9100DF4592 /* Modules */ = {
201 | isa = PBXGroup;
202 | children = (
203 | 08FBAB8026A20DA200DF4592 /* Error */,
204 | 08FBAB7E26A20D5800DF4592 /* Product */,
205 | 08FBAB7B26A20C9500DF4592 /* Main */,
206 | );
207 | path = Modules;
208 | sourceTree = "";
209 | };
210 | 08FBAB7B26A20C9500DF4592 /* Main */ = {
211 | isa = PBXGroup;
212 | children = (
213 | 9220A0ED250132D4000562F3 /* View */,
214 | 9220A0E9250132D4000562F3 /* Presenter */,
215 | 0806B0B526A2BBAD00489884 /* Router */,
216 | 0806B0B926A2BD7400489884 /* Builder */,
217 | );
218 | path = Main;
219 | sourceTree = "";
220 | };
221 | 08FBAB7C26A20CB100DF4592 /* Common */ = {
222 | isa = PBXGroup;
223 | children = (
224 | 0806B0B026A2B95200489884 /* Components */,
225 | 9220A0F7250132F7000562F3 /* Services */,
226 | 08FBAB7D26A20CB500DF4592 /* Extensions */,
227 | );
228 | path = Common;
229 | sourceTree = "";
230 | };
231 | 08FBAB7D26A20CB500DF4592 /* Extensions */ = {
232 | isa = PBXGroup;
233 | children = (
234 | 92ECA737242A347800CCE0B7 /* UIView.swift */,
235 | 9220A0F5250132EC000562F3 /* UIViewController.swift */,
236 | );
237 | path = Extensions;
238 | sourceTree = "";
239 | };
240 | 08FBAB7E26A20D5800DF4592 /* Product */ = {
241 | isa = PBXGroup;
242 | children = (
243 | 9220A0EB250132D4000562F3 /* Model */,
244 | 08FBAB7F26A20D6400DF4592 /* View */,
245 | 0806B0CC26A2CB7C00489884 /* Presenter */,
246 | 0806B0CF26A2CC0400489884 /* Builder */,
247 | );
248 | path = Product;
249 | sourceTree = "";
250 | };
251 | 08FBAB7F26A20D6400DF4592 /* View */ = {
252 | isa = PBXGroup;
253 | children = (
254 | 9245211F2427CCB00050F4DD /* ProductViewController.xib */,
255 | 924521212427CCDA0050F4DD /* ProductViewController.swift */,
256 | );
257 | path = View;
258 | sourceTree = "";
259 | };
260 | 08FBAB8026A20DA200DF4592 /* Error */ = {
261 | isa = PBXGroup;
262 | children = (
263 | 0806B0C926A2C48D00489884 /* Model */,
264 | 08FBAB8126A20DA700DF4592 /* View */,
265 | 0806B0C326A2C2EE00489884 /* Presenter */,
266 | 0806B0C626A2C3E600489884 /* Builder */,
267 | );
268 | path = Error;
269 | sourceTree = "";
270 | };
271 | 08FBAB8126A20DA700DF4592 /* View */ = {
272 | isa = PBXGroup;
273 | children = (
274 | 92ECA7332429297E00CCE0B7 /* ErrorViewController.xib */,
275 | 92ECA73524292C7F00CCE0B7 /* ErrorViewController.swift */,
276 | );
277 | path = View;
278 | sourceTree = "";
279 | };
280 | 1D168A74C45B9B979B0659DA /* Pods */ = {
281 | isa = PBXGroup;
282 | children = (
283 | 79180CF1F92ACB640AF74021 /* Pods-BarcodeScanner.debug.xcconfig */,
284 | EF879855EA857755783B90DA /* Pods-BarcodeScanner.release.xcconfig */,
285 | );
286 | path = Pods;
287 | sourceTree = "";
288 | };
289 | 9220A0E9250132D4000562F3 /* Presenter */ = {
290 | isa = PBXGroup;
291 | children = (
292 | 9220A0EA250132D4000562F3 /* MainPresenter.swift */,
293 | );
294 | path = Presenter;
295 | sourceTree = "";
296 | };
297 | 9220A0EB250132D4000562F3 /* Model */ = {
298 | isa = PBXGroup;
299 | children = (
300 | 9220A0EC250132D4000562F3 /* Product.swift */,
301 | );
302 | path = Model;
303 | sourceTree = "";
304 | };
305 | 9220A0ED250132D4000562F3 /* View */ = {
306 | isa = PBXGroup;
307 | children = (
308 | 9220A0EE250132D4000562F3 /* MainViewController.xib */,
309 | 9220A0EF250132D4000562F3 /* MainViewController.swift */,
310 | );
311 | path = View;
312 | sourceTree = "";
313 | };
314 | 9220A0F7250132F7000562F3 /* Services */ = {
315 | isa = PBXGroup;
316 | children = (
317 | 9220A0FA250132F7000562F3 /* Network */,
318 | );
319 | path = Services;
320 | sourceTree = "";
321 | };
322 | 9220A0FA250132F7000562F3 /* Network */ = {
323 | isa = PBXGroup;
324 | children = (
325 | 9220A0FB250132F7000562F3 /* NetworkService.swift */,
326 | );
327 | path = Network;
328 | sourceTree = "";
329 | };
330 | 9254557324265D65007F5FD4 = {
331 | isa = PBXGroup;
332 | children = (
333 | 9254557E24265D65007F5FD4 /* BarcodeScanner */,
334 | 9254557D24265D65007F5FD4 /* Products */,
335 | 1D168A74C45B9B979B0659DA /* Pods */,
336 | ADF2B6EB63A2FEF070267165 /* Frameworks */,
337 | );
338 | sourceTree = "";
339 | };
340 | 9254557D24265D65007F5FD4 /* Products */ = {
341 | isa = PBXGroup;
342 | children = (
343 | 9254557C24265D65007F5FD4 /* BarcodeScanner.app */,
344 | );
345 | name = Products;
346 | sourceTree = "";
347 | };
348 | 9254557E24265D65007F5FD4 /* BarcodeScanner */ = {
349 | isa = PBXGroup;
350 | children = (
351 | 08FBAB7C26A20CB100DF4592 /* Common */,
352 | 08FBAB7A26A20C9100DF4592 /* Modules */,
353 | 08FBAB7926A20BA000DF4592 /* Supporting Files */,
354 | );
355 | path = BarcodeScanner;
356 | sourceTree = "";
357 | };
358 | 92ECA6DE242920D000CCE0B7 /* Font */ = {
359 | isa = PBXGroup;
360 | children = (
361 | 92ECA6E6242920D000CCE0B7 /* ProximaNovaExCn-Thin.ttf */,
362 | 92ECA6E7242920D000CCE0B7 /* ProximaNovaExCn-Light.ttf */,
363 | 92ECA6ED242920D000CCE0B7 /* ProximaNovaExCn-Regular.ttf */,
364 | 92ECA6F2242920D000CCE0B7 /* ProximaNovaExCn-Bold.ttf */,
365 | );
366 | path = Font;
367 | sourceTree = "";
368 | };
369 | ADF2B6EB63A2FEF070267165 /* Frameworks */ = {
370 | isa = PBXGroup;
371 | children = (
372 | F63026D1ABCF9F9F9E9B3E1D /* libPods-BarcodeScanner.a */,
373 | );
374 | name = Frameworks;
375 | sourceTree = "";
376 | };
377 | /* End PBXGroup section */
378 |
379 | /* Begin PBXNativeTarget section */
380 | 9254557B24265D65007F5FD4 /* BarcodeScanner */ = {
381 | isa = PBXNativeTarget;
382 | buildConfigurationList = 9254559024265D66007F5FD4 /* Build configuration list for PBXNativeTarget "BarcodeScanner" */;
383 | buildPhases = (
384 | DE18BDFE1ACC8162E13A9DD2 /* [CP] Check Pods Manifest.lock */,
385 | 9254557824265D65007F5FD4 /* Sources */,
386 | 9254557924265D65007F5FD4 /* Frameworks */,
387 | 9254557A24265D65007F5FD4 /* Resources */,
388 | );
389 | buildRules = (
390 | );
391 | dependencies = (
392 | );
393 | name = BarcodeScanner;
394 | productName = BarcodeScanner;
395 | productReference = 9254557C24265D65007F5FD4 /* BarcodeScanner.app */;
396 | productType = "com.apple.product-type.application";
397 | };
398 | /* End PBXNativeTarget section */
399 |
400 | /* Begin PBXProject section */
401 | 9254557424265D65007F5FD4 /* Project object */ = {
402 | isa = PBXProject;
403 | attributes = {
404 | LastSwiftUpdateCheck = 1130;
405 | LastUpgradeCheck = 1130;
406 | ORGANIZATIONNAME = "onl1ner onl1ner";
407 | TargetAttributes = {
408 | 9254557B24265D65007F5FD4 = {
409 | CreatedOnToolsVersion = 11.3.1;
410 | };
411 | };
412 | };
413 | buildConfigurationList = 9254557724265D65007F5FD4 /* Build configuration list for PBXProject "BarcodeScanner" */;
414 | compatibilityVersion = "Xcode 9.3";
415 | developmentRegion = en;
416 | hasScannedForEncodings = 0;
417 | knownRegions = (
418 | en,
419 | Base,
420 | );
421 | mainGroup = 9254557324265D65007F5FD4;
422 | productRefGroup = 9254557D24265D65007F5FD4 /* Products */;
423 | projectDirPath = "";
424 | projectRoot = "";
425 | targets = (
426 | 9254557B24265D65007F5FD4 /* BarcodeScanner */,
427 | );
428 | };
429 | /* End PBXProject section */
430 |
431 | /* Begin PBXResourcesBuildPhase section */
432 | 9254557A24265D65007F5FD4 /* Resources */ = {
433 | isa = PBXResourcesBuildPhase;
434 | buildActionMask = 2147483647;
435 | files = (
436 | 92ECA7342429297E00CCE0B7 /* ErrorViewController.xib in Resources */,
437 | 9254558C24265D66007F5FD4 /* LaunchScreen.storyboard in Resources */,
438 | 92ECA711242920D000CCE0B7 /* ProximaNovaExCn-Light.ttf in Resources */,
439 | 9254558924265D66007F5FD4 /* Assets.xcassets in Resources */,
440 | 92ECA717242920D000CCE0B7 /* ProximaNovaExCn-Regular.ttf in Resources */,
441 | 924521202427CCB00050F4DD /* ProductViewController.xib in Resources */,
442 | 92ECA71C242920D000CCE0B7 /* ProximaNovaExCn-Bold.ttf in Resources */,
443 | 9220A0F2250132D4000562F3 /* MainViewController.xib in Resources */,
444 | 92ECA710242920D000CCE0B7 /* ProximaNovaExCn-Thin.ttf in Resources */,
445 | );
446 | runOnlyForDeploymentPostprocessing = 0;
447 | };
448 | /* End PBXResourcesBuildPhase section */
449 |
450 | /* Begin PBXShellScriptBuildPhase section */
451 | DE18BDFE1ACC8162E13A9DD2 /* [CP] Check Pods Manifest.lock */ = {
452 | isa = PBXShellScriptBuildPhase;
453 | buildActionMask = 2147483647;
454 | files = (
455 | );
456 | inputFileListPaths = (
457 | );
458 | inputPaths = (
459 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
460 | "${PODS_ROOT}/Manifest.lock",
461 | );
462 | name = "[CP] Check Pods Manifest.lock";
463 | outputFileListPaths = (
464 | );
465 | outputPaths = (
466 | "$(DERIVED_FILE_DIR)/Pods-BarcodeScanner-checkManifestLockResult.txt",
467 | );
468 | runOnlyForDeploymentPostprocessing = 0;
469 | shellPath = /bin/sh;
470 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
471 | showEnvVarsInLog = 0;
472 | };
473 | /* End PBXShellScriptBuildPhase section */
474 |
475 | /* Begin PBXSourcesBuildPhase section */
476 | 9254557824265D65007F5FD4 /* Sources */ = {
477 | isa = PBXSourcesBuildPhase;
478 | buildActionMask = 2147483647;
479 | files = (
480 | 924521222427CCDA0050F4DD /* ProductViewController.swift in Sources */,
481 | 0806B0CB26A2C4B400489884 /* NetworkError.swift in Sources */,
482 | 0806B0B726A2BBB600489884 /* MainRouter.swift in Sources */,
483 | 9220A0FD250132F7000562F3 /* NetworkService.swift in Sources */,
484 | 9254558024265D65007F5FD4 /* AppDelegate.swift in Sources */,
485 | 0806B0D126A2CC0D00489884 /* ProductBuilder.swift in Sources */,
486 | 0806B0D526A2DE6D00489884 /* STScanArea.swift in Sources */,
487 | 9220A0F3250132D4000562F3 /* MainViewController.swift in Sources */,
488 | 0806B0C826A2C3F700489884 /* ErrorBuilder.swift in Sources */,
489 | 9220A0FC250132F7000562F3 /* STCamera.swift in Sources */,
490 | 9220A0F0250132D4000562F3 /* MainPresenter.swift in Sources */,
491 | 9254558224265D65007F5FD4 /* SceneDelegate.swift in Sources */,
492 | 0806B0B326A2B96400489884 /* FlashlightStatus.swift in Sources */,
493 | 92ECA738242A347800CCE0B7 /* UIView.swift in Sources */,
494 | 0806B0CE26A2CB8800489884 /* ProductPresenter.swift in Sources */,
495 | 0806B0C526A2C2F900489884 /* ErrorPresenter.swift in Sources */,
496 | 0806B0BF26A2C14700489884 /* STModal.swift in Sources */,
497 | 0806B0C226A2C17000489884 /* STAlert.swift in Sources */,
498 | 0806B0BB26A2BD7B00489884 /* MainBuilder.swift in Sources */,
499 | 92ECA73624292C7F00CCE0B7 /* ErrorViewController.swift in Sources */,
500 | 9220A0F1250132D4000562F3 /* Product.swift in Sources */,
501 | 9220A0F6250132EC000562F3 /* UIViewController.swift in Sources */,
502 | );
503 | runOnlyForDeploymentPostprocessing = 0;
504 | };
505 | /* End PBXSourcesBuildPhase section */
506 |
507 | /* Begin PBXVariantGroup section */
508 | 9254558A24265D66007F5FD4 /* LaunchScreen.storyboard */ = {
509 | isa = PBXVariantGroup;
510 | children = (
511 | 9254558B24265D66007F5FD4 /* Base */,
512 | );
513 | name = LaunchScreen.storyboard;
514 | sourceTree = "";
515 | };
516 | /* End PBXVariantGroup section */
517 |
518 | /* Begin XCBuildConfiguration section */
519 | 9254558E24265D66007F5FD4 /* Debug */ = {
520 | isa = XCBuildConfiguration;
521 | buildSettings = {
522 | ALWAYS_SEARCH_USER_PATHS = NO;
523 | CLANG_ANALYZER_NONNULL = YES;
524 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
525 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
526 | CLANG_CXX_LIBRARY = "libc++";
527 | CLANG_ENABLE_MODULES = YES;
528 | CLANG_ENABLE_OBJC_ARC = YES;
529 | CLANG_ENABLE_OBJC_WEAK = YES;
530 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
531 | CLANG_WARN_BOOL_CONVERSION = YES;
532 | CLANG_WARN_COMMA = YES;
533 | CLANG_WARN_CONSTANT_CONVERSION = YES;
534 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
535 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
536 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
537 | CLANG_WARN_EMPTY_BODY = YES;
538 | CLANG_WARN_ENUM_CONVERSION = YES;
539 | CLANG_WARN_INFINITE_RECURSION = YES;
540 | CLANG_WARN_INT_CONVERSION = YES;
541 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
542 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
543 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
544 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
545 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
546 | CLANG_WARN_STRICT_PROTOTYPES = YES;
547 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
548 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
549 | CLANG_WARN_UNREACHABLE_CODE = YES;
550 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
551 | COPY_PHASE_STRIP = NO;
552 | DEBUG_INFORMATION_FORMAT = dwarf;
553 | ENABLE_STRICT_OBJC_MSGSEND = YES;
554 | ENABLE_TESTABILITY = YES;
555 | GCC_C_LANGUAGE_STANDARD = gnu11;
556 | GCC_DYNAMIC_NO_PIC = NO;
557 | GCC_NO_COMMON_BLOCKS = YES;
558 | GCC_OPTIMIZATION_LEVEL = 0;
559 | GCC_PREPROCESSOR_DEFINITIONS = (
560 | "DEBUG=1",
561 | "$(inherited)",
562 | );
563 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
564 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
565 | GCC_WARN_UNDECLARED_SELECTOR = YES;
566 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
567 | GCC_WARN_UNUSED_FUNCTION = YES;
568 | GCC_WARN_UNUSED_VARIABLE = YES;
569 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
570 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
571 | MTL_FAST_MATH = YES;
572 | ONLY_ACTIVE_ARCH = YES;
573 | SDKROOT = iphoneos;
574 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
575 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
576 | };
577 | name = Debug;
578 | };
579 | 9254558F24265D66007F5FD4 /* Release */ = {
580 | isa = XCBuildConfiguration;
581 | buildSettings = {
582 | ALWAYS_SEARCH_USER_PATHS = NO;
583 | CLANG_ANALYZER_NONNULL = YES;
584 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
585 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
586 | CLANG_CXX_LIBRARY = "libc++";
587 | CLANG_ENABLE_MODULES = YES;
588 | CLANG_ENABLE_OBJC_ARC = YES;
589 | CLANG_ENABLE_OBJC_WEAK = YES;
590 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
591 | CLANG_WARN_BOOL_CONVERSION = YES;
592 | CLANG_WARN_COMMA = YES;
593 | CLANG_WARN_CONSTANT_CONVERSION = YES;
594 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
595 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
596 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
597 | CLANG_WARN_EMPTY_BODY = YES;
598 | CLANG_WARN_ENUM_CONVERSION = YES;
599 | CLANG_WARN_INFINITE_RECURSION = YES;
600 | CLANG_WARN_INT_CONVERSION = YES;
601 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
602 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
603 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
604 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
605 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
606 | CLANG_WARN_STRICT_PROTOTYPES = YES;
607 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
608 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
609 | CLANG_WARN_UNREACHABLE_CODE = YES;
610 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
611 | COPY_PHASE_STRIP = NO;
612 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
613 | ENABLE_NS_ASSERTIONS = NO;
614 | ENABLE_STRICT_OBJC_MSGSEND = YES;
615 | GCC_C_LANGUAGE_STANDARD = gnu11;
616 | GCC_NO_COMMON_BLOCKS = YES;
617 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
618 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
619 | GCC_WARN_UNDECLARED_SELECTOR = YES;
620 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
621 | GCC_WARN_UNUSED_FUNCTION = YES;
622 | GCC_WARN_UNUSED_VARIABLE = YES;
623 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
624 | MTL_ENABLE_DEBUG_INFO = NO;
625 | MTL_FAST_MATH = YES;
626 | SDKROOT = iphoneos;
627 | SWIFT_COMPILATION_MODE = wholemodule;
628 | SWIFT_OPTIMIZATION_LEVEL = "-O";
629 | VALIDATE_PRODUCT = YES;
630 | };
631 | name = Release;
632 | };
633 | 9254559124265D66007F5FD4 /* Debug */ = {
634 | isa = XCBuildConfiguration;
635 | baseConfigurationReference = 79180CF1F92ACB640AF74021 /* Pods-BarcodeScanner.debug.xcconfig */;
636 | buildSettings = {
637 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
638 | CODE_SIGN_STYLE = Automatic;
639 | DEVELOPMENT_TEAM = H72YUS24CN;
640 | INFOPLIST_FILE = "BarcodeScanner/Supporting Files/Info.plist";
641 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
642 | LD_RUNPATH_SEARCH_PATHS = (
643 | "$(inherited)",
644 | "@executable_path/Frameworks",
645 | );
646 | MARKETING_VERSION = 2.0;
647 | PRODUCT_BUNDLE_IDENTIFIER = com.ean.barcode.scanner;
648 | PRODUCT_NAME = "$(TARGET_NAME)";
649 | SWIFT_VERSION = 5.0;
650 | TARGETED_DEVICE_FAMILY = 1;
651 | };
652 | name = Debug;
653 | };
654 | 9254559224265D66007F5FD4 /* Release */ = {
655 | isa = XCBuildConfiguration;
656 | baseConfigurationReference = EF879855EA857755783B90DA /* Pods-BarcodeScanner.release.xcconfig */;
657 | buildSettings = {
658 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
659 | CODE_SIGN_STYLE = Automatic;
660 | DEVELOPMENT_TEAM = H72YUS24CN;
661 | INFOPLIST_FILE = "BarcodeScanner/Supporting Files/Info.plist";
662 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
663 | LD_RUNPATH_SEARCH_PATHS = (
664 | "$(inherited)",
665 | "@executable_path/Frameworks",
666 | );
667 | MARKETING_VERSION = 2.0;
668 | PRODUCT_BUNDLE_IDENTIFIER = com.ean.barcode.scanner;
669 | PRODUCT_NAME = "$(TARGET_NAME)";
670 | SWIFT_VERSION = 5.0;
671 | TARGETED_DEVICE_FAMILY = 1;
672 | };
673 | name = Release;
674 | };
675 | /* End XCBuildConfiguration section */
676 |
677 | /* Begin XCConfigurationList section */
678 | 9254557724265D65007F5FD4 /* Build configuration list for PBXProject "BarcodeScanner" */ = {
679 | isa = XCConfigurationList;
680 | buildConfigurations = (
681 | 9254558E24265D66007F5FD4 /* Debug */,
682 | 9254558F24265D66007F5FD4 /* Release */,
683 | );
684 | defaultConfigurationIsVisible = 0;
685 | defaultConfigurationName = Release;
686 | };
687 | 9254559024265D66007F5FD4 /* Build configuration list for PBXNativeTarget "BarcodeScanner" */ = {
688 | isa = XCConfigurationList;
689 | buildConfigurations = (
690 | 9254559124265D66007F5FD4 /* Debug */,
691 | 9254559224265D66007F5FD4 /* Release */,
692 | );
693 | defaultConfigurationIsVisible = 0;
694 | defaultConfigurationName = Release;
695 | };
696 | /* End XCConfigurationList section */
697 | };
698 | rootObject = 9254557424265D65007F5FD4 /* Project object */;
699 | }
700 |
--------------------------------------------------------------------------------