This repository has been archived by the owner on Oct 11, 2022. It is now read-only.
/
AlgoliaController.swift
204 lines (169 loc) · 6.67 KB
/
AlgoliaController.swift
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//
// AlgoliaController.swift
// DemoDirectory
//
// Created by Vladislav Fitc on 19/04/2021.
// Copyright © 2021 Algolia. All rights reserved.
//
import Foundation
import InstantSearch
class AlgoliaController {
let appID: ApplicationID
let apiKey: APIKey
let indexName: IndexName
let facetAttribute: Attribute
let suggestions: SuggestionsViewModel
let facetList: FacetListViewModel
let facetSearch: FacetSearchViewModel
let searcher: HitsSearcher
let queryInputInteractor: QueryInputInteractor
let hitsInteractor: HitsInteractor<Hit<StoreItem>>
let statsInteractor: StatsInteractor
let currentFiltersInteractor: CurrentFiltersInteractor
let filterState: FilterState
let filterClearInteractor: FilterClearInteractor
let sortByInteractor: SortByInteractor
let areFacetsSearchable: Bool
let indexMain: IndexName = "instant_search"
let indexPriceAsc: IndexName = "instant_search_price_asc"
let indexPriceDesc: IndexName = "instant_search_price_desc"
init(appID: ApplicationID,
apiKey: APIKey,
indexName: IndexName,
facetAttribute: Attribute,
areFacetsSearchable: Bool) {
self.appID = appID
self.apiKey = apiKey
self.indexName = indexName
self.facetAttribute = facetAttribute
self.searcher = HitsSearcher(appID: appID,
apiKey: apiKey,
indexName: indexName)
self.hitsInteractor = .init()
self.statsInteractor = .init()
self.filterState = .init()
self.currentFiltersInteractor = .init()
self.queryInputInteractor = .init()
self.filterClearInteractor = .init()
self.sortByInteractor = .init(items: [
1: indexMain,
2: indexPriceAsc,
3: indexPriceDesc
], selected: 1)
self.suggestions = .init()
self.facetList = .init()
self.facetSearch = .init(appID: appID,
apiKey: apiKey,
indexName: indexName,
facetAttribute: facetAttribute)
self.areFacetsSearchable = areFacetsSearchable
setupConnections()
}
fileprivate func setupConnections() {
searcher.connectFilterState(filterState)
hitsInteractor.connectSearcher(searcher)
statsInteractor.connectSearcher(searcher)
currentFiltersInteractor.connectFilterState(filterState)
queryInputInteractor.connectSearcher(searcher)
filterClearInteractor.connectFilterState(filterState,
filterGroupIDs: [.or(name: facetAttribute.rawValue, filterType: .facet)],
clearMode: .specified)
sortByInteractor.connectSearcher(searcher)
queryInputInteractor.connectSearcher(suggestions.searcher)
if areFacetsSearchable {
facetSearch.searcher.connectFilterState(filterState)
facetSearch.facetListInteractor.connectFilterState(filterState, with: facetAttribute, operator: .or)
} else {
facetList.facetListInteractor.connectSearcher(searcher, with: facetAttribute)
facetList.facetListInteractor.connectFilterState(filterState, with: facetAttribute, operator: .or)
}
}
func setup(_ contentView: ContentView) {
hitsInteractor.connectController(contentView.hitsController)
statsInteractor.connectController(contentView.statsController)
currentFiltersInteractor.connectController(contentView.currentFiltersController)
queryInputInteractor.connectController(contentView.queryInputController)
filterClearInteractor.connectController(contentView.filterClearController)
sortByInteractor.connectController(contentView.sortByController) { [indexMain = self.indexMain,
indexPriceAsc = self.indexPriceAsc,
indexPriceDesc = self.indexPriceDesc] indexName in
switch indexName {
case indexMain:
return "Featured"
case indexPriceAsc:
return "Price ascending"
case indexPriceDesc:
return "Price descending"
default:
return indexName.rawValue
}
}
suggestions.setup(contentView)
if areFacetsSearchable {
facetSearch.setup(contentView)
} else {
facetList.setup(contentView)
}
searcher.search()
}
class SuggestionsViewModel {
let searcher: HitsSearcher
let hitsInteractor: HitsInteractor<QuerySuggestion>
init() {
searcher = .init(appID: "latency",
apiKey: "af044fb0788d6bb15f807e4420592bc5",
indexName: "instantsearch_query_suggestions")
hitsInteractor = .init()
hitsInteractor.connectSearcher(searcher)
}
func setup(_ contentView: ContentView) {
hitsInteractor.connectController(contentView.suggestionsController)
searcher.search()
}
}
class FacetListViewModel {
let facetListInteractor: FacetListInteractor
init() {
facetListInteractor = .init()
}
func setup(_ contentView: ContentView) {
facetListInteractor.connectController(contentView.facetListController, with: FacetListPresenter(sortBy: [.isRefined, .count(order: .descending)]))
}
}
class FacetSearchViewModel {
let searcher: FacetSearcher
let queryInputInteractor: QueryInputInteractor
let facetListInteractor: FacetListInteractor
init(appID: ApplicationID,
apiKey: APIKey,
indexName: IndexName,
facetAttribute: Attribute) {
var query = Query()
query.maxFacetHits = 100
searcher = .init(appID: appID,
apiKey: apiKey,
indexName: indexName,
facetName: facetAttribute,
query: query,
requestOptions: nil)
queryInputInteractor = .init()
facetListInteractor = .init()
queryInputInteractor.connectSearcher(searcher)
facetListInteractor.connectFacetSearcher(searcher)
searcher.search()
}
func setup(_ contentView: ContentView) {
facetListInteractor.connectController(contentView.facetListController, with: FacetListPresenter(sortBy: [.isRefined, .count(order: .descending)]))
queryInputInteractor.connectController(contentView.facetSearchQueryInputController)
}
}
}
extension AlgoliaController {
static func test(areFacetsSearchable: Bool) -> AlgoliaController {
AlgoliaController(appID: "latency",
apiKey: "1f6fd3a6fb973cb08419fe7d288fa4db",
indexName: "instant_search",
facetAttribute: "brand",
areFacetsSearchable: areFacetsSearchable)
}
}