2 // FilterViewController.swift
5 // Created by Pawel Dabrowski on 30/05/2018.
6 // Copyright © 2018 Fundacja Nowoczesna Polska. All rights reserved.
12 enum FilterSection: Int{
20 return "filter_\(self)".localized.uppercased()
23 var failedText: String{
24 return "load_\(self)_failed".localized
28 class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
32 minimumLineSpacing = 0
36 required init?(coder aDecoder: NSCoder) {
37 fatalError("init(coder:) has not been implemented")
40 override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
41 let attributes = super.layoutAttributesForElements(in: rect)
43 var leftMargin = sectionInset.left
44 var maxY: CGFloat = -1.0
45 attributes?.forEach { layoutAttribute in
47 if(layoutAttribute.representedElementCategory == .cell){
48 if layoutAttribute.frame.origin.y >= maxY {
49 leftMargin = sectionInset.left
52 layoutAttribute.frame.origin.x = leftMargin
54 leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
55 maxY = max(layoutAttribute.frame.maxY , maxY)
62 protocol FilterViewControllerDelegate: class {
63 func filterViewControllerDidSelectItems(kindsArray: [CategoryModel], epochsArray: [CategoryModel], genresArray: [CategoryModel], onlyLectures: Bool, hasAudiobook: Bool, filterChanged: Bool)
66 class FilterViewController: WLViewController {
68 class func instance(delegate: FilterViewControllerDelegate, selectedKindsArray: [CategoryModel], selectedEpochsArray: [CategoryModel], selectedGenresArray: [CategoryModel], onlyLectures: Bool, hasAudiobook: Bool) -> FilterViewController{
69 let controller = FilterViewController.instance()
70 controller.initialSelectedKindsArray = selectedKindsArray
71 controller.initialSelectedEpochsArray = selectedEpochsArray
72 controller.initialSelectedGenresArray = selectedGenresArray
73 controller.onlyLectures = onlyLectures
74 controller.hasAudiobook = hasAudiobook
75 controller.delegate = delegate
79 weak var delegate: FilterViewControllerDelegate!
80 @IBOutlet weak var collectionView: UICollectionView!
82 var initialSelectedKindsArray: [CategoryModel]!
83 var initialSelectedEpochsArray: [CategoryModel]!
84 var initialSelectedGenresArray: [CategoryModel]!
86 var kindsArray: [CategoryModel]?
87 var epochsArray: [CategoryModel]?
88 var genresArray: [CategoryModel]?
90 var kindsSection: FilterSectionHeaderCollectionReusableView?
91 var epochsSection: FilterSectionHeaderCollectionReusableView?
92 var genresSection: FilterSectionHeaderCollectionReusableView?
94 var isKindsDownloading = false
95 var isEpochsDownloading = false
96 var isGenresDownloading = false
98 var filterChanged = false
99 var onlyLectures = false
100 var hasAudiobook = false
102 override func viewDidLoad() {
105 title = "filters".localized
107 setupCollectionView()
109 getData(filterSection: .epochs)
110 getData(filterSection: .kinds)
111 getData(filterSection: .genres)
114 @IBAction func closeAction(_ sender: Any) {
115 navigationController?.dismiss(animated: true, completion: nil)
118 @IBAction func confirmAction(_ sender: Any) {
119 delegate.filterViewControllerDidSelectItems(kindsArray: kindsArray?.filter({$0.checked == true}) ?? [CategoryModel](), epochsArray: epochsArray?.filter({$0.checked == true}) ?? [CategoryModel](), genresArray: genresArray?.filter({$0.checked == true}) ?? [CategoryModel](), onlyLectures: onlyLectures, hasAudiobook: hasAudiobook, filterChanged: filterChanged)
122 func getSection(filterSection: FilterSection) -> FilterSectionHeaderCollectionReusableView? {
123 switch filterSection {
135 func setDataSource(filterSection:FilterSection, dSource: [CategoryModel]?) {
136 switch filterSection {
138 if let arr = dSource{
139 for obj in initialSelectedEpochsArray{
140 arr.first(where: {$0.slug == obj.slug})?.checked = true
143 epochsArray = dSource
145 if let arr = dSource{
146 for obj in initialSelectedGenresArray{
147 arr.first(where: {$0.slug == obj.slug})?.checked = true
150 genresArray = dSource
152 if let arr = dSource{
153 for obj in initialSelectedKindsArray{
154 arr.first(where: {$0.slug == obj.slug})?.checked = true
163 func setIsDownloading(isDownloading: Bool, section: FilterSection){
166 isEpochsDownloading = isDownloading
168 isGenresDownloading = isDownloading
170 isKindsDownloading = isDownloading
176 func getIsDownloading(section: FilterSection) -> Bool{
179 return isEpochsDownloading
181 return isGenresDownloading
183 return isKindsDownloading
189 func getData(filterSection: FilterSection){
191 getSection(filterSection: filterSection)?.refreshButton.setIndicatorButtonState(state: .loading)
192 setIsDownloading(isDownloading: true, section: filterSection)
194 syncManager.getCategories(filterSection: filterSection, bookOnly: true) { [weak self] (result) in
195 self?.setIsDownloading(isDownloading: false, section: filterSection)
197 case .success(let model):
198 self?.getSection(filterSection: filterSection)?.refreshButton.setIndicatorButtonState(state: .hidden)
199 self?.setDataSource(filterSection: filterSection, dSource: model as? [CategoryModel])
200 self?.collectionView.reloadSections([filterSection.rawValue])
201 case .failure/*(let *error)*/:
202 self?.getSection(filterSection: filterSection)?.refreshButton.setIndicatorButtonState(state: .button)
203 self?.view.makeToast(filterSection.failedText, duration: 3.0, position: .bottom)
208 func setupCollectionView(){
210 collectionView.backgroundColor = UIColor.clear
211 collectionView.delegate = self
212 collectionView.dataSource = self
213 collectionView.register(UINib.init(nibName: "FilterCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "FilterCollectionViewCell")
214 collectionView.register(UINib.init(nibName: "FilterSectionHeaderCollectionReusableView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "FilterSectionHeaderCollectionReusableView")
215 collectionView.register(UINib.init(nibName: "FilterOnlyLecturesReusableView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "FilterOnlyLecturesReusableView")
217 if #available(iOS 11.0, *) {
218 collectionView.contentInsetAdjustmentBehavior = .always
221 collectionView.setCollectionViewLayout(LeftAlignedCollectionViewFlowLayout(), animated: true)
224 func getArrayForSection(filterSection: FilterSection) -> [CategoryModel]?{
225 switch filterSection{
226 case .onlyLectures, .hasAudiobook:
237 func numberOfRowsInSection(filterSection: FilterSection) -> Int{
238 return getArrayForSection(filterSection: filterSection)?.count ?? 0
241 func clearSectionHeaderReference(section: FilterSectionHeaderCollectionReusableView) {
242 if genresSection == section{
245 if epochsSection == section{
248 if kindsSection == section{
254 extension FilterViewController: UICollectionViewDelegateFlowLayout{
256 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
258 if let items = getArrayForSection(filterSection: FilterSection(rawValue: indexPath.section)!){
259 let item = items[indexPath.row]
260 return CGSize(width: item.name.uppercased().width(withConstrainedHeight: 20, font: UIFont.systemFont(ofSize: 14, weight: .medium)) + 40, height: 30)
262 return CGSize(width: 50, height: 30)
265 func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
267 if indexPath.section == 0{
268 let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FilterOnlyLecturesReusableView", for: indexPath) as? FilterOnlyLecturesReusableView
269 sectionHeader?.delegate = self
270 sectionHeader?.onSwitch.isOn = onlyLectures
271 sectionHeader?.setup(isAudiobook: false)
272 return sectionHeader!
274 if indexPath.section == 1{
275 let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FilterOnlyLecturesReusableView", for: indexPath) as? FilterOnlyLecturesReusableView
276 sectionHeader?.delegate = self
277 sectionHeader?.onSwitch.isOn = hasAudiobook
278 sectionHeader?.setup(isAudiobook: true)
279 return sectionHeader!
283 let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FilterSectionHeaderCollectionReusableView", for: indexPath) as! FilterSectionHeaderCollectionReusableView
284 clearSectionHeaderReference(section: sectionHeader)
286 let filterSection = FilterSection(rawValue: indexPath.section)!
287 sectionHeader.setup(filterSection: filterSection, isDownloading: getIsDownloading(section: filterSection))
288 sectionHeader.delegate = self
290 if indexPath.section == FilterSection.epochs.rawValue{
291 epochsSection = sectionHeader
293 else if indexPath.section == FilterSection.genres.rawValue{
294 genresSection = sectionHeader
296 else if indexPath.section == FilterSection.kinds.rawValue{
297 kindsSection = sectionHeader
303 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
305 if section == 0 || section == 1{
306 return CGSize(width: UIScreen.main.bounds.width, height: 44)
309 if getArrayForSection(filterSection: FilterSection(rawValue: section)!) != nil{
310 return CGSize(width: UIScreen.main.bounds.width, height: 44)
313 return CGSize(width: UIScreen.main.bounds.width, height: 180)
319 extension FilterViewController: UICollectionViewDataSource{ //UICollectionViewDataSource
321 func numberOfSections(in collectionView: UICollectionView) -> Int {
325 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
326 return numberOfRowsInSection(filterSection: FilterSection(rawValue: section)!)
329 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
331 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCollectionViewCell", for: indexPath) as! FilterCollectionViewCell
333 if let items = getArrayForSection(filterSection: FilterSection(rawValue: indexPath.section)!){
334 cell.setup(categoryModel: items[indexPath.row])
340 extension FilterViewController: UICollectionViewDelegate{
341 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
343 if let items = getArrayForSection(filterSection: FilterSection(rawValue: indexPath.section)!), items.count > indexPath.row{
345 let item = items[indexPath.row]
346 item.checked = !item.checked
347 if let cell = collectionView.cellForItem(at: indexPath) as? FilterCollectionViewCell{
348 cell.setChecked(value: item.checked)
354 extension FilterViewController: FilterOnlyLecturesReusableViewDelegate{
355 func filterOnlyLecturesReusableViewSwitchValueChanged(value: Bool, isAudiobook: Bool){
366 extension FilterViewController: FilterSectionHeaderCollectionReusableViewDelegate{
367 func filterSectionRefreshButtonTapped(section: FilterSection){
368 getData(filterSection: section)