diff --git a/AltStore/Extensions/StoreApp+Filterable.swift b/AltStore/Extensions/StoreApp+Filterable.swift new file mode 100644 index 00000000..9b228b36 --- /dev/null +++ b/AltStore/Extensions/StoreApp+Filterable.swift @@ -0,0 +1,17 @@ +// +// StoreApp+Searchable.swift +// SideStore +// +// Created by Fabian Thies on 01.12.22. +// Copyright © 2022 SideStore. All rights reserved. +// + +import AltStoreCore + +extension StoreApp: Filterable { + func matches(_ searchText: String) -> Bool { + searchText.isEmpty || + self.name.lowercased().contains(searchText.lowercased()) || + self.developerName.lowercased().contains(searchText.lowercased()) + } +} diff --git a/AltStore/Protocols/Filterable.swift b/AltStore/Protocols/Filterable.swift new file mode 100644 index 00000000..b5051799 --- /dev/null +++ b/AltStore/Protocols/Filterable.swift @@ -0,0 +1,23 @@ +// +// Filterable.swift +// SideStore +// +// Created by Fabian Thies on 01.12.22. +// Copyright © 2022 SideStore. All rights reserved. +// + +import Foundation + +protocol Filterable { + func matches(_ searchText: String) -> Bool +} + +extension Collection where Element: Filterable { + func matches(_ searchText: String) -> Bool { + self.contains(where: { $0.matches(searchText) }) + } + + func items(matching searchText: String) -> [Element] { + self.filter { $0.matches(searchText) } + } +} diff --git a/AltStore/View Extensions/Modifiers.swift b/AltStore/View Extensions/Modifiers.swift new file mode 100644 index 00000000..a4eb06ac --- /dev/null +++ b/AltStore/View Extensions/Modifiers.swift @@ -0,0 +1,29 @@ +// +// Modifiers.swift +// SideStore +// +// Created by Fabian Thies on 01.12.22. +// Copyright © 2022 SideStore. All rights reserved. +// + +import SwiftUI + +extension View { + + @ViewBuilder func `if`(_ condition: Bool, transform: (Self) -> Content) -> some View { + if condition { + transform(self) + } else { + self + } + } + + + @ViewBuilder func searchable(text: Binding, placeholder: String) -> some View { + if #available(iOS 15.0, *) { + self.searchable(text: text, prompt: Text(placeholder)) + } else { + self + } + } +} diff --git a/AltStore/Views/Browse/BrowseAppPreviewView.swift b/AltStore/Views/Browse/BrowseAppPreviewView.swift index da714c77..8df2cd84 100644 --- a/AltStore/Views/Browse/BrowseAppPreviewView.swift +++ b/AltStore/Views/Browse/BrowseAppPreviewView.swift @@ -14,7 +14,7 @@ struct BrowseAppPreviewView: View { let storeApp: StoreApp var body: some View { - VStack { + VStack(spacing: 16) { AppRowView(app: storeApp) if let subtitle = storeApp.subtitle { diff --git a/AltStore/Views/Browse/BrowseView.swift b/AltStore/Views/Browse/BrowseView.swift index b8b261bc..cd9fbba2 100644 --- a/AltStore/Views/Browse/BrowseView.swift +++ b/AltStore/Views/Browse/BrowseView.swift @@ -15,11 +15,11 @@ struct BrowseView: View { NSSortDescriptor(keyPath: \StoreApp.sortIndex, ascending: true), NSSortDescriptor(keyPath: \StoreApp.name, ascending: true), NSSortDescriptor(keyPath: \StoreApp.bundleIdentifier, ascending: true) - ]/*, predicate: NSPredicate(format: "%K != %@", #keyPath(StoreApp.bundleIdentifier), StoreApp.altstoreAppID)*/) + ], predicate: NSPredicate(format: "%K != %@", #keyPath(StoreApp.bundleIdentifier), StoreApp.altstoreAppID)) var apps: FetchedResults var filteredApps: [StoreApp] { - apps.filter { $0.matches(self.searchText) } + apps.items(matching: self.searchText) } @State @@ -31,7 +31,7 @@ struct BrowseView: View { var body: some View { ScrollView { - LazyVStack(spacing: 24) { + LazyVStack(spacing: 32) { ForEach(filteredApps, id: \.bundleIdentifier) { app in NavigationLink { AppDetailView(storeApp: app) @@ -68,32 +68,3 @@ struct BrowseView_Previews: PreviewProvider { BrowseView() } } - - -extension StoreApp { - func matches(_ searchText: String) -> Bool { - searchText.isEmpty || - self.name.lowercased().contains(searchText.lowercased()) || - self.developerName.lowercased().contains(searchText.lowercased()) - } -} - -extension View { - - @ViewBuilder func `if`(_ condition: Bool, transform: (Self) -> Content) -> some View { - if condition { - transform(self) - } else { - self - } - } - - - @ViewBuilder func searchable(text: Binding, placeholder: String) -> some View { - if #available(iOS 15.0, *) { - self.searchable(text: text, prompt: Text(placeholder)) - } else { - self - } - } -}