Add search bar iOS

This commit is contained in:
2020-12-06 14:59:27 +01:00
parent c390c014e4
commit 6789bf3aa6
5 changed files with 130 additions and 2 deletions

View File

@@ -13,6 +13,8 @@
954E68352574E3890034EBA8 /* iOSServerApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954E68342574E3890034EBA8 /* iOSServerApi.swift */; }; 954E68352574E3890034EBA8 /* iOSServerApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954E68342574E3890034EBA8 /* iOSServerApi.swift */; };
954E683D2574ED9E0034EBA8 /* UserDefaultsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954E683C2574ED9E0034EBA8 /* UserDefaultsExtensions.swift */; }; 954E683D2574ED9E0034EBA8 /* UserDefaultsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 954E683C2574ED9E0034EBA8 /* UserDefaultsExtensions.swift */; };
9553DB09257173ED006AE167 /* iOSRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9553DB08257173ED006AE167 /* iOSRepository.swift */; }; 9553DB09257173ED006AE167 /* iOSRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9553DB08257173ED006AE167 /* iOSRepository.swift */; };
955B7A0E257D098C0091B1F9 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955B7A0D257D098C0091B1F9 /* SearchBar.swift */; };
955B7A10257D10A70091B1F9 /* ViewControllerResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955B7A0F257D10A70091B1F9 /* ViewControllerResolver.swift */; };
95906F48257508660060F5D0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95906F47257506360060F5D0 /* Assets.xcassets */; }; 95906F48257508660060F5D0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 95906F47257506360060F5D0 /* Assets.xcassets */; };
95906F4D257510370060F5D0 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 95906F4C257510370060F5D0 /* GoogleService-Info.plist */; }; 95906F4D257510370060F5D0 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 95906F4C257510370060F5D0 /* GoogleService-Info.plist */; };
95BC3BF82572BCF900F24400 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BC3BF72572BCF900F24400 /* AttachmentView.swift */; }; 95BC3BF82572BCF900F24400 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BC3BF72572BCF900F24400 /* AttachmentView.swift */; };
@@ -49,6 +51,8 @@
954E68342574E3890034EBA8 /* iOSServerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSServerApi.swift; sourceTree = "<group>"; }; 954E68342574E3890034EBA8 /* iOSServerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSServerApi.swift; sourceTree = "<group>"; };
954E683C2574ED9E0034EBA8 /* UserDefaultsExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsExtensions.swift; sourceTree = "<group>"; }; 954E683C2574ED9E0034EBA8 /* UserDefaultsExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsExtensions.swift; sourceTree = "<group>"; };
9553DB08257173ED006AE167 /* iOSRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSRepository.swift; sourceTree = "<group>"; }; 9553DB08257173ED006AE167 /* iOSRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSRepository.swift; sourceTree = "<group>"; };
955B7A0D257D098C0091B1F9 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
955B7A0F257D10A70091B1F9 /* ViewControllerResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerResolver.swift; sourceTree = "<group>"; };
95906F47257506360060F5D0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 95906F47257506360060F5D0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
95906F4C257510370060F5D0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; 95906F4C257510370060F5D0 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
959B531E25764726009AD895 /* circolapp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = circolapp.entitlements; sourceTree = "<group>"; }; 959B531E25764726009AD895 /* circolapp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = circolapp.entitlements; sourceTree = "<group>"; };
@@ -100,6 +104,8 @@
95CA31BF255C28C300AC095B /* CircularView.swift */, 95CA31BF255C28C300AC095B /* CircularView.swift */,
95BC3BF72572BCF900F24400 /* AttachmentView.swift */, 95BC3BF72572BCF900F24400 /* AttachmentView.swift */,
9512D3C0257AB4F60023C3A1 /* NewReminderView.swift */, 9512D3C0257AB4F60023C3A1 /* NewReminderView.swift */,
955B7A0D257D098C0091B1F9 /* SearchBar.swift */,
955B7A0F257D10A70091B1F9 /* ViewControllerResolver.swift */,
); );
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -278,11 +284,13 @@
95CA31C0255C28C300AC095B /* CircularView.swift in Sources */, 95CA31C0255C28C300AC095B /* CircularView.swift in Sources */,
952DEDDF2576F8DC001DF85D /* SceneDelegate.swift in Sources */, 952DEDDF2576F8DC001DF85D /* SceneDelegate.swift in Sources */,
95CA31B2255C1EDE00AC095B /* ContentView.swift in Sources */, 95CA31B2255C1EDE00AC095B /* ContentView.swift in Sources */,
955B7A10257D10A70091B1F9 /* ViewControllerResolver.swift in Sources */,
954E68352574E3890034EBA8 /* iOSServerApi.swift in Sources */, 954E68352574E3890034EBA8 /* iOSServerApi.swift in Sources */,
95CA31B0255C1EDE00AC095B /* AppDelegate.swift in Sources */, 95CA31B0255C1EDE00AC095B /* AppDelegate.swift in Sources */,
95BC3BF82572BCF900F24400 /* AttachmentView.swift in Sources */, 95BC3BF82572BCF900F24400 /* AttachmentView.swift in Sources */,
9512D3C1257AB4F60023C3A1 /* NewReminderView.swift in Sources */, 9512D3C1257AB4F60023C3A1 /* NewReminderView.swift in Sources */,
954E683D2574ED9E0034EBA8 /* UserDefaultsExtensions.swift in Sources */, 954E683D2574ED9E0034EBA8 /* UserDefaultsExtensions.swift in Sources */,
955B7A0E257D098C0091B1F9 /* SearchBar.swift in Sources */,
95C46A51255D3A34007A75E5 /* CircularViewModel.swift in Sources */, 95C46A51255D3A34007A75E5 /* CircularViewModel.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@@ -25,6 +25,7 @@ class CircularViewModel: ObservableObject {
private var circularWatcher: Ktor_ioCloseable? = nil private var circularWatcher: Ktor_ioCloseable? = nil
private var userDefaultsObserver: NSKeyValueObservation? = nil private var userDefaultsObserver: NSKeyValueObservation? = nil
private var schoolID = 0 private var schoolID = 0
private var category: Category = .all
private let repository: CircularRepository private let repository: CircularRepository
private let key = "school" private let key = "school"
@@ -58,6 +59,7 @@ class CircularViewModel: ObservableObject {
} }
func startObservingCirculars() { func startObservingCirculars() {
category = .all
stopObserving() stopObserving()
circularWatcher = repository.circularDao.getCFlowCirculars(school: Int32(schoolID)).watch { circulars in circularWatcher = repository.circularDao.getCFlowCirculars(school: Int32(schoolID)).watch { circulars in
self.circulars = circulars as! Array<Circular>; self.circulars = circulars as! Array<Circular>;
@@ -65,13 +67,15 @@ class CircularViewModel: ObservableObject {
} }
func startObservingFavourites() { func startObservingFavourites() {
category = .favourites
stopObserving() stopObserving()
circularWatcher = repository.circularDao.getFavouritesC(school: Int32(schoolID)).watch { circulars in circularWatcher = repository.circularDao.getFavouritesC(school: Int32(schoolID)).watch { circulars in
self.circulars = circulars as! Array<Circular>; self.circulars = circulars as! Array<Circular>;
} }
} }
func startObservingAlarms() { func startObservingReminders() {
category = .reminders
stopObserving() stopObserving()
circularWatcher = repository.circularDao.getCFlowReminders(school: Int32(schoolID)).watch { circulars in circularWatcher = repository.circularDao.getCFlowReminders(school: Int32(schoolID)).watch { circulars in
self.circulars = circulars as! Array<Circular>; self.circulars = circulars as! Array<Circular>;
@@ -81,4 +85,28 @@ class CircularViewModel: ObservableObject {
func stopObserving() { func stopObserving() {
circularWatcher?.close() circularWatcher?.close()
} }
func search(query: String) {
let wrappedQuery = "%" + query + "%"
stopObserving()
switch category {
case .all:
circularWatcher = repository.circularDao.searchCircularsC(query: wrappedQuery, school: Int32(schoolID)).watch { circulars in
self.circulars = circulars as! Array<Circular>;
}
case .favourites:
circularWatcher = repository.circularDao.searchFavouritesC(query: wrappedQuery, school: Int32(schoolID)).watch { circulars in
self.circulars = circulars as! Array<Circular>;
}
case .reminders:
circularWatcher = repository.circularDao.searchRemindersC(query: wrappedQuery, school: Int32(schoolID)).watch { circulars in
self.circulars = circulars as! Array<Circular>;
}
}
}
}
enum Category {
case all, favourites, reminders
} }

View File

@@ -22,6 +22,7 @@ import Shared
struct ContentView: View { struct ContentView: View {
@ObservedObject var circularViewModel = CircularViewModel(repository: iOSRepository.getCircularRepository()) @ObservedObject var circularViewModel = CircularViewModel(repository: iOSRepository.getCircularRepository())
@ObservedObject var searchBar: SearchBar = SearchBar(placeholder: "Search circulars")
var body: some View { var body: some View {
NavigationView { NavigationView {
@@ -29,6 +30,10 @@ struct ContentView: View {
CircularView(circular: circular) CircularView(circular: circular)
} }
.navigationBarTitle(Text("Circulars"), displayMode: .large) .navigationBarTitle(Text("Circulars"), displayMode: .large)
.addSearchBar(self.searchBar)
.onReceive(searchBar.$text) {query in
self.circularViewModel.search(query: query)
}
.onAppear { .onAppear {
self.circularViewModel.startObservingCirculars() self.circularViewModel.startObservingCirculars()
} }
@@ -52,7 +57,7 @@ struct ContentView: View {
} }
Button(action: { Button(action: {
self.circularViewModel.startObservingAlarms() self.circularViewModel.startObservingReminders()
}) { }) {
Image(systemName: "alarm") Image(systemName: "alarm")
} }

View File

@@ -0,0 +1,48 @@
import UIKit
import SwiftUI
class SearchBar: NSObject, ObservableObject {
@Published var text: String = ""
let searchController: UISearchController = UISearchController(searchResultsController: nil)
init(placeholder: String) {
super.init()
self.searchController.obscuresBackgroundDuringPresentation = false
self.searchController.searchResultsUpdater = self
self.searchController.searchBar.placeholder = placeholder
}
}
extension SearchBar: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
// Publish search bar text changes.
if let searchBarText = searchController.searchBar.text {
self.text = searchBarText
}
}
}
struct SearchBarModifier: ViewModifier {
let searchBar: SearchBar
func body(content: Content) -> some View {
content
.overlay(
ViewControllerResolver { viewController in
viewController.navigationItem.searchController = self.searchBar.searchController
}
.frame(width: 0, height: 0)
)
}
}
extension View {
func addSearchBar(_ searchBar: SearchBar) -> some View {
return self.modifier(SearchBarModifier(searchBar: searchBar))
}
}

View File

@@ -0,0 +1,39 @@
import Foundation
import SwiftUI
final class ViewControllerResolver: UIViewControllerRepresentable {
let onResolve: (UIViewController) -> Void
init(onResolve: @escaping (UIViewController) -> Void) {
self.onResolve = onResolve
}
func makeUIViewController(context: Context) -> ParentResolverViewController {
ParentResolverViewController(onResolve: onResolve)
}
func updateUIViewController(_ uiViewController: ParentResolverViewController, context: Context) { }
}
class ParentResolverViewController: UIViewController {
let onResolve: (UIViewController) -> Void
init(onResolve: @escaping (UIViewController) -> Void) {
self.onResolve = onResolve
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("Use init(onResolve:) to instantiate ParentResolverViewController.")
}
override func didMove(toParent parent: UIViewController?) {
super.didMove(toParent: parent)
if let parent = parent {
onResolve(parent)
}
}
}