feat(Categories): add loading activity indicator while filtering Categories
MODIFY
ACHNBrowserUI/ACHNBrowserUI.xcodeproj/project.pbxproj
ACHNBrowserUI/ACHNBrowserUI.xcodeproj/project.pbxproj
02F2D4472455D81C009741DA /* simple-orange@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 02F2D3F72455D81C009741DA /* simple-orange@3x.png */; };
02F2D4482455D81C009741DA /* simple-mint@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 02F2D3F82455D81C009741DA /* simple-mint@3x.png */; };
4C382EE8244E418800F446BA /* DismissingKeyboardOnSwipe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C382EE7244E418800F446BA /* DismissingKeyboardOnSwipe.swift */; };
+ 4C7FE78324574FB50011E8AB /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7FE78224574FB50011E8AB /* ActivityIndicator.swift */; };
68345579244C994C0072FC0C /* LikeButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68345578244C994C0072FC0C /* LikeButtonView.swift */; };
6834557B244CA8E10072FC0C /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6834557A244CA8E10072FC0C /* URL.swift */; };
68345589244E4DEF0072FC0C /* ACNHEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 68345588244E4DEF0072FC0C /* ACNHEvents */; };
02F2D3F72455D81C009741DA /* simple-orange@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "simple-orange@3x.png"; sourceTree = "<group>"; };
02F2D3F82455D81C009741DA /* simple-mint@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "simple-mint@3x.png"; sourceTree = "<group>"; };
4C382EE7244E418800F446BA /* DismissingKeyboardOnSwipe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissingKeyboardOnSwipe.swift; sourceTree = "<group>"; };
+ 4C7FE78224574FB50011E8AB /* ActivityIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = "<group>"; };
68345578244C994C0072FC0C /* LikeButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeButtonView.swift; sourceTree = "<group>"; };
6834557A244CA8E10072FC0C /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
6834558A244E4E0B0072FC0C /* DashboardEventTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardEventTextView.swift; sourceTree = "<group>"; };
68345578244C994C0072FC0C /* LikeButtonView.swift */,
69CA5ED9244CBA8600B275B6 /* CalendarView.swift */,
69CA5F00244F1AD300B275B6 /* SectionHeaderView.swift */,
+ 4C7FE78224574FB50011E8AB /* ActivityIndicator.swift */,
);
path = shared;
sourceTree = "<group>";
69CA5EF6244DBFCB00B275B6 /* Fruit.swift in Sources */,
693E0B1B244C2B9300D20E46 /* AppUserDefault.swift in Sources */,
69BEA989243E68D400F02C61 /* UserCollection.swift in Sources */,
+ 4C7FE78324574FB50011E8AB /* ActivityIndicator.swift in Sources */,
6942FC37244988F80062FE8F /* SafariView.swift in Sources */,
693E0B1D244C315B00D20E46 /* DashboardViewModel.swift in Sources */,
69AF8C7C243E4D29001DD9CB /* Color.swift in Sources */,

MODIFY
ACHNBrowserUI/ACHNBrowserUI/viewModels/CategoriesSearchViewModel.swift
ACHNBrowserUI/ACHNBrowserUI/viewModels/CategoriesSearchViewModel.swift
@@ -13,18 +13,24 @@ import Combine
class CategoriesSearchViewModel: ObservableObject {
@Published var searchText = ""
@Published var searchResults: [Category: [Item]] = [:]
+ @Published var isLoadingData = false
private var searchCancellable: AnyCancellable?
init() {
searchCancellable = $searchText
- .debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
+ .handleEvents(receiveOutput: { [weak self] _ in self?.isLoadingData = true })
+ .debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)
.removeDuplicates()
.filter { !$0.isEmpty }
.map(itemsInCategory(with:))
.subscribe(on: DispatchQueue.global())
.receive(on: DispatchQueue.main)
- .sink(receiveValue: { [weak self] in self?.searchResults = $0})
+ .sink(receiveValue: { [weak self] in
+ guard let self = self else { return }
+ self.searchResults = $0
+ self.isLoadingData = false
+ })
}
private func itemsInCategory(with string: String) -> [Category: [Item]] {

MODIFY
ACHNBrowserUI/ACHNBrowserUI/views/categories/CategoriesView.swift
ACHNBrowserUI/ACHNBrowserUI/views/categories/CategoriesView.swift
@@ -12,6 +12,7 @@ struct CategoriesView: View {
let categories: [Category]
@ObservedObject var viewModel = CategoriesSearchViewModel()
+ @State var isLoadingData = false
func makeCategories() -> some View {
ForEach(categories, id: \.self) { categorie in
@@ -75,6 +76,7 @@ struct CategoriesView: View {
}
.navigationBarTitle(Text("Catalog"), displayMode: .inline)
.background(Color.grassBackground)
+ .onReceive(viewModel.$isLoadingData) { self.isLoadingData = $0 }
ItemsListView(viewModel: ItemsViewModel(category: .housewares))
}
@@ -89,8 +91,13 @@ struct CategoriesView: View {
}
private var searchList: some View {
+ ZStack {
List {
ForEach(searchCategories, id: \.0, content: searchSection)
+ }
+ loadingView
+ .opacity(isLoadingData ? 80/100 : 0)
+ .animation(.default)
}.modifier(DismissingKeyboardOnSwipe())
}
@@ -111,6 +118,15 @@ struct CategoriesView: View {
ItemRowView(item: item)
}
}
+
+ private var loadingView: some View {
+ VStack {
+ HStack { Spacer() }
+ Spacer()
+ ActivityIndicator(isAnimating: $isLoadingData, style: .large)
+ Spacer()
+ }.background(Color.dialogue)
+ }
}
struct CategoriesView_Previews: PreviewProvider {

feat(Categories): add loading activity indicator while filtering Categories