Revisited Navigator

This commit is contained in:
Lumaa 2024-08-10 15:43:47 +02:00
parent d958940d81
commit ac6219450a
7 changed files with 73 additions and 16 deletions

View File

@ -3,8 +3,8 @@
import SwiftUI import SwiftUI
struct TabsView: View { struct TabsView: View {
@Binding var selectedTab: TabDestination @State var selectedTab: TabDestination = Navigator.shared.selectedTab
var postButton: () -> Void = {} var postButton: () -> Void = {}
var tapAction: () -> Void = {} var tapAction: () -> Void = {}
var retapAction: () -> Void = {} var retapAction: () -> Void = {}
@ -92,6 +92,9 @@ struct TabsView: View {
} }
.padding(.horizontal, 30) .padding(.horizontal, 30)
.background(Color.appBackground) .background(Color.appBackground)
.onChange(of: selectedTab) { _, newValue in
Navigator.shared.selectedTab = newValue
}
} }
} }

View File

@ -5,17 +5,67 @@ import SwiftUI
@Observable @Observable
public class Navigator: ObservableObject { public class Navigator: ObservableObject {
public static var shared: Navigator = Navigator()
public var path: [RouterDestination] = [] public var path: [RouterDestination] = []
public var presentedSheet: SheetDestination? public var presentedSheet: SheetDestination?
public var presentedCover: SheetDestination? public var presentedCover: SheetDestination?
public var selectedTab: TabDestination = .timeline public var selectedTab: TabDestination {
set {
change(to: newValue)
}
get {
return self.currentTab
}
}
private var currentTab: TabDestination = .timeline
public private(set) var memorizedNav: [TabDestination : [RouterDestination]] = [:]
public var showTabbar: Bool {
get {
self.visiTabbar
}
set {
withAnimation(.spring) {
self.visiTabbar = newValue
}
}
}
private var visiTabbar: Bool = true
public var client: Client? public var client: Client?
public func navigate(to: RouterDestination) { public func navigate(to: RouterDestination) {
path.append(to) path.append(to)
} }
/// Changes the current tab from the current ``Navigator`` class
func change(to tab: TabDestination) {
savePath()
withAnimation(.spring) {
loadPath(from: tab)
}
}
private func savePath() {
let lastTab: TabDestination = self.currentTab
let lastPath: [RouterDestination] = self.path
memorizedNav.updateValue(lastPath, forKey: lastTab)
}
private func loadPath(from tab: TabDestination) {
if let (newTab, newPath) = memorizedNav.first(where: { $0.key == tab }).map({ [$0.key : $0.value] })?.first {
self.currentTab = newTab
self.path = newPath
} else {
print("Couldn't find Navigator data from \(tab.id), created new ones")
self.currentTab = tab
self.path = []
}
}
public func handle(url: URL) -> OpenURLAction.Result { public func handle(url: URL) -> OpenURLAction.Result {
guard let client = self.client else { return .systemAction } guard let client = self.client else { return .systemAction }
let path: String = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "") // remove all path let path: String = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "") // remove all path
@ -64,15 +114,16 @@ public class Navigator: ObservableObject {
} }
return OpenURLAction.Result.handled return OpenURLAction.Result.handled
} }
/// This only applies on the current path, not the saved ones in ``memorizedNav``
public func removeSettingsOfPath() { public func removeSettingsOfPath() {
self.path = self.path.filter({ !RouterDestination.allSettings.contains($0) }) self.path = self.path.filter({ !RouterDestination.allSettings.contains($0) })
} }
} }
/// This can be used for universal ``SheetDestination``s
public class UniversalNavigator: Navigator { public class UniversalNavigator: Navigator {
static var shared: UniversalNavigator = UniversalNavigator() public static var `static`: UniversalNavigator = UniversalNavigator()
public var tabNavigator: Navigator?
} }
public enum TabDestination: Identifiable { public enum TabDestination: Identifiable {

View File

@ -5,7 +5,7 @@ import SwiftUI
struct AccountView: View { struct AccountView: View {
@Environment(AccountManager.self) private var accountManager: AccountManager @Environment(AccountManager.self) private var accountManager: AccountManager
@State private var navigator: Navigator = Navigator() @State private var navigator: Navigator = Navigator.shared
@State public var account: Account @State public var account: Account
var body: some View { var body: some View {

View File

@ -8,12 +8,13 @@ struct ContentView: View {
private var huggingFace: HuggingFace = HuggingFace() private var huggingFace: HuggingFace = HuggingFace()
@State private var preferences: UserPreferences = .defaultPreferences @State private var preferences: UserPreferences = .defaultPreferences
@StateObject private var uniNavigator = UniversalNavigator.shared @State private var navigator: Navigator = .shared
@StateObject private var uniNavigator = UniversalNavigator.static
@StateObject private var accountManager: AccountManager = AccountManager.shared @StateObject private var accountManager: AccountManager = AccountManager.shared
var body: some View { var body: some View {
ZStack { ZStack {
TabView(selection: $uniNavigator.selectedTab, content: { TabView(selection: $navigator.selectedTab, content: {
if accountManager.getAccount() != nil { if accountManager.getAccount() != nil {
TimelineView(timelineModel: FetchTimeline(client: accountManager.forceClient())) TimelineView(timelineModel: FetchTimeline(client: accountManager.forceClient()))
.background(Color.appBackground) .background(Color.appBackground)
@ -40,8 +41,10 @@ struct ContentView: View {
} }
.frame(maxWidth: appDelegate.windowWidth) .frame(maxWidth: appDelegate.windowWidth)
.overlay(alignment: .bottom) { .overlay(alignment: .bottom) {
TabsView(selectedTab: $uniNavigator.selectedTab, postButton: { TabsView(postButton: {
uniNavigator.presentedSheet = .post(content: "", replyId: nil, editId: nil) uniNavigator.presentedSheet = .post(content: "", replyId: nil, editId: nil)
}, retapAction: {
Navigator.shared.path = []
}) })
.safeAreaPadding(.vertical, 10) .safeAreaPadding(.vertical, 10)
.zIndex(10) .zIndex(10)

View File

@ -5,8 +5,8 @@ import SwiftUI
struct DiscoveryView: View { struct DiscoveryView: View {
@Environment(AccountManager.self) private var accountManager: AccountManager @Environment(AccountManager.self) private var accountManager: AccountManager
@State private var navigator: Navigator = Navigator() @State private var navigator: Navigator = Navigator.shared
@State private var searchQuery: String = "" @State private var searchQuery: String = ""
@State private var results: [String : SearchResults] = [:] @State private var results: [String : SearchResults] = [:]
@State private var querying: Bool = false @State private var querying: Bool = false

View File

@ -6,7 +6,7 @@ import TipKit
struct NotificationsView: View { struct NotificationsView: View {
@Environment(AccountManager.self) private var accountManager @Environment(AccountManager.self) private var accountManager
@State private var navigator: Navigator = Navigator() @State private var navigator: Navigator = Navigator.shared
@State private var notifications: [GroupedNotification] = [] @State private var notifications: [GroupedNotification] = []
@State private var loadingNotifs: Bool = true @State private var loadingNotifs: Bool = true
@State private var lastId: Int? = nil @State private var lastId: Int? = nil

View File

@ -5,7 +5,7 @@ import SwiftData
struct TimelineView: View { struct TimelineView: View {
@Environment(AccountManager.self) private var accountManager: AccountManager @Environment(AccountManager.self) private var accountManager: AccountManager
@State var navigator: Navigator = Navigator() @State var navigator: Navigator = Navigator.shared
@State private var showPicker: Bool = false @State private var showPicker: Bool = false
@State private var timelines: [TimelineFilter] = [.home, .trending, .local, .federated] @State private var timelines: [TimelineFilter] = [.home, .trending, .local, .federated]