Fix for native navigation (#233)
Some checks failed
Build and Release / Build IPA (push) Has been cancelled
Build and Release / Build macOS App (push) Has been cancelled

Co-authored-by: cranci <100066266+cranci1@users.noreply.github.com>
This commit is contained in:
Ek20000 2025-08-15 15:35:58 +02:00 committed by GitHub
parent 8b2f9c08cd
commit 122e248d9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 112 additions and 99 deletions

View file

@ -52,7 +52,7 @@ struct ContentView: View {
}
}
}
.searchable(text: $searchQuery)
//.searchable(text: $searchQuery)
} else {
ZStack(alignment: .bottom) {
ZStack {

View file

@ -632,10 +632,12 @@ struct MediaInfoView: View {
@ViewBuilder
private var flatEpisodeList: some View {
VStack(spacing: 15) {
ForEach(currentEpisodeList.indices.filter { selectedRange.contains($0) }, id: \.self) { i in
let ep = currentEpisodeList[i]
createEpisodeCell(episode: ep, index: i, season: isGroupedBySeasons ? selectedSeason + 1 : 1)
ScrollView {
VStack(spacing: 15) {
ForEach(currentEpisodeList.indices.filter { selectedRange.contains($0) }, id: \.self) { i in
let ep = currentEpisodeList[i]
createEpisodeCell(episode: ep, index: i, season: isGroupedBySeasons ? selectedSeason + 1 : 1)
}
}
}
}
@ -644,10 +646,12 @@ struct MediaInfoView: View {
private var seasonsEpisodeList: some View {
let seasons = groupedEpisodes()
if !seasons.isEmpty, selectedSeason < seasons.count {
VStack(spacing: 15) {
ForEach(seasons[selectedSeason].indices.filter { selectedRange.contains($0) }, id: \.self) { i in
let ep = seasons[selectedSeason][i]
createEpisodeCell(episode: ep, index: i, season: selectedSeason + 1)
ScrollView {
VStack(spacing: 15) {
ForEach(seasons[selectedSeason].indices.filter { selectedRange.contains($0) }, id: \.self) { i in
let ep = seasons[selectedSeason][i]
createEpisodeCell(episode: ep, index: i, season: selectedSeason + 1)
}
}
}
} else {

View file

@ -69,3 +69,46 @@ struct SearchHistoryRow: View {
}
}
}
struct SearchBar: View {
@Binding var text: String
@Binding var isSearching: Bool
@FocusState private var isFocused: Bool
var body: some View {
HStack {
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(.gray)
TextField("Search", text: $text)
.focused($isFocused)
.submitLabel(.search)
.autocorrectionDisabled(true)
.autocapitalization(.none)
.disableAutocorrection(true)
.textInputAutocapitalization(.never)
.onChange(of: text) { _ in
// This triggers search while typing
NotificationCenter.default.post(name: .tabBarSearchQueryUpdated, object: nil, userInfo: ["searchQuery": text])
}
.onSubmit {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
if !text.isEmpty {
Button(action: {
text = ""
isFocused = false
}) {
Image(systemName: "xmark.circle.fill")
.foregroundColor(.gray)
}
}
}
.padding(8)
.background(Color(.systemGray6))
.cornerRadius(10)
}
}
}

View file

@ -20,6 +20,7 @@ struct SearchView: View {
@AppStorage("selectedModuleId") private var selectedModuleId: String?
@AppStorage("mediaColumnsPortrait") private var mediaColumnsPortrait: Int = 2
@AppStorage("mediaColumnsLandscape") private var mediaColumnsLandscape: Int = 4
@AppStorage("useNativeTabBar") private var useNativeTabBar: Bool = false
@StateObject private var jsController = JSController.shared
@EnvironmentObject var moduleManager: ModuleManager
@ -74,51 +75,64 @@ struct SearchView: View {
}
private var mainContent: some View {
VStack(alignment: .leading) {
HStack {
Text(LocalizedStringKey("Search"))
.font(.largeTitle)
.fontWeight(.bold)
VStack(alignment: .leading) {
HStack {
Text(LocalizedStringKey("Search"))
.font(.largeTitle)
.fontWeight(.bold)
Spacer()
ModuleSelectorMenu(
selectedModule: selectedModule,
moduleGroups: getModuleLanguageGroups(),
modulesByLanguage: getModulesByLanguage(),
selectedModuleId: selectedModuleId,
onModuleSelected: { moduleId in
selectedModuleId = moduleId
}
)
}
.padding(.horizontal, 20)
.padding(.top, 20)
Spacer()
if useNativeTabBar {
SearchBar(text: $searchQuery, isSearching: $isSearching)
.padding(.horizontal, 20)
.padding(.top, 10)
}
ModuleSelectorMenu(
selectedModule: selectedModule,
moduleGroups: getModuleLanguageGroups(),
modulesByLanguage: getModulesByLanguage(),
selectedModuleId: selectedModuleId,
onModuleSelected: { moduleId in
selectedModuleId = moduleId
}
)
}
.padding(.horizontal, 20)
.padding(.top, 20)
ScrollView(showsIndicators: false) {
SearchContent(
selectedModule: selectedModule,
searchQuery: searchQuery,
searchHistory: searchHistory,
searchItems: searchItems,
isSearching: isSearching,
hasNoResults: hasNoResults,
columns: columns,
columnsCount: columnsCount,
cellWidth: cellWidth,
onHistoryItemSelected: { query in
searchQuery = query
searchDebounceTimer?.invalidate()
ScrollView(showsIndicators: false) {
SearchContent(
selectedModule: selectedModule,
searchQuery: searchQuery,
searchHistory: searchHistory,
searchItems: searchItems,
isSearching: isSearching,
hasNoResults: hasNoResults,
columns: columns,
columnsCount: columnsCount,
cellWidth: cellWidth,
onHistoryItemSelected: { query in
searchQuery = query
searchDebounceTimer?.invalidate()
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
NotificationCenter.default.post(name: .tabBarSearchQueryUpdated, object: nil, userInfo: ["searchQuery": query])
performSearch()
},
onHistoryItemDeleted: { index in
removeFromHistory(at: index)
},
onClearHistory: clearSearchHistory
)
}
.scrollViewBottomPadding()
.simultaneousGesture(
DragGesture().onChanged { _ in
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
NotificationCenter.default.post(name: .tabBarSearchQueryUpdated, object: nil, userInfo: ["searchQuery": query])
performSearch()
},
onHistoryItemDeleted: { index in
removeFromHistory(at: index)
},
onClearHistory: clearSearchHistory
}
)
}
.scrollViewBottomPadding()
@ -128,8 +142,6 @@ struct SearchView: View {
}
)
}
.navigationBarHidden(true)
}
var body: some View {
Group {
@ -348,49 +360,3 @@ struct SearchView: View {
return getModulesByLanguage()[language] ?? []
}
}
struct SearchBar: View {
@State private var debounceTimer: Timer?
@Binding var text: String
@Binding var isFocused: Bool
var onSearchButtonClicked: () -> Void
var body: some View {
HStack {
TextField(LocalizedStringKey("Search..."), text: $text, onEditingChanged: { isEditing in
isFocused = isEditing
}, onCommit: onSearchButtonClicked)
.padding(7)
.padding(.horizontal, 25)
.background(Color(.systemGray6))
.cornerRadius(8)
.onChange(of: text) { newValue in
debounceTimer?.invalidate()
if !newValue.isEmpty {
debounceTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
onSearchButtonClicked()
}
}
}
.overlay(
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(.secondary)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 8)
if !text.isEmpty {
Button(action: {
self.text = ""
}) {
Image(systemName: "multiply.circle.fill")
.foregroundColor(.secondary)
.padding(.trailing, 8)
}
}
}
)
}
}
}