mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-14 17:23:25 +01:00
[ADD] Search bar for BrowseView on iOS 15
This commit is contained in:
committed by
Joe Mattiello
parent
0c034b61d9
commit
0e7083539d
17
AltStore/Extensions/StoreApp+Filterable.swift
Normal file
17
AltStore/Extensions/StoreApp+Filterable.swift
Normal file
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
23
AltStore/Protocols/Filterable.swift
Normal file
23
AltStore/Protocols/Filterable.swift
Normal file
@@ -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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
29
AltStore/View Extensions/Modifiers.swift
Normal file
29
AltStore/View Extensions/Modifiers.swift
Normal file
@@ -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`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
|
||||||
|
if condition {
|
||||||
|
transform(self)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ViewBuilder func searchable(text: Binding<String>, placeholder: String) -> some View {
|
||||||
|
if #available(iOS 15.0, *) {
|
||||||
|
self.searchable(text: text, prompt: Text(placeholder))
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ struct BrowseAppPreviewView: View {
|
|||||||
let storeApp: StoreApp
|
let storeApp: StoreApp
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack(spacing: 16) {
|
||||||
AppRowView(app: storeApp)
|
AppRowView(app: storeApp)
|
||||||
|
|
||||||
if let subtitle = storeApp.subtitle {
|
if let subtitle = storeApp.subtitle {
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ struct BrowseView: View {
|
|||||||
NSSortDescriptor(keyPath: \StoreApp.sortIndex, ascending: true),
|
NSSortDescriptor(keyPath: \StoreApp.sortIndex, ascending: true),
|
||||||
NSSortDescriptor(keyPath: \StoreApp.name, ascending: true),
|
NSSortDescriptor(keyPath: \StoreApp.name, ascending: true),
|
||||||
NSSortDescriptor(keyPath: \StoreApp.bundleIdentifier, 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<StoreApp>
|
var apps: FetchedResults<StoreApp>
|
||||||
|
|
||||||
var filteredApps: [StoreApp] {
|
var filteredApps: [StoreApp] {
|
||||||
apps.filter { $0.matches(self.searchText) }
|
apps.items(matching: self.searchText)
|
||||||
}
|
}
|
||||||
|
|
||||||
@State
|
@State
|
||||||
@@ -31,7 +31,7 @@ struct BrowseView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVStack(spacing: 24) {
|
LazyVStack(spacing: 32) {
|
||||||
ForEach(filteredApps, id: \.bundleIdentifier) { app in
|
ForEach(filteredApps, id: \.bundleIdentifier) { app in
|
||||||
NavigationLink {
|
NavigationLink {
|
||||||
AppDetailView(storeApp: app)
|
AppDetailView(storeApp: app)
|
||||||
@@ -68,32 +68,3 @@ struct BrowseView_Previews: PreviewProvider {
|
|||||||
BrowseView()
|
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`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
|
|
||||||
if condition {
|
|
||||||
transform(self)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ViewBuilder func searchable(text: Binding<String>, placeholder: String) -> some View {
|
|
||||||
if #available(iOS 15.0, *) {
|
|
||||||
self.searchable(text: text, prompt: Text(placeholder))
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user