├── .DS_Store
├── .gitmodules
├── LICENSE.md
├── Left.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ │ └── Left.xcscmblueprint
│ └── xcuserdata
│ │ └── ale_patron.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── xcuserdata
│ └── ale_patron.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ ├── Left.xcscheme
│ └── xcschememanagement.plist
├── Left.xcworkspace
├── contents.xcworkspacedata
└── xcuserdata
│ └── ale_patron.xcuserdatad
│ ├── UserInterfaceState.xcuserstate
│ └── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
├── Left
├── .DS_Store
├── Assets.xcassets
│ ├── .DS_Store
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-40@2x-1.png
│ │ ├── Icon-40@2x.png
│ │ ├── Icon-40@3x.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-76@1x.png
│ │ ├── Icon-76@2x.png
│ │ └── Icon-83.5@2x.png
│ ├── Contents.json
│ ├── LaunchImage.launchimage
│ │ └── Contents.json
│ ├── back.imageset
│ │ ├── Contents.json
│ │ ├── back@2x.png
│ │ └── back@3x.png
│ ├── default.imageset
│ │ ├── Contents.json
│ │ ├── default-1.png
│ │ ├── default-2.png
│ │ └── default.png
│ ├── delete-ingredient.imageset
│ │ ├── Contents.json
│ │ ├── delete-ingredient-1.png
│ │ ├── delete-ingredient-2.png
│ │ └── delete-ingredient.png
│ ├── forward.imageset
│ │ ├── Contents.json
│ │ ├── forward@2x.png
│ │ └── forward@3x.png
│ ├── placeholder-favorites.imageset
│ │ ├── Contents.json
│ │ ├── placeholder-favorites.png
│ │ └── placeholder-favorites@2x.png
│ ├── placeholder-search.imageset
│ │ ├── Contents.json
│ │ ├── placeholder-search.png
│ │ └── placeholder-search@2x.png
│ ├── safari-activity.imageset
│ │ ├── Contents.json
│ │ ├── safari.png
│ │ ├── safari@2x.png
│ │ └── safari@3x.png
│ ├── search-tab-bar.imageset
│ │ ├── Contents.json
│ │ ├── search@1x.png
│ │ ├── search@2x.png
│ │ └── search@3x.png
│ ├── star-filled.imageset
│ │ ├── Contents.json
│ │ ├── star-filled-1.png
│ │ ├── star-filled-2.png
│ │ └── star-filled.png
│ ├── star-navbar.imageset
│ │ ├── Contents.json
│ │ ├── star@1x.png
│ │ ├── star@2x.png
│ │ └── star@3x.png
│ ├── star-tab-bar.imageset
│ │ ├── Contents.json
│ │ ├── star@1x.png
│ │ ├── star@2x.png
│ │ └── star@3x.png
│ ├── star.imageset
│ │ ├── Contents.json
│ │ ├── star-1.png
│ │ ├── star-2.png
│ │ └── star.png
│ ├── trash-filled.imageset
│ │ ├── Contents.json
│ │ ├── trash-1.png
│ │ ├── trash-2.png
│ │ └── trash.png
│ └── trash.imageset
│ │ ├── Contents.json
│ │ ├── delete-1.png
│ │ ├── delete-2.png
│ │ └── delete.png
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Extensions
│ ├── SearchTableView+Keyboard.swift
│ ├── String.swift
│ ├── UIColor.swift
│ └── UIViewController.swift
├── Info.plist
├── LFTReviewCollectionCell.xib
├── Model
│ └── RecipeItem.swift
├── Navigation
│ └── NavViewController.swift
├── Other
│ ├── AppDelegate.swift
│ ├── Left-Bridging-Header.h
│ └── SafariActivity.swift
├── Services
│ ├── FavoritesManager.swift
│ ├── Food2ForkService.swift
│ ├── JSONParser.swift
│ ├── RecipesLoader.swift
│ ├── SKStoreReviewManager.swift
│ └── ShortcutsManager.swift
├── View Controller
│ ├── FavoritesCollectionView.swift
│ ├── RecipeWebView.swift
│ ├── ResultsCollectionView.swift
│ └── SearchTableView.swift
└── View
│ └── RecipeCollectionCell.swift
├── LeftTests
├── Info.plist
└── LeftTests.swift
├── LeftUITests
├── Info.plist
└── LeftUITests.swift
├── Podfile
├── Podfile.lock
├── Pods
├── .DS_Store
├── Alamofire
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ ├── AFError.swift
│ │ ├── Alamofire.swift
│ │ ├── DispatchQueue+Alamofire.swift
│ │ ├── MultipartFormData.swift
│ │ ├── NetworkReachabilityManager.swift
│ │ ├── Notifications.swift
│ │ ├── ParameterEncoding.swift
│ │ ├── Request.swift
│ │ ├── Response.swift
│ │ ├── ResponseSerialization.swift
│ │ ├── Result.swift
│ │ ├── ServerTrustPolicy.swift
│ │ ├── SessionDelegate.swift
│ │ ├── SessionManager.swift
│ │ ├── TaskDelegate.swift
│ │ ├── Timeline.swift
│ │ └── Validation.swift
├── AlamofireNetworkActivityIndicator
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ └── NetworkActivityIndicatorManager.swift
├── DZNEmptyDataSet
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ ├── UIScrollView+EmptyDataSet.h
│ │ └── UIScrollView+EmptyDataSet.m
├── Local Podspecs
│ └── SwiftyJSON.podspec.json
├── Manifest.lock
├── Nuke
│ ├── LICENSE
│ ├── README.md
│ └── Sources
│ │ ├── Cache.swift
│ │ ├── CancellationToken.swift
│ │ ├── DataDecoder.swift
│ │ ├── DataLoader.swift
│ │ ├── Deduplicator.swift
│ │ ├── Loader.swift
│ │ ├── Manager.swift
│ │ ├── Nuke.swift
│ │ ├── Preheater.swift
│ │ ├── Processor.swift
│ │ ├── Promise.swift
│ │ ├── Request.swift
│ │ └── Scheduler.swift
├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── xcuserdata
│ │ └── ale_patron.xcuserdatad
│ │ └── xcschemes
│ │ ├── Alamofire.xcscheme
│ │ ├── AlamofireNetworkActivityIndicator.xcscheme
│ │ ├── DZNEmptyDataSet.xcscheme
│ │ ├── Nuke.xcscheme
│ │ ├── Pods-Left.xcscheme
│ │ ├── SwiftyDrop.xcscheme
│ │ ├── SwiftyJSON.xcscheme
│ │ ├── UIScrollView-InfiniteScroll.xcscheme
│ │ └── xcschememanagement.plist
├── SwiftyDrop
│ ├── LICENSE
│ ├── README.md
│ └── SwiftyDrop
│ │ └── Drop.swift
├── SwiftyJSON
│ ├── LICENSE
│ ├── README.md
│ └── Source
│ │ └── SwiftyJSON.swift
├── Target Support Files
│ ├── Alamofire
│ │ ├── Alamofire-dummy.m
│ │ ├── Alamofire-prefix.pch
│ │ ├── Alamofire-umbrella.h
│ │ ├── Alamofire.modulemap
│ │ ├── Alamofire.xcconfig
│ │ └── Info.plist
│ ├── AlamofireNetworkActivityIndicator
│ │ ├── AlamofireNetworkActivityIndicator-dummy.m
│ │ ├── AlamofireNetworkActivityIndicator-prefix.pch
│ │ ├── AlamofireNetworkActivityIndicator-umbrella.h
│ │ ├── AlamofireNetworkActivityIndicator.modulemap
│ │ ├── AlamofireNetworkActivityIndicator.xcconfig
│ │ └── Info.plist
│ ├── DZNEmptyDataSet
│ │ ├── DZNEmptyDataSet-dummy.m
│ │ ├── DZNEmptyDataSet-prefix.pch
│ │ ├── DZNEmptyDataSet-umbrella.h
│ │ ├── DZNEmptyDataSet.modulemap
│ │ ├── DZNEmptyDataSet.xcconfig
│ │ └── Info.plist
│ ├── Nuke
│ │ ├── Info.plist
│ │ ├── Nuke-dummy.m
│ │ ├── Nuke-prefix.pch
│ │ ├── Nuke-umbrella.h
│ │ ├── Nuke.modulemap
│ │ └── Nuke.xcconfig
│ ├── Pods-Left
│ │ ├── Info.plist
│ │ ├── Pods-Left-acknowledgements.markdown
│ │ ├── Pods-Left-acknowledgements.plist
│ │ ├── Pods-Left-dummy.m
│ │ ├── Pods-Left-frameworks.sh
│ │ ├── Pods-Left-resources.sh
│ │ ├── Pods-Left-umbrella.h
│ │ ├── Pods-Left.debug.xcconfig
│ │ ├── Pods-Left.modulemap
│ │ └── Pods-Left.release.xcconfig
│ ├── SwiftyDrop
│ │ ├── Info.plist
│ │ ├── SwiftyDrop-dummy.m
│ │ ├── SwiftyDrop-prefix.pch
│ │ ├── SwiftyDrop-umbrella.h
│ │ ├── SwiftyDrop.modulemap
│ │ └── SwiftyDrop.xcconfig
│ ├── SwiftyJSON
│ │ ├── Info.plist
│ │ ├── SwiftyJSON-dummy.m
│ │ ├── SwiftyJSON-prefix.pch
│ │ ├── SwiftyJSON-umbrella.h
│ │ ├── SwiftyJSON.modulemap
│ │ └── SwiftyJSON.xcconfig
│ └── UIScrollView-InfiniteScroll
│ │ ├── Info.plist
│ │ ├── UIScrollView-InfiniteScroll-dummy.m
│ │ ├── UIScrollView-InfiniteScroll-prefix.pch
│ │ ├── UIScrollView-InfiniteScroll-umbrella.h
│ │ ├── UIScrollView-InfiniteScroll.modulemap
│ │ └── UIScrollView-InfiniteScroll.xcconfig
└── UIScrollView-InfiniteScroll
│ ├── Classes
│ ├── UIScrollView+InfiniteScroll.h
│ └── UIScrollView+InfiniteScroll.m
│ ├── LICENSE
│ └── README.md
├── README.md
├── left1.png
└── left2.png
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/.DS_Store
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Alamofire"]
2 | path = Alamofire
3 | url = https://github.com/Alamofire/Alamofire.git
4 | [submodule "Vendor/Freddy"]
5 | path = Vendor/Freddy
6 | url = https://github.com/bignerdranch/Freddy.git
7 | [submodule "SwiftyJSON"]
8 | path = SwiftyJSON
9 | url = https://github.com/SwiftyJSON/SwiftyJSON
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Alejandrina Patron
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Left.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Left.xcodeproj/project.xcworkspace/xcshareddata/Left.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "8117E2D88D6DFC26835CAE7E84D922F008CA7B7E",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "6ADA245F937D8ED6D99F5A7865E19F5267A169E2" : 0,
8 | "8117E2D88D6DFC26835CAE7E84D922F008CA7B7E" : 0,
9 | "C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3" : 0,
10 | "67620B5EFA902936DF04070AF595B76AB0333747" : 0
11 | },
12 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "42669628-17D7-439E-8E6A-5AA87D2652AC",
13 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
14 | "6ADA245F937D8ED6D99F5A7865E19F5267A169E2" : "Left\/Vendor\/Freddy\/",
15 | "8117E2D88D6DFC26835CAE7E84D922F008CA7B7E" : "Left\/",
16 | "C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3" : "Left\/SwiftyJSON\/",
17 | "67620B5EFA902936DF04070AF595B76AB0333747" : "Left\/Alamofire\/"
18 | },
19 | "DVTSourceControlWorkspaceBlueprintNameKey" : "Left",
20 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
21 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Left.xcodeproj",
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
23 | {
24 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Alamofire\/Alamofire.git",
25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "67620B5EFA902936DF04070AF595B76AB0333747"
27 | },
28 | {
29 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/bignerdranch\/Freddy.git",
30 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
31 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "6ADA245F937D8ED6D99F5A7865E19F5267A169E2"
32 | },
33 | {
34 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.gatech.edu\/apl7\/Left.git",
35 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
36 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8117E2D88D6DFC26835CAE7E84D922F008CA7B7E"
37 | },
38 | {
39 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/SwiftyJSON\/SwiftyJSON",
40 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
41 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "C861FC00CEE0F6A6BE81FCFF6785FAA78C58EBB3"
42 | }
43 | ]
44 | }
--------------------------------------------------------------------------------
/Left.xcodeproj/project.xcworkspace/xcuserdata/ale_patron.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left.xcodeproj/project.xcworkspace/xcuserdata/ale_patron.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Left.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Left.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/Left.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/Left.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Left.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | ED8039961BAC9D40009487B5
16 |
17 | primary
18 |
19 |
20 | ED8039AC1BAC9D40009487B5
21 |
22 | primary
23 |
24 |
25 | ED8039B71BAC9D40009487B5
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Left.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Left.xcworkspace/xcuserdata/ale_patron.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left.xcworkspace/xcuserdata/ale_patron.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Left.xcworkspace/xcuserdata/ale_patron.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Left/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/.DS_Store
--------------------------------------------------------------------------------
/Left/Assets.xcassets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/.DS_Store
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "29x29",
26 | "scale" : "3x"
27 | },
28 | {
29 | "size" : "40x40",
30 | "idiom" : "iphone",
31 | "filename" : "Icon-40@2x.png",
32 | "scale" : "2x"
33 | },
34 | {
35 | "size" : "40x40",
36 | "idiom" : "iphone",
37 | "filename" : "Icon-40@3x.png",
38 | "scale" : "3x"
39 | },
40 | {
41 | "idiom" : "iphone",
42 | "size" : "57x57",
43 | "scale" : "1x"
44 | },
45 | {
46 | "idiom" : "iphone",
47 | "size" : "57x57",
48 | "scale" : "2x"
49 | },
50 | {
51 | "size" : "60x60",
52 | "idiom" : "iphone",
53 | "filename" : "Icon-60@2x.png",
54 | "scale" : "2x"
55 | },
56 | {
57 | "size" : "60x60",
58 | "idiom" : "iphone",
59 | "filename" : "Icon-60@3x.png",
60 | "scale" : "3x"
61 | },
62 | {
63 | "idiom" : "ipad",
64 | "size" : "20x20",
65 | "scale" : "1x"
66 | },
67 | {
68 | "idiom" : "ipad",
69 | "size" : "20x20",
70 | "scale" : "2x"
71 | },
72 | {
73 | "idiom" : "ipad",
74 | "size" : "29x29",
75 | "scale" : "1x"
76 | },
77 | {
78 | "idiom" : "ipad",
79 | "size" : "29x29",
80 | "scale" : "2x"
81 | },
82 | {
83 | "idiom" : "ipad",
84 | "size" : "40x40",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-40@2x-1.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "idiom" : "ipad",
95 | "size" : "50x50",
96 | "scale" : "1x"
97 | },
98 | {
99 | "idiom" : "ipad",
100 | "size" : "50x50",
101 | "scale" : "2x"
102 | },
103 | {
104 | "idiom" : "ipad",
105 | "size" : "72x72",
106 | "scale" : "1x"
107 | },
108 | {
109 | "idiom" : "ipad",
110 | "size" : "72x72",
111 | "scale" : "2x"
112 | },
113 | {
114 | "size" : "76x76",
115 | "idiom" : "ipad",
116 | "filename" : "Icon-76@1x.png",
117 | "scale" : "1x"
118 | },
119 | {
120 | "size" : "76x76",
121 | "idiom" : "ipad",
122 | "filename" : "Icon-76@2x.png",
123 | "scale" : "2x"
124 | },
125 | {
126 | "size" : "83.5x83.5",
127 | "idiom" : "ipad",
128 | "filename" : "Icon-83.5@2x.png",
129 | "scale" : "2x"
130 | }
131 | ],
132 | "info" : {
133 | "version" : 1,
134 | "author" : "xcode"
135 | }
136 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-40@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-40@2x-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-76@1x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "8.0",
8 | "subtype" : "736h",
9 | "scale" : "3x"
10 | },
11 | {
12 | "orientation" : "landscape",
13 | "idiom" : "iphone",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "8.0",
16 | "subtype" : "736h",
17 | "scale" : "3x"
18 | },
19 | {
20 | "orientation" : "portrait",
21 | "idiom" : "iphone",
22 | "extent" : "full-screen",
23 | "minimum-system-version" : "8.0",
24 | "subtype" : "667h",
25 | "scale" : "2x"
26 | },
27 | {
28 | "orientation" : "portrait",
29 | "idiom" : "iphone",
30 | "extent" : "full-screen",
31 | "minimum-system-version" : "7.0",
32 | "scale" : "2x"
33 | },
34 | {
35 | "orientation" : "portrait",
36 | "idiom" : "iphone",
37 | "extent" : "full-screen",
38 | "minimum-system-version" : "7.0",
39 | "subtype" : "retina4",
40 | "scale" : "2x"
41 | },
42 | {
43 | "orientation" : "portrait",
44 | "idiom" : "iphone",
45 | "extent" : "full-screen",
46 | "scale" : "1x"
47 | },
48 | {
49 | "orientation" : "portrait",
50 | "idiom" : "iphone",
51 | "extent" : "full-screen",
52 | "scale" : "2x"
53 | },
54 | {
55 | "orientation" : "portrait",
56 | "idiom" : "iphone",
57 | "extent" : "full-screen",
58 | "subtype" : "retina4",
59 | "scale" : "2x"
60 | }
61 | ],
62 | "info" : {
63 | "version" : 1,
64 | "author" : "xcode"
65 | }
66 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "back@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "back@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/back.imageset/back@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/back.imageset/back@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/back.imageset/back@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/back.imageset/back@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/default.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "default.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "default-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "default-2.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/default.imageset/default-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/default.imageset/default-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/default.imageset/default-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/default.imageset/default-2.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/default.imageset/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/default.imageset/default.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/delete-ingredient.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "delete-ingredient.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "delete-ingredient-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "delete-ingredient-2.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/delete-ingredient.imageset/delete-ingredient-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/delete-ingredient.imageset/delete-ingredient-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/delete-ingredient.imageset/delete-ingredient-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/delete-ingredient.imageset/delete-ingredient-2.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/delete-ingredient.imageset/delete-ingredient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/delete-ingredient.imageset/delete-ingredient.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/forward.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "forward@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "forward@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/forward.imageset/forward@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/forward.imageset/forward@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/forward.imageset/forward@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/forward.imageset/forward@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/placeholder-favorites.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "placeholder-favorites.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "placeholder-favorites@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/placeholder-favorites.imageset/placeholder-favorites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/placeholder-favorites.imageset/placeholder-favorites.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/placeholder-favorites.imageset/placeholder-favorites@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/placeholder-favorites.imageset/placeholder-favorites@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/placeholder-search.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "placeholder-search.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "placeholder-search@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/placeholder-search.imageset/placeholder-search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/placeholder-search.imageset/placeholder-search.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/placeholder-search.imageset/placeholder-search@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/placeholder-search.imageset/placeholder-search@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/safari-activity.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "safari.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "safari@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "safari@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/safari-activity.imageset/safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/safari-activity.imageset/safari.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/safari-activity.imageset/safari@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/safari-activity.imageset/safari@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/safari-activity.imageset/safari@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/safari-activity.imageset/safari@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/search-tab-bar.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "search@1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "search@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "search@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/search-tab-bar.imageset/search@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/search-tab-bar.imageset/search@1x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/search-tab-bar.imageset/search@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/search-tab-bar.imageset/search@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/search-tab-bar.imageset/search@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/search-tab-bar.imageset/search@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-filled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "star-filled.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "star-filled-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "star-filled-2.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-filled.imageset/star-filled-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-filled.imageset/star-filled-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-filled.imageset/star-filled-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-filled.imageset/star-filled-2.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-filled.imageset/star-filled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-filled.imageset/star-filled.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-navbar.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "star@1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "star@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "star@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-navbar.imageset/star@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-navbar.imageset/star@1x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-navbar.imageset/star@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-navbar.imageset/star@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-navbar.imageset/star@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-navbar.imageset/star@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-tab-bar.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "star@1x.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "star@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "star@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-tab-bar.imageset/star@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-tab-bar.imageset/star@1x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-tab-bar.imageset/star@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-tab-bar.imageset/star@2x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star-tab-bar.imageset/star@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star-tab-bar.imageset/star@3x.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "star.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "star-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "star-2.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star.imageset/star-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star.imageset/star-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star.imageset/star-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star.imageset/star-2.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/star.imageset/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/star.imageset/star.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash-filled.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "trash.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "trash-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "trash-2.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash-filled.imageset/trash-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/trash-filled.imageset/trash-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash-filled.imageset/trash-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/trash-filled.imageset/trash-2.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash-filled.imageset/trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/trash-filled.imageset/trash.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "delete.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "delete-1.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "delete-2.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash.imageset/delete-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/trash.imageset/delete-1.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash.imageset/delete-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/trash.imageset/delete-2.png
--------------------------------------------------------------------------------
/Left/Assets.xcassets/trash.imageset/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Left/Assets.xcassets/trash.imageset/delete.png
--------------------------------------------------------------------------------
/Left/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 |
27 |
28 |
29 |
30 |
31 |
32 |
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 |
--------------------------------------------------------------------------------
/Left/Extensions/SearchTableView+Keyboard.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchTableView+Keyboard.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 1/25/17.
6 | // Copyright © 2017 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension SearchTableView {
12 | func subscribeToKeyboardNotifications() {
13 | NotificationCenter.default.addObserver(self, selector: #selector(SearchTableView.keyboardWillShow),
14 | name: NSNotification.Name.UIKeyboardWillShow,
15 | object: nil)
16 | NotificationCenter.default.addObserver(self, selector: #selector(SearchTableView.keyboardWillHide),
17 | name: NSNotification.Name.UIKeyboardWillHide,
18 | object: nil)
19 | }
20 |
21 | func unsubscribeFromKeyboardNotifications() {
22 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
23 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
24 | }
25 |
26 | func keyboardWillShow(notification: NSNotification) {
27 | if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
28 | let keyboardHeight = keyboardSize.height
29 | // if (self.view.frame.origin.y >= 0) {
30 | // view.frame.origin.y -= (keyboardHeight - (self.tabBarController?.tabBar.frame.size.height)!)
31 | // }
32 | self.searchButton.frame.origin.y -= (keyboardHeight - (self.tabBarController?.tabBar.frame.size.height)!)
33 | }
34 | }
35 |
36 | func keyboardWillHide(notification: NSNotification) {
37 | if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
38 | let keyboardHeight = keyboardSize.height
39 | // if (self.view.frame.origin.y < 0) {
40 | // view.frame.origin.y += (keyboardHeight - (self.tabBarController?.tabBar.frame.size.height)!)
41 | // }
42 | self.searchButton.frame.origin.y += (keyboardHeight - (self.tabBarController?.tabBar.frame.size.height)!)
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/Left/Extensions/String.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/4/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | extension String {
10 |
11 | func verifyRecipeName() -> String {
12 | var verifiedString = self
13 | verifiedString = verifiedString.replacingOccurrences(of: "&", with: "&")
14 | verifiedString = verifiedString.replacingOccurrences(of: "’", with: "'")
15 | verifiedString = verifiedString.replacingOccurrences(of: "™", with: "®")
16 | verifiedString = verifiedString.replacingOccurrences(of: " ", with: " ")
17 |
18 | return verifiedString
19 | }
20 |
21 | func urlToImg(completion: @escaping (UIImage?) -> ()) {
22 | DispatchQueue.global(qos: .background).async {
23 | let url = NSURL(string: self)
24 | if let data = NSData(contentsOf: url! as URL) {
25 | if let image = UIImage(data: data as Data) {
26 | DispatchQueue.main.async {
27 | completion(image)
28 | }
29 | }
30 | } else {
31 | DispatchQueue.main.async {
32 | completion(nil)
33 | }
34 | }
35 | }
36 | }
37 |
38 | func trim() -> String {
39 | return self.trimmingCharacters(in: NSCharacterSet.whitespaces)
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Left/Extensions/UIColor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/4/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | extension UIColor {
10 | class func LeftColor() -> UIColor {
11 | return UIColor(red: 153.0/255.0, green: 51.0/255.0, blue:255.0/255.0, alpha: 1.0)
12 | }
13 | }
--------------------------------------------------------------------------------
/Left/Extensions/UIViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/4/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import SwiftyDrop
10 |
11 | extension UIViewController {
12 |
13 | func showAlert(alertType: AlertType) {
14 | switch alertType {
15 | case .MoreThanFiveIngredients:
16 | let alert = UIAlertController(title: "Oops!", message: "You cannot use more than 5 ingredients", preferredStyle: .alert)
17 | let action = UIAlertAction(title: "Got it", style: .default) { _ in }
18 | alert.addAction(action)
19 | self.present(alert, animated: true) {}
20 |
21 | case .NoResults:
22 | let alert = UIAlertController(title: "😢", message: "No results found...", preferredStyle: .alert)
23 | let action = UIAlertAction(title: "Ok", style: .default) { _ in }
24 | alert.addAction(action)
25 | self.present(alert, animated: true) {}
26 |
27 | case .SearchFailure:
28 | let alert = UIAlertController(title: "Something went wrong", message: "Are you sure you are connected to the Internet? 🔌🌎", preferredStyle: .alert)
29 | let action = UIAlertAction(title: "Ok", style: .default) { _ in }
30 | alert.addAction(action)
31 | self.present(alert, animated: true) {}
32 |
33 | case .AtLeastOneIngredient:
34 | let alert = UIAlertController(title: "Hey", message: "Please provide at least one ingredient!", preferredStyle: .alert)
35 | let action = UIAlertAction(title: "Ok", style: .default) { _ in }
36 | alert.addAction(action)
37 | self.present(alert, animated: true) {}
38 | }
39 | }
40 | }
41 |
42 | // MARK: Alert Type
43 |
44 | enum AlertType {
45 | case MoreThanFiveIngredients
46 | case NoResults
47 | case SearchFailure
48 | case AtLeastOneIngredient
49 | }
50 |
51 | // MARK: Custom SwiftyDrop
52 |
53 | enum Custom: DropStatable {
54 | case Left
55 | var backgroundColor: UIColor? {
56 | switch self {
57 | case .Left: return UIColor.LeftColor()
58 | }
59 | }
60 | var font: UIFont? {
61 | switch self {
62 | case .Left: return UIFont(name: "HelveticaNeue", size: 16.0)
63 | }
64 | }
65 | var textColor: UIColor? {
66 | switch self {
67 | case .Left: return .white
68 | }
69 | }
70 | var blurEffect: UIBlurEffect? {
71 | switch self {
72 | case .Left: return nil
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Left/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 2.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSAllowsArbitraryLoads
28 |
29 |
30 | NSHumanReadableCopyright
31 | Copyright © 2016 Ale Patron. All rights reserved.
32 | UILaunchStoryboardName
33 | LaunchScreen
34 | UIMainStoryboardFile
35 | Main
36 | UIRequiredDeviceCapabilities
37 |
38 | armv7
39 |
40 | UIRequiresFullScreen
41 |
42 | UIStatusBarHidden
43 |
44 | UIStatusBarStyle
45 | UIStatusBarStyleLightContent
46 | UIStatusBarTintParameters
47 |
48 | UINavigationBar
49 |
50 | Style
51 | UIBarStyleDefault
52 | Translucent
53 |
54 |
55 |
56 | UISupportedInterfaceOrientations
57 |
58 | UIInterfaceOrientationPortrait
59 | UIInterfaceOrientationPortraitUpsideDown
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Left/LFTReviewCollectionCell.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 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
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 |
72 |
73 |
--------------------------------------------------------------------------------
/Left/Model/RecipeItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecipeItem.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 11/4/15.
6 | // Copyright © 2015 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let RecipeOpenCountKey = "recipeOpenCount"
12 |
13 | class RecipeItem: NSObject {
14 | var name: String
15 | var photo: UIImage?
16 | var url: String
17 | var photoUrl: String?
18 |
19 | let nameKey = "name"
20 | let photoKey = "photo"
21 | let urlKey = "url"
22 |
23 | func encodeWithCoder(_ aCoder: NSCoder) {
24 | aCoder.encode(name, forKey: nameKey)
25 | if let thePhoto = photo {
26 | aCoder.encode(thePhoto, forKey: photoKey)
27 | }
28 | aCoder.encode(url, forKey: urlKey)
29 | }
30 |
31 | required internal init?(coder aDecoder: NSCoder) {
32 | name = aDecoder.decodeObject(forKey: nameKey) as! String
33 | photo = aDecoder.decodeObject(forKey: photoKey) as? UIImage
34 | url = aDecoder.decodeObject(forKey: urlKey) as! String
35 | }
36 |
37 | init(name: String, photo: UIImage?, url: String) {
38 | self.name = name
39 | self.photo = photo
40 | self.url = url
41 | }
42 |
43 | init(name: String, photoUrl: String?, photo: UIImage?, url: String) {
44 | self.name = name
45 | self.photoUrl = photoUrl
46 | self.photo = photo
47 | self.url = url
48 | }
49 |
50 | // MARK: 3D touch quick actions
51 |
52 | func updateOpenCount() {
53 | if #available(iOS 9.0, *) {
54 | let data = UserDefaults.standard
55 | var dict: [String : Int] = data.dictionary(forKey: RecipeOpenCountKey) as? [String : Int] ?? [:]
56 | let key = "\(self.name)~~\(self.url)"
57 | let previousCount = dict[key] ?? 0
58 | dict.updateValue(previousCount + 1, forKey: key)
59 | data.set(dict, forKey: RecipeOpenCountKey)
60 |
61 | RecipeItem.updateShortcutItems()
62 | }
63 | }
64 |
65 | func removeFromDefaults(index: Int) {
66 | // 3D touch available iOS 9.0+
67 | if #available(iOS 9.0, *) {
68 | let data = UserDefaults.standard
69 | var dict: [String : Int] = data.dictionary(forKey: RecipeOpenCountKey) as? [String : Int] ?? [ : ]
70 | let recipeKey = "\(self.name)~~\(self.url)"
71 | dict.removeValue(forKey: recipeKey)
72 | data.set(dict, forKey: RecipeOpenCountKey)
73 |
74 | RecipeItem.updateShortcutItems()
75 | }
76 | }
77 |
78 | static func updateShortcutItems() {
79 | if #available(iOS 9.0, *) {
80 | let data = UserDefaults.standard
81 | let dict: [String : Int] = data.dictionary(forKey: RecipeOpenCountKey) as? [String : Int] ?? [ : ]
82 | let sortedDict = dict.sorted{ $0.1 > $1.1 }
83 | var shortcuts: [UIApplicationShortcutItem] = []
84 |
85 | for i in 0.. Bool {
18 | NetworkActivityIndicatorManager.shared.isEnabled = true
19 | return true
20 | }
21 |
22 | @available(iOS 9.0, *)
23 | func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
24 |
25 | guard let info = shortcutItem.userInfo else { return }
26 | guard let recipeName = info["NAME"] as? String else { return }
27 | guard let recipeURL = info["URL"] as? String else { return }
28 |
29 | openRecipeFromQuickAction(recipeName: recipeName, recipeURL: recipeURL)
30 | completionHandler(true)
31 | }
32 |
33 | private func openRecipeFromQuickAction(recipeName: String, recipeURL: String) {
34 | let webView = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "RecipeWebView") as! RecipeWebView
35 | webView.recipe = RecipeItem(name: recipeName, photo: nil, url: recipeURL)
36 | let tabsController = self.window?.rootViewController as! UITabBarController
37 | tabsController.selectedIndex = 1
38 | let favsTab = tabsController.viewControllers?[1] as! UINavigationController
39 | favsTab.popToRootViewController(animated: true)
40 | favsTab.pushViewController(webView, animated: true)
41 | }
42 |
43 | func applicationWillResignActive(_ application: UIApplication) {
44 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
45 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
46 | }
47 |
48 | func applicationDidEnterBackground(_ application: UIApplication) {
49 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
50 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
51 |
52 | // Dismiss keyboard when user presses home button while typing an ingredient on SearchVC
53 | self.window?.endEditing(true)
54 | }
55 |
56 | func applicationWillEnterForeground(_ application: UIApplication) {
57 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
58 | }
59 |
60 | func applicationDidBecomeActive(_ application: UIApplication) {
61 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
62 | }
63 |
64 | func applicationWillTerminate(_ application: UIApplication) {
65 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
66 | }
67 |
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Left/Other/Left-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Left-Bridging-Header.h
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 6/3/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | #ifndef BridgingHeader_h
10 | #define BridgingHeader_h
11 |
12 | #import
13 | #import
14 |
15 |
16 | #endif /* BridgingHeader_h */
17 |
--------------------------------------------------------------------------------
/Left/Other/SafariActivity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SafariActivity.swift
3 | //
4 | //
5 | // Created by Alejandrina Patron on 4/14/16.
6 | //
7 | //
8 |
9 | import UIKit
10 |
11 | class SafariActivity : UIActivity {
12 |
13 | var URL: NSURL?
14 |
15 | override var activityType: UIActivityType? {
16 | return UIActivityType(rawValue: NSStringFromClass(SafariActivity.self))
17 | }
18 |
19 | override var activityTitle: String? {
20 | return "Open in Safari"
21 | }
22 |
23 | override var activityImage: UIImage? {
24 | return UIImage(named: "safari-activity")
25 | }
26 |
27 | override func prepare(withActivityItems activityItems: [Any]) {
28 | for item in activityItems {
29 | if let item = item as? NSURL {
30 | URL = item
31 | }
32 | }
33 | }
34 |
35 | override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
36 | for item in activityItems {
37 | if let _ = item as? NSURL {
38 | return true
39 | }
40 | }
41 | return false
42 | }
43 |
44 | override func perform() {
45 | if let URL = URL {
46 | UIApplication.shared.openURL(URL as URL)
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/Left/Services/FavoritesManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FavoritesManager.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 3/4/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class FavoritesManager {
12 |
13 | // Singleton
14 | static let shared = FavoritesManager()
15 |
16 | private var favoriteRecipes = [RecipeItem]()
17 |
18 | func addRecipe(recipe: RecipeItem) {
19 | favoriteRecipes.append(recipe)
20 | save()
21 | }
22 |
23 | func deleteRecipeAtIndex(index: Int) {
24 | favoriteRecipes.remove(at: index)
25 | save()
26 | }
27 |
28 | func recipeAtIndex(index: Int) -> RecipeItem? {
29 | return favoriteRecipes[index]
30 | }
31 |
32 | func recipeCount() -> Int {
33 | return favoriteRecipes.count
34 | }
35 |
36 | func archivePath() -> String? {
37 | let directoryList = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
38 | if let documentsPath = directoryList.first {
39 | return documentsPath + "/Favorites"
40 | }
41 | assertionFailure("Could not determine where to save file.")
42 | return nil
43 | }
44 |
45 | func save() {
46 | if let theArchivePath = archivePath() {
47 | if NSKeyedArchiver.archiveRootObject(favoriteRecipes, toFile: theArchivePath) {
48 | print("We saved!")
49 | } else {
50 | assertionFailure("Could not save to \(theArchivePath)")
51 | }
52 | }
53 | }
54 |
55 | func unarchivedSavedItems() {
56 | if let theArchivePath = archivePath() {
57 | if FileManager.default.fileExists(atPath: theArchivePath) {
58 | favoriteRecipes = NSKeyedUnarchiver.unarchiveObject(withFile: theArchivePath) as! [RecipeItem]
59 | }
60 | }
61 | }
62 |
63 | init() {
64 | unarchivedSavedItems()
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Left/Services/Food2ForkService.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Food2ForkService.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/3/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import Alamofire
10 | import SwiftyJSON
11 |
12 | public struct Food2ForkService {
13 |
14 | private static let API_KEY: String = "570024717057c65d605c4d54f84f2300"
15 | private static let BASE_URL: String = "http://food2fork.com/api/search?key=" + API_KEY + "&q="
16 |
17 | static func recipesForIngredients(ingredients: String, page: Int, completion: @escaping ([RecipeItem], Error?) -> ()) {
18 | var urlString = BASE_URL + ingredients + "&page=\(page)"
19 | urlString = urlString.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
20 | Alamofire.request(urlString).responseJSON { response in
21 | switch response.result {
22 | case .success:
23 | let result = JSON(response.result.value!)
24 | let recipes = JSONParser.parseRecipes(data: result)
25 | completion(recipes, nil)
26 | case .failure(let error):
27 | completion([], error)
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Left/Services/JSONParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JSONParser.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/3/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import SwiftyJSON
10 |
11 | struct JSONParser {
12 |
13 | static func parseRecipes(data: JSON) -> [RecipeItem] {
14 | return self.JSONObjectsFromData(data: data)?.map(self.parseRecipe) ?? []
15 | }
16 |
17 | // MARK: Helper
18 |
19 | private static func parseRecipe(recipe: JSON) -> RecipeItem {
20 | let name = (recipe["title"].string ?? "").verifyRecipeName()
21 | let url: String = recipe["source_url"].string ?? ""
22 | let photoURL: String = recipe["image_url"].string!
23 | return RecipeItem(name: name, photoUrl: photoURL, photo: nil, url: url)
24 | }
25 |
26 | private static func JSONObjectsFromData(data: JSON?) -> [JSON]? {
27 | if let data = data {
28 | if let items = data["recipes"].array {
29 | return items
30 | }
31 | }
32 | return nil
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Left/Services/RecipesLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecipesLoader.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/4/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class RecipesLoader {
12 | private var hasMore: Bool
13 | private var isLoading: Bool = false
14 | private var page: Int = 1
15 | private let ingredients: String
16 |
17 | init(ingredients: String) {
18 | self.ingredients = ingredients
19 | self.hasMore = true
20 | }
21 |
22 | func load(page: Int = 1, completion: @escaping ([RecipeItem], Error?) -> ()) {
23 | if isLoading {
24 | return
25 | }
26 | Food2ForkService.recipesForIngredients(ingredients: self.ingredients, page: page, completion: completion)
27 |
28 | }
29 | func loadMore(completion: @escaping ([RecipeItem], Error?) -> ()) {
30 | page += 1
31 | load(page: page, completion: completion)
32 | }
33 |
34 | func hasMoreRecipes() -> Bool {
35 | return hasMore
36 | }
37 |
38 | func setHasMore(hasMore: Bool) {
39 | self.hasMore = hasMore
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Left/Services/SKStoreReviewManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SKStoreReviewManager.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 5/14/17.
6 | // Copyright © 2017 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import StoreKit
10 |
11 | struct SKStoreReviewManager {
12 |
13 | private static let APP_RUNS_KEY = "APP_RUNS"
14 |
15 | static func incrementAppRuns() {
16 | let defaults = UserDefaults.standard
17 | var appRuns = defaults.value(forKey: APP_RUNS_KEY) as? Int ?? 0
18 | appRuns += 1
19 | defaults.set(appRuns, forKey: APP_RUNS_KEY)
20 | }
21 |
22 | static func askForReview() {
23 | let defaults = UserDefaults.standard
24 | let appRuns = defaults.value(forKey: APP_RUNS_KEY) as? Int ?? 0
25 |
26 | if #available(iOS 10.3, *) {
27 | if appRuns > 0 && appRuns % 15 == 0 {
28 | SKStoreReviewController.requestReview()
29 | }
30 | } else {
31 | // Fallback on earlier versions
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Left/Services/ShortcutsManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShortcutsManager.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 6/11/17.
6 | // Copyright © 2017 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct ShortcutsManager {
12 |
13 | static func updateCount(for recipe: RecipeItem) {
14 |
15 | }
16 |
17 | static func removeFromDefaults(at index: Int) {
18 | // 3D touch available iOS 9.0+
19 | // if #available(iOS 9.0, *) {
20 | // let data = UserDefaults.standard
21 | // var dict: [String : Int] = data.dictionary(forKey: RecipeOpenCountKey) as? [String : Int] ?? [ : ]
22 | // let recipeKey = "\(self.name)~~\(self.url)"
23 | // dict.removeValue(forKey: recipeKey)
24 | // data.set(dict, forKey: RecipeOpenCountKey)
25 | //
26 | // RecipeItem.updateShortcutItems()
27 | // }
28 | }
29 |
30 | static func updateShortcutItems() {
31 |
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Left/View Controller/RecipeWebView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecipeWebView.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/4/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftyDrop
11 |
12 | class RecipeWebView: UIViewController, UIWebViewDelegate {
13 |
14 | @IBOutlet weak var webView: UIWebView!
15 | @IBOutlet weak var backButton: UIBarButtonItem!
16 | @IBOutlet weak var forwardButton: UIBarButtonItem!
17 | @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
18 |
19 | let favoritesManager = FavoritesManager.shared
20 | var recipe: RecipeItem!
21 | var saveButton: UIBarButtonItem!
22 |
23 | override func viewDidLoad() {
24 | super.viewDidLoad()
25 |
26 | // NOTE: saveButton visible when coming from Results but not from Favorites
27 | if let saveButton = self.navigationItem.rightBarButtonItem {
28 | saveButton.target = self
29 | saveButton.action = #selector(RecipeWebView.saveButtonPressed(sender:))
30 | } else {
31 | // Update open count of recipe for 3D touch quick actions
32 | // Only when coming from Favorites
33 | recipe.updateOpenCount()
34 | }
35 |
36 | self.navigationItem.title = recipe.name
37 | activityIndicator.hidesWhenStopped = true
38 | openUrl()
39 | }
40 |
41 | // override func viewWillAppear(_ animated: Bool) {
42 | // super.viewWillAppear(animated)
43 | //
44 | // self.tabBarController?.tabBar.isHidden = true
45 | // }
46 |
47 | @IBAction func refresh(sender: UIBarButtonItem) {
48 | webView.reload()
49 | }
50 |
51 | @IBAction func back(sender: UIBarButtonItem) {
52 | if webView.canGoBack {
53 | webView.goBack()
54 | }
55 | }
56 |
57 | @IBAction func forward(sender: UIBarButtonItem) {
58 | if webView.canGoForward {
59 | webView.goForward()
60 | }
61 | }
62 |
63 | @IBAction func action(sender: UIBarButtonItem) {
64 | showActivityViewController()
65 | }
66 |
67 | func webViewDidStartLoad(_ webView: UIWebView) {
68 | activityIndicator.startAnimating()
69 | }
70 |
71 | func webViewDidFinishLoad(_ webView: UIWebView) {
72 | activityIndicator.stopAnimating()
73 | updateNavButtons()
74 | }
75 |
76 | // MARK: Helper
77 |
78 | private func openUrl() {
79 | let url = NSURL(string: (self.recipe.url))
80 | let requesObj = NSURLRequest(url: url! as URL)
81 | webView.loadRequest(requesObj as URLRequest)
82 | }
83 |
84 | private func updateNavButtons() {
85 | backButton.isEnabled = webView.canGoBack
86 | forwardButton.isEnabled = webView.canGoForward
87 | }
88 |
89 | @objc private func saveButtonPressed(sender: UIBarButtonItem!) {
90 | favoritesManager.addRecipe(recipe: self.recipe)
91 | Drop.down("Added to your favorites ⭐", state: Custom.Left)
92 |
93 | // Haptic feedback (available iOS 10+)
94 | if #available(iOS 10.0, *) {
95 | let savedRecipeFeedbackGenerator = UIImpactFeedbackGenerator(style: .heavy)
96 | savedRecipeFeedbackGenerator.impactOccurred()
97 | }
98 | }
99 |
100 | // MARK: Safari Activity
101 |
102 | func showActivityViewController() {
103 | let activityItems: [AnyObject] =
104 | ["I found this recipe on Left app " as AnyObject, NSURL(string: self.recipe.url) as AnyObject]
105 | let activities: [UIActivity] = [SafariActivity()]
106 | let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: activities)
107 | activityViewController.view.tintColor = UIColor.LeftColor()
108 | present(activityViewController, animated: true, completion: {})
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/Left/View Controller/SearchTableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchTableView.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 8/6/16.
6 | // Copyright © 2016 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import DZNEmptyDataSet
11 |
12 | class SearchTableView: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate {
13 |
14 | @IBOutlet weak var textField: UITextField!
15 | @IBOutlet weak var tableView: UITableView!
16 | @IBOutlet weak var searchButton: UIButton!
17 |
18 | let textFieldPlaceholder = "Type an ingredient and press +"
19 | var ingredients = [String]()
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 |
24 | SKStoreReviewManager.incrementAppRuns()
25 | SKStoreReviewManager.askForReview()
26 |
27 | subscribeToKeyboardNotifications()
28 |
29 | self.tableView.emptyDataSetSource = self
30 | self.tableView.emptyDataSetDelegate = self
31 | self.tableView.dataSource = self
32 |
33 | tableView.tableFooterView = UIView(frame: CGRect.zero)
34 |
35 | textField.placeholder = textFieldPlaceholder
36 | textField.tintColor = UIColor.LeftColor()
37 | textField.delegate = self
38 |
39 | searchButtonEnabled()
40 |
41 | let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(SearchTableView.dismissKeyboard))
42 | self.view.addGestureRecognizer(tap)
43 | }
44 |
45 | // override func viewWillDisappear(_ animated: Bool) {
46 | // super.viewWillDisappear(animated)
47 | // unsubscribeFromKeyboardNotifications()
48 | // }
49 |
50 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
51 | if segue.identifier == "resultsSegue" {
52 | let destinationVC = segue.destination as! ResultsCollectionView
53 | destinationVC.ingredients = ingredients
54 | }
55 | }
56 |
57 | // MARK: IBAction
58 |
59 | @IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
60 | addIngreditent()
61 | }
62 |
63 | @IBAction func searchButtonPressed(_ sender: UIButton) {
64 | dismissKeyboard()
65 | performSegue(withIdentifier: "resultsSegue", sender: sender)
66 | }
67 |
68 | // MARK: Table View Delegate
69 |
70 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
71 | return ingredients.count
72 | }
73 |
74 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
75 | let cell = tableView.dequeueReusableCell(withIdentifier: "ingredientCell") as! IngredientCell
76 | cell.ingredient = ingredients[indexPath.row]
77 |
78 | // Handle delete button action
79 | cell.deleteButton.layer.setValue(indexPath.row, forKey: "index")
80 | cell.deleteButton.addTarget(self, action: #selector(SearchTableView.deleteIngredient(sender:)), for: UIControlEvents.touchUpInside)
81 |
82 | return cell
83 | }
84 |
85 | // MARK: Text Field Delegate
86 |
87 | func textFieldShouldReturn(_ textField: UITextField) -> Bool {
88 | textField.resignFirstResponder()
89 | addIngreditent()
90 | return true
91 | }
92 |
93 | // MARK: DZNEMptyDataSet Delegate
94 | func image(forEmptyDataSet scrollView: UIScrollView!) -> UIImage! {
95 | return UIImage(named: "placeholder-search")
96 | }
97 |
98 | func description(forEmptyDataSet scrollView: UIScrollView!) -> NSAttributedString! {
99 | let message = "What do you have Left today?"
100 | let attribute = [NSForegroundColorAttributeName: UIColor.lightGray, NSFontAttributeName: UIFont(name: "HelveticaNeue", size: 22.0)!]
101 | return NSAttributedString(string: message, attributes: attribute)
102 | }
103 |
104 |
105 | // MARK: Helper
106 |
107 | func dismissKeyboard() {
108 | self.view.endEditing(true)
109 | textField.resignFirstResponder()
110 | }
111 |
112 | func searchButtonEnabled() {
113 | if ingredients.count > 0 {
114 | searchButton.isEnabled = true
115 | searchButton.backgroundColor = UIColor.LeftColor()
116 | } else {
117 | searchButton.isEnabled = false
118 | searchButton.backgroundColor = UIColor.lightGray
119 | }
120 | }
121 |
122 | func addIngreditent() {
123 | if let ingredient = textField.text {
124 | let trimmedIngredient = ingredient.trim()
125 | if !trimmedIngredient.isEmpty {
126 | self.ingredients.append(trimmedIngredient)
127 | self.tableView.reloadData()
128 | self.textField.text = ""
129 | self.textField.placeholder = textFieldPlaceholder
130 | dismissKeyboard()
131 | searchButtonEnabled()
132 | }
133 | }
134 | }
135 |
136 | func deleteIngredient(sender: UIButton) {
137 | let index: Int = (sender.layer.value(forKey: "index")) as! Int
138 | ingredients.remove(at: index)
139 | tableView.reloadData()
140 | dismissKeyboard()
141 | searchButtonEnabled()
142 | }
143 | }
144 |
145 | // MARK: UITableViewCell
146 |
147 | class IngredientCell: UITableViewCell {
148 |
149 | @IBOutlet weak var ingredientLabel: UILabel!
150 | @IBOutlet weak var deleteButton: UIButton!
151 |
152 | var ingredient: String! {
153 | didSet {
154 | self.ingredientLabel.text = ingredient
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/Left/View/RecipeCollectionCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LFTRecipeCollectionCell.swift
3 | // Left
4 | //
5 | // Created by Alejandrina Patron on 6/9/17.
6 | // Copyright © 2017 Ale Patrón. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class RecipeCollectionCell: UICollectionViewCell {
12 |
13 | @IBOutlet weak var actionButton: UIButton!
14 | @IBOutlet weak var recipePhoto: UIImageView!
15 | @IBOutlet weak var recipeName: UILabel!
16 |
17 | var recipe: RecipeItem! {
18 | didSet {
19 | recipeName.text = recipe.name
20 | recipePhoto.contentMode = UIViewContentMode.scaleAspectFill
21 | recipePhoto.clipsToBounds = true
22 | if recipe.photo != nil {
23 | recipePhoto.image = recipe.photo
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/LeftTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LeftTests/LeftTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LeftTests.swift
3 | // LeftTests
4 | //
5 | // Created by Alejandrina Patron on 9/18/15.
6 | // Copyright © 2015 A(pps)PL. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Left
11 |
12 | class LeftTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure // Put the code you want to measure the time of here.
32 | }
33 | }
34 |
35 |
36 |
--------------------------------------------------------------------------------
/LeftUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LeftUITests/LeftUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LeftUITests.swift
3 | // LeftUITests
4 | //
5 | // Created by Alejandrina Patron on 9/18/15.
6 | // Copyright © 2015 A(pps)PL. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class LeftUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 | platform :ios, ‘10.0’
3 | use_frameworks!
4 | target 'Left' do
5 | pod 'Alamofire', '~> 4.0’
6 | pod 'SwiftyJSON'
7 | pod 'AlamofireNetworkActivityIndicator', '~> 2.0’
8 | pod 'UIScrollView-InfiniteScroll'
9 | pod 'Nuke', '~> 4.0'
10 | pod 'DZNEmptyDataSet'
11 | pod 'SwiftyDrop', '~>3.0'
12 | end
13 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (4.2.0)
3 | - AlamofireNetworkActivityIndicator (2.1.0):
4 | - Alamofire (~> 4.1)
5 | - DZNEmptyDataSet (1.8.1)
6 | - Nuke (4.1.2)
7 | - SwiftyDrop (3.0.3)
8 | - SwiftyJSON (3.1.3)
9 | - UIScrollView-InfiniteScroll (0.9.1)
10 |
11 | DEPENDENCIES:
12 | - Alamofire (~> 4.0)
13 | - AlamofireNetworkActivityIndicator (~> 2.0)
14 | - DZNEmptyDataSet
15 | - Nuke (~> 4.0)
16 | - SwiftyDrop (~> 3.0)
17 | - SwiftyJSON
18 | - UIScrollView-InfiniteScroll
19 |
20 | SPEC CHECKSUMS:
21 | Alamofire: aa2e09d871c9160ac53c90e83c68064a94e3dfbe
22 | AlamofireNetworkActivityIndicator: 4716f6554bdfb9c7cf13b1e0e3af21163129690a
23 | DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
24 | Nuke: 7cfd2acdf90c36f66e6ea40795bac0d851a9afe0
25 | SwiftyDrop: 785f95aabc26c4d832576bb78dc4ba7d0594a95b
26 | SwiftyJSON: 38a8ea2006779c0fc4c310cb2ee8195327740faf
27 | UIScrollView-InfiniteScroll: 14e204c50ca4040467e1cbfa141dad7a18919b56
28 |
29 | PODFILE CHECKSUM: 62ca1498b01d9b14899d0aff32d9cfc3d0ccce8e
30 |
31 | COCOAPODS: 1.2.0.beta.1
32 |
--------------------------------------------------------------------------------
/Pods/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/Pods/.DS_Store
--------------------------------------------------------------------------------
/Pods/Alamofire/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DispatchQueue+Alamofire.swift
3 | //
4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
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
14 | // all 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
22 | // THE SOFTWARE.
23 | //
24 |
25 | import Dispatch
26 | import Foundation
27 |
28 | extension DispatchQueue {
29 | static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) }
30 | static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) }
31 | static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) }
32 | static var background: DispatchQueue { return DispatchQueue.global(qos: .background) }
33 |
34 | func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
35 | asyncAfter(deadline: .now() + delay, execute: closure)
36 | }
37 |
38 | func syncResult(_ closure: () -> T) -> T {
39 | var result: T!
40 | sync { result = closure() }
41 | return result
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Pods/Alamofire/Source/Notifications.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Notifications.swift
3 | //
4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
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
14 | // all 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
22 | // THE SOFTWARE.
23 | //
24 |
25 | import Foundation
26 |
27 | extension Notification.Name {
28 | /// Used as a namespace for all `URLSessionTask` related notifications.
29 | public struct Task {
30 | /// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`.
31 | public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume")
32 |
33 | /// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`.
34 | public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend")
35 |
36 | /// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`.
37 | public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel")
38 |
39 | /// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`.
40 | public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete")
41 | }
42 | }
43 |
44 | // MARK: -
45 |
46 | extension Notification {
47 | /// Used as a namespace for all `Notification` user info dictionary keys.
48 | public struct Key {
49 | /// User info dictionary key representing the `URLSessionTask` associated with the notification.
50 | public static let Task = "org.alamofire.notification.key.task"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Pods/Alamofire/Source/Result.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Result.swift
3 | //
4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
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
14 | // all 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
22 | // THE SOFTWARE.
23 | //
24 |
25 | import Foundation
26 |
27 | /// Used to represent whether a request was successful or encountered an error.
28 | ///
29 | /// - success: The request and all post processing operations were successful resulting in the serialization of the
30 | /// provided associated value.
31 | ///
32 | /// - failure: The request encountered an error resulting in a failure. The associated values are the original data
33 | /// provided by the server as well as the error that caused the failure.
34 | public enum Result {
35 | case success(Value)
36 | case failure(Error)
37 |
38 | /// Returns `true` if the result is a success, `false` otherwise.
39 | public var isSuccess: Bool {
40 | switch self {
41 | case .success:
42 | return true
43 | case .failure:
44 | return false
45 | }
46 | }
47 |
48 | /// Returns `true` if the result is a failure, `false` otherwise.
49 | public var isFailure: Bool {
50 | return !isSuccess
51 | }
52 |
53 | /// Returns the associated value if the result is a success, `nil` otherwise.
54 | public var value: Value? {
55 | switch self {
56 | case .success(let value):
57 | return value
58 | case .failure:
59 | return nil
60 | }
61 | }
62 |
63 | /// Returns the associated error value if the result is a failure, `nil` otherwise.
64 | public var error: Error? {
65 | switch self {
66 | case .success:
67 | return nil
68 | case .failure(let error):
69 | return error
70 | }
71 | }
72 | }
73 |
74 | // MARK: - CustomStringConvertible
75 |
76 | extension Result: CustomStringConvertible {
77 | /// The textual representation used when written to an output stream, which includes whether the result was a
78 | /// success or failure.
79 | public var description: String {
80 | switch self {
81 | case .success:
82 | return "SUCCESS"
83 | case .failure:
84 | return "FAILURE"
85 | }
86 | }
87 | }
88 |
89 | // MARK: - CustomDebugStringConvertible
90 |
91 | extension Result: CustomDebugStringConvertible {
92 | /// The debug textual representation used when written to an output stream, which includes whether the result was a
93 | /// success or failure in addition to the value or error.
94 | public var debugDescription: String {
95 | switch self {
96 | case .success(let value):
97 | return "SUCCESS: \(value)"
98 | case .failure(let error):
99 | return "FAILURE: \(error)"
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Pods/AlamofireNetworkActivityIndicator/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Alamofire Software Foundation (http://alamofire.org/)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Pods/DZNEmptyDataSet/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Ignacio Romero Zurbuchen iromero@dzen.cl
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/Pods/Local Podspecs/SwiftyJSON.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "SwiftyJSON",
3 | "version": "2.3.2",
4 | "summary": "SwiftyJSON makes it easy to deal with JSON data in Swift",
5 | "homepage": "https://github.com/SwiftyJSON/SwiftyJSON",
6 | "license": {
7 | "type": "MIT"
8 | },
9 | "authors": {
10 | "lingoer": "lingoerer@gmail.com",
11 | "tangplin": "tangplin@gmail.com"
12 | },
13 | "requires_arc": true,
14 | "platforms": {
15 | "osx": "10.9",
16 | "ios": "8.0",
17 | "watchos": "2.0",
18 | "tvos": "9.0"
19 | },
20 | "source": {
21 | "git": "https://github.com/SwiftyJSON/SwiftyJSON.git",
22 | "tag": "2.3.2"
23 | },
24 | "source_files": "Source/*.swift"
25 | }
26 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (4.2.0)
3 | - AlamofireNetworkActivityIndicator (2.1.0):
4 | - Alamofire (~> 4.1)
5 | - DZNEmptyDataSet (1.8.1)
6 | - Nuke (4.1.2)
7 | - SwiftyDrop (3.0.3)
8 | - SwiftyJSON (3.1.3)
9 | - UIScrollView-InfiniteScroll (0.9.1)
10 |
11 | DEPENDENCIES:
12 | - Alamofire (~> 4.0)
13 | - AlamofireNetworkActivityIndicator (~> 2.0)
14 | - DZNEmptyDataSet
15 | - Nuke (~> 4.0)
16 | - SwiftyDrop (~> 3.0)
17 | - SwiftyJSON
18 | - UIScrollView-InfiniteScroll
19 |
20 | SPEC CHECKSUMS:
21 | Alamofire: aa2e09d871c9160ac53c90e83c68064a94e3dfbe
22 | AlamofireNetworkActivityIndicator: 4716f6554bdfb9c7cf13b1e0e3af21163129690a
23 | DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
24 | Nuke: 7cfd2acdf90c36f66e6ea40795bac0d851a9afe0
25 | SwiftyDrop: 785f95aabc26c4d832576bb78dc4ba7d0594a95b
26 | SwiftyJSON: 38a8ea2006779c0fc4c310cb2ee8195327740faf
27 | UIScrollView-InfiniteScroll: 14e204c50ca4040467e1cbfa141dad7a18919b56
28 |
29 | PODFILE CHECKSUM: 62ca1498b01d9b14899d0aff32d9cfc3d0ccce8e
30 |
31 | COCOAPODS: 1.2.0.beta.1
32 |
--------------------------------------------------------------------------------
/Pods/Nuke/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Alexander Grebenyuk
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/CancellationToken.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | /// Manages cancellation tokens and signals them when cancellation is requested.
8 | ///
9 | /// All `CancellationTokenSource` methods are thread safe.
10 | public final class CancellationTokenSource {
11 | public private(set) var isCancelling = false
12 | private var observers = [(Void) -> Void]()
13 | private let lock: Lock
14 |
15 | public var token: CancellationToken {
16 | return CancellationToken(source: self)
17 | }
18 |
19 | public init() {
20 | self.lock = Lock()
21 | }
22 |
23 | // Allows to create cts with a shared mutex to avoid excessive allocations.
24 | // This optimization gives you small wins in absolute numbers. It's also
25 | // tricky to get right thus `internal` access modifier.
26 | internal init(lock: Lock) { self.lock = lock }
27 | internal static let lock = Lock()
28 |
29 | fileprivate func register(_ closure: @escaping (Void) -> Void) {
30 | if isCancelling { closure(); return } // fast pre-lock check
31 | lock.sync {
32 | if isCancelling {
33 | closure()
34 | } else {
35 | observers.append(closure)
36 | }
37 | }
38 | }
39 |
40 | /// Communicates a request for cancellation to the managed token.
41 | public func cancel() {
42 | if isCancelling { return } // fast pre-lock check
43 | lock.sync {
44 | if !isCancelling {
45 | isCancelling = true
46 | observers.forEach { $0() }
47 | observers.removeAll()
48 | }
49 | }
50 | }
51 | }
52 |
53 | /// Enables cooperative cancellation of operations.
54 | ///
55 | /// You create a cancellation token by instantiating a `CancellationTokenSource`
56 | /// object and calling its `token` property. You then pass the token to any
57 | /// number of threads, tasks, or operations that should receive notice of
58 | /// cancellation. When the owning object calls `cancel()`, the `isCancelling`
59 | /// property on every copy of the cancellation token is set to `true`.
60 | /// The registered objects can respond in whatever manner is appropriate.
61 | ///
62 | /// All `CancellationToken` methods are thread safe.
63 | public struct CancellationToken {
64 | fileprivate let source: CancellationTokenSource
65 |
66 | /// Returns `true` if cancellation has been requested for this token.
67 | public var isCancelling: Bool { return source.isCancelling }
68 |
69 | /// Registers the closure that will be called when the token is canceled.
70 | /// If this token is already cancelled, the closure will be run immediately
71 | /// and synchronously.
72 | /// - warning: Make sure that you don't capture token inside a closure to
73 | /// avoid retain cycles.
74 | public func register(closure: @escaping (Void) -> Void) { source.register(closure) }
75 | }
76 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/DataDecoder.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | #if os(macOS)
6 | import Cocoa
7 | #else
8 | import UIKit
9 | #endif
10 |
11 | #if os(watchOS)
12 | import WatchKit
13 | #endif
14 |
15 | /// Decodes image data.
16 | public protocol DataDecoding {
17 | /// Decodes image data.
18 | func decode(data: Data, response: URLResponse) -> Image?
19 | }
20 |
21 | private let queue = DispatchQueue(label: "com.github.kean.Nuke.DataDecoder")
22 |
23 | /// Decodes image data.
24 | public struct DataDecoder: DataDecoding {
25 | /// Initializes the receiver.
26 | public init() {}
27 |
28 | /// Creates an `UIImage` (`NSImage` on macOS) with the given data.
29 | /// Image scale is set to the scale of the main screen.
30 | public func decode(data: Data, response: URLResponse) -> Image? {
31 | guard DataDecoder.validate(response: response) else { return nil }
32 | // Image initializers are not thread safe:
33 | // - https://github.com/AFNetworking/AFNetworking/issues/2572
34 | // - https://github.com/Alamofire/AlamofireImage/issues/75
35 | return queue.sync {
36 | #if os(macOS)
37 | return NSImage(data: data)
38 | #else
39 | #if os(iOS) || os(tvOS)
40 | let scale = UIScreen.main.scale
41 | #else
42 | let scale = WKInterfaceDevice.current().screenScale
43 | #endif
44 | return UIImage(data: data, scale: scale)
45 | #endif
46 | }
47 | }
48 |
49 | private static func validate(response: URLResponse) -> Bool {
50 | guard let response = response as? HTTPURLResponse else { return true }
51 | return (200..<300).contains(response.statusCode)
52 | }
53 | }
54 |
55 | /// Composes multiple data decoders.
56 | public final class DataDecoderComposition: DataDecoding {
57 | public let decoders: [DataDecoding]
58 |
59 | /// Composes multiple data decoders.
60 | public init(decoders: [DataDecoding]) {
61 | self.decoders = decoders
62 | }
63 |
64 | /// Decoders are applied in order in which they are present in the decoders
65 | /// array. The decoding stops when one of the decoders produces an image.
66 | public func decode(data: Data, response: URLResponse) -> Image? {
67 | for decoder in decoders {
68 | if let image = decoder.decode(data: data, response: response) {
69 | return image
70 | }
71 | }
72 | return nil
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/DataLoader.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | /// Loads data.
8 | public protocol DataLoading {
9 | /// Loads data with the given request.
10 | func loadData(with request: URLRequest, token: CancellationToken?) -> Promise<(Data, URLResponse)>
11 | }
12 |
13 | /// Provides basic networking using `URLSession`.
14 | public final class DataLoader: DataLoading {
15 | public private(set) var session: URLSession
16 | private let scheduler: AsyncScheduler
17 |
18 | /// Initializes `DataLoader` with the given configuration.
19 | /// - parameter configuration: `URLSessionConfiguration.default` with
20 | /// `URLCache` with 0MB memory capacity and 200MB disk capacity.
21 | /// - parameter scheduler: `OperationQueueScheduler` with `maxConcurrentOperationCount` 8 by default.
22 | /// Scheduler is wrapped in a `RateLimiter` to prevent `URLSession` trashing.
23 | public init(configuration: URLSessionConfiguration = DataLoader.defaultConfiguration(), scheduler: AsyncScheduler = RateLimiter(scheduler: OperationQueueScheduler(maxConcurrentOperationCount: 8))) {
24 | self.session = URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
25 | self.scheduler = scheduler
26 | }
27 |
28 | private static func defaultConfiguration() -> URLSessionConfiguration {
29 | let conf = URLSessionConfiguration.default
30 | conf.urlCache = URLCache(memoryCapacity: 0, diskCapacity: (200 * 1024 * 1024), diskPath: "com.github.kean.Nuke.Cache")
31 | return conf
32 | }
33 |
34 | /// Loads data with the given request.
35 | public func loadData(with request: URLRequest, token: CancellationToken? = nil) -> Promise<(Data, URLResponse)> {
36 | return Promise() { fulfill, reject in
37 | scheduler.execute(token: token) { finish in
38 | let task = self.session.dataTask(with: request) { data, response, error in
39 | if let data = data, let response = response {
40 | fulfill((data, response))
41 | } else {
42 | reject(error ?? NSError(domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil))
43 | }
44 | finish()
45 | }
46 | token?.register {
47 | task.cancel()
48 | finish()
49 | }
50 | task.resume()
51 | }
52 | }
53 | }
54 | }
55 |
56 | /// Stores `CachedURLResponse` objects.
57 | public protocol DataCaching {
58 | /// Returns response for the given request.
59 | func response(for request: URLRequest, token: CancellationToken?) -> Promise
60 |
61 | /// Stores response for the given request.
62 | func setResponse(_ response: CachedURLResponse, for request: URLRequest)
63 | }
64 |
65 | public final class CachingDataLoader: DataLoading {
66 | private var loader: DataLoading
67 | private var cache: DataCaching
68 |
69 | public init(loader: DataLoading, cache: DataCaching) {
70 | self.loader = loader
71 | self.cache = cache
72 | }
73 |
74 | public func loadData(with request: URLRequest, token: CancellationToken?) -> Promise<(Data, URLResponse)> {
75 | return cache.response(for: request, token: token)
76 | .then { ($0.data, $0.response) }
77 | .recover { _ in
78 | self.loader.loadData(with: request, token: token).then {
79 | self.cache.setResponse(CachedURLResponse(response: $0.1, data: $0.0), for: request)
80 | }
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/Deduplicator.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | /// Combines requests with the same `loadKey` into a single request. This request
8 | /// is only cancelled when all underlying requests are cancelled.
9 | ///
10 | /// All `Deduplicator` methods are thread-safe.
11 | public final class Deduplicator: Loading {
12 | private let loader: Loading
13 | private var tasks = [AnyHashable: Task]()
14 | private let queue = DispatchQueue(label: "com.github.kean.Nuke.Deduplicator")
15 |
16 | /// Initializes the `Deduplicator` instance with the underlying
17 | /// `loader` used for actual image loading, and the request `equator`.
18 | /// - parameter loader: Underlying loader used for loading images.
19 | public init(loader: Loading) {
20 | self.loader = loader
21 | }
22 |
23 | /// Returns an existing pending promise if there is one. Starts a new request otherwise.
24 | public func loadImage(with request: Request, token: CancellationToken? = nil) -> Promise {
25 | return queue.sync {
26 | let key = Request.loadKey(for: request)
27 | var task: Task! = tasks[key] // Find existing promise
28 | if task == nil {
29 | let cts = CancellationTokenSource()
30 | let promise = loader.loadImage(with: request, token: cts.token)
31 | task = Task(promise: promise, cts: cts)
32 | tasks[key] = task
33 | promise.completion(on: queue) { [weak self, weak task] _ in
34 | if let task = task { self?.remove(task, key: key) }
35 | }
36 | } else {
37 | task.retainCount += 1
38 | }
39 |
40 | token?.register { [weak self, weak task] in
41 | if let task = task { self?.cancel(task, key: key) }
42 | }
43 |
44 | return task.promise
45 | }
46 | }
47 |
48 | private func cancel(_ task: Task, key: AnyHashable) {
49 | queue.async {
50 | task.retainCount -= 1
51 | if task.retainCount == 0 { // No more requests registered
52 | task.cts.cancel() // Cancel underlying request
53 | self.remove(task, key: key)
54 | }
55 | }
56 | }
57 |
58 | private func remove(_ task: Task, key: AnyHashable) {
59 | if tasks[key] === task { // Still managed by Deduplicator
60 | tasks[key] = nil
61 | }
62 | }
63 |
64 | private final class Task {
65 | let promise: Promise
66 | let cts: CancellationTokenSource
67 | var retainCount = 1
68 | init(promise: Promise, cts: CancellationTokenSource) {
69 | self.promise = promise
70 | self.cts = cts
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/Loader.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | /// Loads images.
8 | public protocol Loading {
9 | /// Loads an image with the given request.
10 | func loadImage(with request: Request, token: CancellationToken?) -> Promise
11 | }
12 |
13 | public extension Loading {
14 | /// Loads an image with the given URL.
15 | func loadImage(with url: URL, token: CancellationToken? = nil) -> Promise {
16 | return loadImage(with: Request(url: url), token: token)
17 | }
18 | }
19 |
20 | /// `Loader` implements an image loading pipeline which consists of the
21 | /// several steps:
22 | ///
23 | /// 1. Read an image from the memory cache (if cache isn't `nil`). If the image
24 | /// is found skip remaining steps.
25 | /// 2. Load data using an object conforming to `DataLoading` protocol.
26 | /// 3. Create an image with the data using `DataDecoding` object.
27 | /// 4. Transform the image using processor (`Processing`) provided in the request.
28 | /// 5. Save the image into the memory cache (if cache isn't `nil`).
29 | ///
30 | /// See built-in `CachingDataLoader` class if you need to add custom data cache
31 | /// into the pipeline.
32 | ///
33 | /// `Loader` is thread-safe.
34 | public final class Loader: Loading {
35 | public let loader: DataLoading
36 | public let decoder: DataDecoding
37 | public let cache: Caching?
38 |
39 | private let schedulers: Schedulers
40 | private let queue = DispatchQueue(label: "com.github.kean.Nuke.Loader")
41 |
42 | /// Returns a processor for the given image and request. Default
43 | /// implementation simply returns `request.processor`.
44 | public var makeProcessor: (Image, Request) -> AnyProcessor? = {
45 | return $1.processor
46 | }
47 |
48 | /// Initializes `Loader` instance with the given loader, decoder and cache.
49 | /// - parameter schedulers: `Schedulers()` by default.
50 | public init(loader: DataLoading, decoder: DataDecoding, cache: Caching?, schedulers: Schedulers = Schedulers()) {
51 | self.loader = loader
52 | self.decoder = decoder
53 | self.cache = cache
54 | self.schedulers = schedulers
55 | }
56 |
57 | /// Loads an image for the given request using image loading pipeline.
58 | public func loadImage(with request: Request, token: CancellationToken? = nil) -> Promise {
59 | return queue.sync { promise(with: request, token: token) }
60 | }
61 |
62 | public func promise(with request: Request, token: CancellationToken? = nil) -> Promise {
63 | if request.memoryCacheOptions.readAllowed, let image = cache?[request] {
64 | return Promise(value: image)
65 | }
66 | // It's safe to capture `Loader` in promises
67 | return loader.loadData(with: request.urlRequest, token: token)
68 | .then(on: queue) { self.decode(data: $0, response: $1, token: token) }
69 | .then(on: queue) { self.process(image: $0, request: request, token: token) }
70 | .then(on: queue) {
71 | if request.memoryCacheOptions.writeAllowed {
72 | self.cache?[request] = $0
73 | }
74 | }
75 | }
76 |
77 | private func decode(data: Data, response: URLResponse, token: CancellationToken? = nil) -> Promise {
78 | return Promise() { fulfill, reject in
79 | schedulers.decoding.execute(token: token) {
80 | if let image = self.decoder.decode(data: data, response: response) {
81 | fulfill(image)
82 | } else {
83 | reject(Error.decodingFailed)
84 | }
85 | }
86 | }
87 | }
88 |
89 | private func process(image: Image, request: Request, token: CancellationToken?) -> Promise {
90 | guard let processor = makeProcessor(image, request) else { return Promise(value: image) }
91 | return Promise() { fulfill, reject in
92 | schedulers.processing.execute(token: token) {
93 | if let image = processor.process(image) {
94 | fulfill(image)
95 | } else {
96 | reject(Error.processingFailed)
97 | }
98 | }
99 | }
100 | }
101 |
102 | /// Schedulers used to execute a corresponding steps of the pipeline.
103 | public struct Schedulers {
104 | /// `DispatchQueueScheduler` with a serial queue by default.
105 | public var decoding: Scheduler = DispatchQueueScheduler(queue: DispatchQueue(label: "com.github.kean.Nuke.Decoding"))
106 | // There is no reason to increase `maxConcurrentOperationCount` for
107 | // built-in `DataDecoder` that locks globally while decoding.
108 |
109 | /// `DispatchQueueScheduler` with a serial queue by default.
110 | public var processing: Scheduler = DispatchQueueScheduler(queue: DispatchQueue(label: "com.github.kean.Nuke.Processing"))
111 | }
112 |
113 | /// Error returns by `Loader` class itself. `Loader` might also return
114 | /// errors from underlying `DataLoading` object.
115 | public enum Error: Swift.Error {
116 | case decodingFailed
117 | case processingFailed
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/Nuke.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | #if os(macOS)
8 | import AppKit.NSImage
9 | /// Alias for NSImage
10 | public typealias Image = NSImage
11 | #else
12 | import UIKit.UIImage
13 | /// Alias for UIImage
14 | public typealias Image = UIImage
15 | #endif
16 |
17 | /// Loads an image into the given target.
18 | ///
19 | /// For more info see `loadImage(with:into:)` method of `Manager`.
20 | public func loadImage(with url: URL, into target: Target) {
21 | Manager.shared.loadImage(with: url, into: target)
22 | }
23 |
24 | /// Loads an image into the given target.
25 | ///
26 | /// For more info see `loadImage(with:into:)` method of `Manager`.
27 | public func loadImage(with request: Request, into target: Target) {
28 | Manager.shared.loadImage(with: request, into: target)
29 | }
30 |
31 | /// Loads an image and calls the given `handler`. The method itself
32 | /// **doesn't do** anything when the image is loaded - you have full
33 | /// control over how to display it, etc.
34 | ///
35 | /// The handler only gets called if the request is still associated with the
36 | /// `target` by the time it's completed.
37 | ///
38 | /// See `loadImage(with:into:)` method for more info.
39 | public func loadImage(with url: URL, into target: AnyObject, handler: @escaping Manager.Handler) {
40 | Manager.shared.loadImage(with: url, into: target, handler: handler)
41 | }
42 |
43 | /// Loads an image and calls the given `handler`.
44 | ///
45 | /// For more info see `loadImage(with:into:handler:)` method of `Manager`.
46 | public func loadImage(with request: Request, into target: AnyObject, handler: @escaping Manager.Handler) {
47 | Manager.shared.loadImage(with: request, into: target, handler: handler)
48 | }
49 |
50 | /// Cancels an outstanding request associated with the target.
51 | public func cancelRequest(for target: AnyObject) {
52 | Manager.shared.cancelRequest(for: target)
53 | }
54 |
55 | public extension Manager {
56 | /// Shared `Manager` instance.
57 | ///
58 | /// Shared manager is created with `Loader.shared` and `Cache.shared`.
59 | public static var shared = Manager(loader: Loader.shared, cache: Cache.shared)
60 | }
61 |
62 | public extension Loader {
63 | /// Shared `Loading` object.
64 | ///
65 | /// Shared loader is created with `DataLoader()`, `DataDecoder()` and
66 | // `Cache.shared`. The resulting loader is wrapped in a `Deduplicator`.
67 | public static var shared: Loading = Deduplicator(loader: Loader(loader: DataLoader(), decoder: DataDecoder(), cache: Cache.shared))
68 | }
69 |
70 | public extension Cache {
71 | /// Shared `Cache` instance.
72 | public static var shared = Cache()
73 | }
74 |
75 | internal final class Lock {
76 | var mutex = UnsafeMutablePointer.allocate(capacity: 1)
77 |
78 | init() {
79 | pthread_mutex_init(mutex, nil)
80 | }
81 |
82 | deinit {
83 | pthread_mutex_destroy(mutex)
84 | mutex.deinitialize()
85 | mutex.deallocate(capacity: 1)
86 | }
87 |
88 | /// In critical places it's better to use lock() and unlock() manually
89 | func sync(_ closure: (Void) -> T) -> T {
90 | pthread_mutex_lock(mutex)
91 | defer { pthread_mutex_unlock(mutex) }
92 | return closure()
93 | }
94 |
95 | func lock() { pthread_mutex_lock(mutex) }
96 | func unlock() { pthread_mutex_unlock(mutex) }
97 | }
98 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/Preheater.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | /// Prefetches and caches image in order to eliminate delays when you request
8 | /// individual images later.
9 | ///
10 | /// To start preheating call `startPreheating(with:)` method. When you
11 | /// need an individual image just start loading an image using `Loading` object.
12 | /// When preheating is no longer necessary call `stopPreheating(with:)` method.
13 | ///
14 | /// All `Preheater` methods are thread-safe.
15 | public final class Preheater {
16 | private let loader: Loading
17 | private let scheduler: AsyncScheduler
18 | private let queue = DispatchQueue(label: "com.github.kean.Nuke.Preheater")
19 | private var tasks = [Task]()
20 |
21 | /// Initializes the `Preheater` instance.
22 | /// - parameter loader: `Loader.shared` by default.
23 | /// - parameter scheduler: Throttles preheating requests. `OperationQueueScheduler`
24 | /// with `maxConcurrentOperationCount` 2 by default.
25 | public init(loader: Loading = Loader.shared, scheduler: AsyncScheduler = OperationQueueScheduler(maxConcurrentOperationCount: 2)) {
26 | self.loader = loader
27 | self.scheduler = scheduler
28 | }
29 |
30 | /// Preheats images for the given requests.
31 | ///
32 | /// When you call this method, `Preheater` starts to load and cache images
33 | /// for the given requests. At any time afterward, you can create tasks
34 | /// for individual images with equivalent requests.
35 | public func startPreheating(with requests: [Request]) {
36 | queue.async {
37 | requests.forEach { self.startPreheating(with: $0) }
38 | }
39 | }
40 |
41 | private func startPreheating(with request: Request) {
42 | // FIXME: use OrderedSet when Swift stdlib has one
43 | guard indexOfTask(with: request) == nil else { return } // already exists
44 |
45 | let task = Task(request: request)
46 | scheduler.execute(token: task.cts.token) { [weak self] finish in
47 | self?.loader.loadImage(with: task.request, token: task.cts.token).completion { _ in
48 | self?.complete(task)
49 | finish()
50 | }
51 | task.cts.token.register { finish() }
52 | }
53 | tasks.append(task)
54 | }
55 |
56 | private func complete(_ task: Task) {
57 | queue.async {
58 | if let idx = self.tasks.index(where: { task === $0 }) {
59 | self.tasks.remove(at: idx)
60 | }
61 | }
62 | }
63 |
64 | /// Stops preheating images for the given requests and cancels outstanding
65 | /// requests.
66 | public func stopPreheating(with requests: [Request]) {
67 | queue.async {
68 | requests.forEach { request in
69 | if let index = self.indexOfTask(with: request) {
70 | let task = self.tasks.remove(at: index)
71 | task.cts.cancel()
72 | }
73 | }
74 | }
75 | }
76 |
77 | private func indexOfTask(with request: Request) -> Int? {
78 | let key = Request.loadKey(for: request)
79 | return tasks.index { key == Request.loadKey(for: $0.request) }
80 | }
81 |
82 | /// Stops all preheating tasks.
83 | public func stopPreheating() {
84 | queue.async {
85 | self.tasks.forEach { $0.cts.cancel() }
86 | self.tasks.removeAll()
87 | }
88 | }
89 |
90 | private final class Task {
91 | let request: Request
92 | var cts = CancellationTokenSource()
93 | init(request: Request) {
94 | self.request = request
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Pods/Nuke/Sources/Processor.swift:
--------------------------------------------------------------------------------
1 | // The MIT License (MIT)
2 | //
3 | // Copyright (c) 2016 Alexander Grebenyuk (github.com/kean).
4 |
5 | import Foundation
6 |
7 | /// Performs image processing.
8 | public protocol Processing: Equatable {
9 | /// Returns processed image.
10 | func process(_ image: Image) -> Image?
11 | }
12 |
13 | /// Composes multiple processors.
14 | public struct ProcessorComposition: Processing {
15 | private let processors: [AnyProcessor]
16 |
17 | /// Composes multiple processors.
18 | public init(_ processors: [AnyProcessor]) {
19 | self.processors = processors
20 | }
21 |
22 | /// Processes the given image by applying each processor in an order in
23 | /// which they were added. If one of the processors fails to produce
24 | /// an image the processing stops and `nil` is returned.
25 | public func process(_ input: Image) -> Image? {
26 | return processors.reduce(input as Image!) { image, processor in
27 | return autoreleasepool { image != nil ? processor.process(image!) : nil }
28 | }
29 | }
30 |
31 | /// Returns true if the underlying processors are pairwise-equivalent.
32 | public static func ==(lhs: ProcessorComposition, rhs: ProcessorComposition) -> Bool {
33 | return lhs.processors.elementsEqual(rhs.processors)
34 | }
35 | }
36 |
37 | /// Type-erased image processor.
38 | public struct AnyProcessor: Processing {
39 | private let _process: (Image) -> Image?
40 | private let _processor: Any
41 | private let _equals: (AnyProcessor) -> Bool
42 |
43 | public init(_ processor: P) {
44 | self._process = { processor.process($0) }
45 | self._processor = processor
46 | self._equals = { ($0._processor as? P) == processor }
47 | }
48 |
49 | public func process(_ image: Image) -> Image? {
50 | return self._process(image)
51 | }
52 |
53 | public static func ==(lhs: AnyProcessor, rhs: AnyProcessor) -> Bool {
54 | return lhs._equals(rhs)
55 | }
56 | }
57 |
58 | #if !os(macOS)
59 |
60 | import UIKit
61 |
62 | /// Decompresses and (optionally) scales down input images. Maintains
63 | /// original aspect ratio.
64 | ///
65 | /// Images are decompressed and scaled in a single pass which is extremely
66 | /// efficient when scaling images down by a large factor.
67 | public struct Decompressor: Processing {
68 | public enum ContentMode {
69 | /// Scales the image so that it completely fills the target size.
70 | /// Doesn't clip images.
71 | case aspectFill
72 |
73 | /// Scales the image so that it fits the target size.
74 | case aspectFit
75 | }
76 |
77 | /// Size to pass to disable resizing.
78 | public static let MaximumSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
79 |
80 | private let targetSize: CGSize
81 | private let contentMode: ContentMode
82 |
83 | /// Initializes `Decompressor` with the given parameters.
84 | /// - parameter targetSize: Size in pixels. `MaximumSize` by default.
85 | /// - parameter contentMode: An option for how to resize the image
86 | /// to the target size. `.aspectFill` by default.
87 | public init(targetSize: CGSize = MaximumSize, contentMode: ContentMode = .aspectFill) {
88 | self.targetSize = targetSize
89 | self.contentMode = contentMode
90 | }
91 |
92 | /// Decompresses and scales the image.
93 | public func process(_ image: Image) -> Image? {
94 | return decompress(image, targetSize: targetSize, contentMode: contentMode)
95 | }
96 |
97 | /// Returns true if both have the same `targetSize` and `contentMode`.
98 | public static func ==(lhs: Decompressor, rhs: Decompressor) -> Bool {
99 | return lhs.targetSize == rhs.targetSize && lhs.contentMode == rhs.contentMode
100 | }
101 | }
102 |
103 | private func decompress(_ image: UIImage, targetSize: CGSize, contentMode: Decompressor.ContentMode) -> UIImage {
104 | guard let cgImage = image.cgImage else { return image }
105 | let bitmapSize = CGSize(width: cgImage.width, height: cgImage.height)
106 | let scaleHor = targetSize.width / bitmapSize.width
107 | let scaleVert = targetSize.height / bitmapSize.height
108 | let scale = contentMode == .aspectFill ? max(scaleHor, scaleVert) : min(scaleHor, scaleVert)
109 | return decompress(image, scale: CGFloat(min(scale, 1)))
110 | }
111 |
112 | private func decompress(_ image: UIImage, scale: CGFloat) -> UIImage {
113 | guard let cgImage = image.cgImage else { return image }
114 |
115 | let size = CGSize(width: round(scale * CGFloat(cgImage.width)),
116 | height: round(scale * CGFloat(cgImage.height)))
117 |
118 | // For more info see:
119 | // - Quartz 2D Programming Guide
120 | // - https://github.com/kean/Nuke/issues/35
121 | // - https://github.com/kean/Nuke/issues/57
122 | let alphaInfo: CGImageAlphaInfo = isOpaque(cgImage) ? .noneSkipLast : .premultipliedLast
123 |
124 | guard let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: 8, bytesPerRow: 0, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: alphaInfo.rawValue) else {
125 | return image
126 | }
127 | ctx.draw(cgImage, in: CGRect(origin: CGPoint.zero, size: size))
128 | guard let decompressed = ctx.makeImage() else { return image }
129 | return UIImage(cgImage: decompressed, scale: image.scale, orientation: image.imageOrientation)
130 | }
131 |
132 | private func isOpaque(_ image: CGImage) -> Bool {
133 | let alpha = image.alphaInfo
134 | return alpha == .none || alpha == .noneSkipFirst || alpha == .noneSkipLast
135 | }
136 | #endif
137 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/Alamofire.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/AlamofireNetworkActivityIndicator.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/DZNEmptyDataSet.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/Nuke.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/Pods-Left.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
66 |
67 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/SwiftyDrop.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/SwiftyJSON.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/UIScrollView-InfiniteScroll.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
66 |
67 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/ale_patron.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Alamofire.xcscheme
8 |
9 | isShown
10 |
11 |
12 | AlamofireNetworkActivityIndicator.xcscheme
13 |
14 | isShown
15 |
16 |
17 | DZNEmptyDataSet.xcscheme
18 |
19 | isShown
20 |
21 |
22 | Nuke.xcscheme
23 |
24 | isShown
25 |
26 |
27 | Pods-Left.xcscheme
28 |
29 | isShown
30 |
31 |
32 | SwiftyDrop.xcscheme
33 |
34 | isShown
35 |
36 |
37 | SwiftyJSON.xcscheme
38 |
39 | isShown
40 |
41 |
42 | UIScrollView-InfiniteScroll.xcscheme
43 |
44 | isShown
45 |
46 |
47 |
48 | SuppressBuildableAutocreation
49 |
50 | 115FA0D867E07C04838493890DBD8D29
51 |
52 | primary
53 |
54 |
55 | 3E9EB2CF4768F4548F3E209CE656A807
56 |
57 | primary
58 |
59 |
60 | 4621C3F9BE4863F63014320D83FFE6F4
61 |
62 | primary
63 |
64 |
65 | 636D2349F190F866F5DE2A564FA53AD3
66 |
67 | primary
68 |
69 |
70 | 88E9EC28B8B46C3631E6B242B50F4442
71 |
72 | primary
73 |
74 |
75 | 9B72E0CDBAB7245D7233A3D60016E7A4
76 |
77 | primary
78 |
79 |
80 | B2E810A917626E6EC56DBE5AC15A1308
81 |
82 | primary
83 |
84 |
85 | D386C75EFD4F03725E4EFB866B600B9A
86 |
87 | primary
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/Pods/SwiftyDrop/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Morita Naoki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Pods/SwiftyDrop/README.md:
--------------------------------------------------------------------------------
1 | # SwiftyDrop
2 |
3 | SwiftyDrop is a lightweight pure Swift simple and beautiful dropdown message.
4 |
5 | [](http://cocoadocs.org/docsets/SwiftyDrop) [](http://cocoadocs.org/docsets/SwiftyDrop) [](http://cocoadocs.org/docsets/SwiftyDrop)
6 | [](https://github.com/Carthage/Carthage)
7 | [](https://gitter.im/morizotter/SwiftyDrop?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8 |
9 | ## Features
10 |
11 | - Easy to use like: `Drop.down("Message")`
12 | - Message field expands depending on the message.
13 |
14 | ## How it looks
15 |
16 | ### States
17 | 
18 | 
19 | 
20 | 
21 |
22 | ### Blurs
23 | 
24 | 
25 |
26 | ### iPad
27 | 
28 |
29 | ## Demo
30 |
31 | Git clone or download this repository and open **SwiftyDrop.xcodeproj** . You can try SwiftyDrop in your Mac or iPhone.
32 |
33 | ## Runtime Requirements
34 |
35 | - iOS8.0 or later
36 | - Xcode 7.0
37 |
38 | ## Installation and Setup
39 |
40 | **Note:** Embedded frameworks require a minimum deployment target of iOS 8.1.
41 |
42 | **Information:** To use SwiftyDrop with a project targeting iOS 8.0 or lower, you must include the `SwiftyDrop/Drop.swift` source file directly in your project.
43 |
44 | ###Installing with CocoaPods
45 |
46 | [CocoaPods](http://cocoapods.org) is a centralised dependency manager that automates the process of adding libraries to your Cocoa application. You can install it with the following command:
47 |
48 | ```bash
49 | $ gem update
50 | $ gem install cocoapods
51 | $ pods --version
52 | ```
53 |
54 | To integrate SwiftyDrop into your Xcode project using CocoaPods, specify it in your `Podfile` and run `pod install`.
55 |
56 | ```bash
57 | platform :ios, '8.0'
58 | use_frameworks!
59 | pod 'SwiftyDrop', '~>2.0'
60 | ```
61 |
62 | ###Installing with Carthage
63 |
64 | Just add to your Cartfile:
65 |
66 | ```ogdl
67 | github "morizotter/SwiftyDrop" ~> 2.0
68 | ```
69 |
70 | ###Manual Installation
71 |
72 | To install SwiftyDrop without a dependency manager, please add all of the files in `/SwiftyDrop` to your Xcode Project.
73 |
74 | ##Usage
75 |
76 | ### Basic
77 |
78 | To start using SwiftyDrop, write the following line wherever you want to show dropdown message:
79 |
80 | ```swift
81 | import SwiftyDrop
82 | ```
83 |
84 | Then invoke SwiftyDrop, by calling:
85 |
86 | ```swift
87 | Drop.down("Message")
88 | ```
89 |
90 | It is really simple!
91 |
92 | ### States
93 |
94 | SwiftyDrop has states of display.
95 |
96 | **Examples**
97 |
98 | ```swift
99 | Drop.down("Message")
100 | Drop.down("Message", state: .Success)
101 | Drop.down("Message", state: .Color(.orangeColor()))
102 | Drop.down("Message", state: .Blur(.Light))
103 | ```
104 |
105 | **Custom states**
106 |
107 | You can customize looks by comforming `DropStatable` protocol.
108 | Examples are:
109 |
110 | ```swift
111 | enum Custom: DropStatable {
112 | case BlackGreen
113 | var backgroundColor: UIColor? {
114 | switch self {
115 | case .BlackGreen: return .blackColor()
116 | }
117 | }
118 | var font: UIFont? {
119 | switch self {
120 | case .BlackGreen: return UIFont(name: "HelveticaNeue-Light", size: 24.0)
121 | }
122 | }
123 | var textColor: UIColor? {
124 | switch self {
125 | case .BlackGreen: return .greenColor()
126 | }
127 | }
128 | var blurEffect: UIBlurEffect? {
129 | switch self {
130 | case .BlackGreen: return nil
131 | }
132 | }
133 | }
134 |
135 | Drop.down(self.sampleText(), state: Custom.BlackGreen)
136 | ```
137 |
138 | Of course you can use class or struct to make custom state if it is comforming to `DropStatable` protocol.
139 |
140 | **Prepared States** are enum:
141 | - .Default
142 | - .Info
143 | - .Success
144 | - .Warning
145 | - .Error
146 | - .Color: UIColor
147 | - .Blur: UIBlurEffectStyle
148 |
149 | ### Duration
150 |
151 | ```swift
152 | Drop.down("Message", duration: 3.0)
153 | ```
154 |
155 | You can change duration like this above. Default duration is 4.0.
156 |
157 | ### Action
158 |
159 | ```swift
160 | Drop.down("Message") {
161 | print("Action fired!")
162 | }
163 | ```
164 |
165 | ## Contribution
166 |
167 | Please file issues or submit pull requests! We're waiting! :)
168 |
169 | ## License
170 |
171 | SwiftyDrop is released under the MIT license. Go read the LICENSE file for more information.
172 |
--------------------------------------------------------------------------------
/Pods/SwiftyJSON/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Ruoyu Fu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Alamofire/Alamofire-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Alamofire : NSObject
3 | @end
4 | @implementation PodsDummy_Alamofire
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double AlamofireVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Alamofire/Alamofire.modulemap:
--------------------------------------------------------------------------------
1 | framework module Alamofire {
2 | umbrella header "Alamofire-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Alamofire/Alamofire.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Alamofire
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Alamofire
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Alamofire/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.2.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_AlamofireNetworkActivityIndicator : NSObject
3 | @end
4 | @implementation PodsDummy_AlamofireNetworkActivityIndicator
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double AlamofireNetworkActivityIndicatorVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char AlamofireNetworkActivityIndicatorVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.modulemap:
--------------------------------------------------------------------------------
1 | framework module AlamofireNetworkActivityIndicator {
2 | umbrella header "AlamofireNetworkActivityIndicator-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/AlamofireNetworkActivityIndicator
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
6 | PODS_BUILD_DIR = $BUILD_DIR
7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_ROOT = ${SRCROOT}
9 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/AlamofireNetworkActivityIndicator
10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
11 | SKIP_INSTALL = YES
12 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/AlamofireNetworkActivityIndicator/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 2.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_DZNEmptyDataSet : NSObject
3 | @end
4 | @implementation PodsDummy_DZNEmptyDataSet
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "UIScrollView+EmptyDataSet.h"
14 |
15 | FOUNDATION_EXPORT double DZNEmptyDataSetVersionNumber;
16 | FOUNDATION_EXPORT const unsigned char DZNEmptyDataSetVersionString[];
17 |
18 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.modulemap:
--------------------------------------------------------------------------------
1 | framework module DZNEmptyDataSet {
2 | umbrella header "DZNEmptyDataSet-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/DZNEmptyDataSet/DZNEmptyDataSet.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/DZNEmptyDataSet
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | OTHER_LDFLAGS = -framework "UIKit"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/DZNEmptyDataSet
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/DZNEmptyDataSet/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.8.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nuke/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.1.2
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nuke/Nuke-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Nuke : NSObject
3 | @end
4 | @implementation PodsDummy_Nuke
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nuke/Nuke-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nuke/Nuke-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double NukeVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char NukeVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nuke/Nuke.modulemap:
--------------------------------------------------------------------------------
1 | framework module Nuke {
2 | umbrella header "Nuke-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Nuke/Nuke.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Nuke
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Nuke
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_Left : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_Left
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | install_framework()
10 | {
11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
12 | local source="${BUILT_PRODUCTS_DIR}/$1"
13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
15 | elif [ -r "$1" ]; then
16 | local source="$1"
17 | fi
18 |
19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
20 |
21 | if [ -L "${source}" ]; then
22 | echo "Symlinked..."
23 | source="$(readlink "${source}")"
24 | fi
25 |
26 | # use filter instead of exclude so missing patterns dont' throw errors
27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
29 |
30 | local basename
31 | basename="$(basename -s .framework "$1")"
32 | binary="${destination}/${basename}.framework/${basename}"
33 | if ! [ -r "$binary" ]; then
34 | binary="${destination}/${basename}"
35 | fi
36 |
37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
39 | strip_invalid_archs "$binary"
40 | fi
41 |
42 | # Resign the code if required by the build settings to avoid unstable apps
43 | code_sign_if_enabled "${destination}/$(basename "$1")"
44 |
45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
47 | local swift_runtime_libs
48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
49 | for lib in $swift_runtime_libs; do
50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
52 | code_sign_if_enabled "${destination}/${lib}"
53 | done
54 | fi
55 | }
56 |
57 | # Signs a framework with the provided identity
58 | code_sign_if_enabled() {
59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
60 | # Use the current code_sign_identitiy
61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
62 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1""
63 |
64 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
65 | code_sign_cmd="$code_sign_cmd &"
66 | fi
67 | echo "$code_sign_cmd"
68 | eval "$code_sign_cmd"
69 | fi
70 | }
71 |
72 | # Strip invalid architectures
73 | strip_invalid_archs() {
74 | binary="$1"
75 | # Get architectures for current file
76 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
77 | stripped=""
78 | for arch in $archs; do
79 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
80 | # Strip non-valid architectures in-place
81 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
82 | stripped="$stripped $arch"
83 | fi
84 | done
85 | if [[ "$stripped" ]]; then
86 | echo "Stripped $binary of architectures:$stripped"
87 | fi
88 | }
89 |
90 |
91 | if [[ "$CONFIGURATION" == "Debug" ]]; then
92 | install_framework "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework"
93 | install_framework "$BUILT_PRODUCTS_DIR/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.framework"
94 | install_framework "$BUILT_PRODUCTS_DIR/DZNEmptyDataSet/DZNEmptyDataSet.framework"
95 | install_framework "$BUILT_PRODUCTS_DIR/Nuke/Nuke.framework"
96 | install_framework "$BUILT_PRODUCTS_DIR/SwiftyDrop/SwiftyDrop.framework"
97 | install_framework "$BUILT_PRODUCTS_DIR/SwiftyJSON/SwiftyJSON.framework"
98 | install_framework "$BUILT_PRODUCTS_DIR/UIScrollView-InfiniteScroll/UIScrollView_InfiniteScroll.framework"
99 | fi
100 | if [[ "$CONFIGURATION" == "Release" ]]; then
101 | install_framework "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework"
102 | install_framework "$BUILT_PRODUCTS_DIR/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.framework"
103 | install_framework "$BUILT_PRODUCTS_DIR/DZNEmptyDataSet/DZNEmptyDataSet.framework"
104 | install_framework "$BUILT_PRODUCTS_DIR/Nuke/Nuke.framework"
105 | install_framework "$BUILT_PRODUCTS_DIR/SwiftyDrop/SwiftyDrop.framework"
106 | install_framework "$BUILT_PRODUCTS_DIR/SwiftyJSON/SwiftyJSON.framework"
107 | install_framework "$BUILT_PRODUCTS_DIR/UIScrollView-InfiniteScroll/UIScrollView_InfiniteScroll.framework"
108 | fi
109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
110 | wait
111 | fi
112 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | case "${TARGETED_DEVICE_FAMILY}" in
12 | 1,2)
13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
14 | ;;
15 | 1)
16 | TARGET_DEVICE_ARGS="--target-device iphone"
17 | ;;
18 | 2)
19 | TARGET_DEVICE_ARGS="--target-device ipad"
20 | ;;
21 | 3)
22 | TARGET_DEVICE_ARGS="--target-device tv"
23 | ;;
24 | *)
25 | TARGET_DEVICE_ARGS="--target-device mac"
26 | ;;
27 | esac
28 |
29 | install_resource()
30 | {
31 | if [[ "$1" = /* ]] ; then
32 | RESOURCE_PATH="$1"
33 | else
34 | RESOURCE_PATH="${PODS_ROOT}/$1"
35 | fi
36 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
37 | cat << EOM
38 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
39 | EOM
40 | exit 1
41 | fi
42 | case $RESOURCE_PATH in
43 | *.storyboard)
44 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
45 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
46 | ;;
47 | *.xib)
48 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
49 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
50 | ;;
51 | *.framework)
52 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
53 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
54 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
55 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
56 | ;;
57 | *.xcdatamodel)
58 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
59 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
60 | ;;
61 | *.xcdatamodeld)
62 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
63 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
64 | ;;
65 | *.xcmappingmodel)
66 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
67 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
68 | ;;
69 | *.xcassets)
70 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
71 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
72 | ;;
73 | *)
74 | echo "$RESOURCE_PATH"
75 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
76 | ;;
77 | esac
78 | }
79 |
80 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
81 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
82 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
83 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
85 | fi
86 | rm -f "$RESOURCES_TO_COPY"
87 |
88 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
89 | then
90 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
91 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
92 | while read line; do
93 | if [[ $line != "${PODS_ROOT}*" ]]; then
94 | XCASSET_FILES+=("$line")
95 | fi
96 | done <<<"$OTHER_XCASSETS"
97 |
98 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
99 | fi
100 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_LeftVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_LeftVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" "$PODS_CONFIGURATION_BUILD_DIR/AlamofireNetworkActivityIndicator" "$PODS_CONFIGURATION_BUILD_DIR/DZNEmptyDataSet" "$PODS_CONFIGURATION_BUILD_DIR/Nuke" "$PODS_CONFIGURATION_BUILD_DIR/SwiftyDrop" "$PODS_CONFIGURATION_BUILD_DIR/SwiftyJSON" "$PODS_CONFIGURATION_BUILD_DIR/UIScrollView-InfiniteScroll"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Alamofire/Alamofire.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Nuke/Nuke.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftyDrop/SwiftyDrop.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftyJSON/SwiftyJSON.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/UIScrollView-InfiniteScroll/UIScrollView_InfiniteScroll.framework/Headers"
6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "AlamofireNetworkActivityIndicator" -framework "DZNEmptyDataSet" -framework "Nuke" -framework "SwiftyDrop" -framework "SwiftyJSON" -framework "UIScrollView_InfiniteScroll"
7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
8 | PODS_BUILD_DIR = $BUILD_DIR
9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_ROOT = ${SRCROOT}/Pods
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_Left {
2 | umbrella header "Pods-Left-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Left/Pods-Left.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" "$PODS_CONFIGURATION_BUILD_DIR/AlamofireNetworkActivityIndicator" "$PODS_CONFIGURATION_BUILD_DIR/DZNEmptyDataSet" "$PODS_CONFIGURATION_BUILD_DIR/Nuke" "$PODS_CONFIGURATION_BUILD_DIR/SwiftyDrop" "$PODS_CONFIGURATION_BUILD_DIR/SwiftyJSON" "$PODS_CONFIGURATION_BUILD_DIR/UIScrollView-InfiniteScroll"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Alamofire/Alamofire.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Nuke/Nuke.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftyDrop/SwiftyDrop.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SwiftyJSON/SwiftyJSON.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/UIScrollView-InfiniteScroll/UIScrollView_InfiniteScroll.framework/Headers"
6 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "AlamofireNetworkActivityIndicator" -framework "DZNEmptyDataSet" -framework "Nuke" -framework "SwiftyDrop" -framework "SwiftyJSON" -framework "UIScrollView_InfiniteScroll"
7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
8 | PODS_BUILD_DIR = $BUILD_DIR
9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
10 | PODS_ROOT = ${SRCROOT}/Pods
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyDrop/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.0.3
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyDrop/SwiftyDrop-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_SwiftyDrop : NSObject
3 | @end
4 | @implementation PodsDummy_SwiftyDrop
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyDrop/SwiftyDrop-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyDrop/SwiftyDrop-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double SwiftyDropVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char SwiftyDropVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyDrop/SwiftyDrop.modulemap:
--------------------------------------------------------------------------------
1 | framework module SwiftyDrop {
2 | umbrella header "SwiftyDrop-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyDrop/SwiftyDrop.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SwiftyDrop
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SwiftyDrop
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyJSON/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 3.1.3
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_SwiftyJSON : NSObject
3 | @end
4 | @implementation PodsDummy_SwiftyJSON
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double SwiftyJSONVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char SwiftyJSONVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.modulemap:
--------------------------------------------------------------------------------
1 | framework module SwiftyJSON {
2 | umbrella header "SwiftyJSON-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SwiftyJSON
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SwiftyJSON
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 | SWIFT_VERSION = 3.0
12 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/UIScrollView-InfiniteScroll/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 0.9.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/UIScrollView-InfiniteScroll/UIScrollView-InfiniteScroll-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_UIScrollView_InfiniteScroll : NSObject
3 | @end
4 | @implementation PodsDummy_UIScrollView_InfiniteScroll
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/UIScrollView-InfiniteScroll/UIScrollView-InfiniteScroll-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/UIScrollView-InfiniteScroll/UIScrollView-InfiniteScroll-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "UIScrollView+InfiniteScroll.h"
14 |
15 | FOUNDATION_EXPORT double UIScrollView_InfiniteScrollVersionNumber;
16 | FOUNDATION_EXPORT const unsigned char UIScrollView_InfiniteScrollVersionString[];
17 |
18 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/UIScrollView-InfiniteScroll/UIScrollView-InfiniteScroll.modulemap:
--------------------------------------------------------------------------------
1 | framework module UIScrollView_InfiniteScroll {
2 | umbrella header "UIScrollView-InfiniteScroll-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/UIScrollView-InfiniteScroll/UIScrollView-InfiniteScroll.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/UIScrollView-InfiniteScroll
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | PODS_BUILD_DIR = $BUILD_DIR
5 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
6 | PODS_ROOT = ${SRCROOT}
7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/UIScrollView-InfiniteScroll
8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
9 | SKIP_INSTALL = YES
10 |
--------------------------------------------------------------------------------
/Pods/UIScrollView-InfiniteScroll/Classes/UIScrollView+InfiniteScroll.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIScrollView+InfiniteScroll.h
3 | //
4 | // UIScrollView infinite scroll category
5 | //
6 | // Created by Andrej Mihajlov on 9/4/13.
7 | // Copyright (c) 2013-2015 Andrej Mihajlov. All rights reserved.
8 | //
9 |
10 | #import
11 |
12 | NS_ASSUME_NONNULL_BEGIN
13 |
14 | @interface UIScrollView (InfiniteScroll)
15 |
16 | /**
17 | * Flag that indicates whether infinite scroll is animating
18 | */
19 | @property (nonatomic, readonly, getter=isAnimatingInfiniteScroll) BOOL animatingInfiniteScroll;
20 |
21 | /**
22 | * Infinite scroll activity indicator style (default: UIActivityIndicatorViewStyleGray on iOS, UIActivityIndicatorViewStyleWhite on tvOS)
23 | */
24 | @property (nonatomic) UIActivityIndicatorViewStyle infiniteScrollIndicatorStyle;
25 |
26 | /**
27 | * Infinite indicator view
28 | *
29 | * You can set your own custom view instead of default activity indicator,
30 | * make sure it implements methods below:
31 | *
32 | * * `- (void)startAnimating`
33 | * * `- (void)stopAnimating`
34 | *
35 | * Infinite scroll will call implemented methods during user interaction.
36 | */
37 | @property (nonatomic, nullable) UIView *infiniteScrollIndicatorView;
38 |
39 | /**
40 | * Vertical margin around indicator view (Default: 11)
41 | */
42 | @property (nonatomic) CGFloat infiniteScrollIndicatorMargin;
43 |
44 | /**
45 | * Sets the offset between the real end of the scroll view content and the scroll position, so the handler can be triggered before reaching end.
46 | * Defaults to 0.0;
47 | */
48 | @property (nonatomic) CGFloat infiniteScrollTriggerOffset;
49 |
50 | /**
51 | * Setup infinite scroll handler
52 | *
53 | * @param handler a handler block
54 | */
55 | - (void)addInfiniteScrollWithHandler:(void(^)(UIScrollView *scrollView))handler;
56 |
57 | /**
58 | * Set a handler to be called to check if the infinite scroll should be shown
59 | *
60 | * @param handler a handler block
61 | */
62 | - (void)setShouldShowInfiniteScrollHandler:(nullable BOOL(^)(UIScrollView *scrollView))handler;
63 |
64 | /**
65 | * Unregister infinite scroll
66 | */
67 | - (void)removeInfiniteScroll;
68 |
69 | /**
70 | * Finish infinite scroll animations
71 | *
72 | * You must call this method from your infinite scroll handler to finish all
73 | * animations properly and reset infinite scroll state
74 | *
75 | * @param handler a completion block handler called when animation finished
76 | */
77 | - (void)finishInfiniteScrollWithCompletion:(nullable void(^)(UIScrollView *scrollView))handler;
78 |
79 | /**
80 | * Finish infinite scroll animations
81 | *
82 | * You must call this method from your infinite scroll handler to finish all
83 | * animations properly and reset infinite scroll state
84 | */
85 | - (void)finishInfiniteScroll;
86 |
87 | @end
88 |
89 | /*
90 | Convenience interface to avoid cast from UIScrollView to common subclasses such as UITableView and UICollectionView.
91 | */
92 |
93 | @interface UITableView (InfiniteScrollConvenienceInterface)
94 |
95 | - (void)addInfiniteScrollWithHandler:(void(^)(UITableView *tableView))handler;
96 | - (void)setShouldShowInfiniteScrollHandler:(BOOL(^)(UITableView *tableView))handler;
97 | - (void)finishInfiniteScrollWithCompletion:(nullable void(^)(UITableView *tableView))handler;
98 |
99 | @end
100 |
101 | @interface UICollectionView (InfiniteScrollConvenienceInterface)
102 |
103 | - (void)addInfiniteScrollWithHandler:(void(^)(UICollectionView *collectionView))handler;
104 | - (void)setShouldShowInfiniteScrollHandler:(BOOL(^)(UICollectionView *collectionView))handler;
105 | - (void)finishInfiniteScrollWithCompletion:(nullable void(^)(UICollectionView *collectionView))handler;
106 |
107 | @end
108 |
109 | NS_ASSUME_NONNULL_END
110 |
--------------------------------------------------------------------------------
/Pods/UIScrollView-InfiniteScroll/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013-2015 Andrei Mihailov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Left
2 | Left is an iOS app that lets you search for recipes that use the ingredients you have "left." Simply input up to 5 ingredients and press
3 | "Search" to see results. Find it on the App Store [here!](https://appsto.re/us/QIpFcb.i)
4 |
5 | #Credits
6 | - [Food2Fork](https://food2fork.com) recipe search API for recipe data.
7 | - [Alamofire](https://github.com/Alamofire/Alamofire) for network requests.
8 | - [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) for JSON parsing.
9 |
10 |
11 |
12 |
13 |
14 |
15 | # License
16 |
17 | Left is available under the MIT license. See the LICENSE file for more info.
18 |
--------------------------------------------------------------------------------
/left1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/left1.png
--------------------------------------------------------------------------------
/left2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apatronl/Left/a9e2fb85b035aa102206847f6435b3d980b08a4f/left2.png
--------------------------------------------------------------------------------