Skip to content

Commit 32521e4

Browse files
nmarkovic04rubikzube
authored andcommitted
Completely redesigned the sample app (#92)
* Completely redesigned the sample app * Updated price to be a Double, as reflected in the Bodega data * Sample app UI polish * Sample app cart UI polish * Updated cart button * Removed UserApplicationUITests (it was empty)
1 parent 14791b3 commit 32521e4

File tree

67 files changed

+3329
-392
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3329
-392
lines changed

AutocompleteClient.xcodeproj/project.pbxproj

Lines changed: 513 additions & 213 deletions
Large diffs are not rendered by default.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "0830"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "F688A43E1F56B4B600F169C1"
18+
BuildableName = "ConstructorAutocomplete.framework"
19+
BlueprintName = "AutocompleteClient"
20+
ReferencedContainer = "container:AutocompleteClient.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES"
30+
codeCoverageEnabled = "YES">
31+
<MacroExpansion>
32+
<BuildableReference
33+
BuildableIdentifier = "primary"
34+
BlueprintIdentifier = "F688A43E1F56B4B600F169C1"
35+
BuildableName = "ConstructorAutocomplete.framework"
36+
BlueprintName = "AutocompleteClient"
37+
ReferencedContainer = "container:AutocompleteClient.xcodeproj">
38+
</BuildableReference>
39+
</MacroExpansion>
40+
<Testables>
41+
<TestableReference
42+
skipped = "NO">
43+
<BuildableReference
44+
BuildableIdentifier = "primary"
45+
BlueprintIdentifier = "F688A4471F56B4B600F169C1"
46+
BuildableName = "AutocompleteClientTests.xctest"
47+
BlueprintName = "AutocompleteClientTests"
48+
ReferencedContainer = "container:AutocompleteClient.xcodeproj">
49+
</BuildableReference>
50+
</TestableReference>
51+
</Testables>
52+
</TestAction>
53+
<LaunchAction
54+
buildConfiguration = "Debug"
55+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
56+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
57+
launchStyle = "0"
58+
useCustomWorkingDirectory = "NO"
59+
ignoresPersistentStateOnLaunch = "NO"
60+
debugDocumentVersioning = "YES"
61+
debugServiceExtension = "internal"
62+
allowLocationSimulation = "YES">
63+
<MacroExpansion>
64+
<BuildableReference
65+
BuildableIdentifier = "primary"
66+
BlueprintIdentifier = "F688A43E1F56B4B600F169C1"
67+
BuildableName = "ConstructorAutocomplete.framework"
68+
BlueprintName = "AutocompleteClient"
69+
ReferencedContainer = "container:AutocompleteClient.xcodeproj">
70+
</BuildableReference>
71+
</MacroExpansion>
72+
</LaunchAction>
73+
<ProfileAction
74+
buildConfiguration = "Release"
75+
shouldUseLaunchSchemeArgsEnv = "YES"
76+
savedToolIdentifier = ""
77+
useCustomWorkingDirectory = "NO"
78+
debugDocumentVersioning = "YES">
79+
<MacroExpansion>
80+
<BuildableReference
81+
BuildableIdentifier = "primary"
82+
BlueprintIdentifier = "F688A43E1F56B4B600F169C1"
83+
BuildableName = "ConstructorAutocomplete.framework"
84+
BlueprintName = "AutocompleteClient"
85+
ReferencedContainer = "container:AutocompleteClient.xcodeproj">
86+
</BuildableReference>
87+
</MacroExpansion>
88+
</ProfileAction>
89+
<AnalyzeAction
90+
buildConfiguration = "Debug">
91+
</AnalyzeAction>
92+
<ArchiveAction
93+
buildConfiguration = "Release"
94+
revealArchiveInOrganizer = "YES">
95+
</ArchiveAction>
96+
</Scheme>

UserApplication/AppDelegate.swift

Lines changed: 85 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -10,134 +10,137 @@ import UIKit
1010
import ConstructorAutocomplete
1111

1212
@UIApplicationMain
13-
class AppDelegate: UIResponder, UIApplicationDelegate, CIOAutocompleteDelegate, CIOAutocompleteUICustomization {
14-
13+
class AppDelegate: UIResponder, UIApplicationDelegate, CIOAutocompleteDelegate, CIOAutocompleteUICustomization, ConstructorIOProvider {
14+
1515
var window: UIWindow?
16-
16+
17+
var constructorIO: ConstructorIO!
18+
19+
func provideConstructorInstance() -> ConstructorIO {
20+
return self.constructorIO
21+
}
22+
23+
var cart: Cart = Cart()
24+
var cartPersistence = CartPersistence()
25+
1726
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18-
27+
28+
self.cart = self.cartPersistence.loadCart() ?? Cart()
29+
1930
self.showAutocompleteViewControllerAsRoot()
20-
2131
return true
2232
}
23-
33+
2434
func applicationWillResignActive(_ application: UIApplication) {
2535
// 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.
2636
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
2737
}
28-
38+
2939
func applicationDidEnterBackground(_ application: UIApplication) {
3040
// 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.
3141
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
3242
}
33-
43+
3444
func applicationWillEnterForeground(_ application: UIApplication) {
3545
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
3646
}
37-
47+
3848
func applicationDidBecomeActive(_ application: UIApplication) {
3949
// 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.
4050
}
41-
51+
4252
func applicationWillTerminate(_ application: UIApplication) {
4353
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
4454
}
45-
55+
4656
func showAutocompleteViewControllerAsRoot() {
4757
// Instantiate the autocomplete controller
48-
let key = "key_OucJxxrfiTVUQx0C"
49-
let config = ConstructorIOConfig(
50-
apiKey: key,
51-
resultCount: AutocompleteResultCount(numResultsForSection: ["Search Suggestions" : 3, "Products" : 0]),
52-
testCells: [
53-
CIOABTestCell(key: "hi", value: "there"),
54-
CIOABTestCell(key: "howare", value: "you")
55-
])
58+
let key = "key_K2hlXt5aVSwoI1Uw"
59+
let config = ConstructorIOConfig(apiKey: key,
60+
resultCount: AutocompleteResultCount(numResultsForSection: ["Search Suggestions" : 3, "Products" : 0]))
5661
let viewController = CIOAutocompleteViewController(config: config)
5762
viewController.searchBarDisplayMode = CIOSearchBarDisplayMode.navigationBar
5863
viewController.searchBarShouldShowCancelButton = false
59-
64+
6065
// set the delegate in order to react to various events
6166
viewController.delegate = self
62-
67+
6368
// set the customization to adjust the look and feel of the UI
6469
viewController.uiCustomization = self
65-
70+
6671
let bgColor = UIColor.white
67-
72+
6873
// embed it in the navigation controller
6974
let navigationController = UINavigationController(rootViewController: viewController)
7075
navigationController.navigationBar.barTintColor = bgColor
71-
76+
7277
self.window = UIWindow(frame: UIScreen.main.bounds)
7378
self.window?.rootViewController = navigationController
7479
self.window?.makeKeyAndVisible()
75-
76-
}
77-
78-
var i = 1
79-
func randomColor() -> UIColor {
80-
let colors = [UIColor.red, .blue, .purple, .orange, .black]
81-
let color = colors[i%colors.count]
82-
i += 1
83-
return color
80+
81+
// Listen for cart changes and react to item being add event
82+
NotificationCenter.default.addObserver(forName: kNotificationDidAddItemToCart, object: nil, queue: OperationQueue.main) { notification in
83+
guard let item = notification.cartItem() else { return }
84+
guard let constructor = viewController.constructorIO else { return }
85+
constructor.trackConversion(itemName: item.title, customerID: "a-customer-id", revenue: Double(item.price))
86+
}
8487
}
85-
88+
8689
// MARK: UI Customization
87-
90+
8891
func sectionHeaderView(sectionName: String, in autocompleteController: CIOAutocompleteViewController) -> UIView? {
8992
let headerView = UIView(frame: CGRect.zero)
9093
headerView.backgroundColor = UIColor.white
91-
94+
9295
let label = UILabel()
9396
label.translatesAutoresizingMaskIntoConstraints = false
9497
headerView.addSubview(label)
95-
98+
9699
let constraintCenterHorizontally = NSLayoutConstraint(item: headerView, attribute: .centerX, relatedBy: .equal, toItem: label, attribute: .centerX, multiplier: 1.0, constant: 0)
97100
headerView.addConstraint(constraintCenterHorizontally)
98-
101+
99102
let constraintCenterVertically = NSLayoutConstraint(item: headerView, attribute: .centerY, relatedBy: .equal, toItem: label, attribute: .centerY, multiplier: 1.0, constant: 0)
100103
headerView.addConstraint(constraintCenterVertically)
101-
104+
102105
label.text = sectionName
103106
label.font = UIFont.boldSystemFont(ofSize: label.font.pointSize)
104107
return headerView
105108
}
106-
109+
107110
func sectionHeaderViewHeight(sectionName: String, in autocompleteController: CIOAutocompleteViewController) -> CGFloat {
108111
return 30
109112
}
110-
113+
111114
func shouldShowSectionHeader(sectionName: String, in autocompleteController: CIOAutocompleteViewController) -> Bool {
112115
return false
113116
}
114-
117+
115118
func sectionSort(in autocompleteController: CIOAutocompleteViewController) -> ((String, String) -> Bool) {
116119
return { (s1, s2) in return s1 > s2 }
117120
}
118-
121+
119122
func errorView(in autocompleteController: CIOAutocompleteViewController) -> UIView? {
120123
return UINib(nibName: "CustomErrorView", bundle: nil).instantiate(withOwner: nil, options: nil).first as? UIView
121124
}
122-
125+
123126
func customizeSearchController(searchController: UISearchController, in autocompleteController: CIOAutocompleteViewController) {
124127
// customize search bar
125128
searchController.searchBar.autocapitalizationType = UITextAutocapitalizationType.none
126129
searchController.searchBar.returnKeyType = .search
127-
128-
if let textField = searchController.searchBar.searchTextField() {
130+
131+
if let textField = searchController.searchBar.searchTextField(){
129132
let val: CGFloat = 0.94
130133
textField.backgroundColor = UIColor(red: val, green: val, blue: val, alpha: 1.0)
131134
}
132-
135+
133136
// customize search controller behaviour
134137
searchController.dimsBackgroundDuringPresentation = false
135138
}
136-
139+
137140
// MARK: Delegate
138-
141+
139142
func autocompleteController(controller: CIOAutocompleteViewController, errorDidOccur error: Error) {
140-
143+
141144
if let err = error as? CIOError {
142145
switch(err) {
143146
case .missingApiKey:
@@ -147,35 +150,54 @@ class AppDelegate: UIResponder, UIApplicationDelegate, CIOAutocompleteDelegate,
147150
}
148151
}
149152
}
150-
153+
154+
func backgroundView(in autocompleteController: CIOAutocompleteViewController) -> UIView? {
155+
let backgroundView = UIView(frame: .zero)
156+
backgroundView.backgroundColor = UIColor.hex(rgb: 0x333333)
157+
158+
if let image = UIImage(named: "img_logo"){
159+
let logoImageView = UIImageView(image: image)
160+
logoImageView.translatesAutoresizingMaskIntoConstraints = false
161+
logoImageView.clipsToBounds = true
162+
logoImageView.contentMode = .scaleAspectFit
163+
backgroundView.addSubview(logoImageView)
164+
logoImageView.centerInSuperviewVertical()
165+
logoImageView.centerInSuperviewHorizontal()
166+
logoImageView.pinToSuperviewLeft(16)
167+
logoImageView.pinAspectRatio(ratio: 0.319)
168+
}
169+
return backgroundView
170+
}
171+
151172
func autocompleteController(controller: CIOAutocompleteViewController, didLoadResults results: [CIOResult], for searchTerm: String) {}
152-
173+
153174
func autocompleteController(controller: CIOAutocompleteViewController, didSelectResult result: CIOResult) {
154175
print("item selected \(result)")
155-
156-
if let navigationController = self.window?.rootViewController as? UINavigationController {
157-
let detailsVC = DetailsViewController()
158-
detailsVC.result = result
159-
detailsVC.constructorIO = controller.constructorIO
160-
navigationController.pushViewController(detailsVC, animated: true)
176+
177+
self.constructorIO = controller.constructorIO
178+
179+
if let navigationController = self.window?.rootViewController as? UINavigationController{
180+
let viewModel = SearchViewModel(term: result.autocompleteResult.value, group: result.group, constructorProvider: self, cart: self.cart)
181+
let searchVC = SearchViewController(viewModel: viewModel, constructorProvider: self)
182+
navigationController.pushViewController(searchVC, animated: true)
161183
}
162184
}
163-
185+
164186
func autocompleteController(controller: CIOAutocompleteViewController, didPerformSearch searchTerm: String) {
165187
print("Search performed for term \(searchTerm)")
166188
}
167-
189+
168190
func autocompleteControllerWillAppear(controller: CIOAutocompleteViewController) {
169191
print("Search controller will appear")
170-
if controller.constructorIO.userID == nil {
192+
if controller.constructorIO.userID == nil{
171193
controller.constructorIO.userID = "user_id$1 3"
172194
}
173195
}
174-
196+
175197
func autocompleteControllerDidLoad(controller: CIOAutocompleteViewController) {
176198
print("Search controller did load")
177199
}
178-
200+
179201
func searchBarPlaceholder(in autocompleteController: CIOAutocompleteViewController) -> String {
180202
return "Search"
181203
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"filename" : "icon_cart.png",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"filename" : "[email protected]",
11+
"scale" : "2x"
12+
},
13+
{
14+
"idiom" : "universal",
15+
"filename" : "[email protected]",
16+
"scale" : "3x"
17+
}
18+
],
19+
"info" : {
20+
"version" : 1,
21+
"author" : "xcode"
22+
}
23+
}
1.56 KB
Loading
3.06 KB
Loading
4.57 KB
Loading

0 commit comments

Comments
 (0)