diff --git a/damus/ContentView.swift b/damus/ContentView.swift index 6771a9bf..4ea84c57 100644 --- a/damus/ContentView.swift +++ b/damus/ContentView.swift @@ -143,6 +143,7 @@ struct ContentView: View { ZStack { if let damus = self.damus_state { TimelineView(events: home.events, loading: .constant(false), damus: damus, show_friend_icon: false, filter: filter) + .environmentObject(navigationCoordinator) } } } @@ -163,10 +164,12 @@ struct ContentView: View { case .search: if #available(iOS 16.0, *) { SearchHomeView(damus_state: damus_state!, model: SearchHomeModel(damus_state: damus_state!)) + .environmentObject(navigationCoordinator) .scrollDismissesKeyboard(.immediately) } else { // Fallback on earlier versions SearchHomeView(damus_state: damus_state!, model: SearchHomeModel(damus_state: damus_state!)) + .environmentObject(navigationCoordinator) } case .home: @@ -174,9 +177,11 @@ struct ContentView: View { case .notifications: NotificationsView(state: damus, notifications: home.notifications) + .environmentObject(navigationCoordinator) case .dms: DirectMessagesView(damus_state: damus_state!, model: damus_state!.dms, settings: damus_state!.settings) + .environmentObject(navigationCoordinator) } } .navigationBarTitle(timeline_name(selected_timeline), displayMode: .inline) @@ -483,8 +488,8 @@ struct ContentView: View { switch local.type { case .dm: selected_timeline = .dms - damus_state.dms.open_dm_by_pk(target.pubkey) - + damus_state.dms.set_active_dm(target.pubkey) + navigationCoordinator.push(route: Route.DMChat(dms: damus_state.dms.active_model)) case .like: fallthrough case .zap: fallthrough case .mention: fallthrough diff --git a/damus/Models/DirectMessagesModel.swift b/damus/Models/DirectMessagesModel.swift index 89f0d457..7402de67 100644 --- a/damus/Models/DirectMessagesModel.swift +++ b/damus/Models/DirectMessagesModel.swift @@ -30,16 +30,6 @@ class DirectMessagesModel: ObservableObject { self.active_model = model } - func open_dm_by_pk(_ pubkey: String) { - self.set_active_dm(pubkey) - self.open_dm = true - } - - func open_dm_by_model(_ model: DirectMessageModel) { - self.set_active_dm_model(model) - self.open_dm = true - } - func set_active_dm(_ pubkey: String) { for model in self.dms where model.pubkey == pubkey { self.set_active_dm_model(model) diff --git a/damus/Util/Router.swift b/damus/Util/Router.swift index 4303ff9b..857e5787 100644 --- a/damus/Util/Router.swift +++ b/damus/Util/Router.swift @@ -22,10 +22,11 @@ enum Route: Hashable { case DMChat(dms: DirectMessageModel) case UserRelays(relays: [String]) case KeySettings(keypair: Keypair) - case AppearanceSettings(settings: UserSettingsStore) // Observed object.. is this an issue? - case NotificationSettings(settings: UserSettingsStore) // Observed object.. is this an issue? - case ZapSettings(settings: UserSettingsStore) // Observed object.. is this an issue? - case TranslationSettings(settings: UserSettingsStore) // Observed object.. is this an issue? + case AppearanceSettings(settings: UserSettingsStore) + case NotificationSettings(settings: UserSettingsStore) + case ZapSettings(settings: UserSettingsStore) + case TranslationSettings(settings: UserSettingsStore) + case SearchSettings(settings: UserSettingsStore) case Thread(thread: ThreadModel) case Reposts(reposts: RepostsModel) case Reactions(reactions: ReactionsModel) @@ -43,8 +44,10 @@ enum Route: Hashable { switch self { case .ProfileByKey(let pubkey): ProfileView(damus_state: damusState, pubkey: pubkey) + .environmentObject(navigationCordinator) case .Profile(let profile, let followers): ProfileView(damus_state: damusState, profile: profile, followers: followers) + .environmentObject(navigationCordinator) case .Followers(let environmentObject): FollowersView(damus_state: damusState) .environmentObject(environmentObject) @@ -60,6 +63,7 @@ enum Route: Hashable { RelayConfigView(state: damusState) case .Bookmarks: BookmarksView(state: damusState) + .environmentObject(navigationCordinator) case .Config: ConfigView(state: damusState) case .EditMetadata: @@ -78,6 +82,8 @@ enum Route: Hashable { ZapSettingsView(settings: settings) case .TranslationSettings(let settings): NotificationSettingsView(settings: settings) + case .SearchSettings(let settings): + SearchSettingsView(settings: settings) case .Thread(let thread): ThreadView(state: damusState, thread: thread) case .Reposts(let reposts): @@ -88,6 +94,7 @@ enum Route: Hashable { ZapsView(state: damusState, target: target) case .Search(let search): SearchView(appstate: damusState, search: search) + .environmentObject(navigationCordinator) case .EULA: EULAView() .environmentObject(navigationCordinator) @@ -146,6 +153,8 @@ enum Route: Hashable { return true case (.TranslationSettings(_), .TranslationSettings(_)): return true + case (.SearchSettings(_), .SearchSettings(_)): + return true case (.Thread(let lhs_threadModel), .Thread(thread: let rhs_threadModel)): return lhs_threadModel.event.id == rhs_threadModel.event.id case (.Reposts(let lhs_reposts), .Reposts(let rhs_reposts)): @@ -219,6 +228,8 @@ enum Route: Hashable { hasher.combine("zapSettings") case .TranslationSettings(_): hasher.combine("translationSettings") + case .SearchSettings(_): + hasher.combine("searchSettings") case .Thread(let threadModel): hasher.combine("thread") hasher.combine(threadModel.event.id) diff --git a/damus/Views/BookmarksView.swift b/damus/Views/BookmarksView.swift index 5af09b0d..27c4f938 100644 --- a/damus/Views/BookmarksView.swift +++ b/damus/Views/BookmarksView.swift @@ -14,6 +14,7 @@ struct BookmarksView: View { @State private var clearAllAlert: Bool = false @Environment(\.dismiss) var dismiss + @EnvironmentObject var navigationCoordinator: NavigationCoordinator @ObservedObject var manager: BookmarksManager init(state: DamusState) { @@ -38,6 +39,7 @@ struct BookmarksView: View { } else { ScrollView { InnerTimelineView(events: EventHolder(events: bookmarks, incoming: []), damus: state, filter: noneFilter) + .environmentObject(navigationCoordinator) } } diff --git a/damus/Views/ConfigView.swift b/damus/Views/ConfigView.swift index f2e3b348..90fcdf74 100644 --- a/damus/Views/ConfigView.swift +++ b/damus/Views/ConfigView.swift @@ -44,7 +44,7 @@ struct ConfigView: View { IconLabel(NSLocalizedString("Appearance", comment: "Section header for text and appearance settings"), img_name: "eye", color: .red) } - NavigationLink(destination: SearchSettingsView(settings: settings)) { + NavigationLink(value: Route.SearchSettings(settings: settings)) { IconLabel(NSLocalizedString("Search/Universe", comment: "Section header for search/universe settings"), img_name: "magnifyingglass", color: .red) } diff --git a/damus/Views/DirectMessagesView.swift b/damus/Views/DirectMessagesView.swift index ea5fa146..8e12e565 100644 --- a/damus/Views/DirectMessagesView.swift +++ b/damus/Views/DirectMessagesView.swift @@ -18,13 +18,11 @@ struct DirectMessagesView: View { @State var dm_type: DMType = .friend @ObservedObject var model: DirectMessagesModel @ObservedObject var settings: UserSettingsStore + + @EnvironmentObject var navigationCoordinator: NavigationCoordinator func MainContent(requests: Bool) -> some View { ScrollView { - let chat = DMChatView(damus_state: damus_state, dms: model.active_model) - NavigationLink(destination: chat, isActive: $model.open_dm) { - EmptyView() - } LazyVStack(spacing: 0) { if model.dms.isEmpty, !model.loading { EmptyTimelineView() @@ -54,7 +52,8 @@ struct DirectMessagesView: View { if ok, let ev = model.events.last { EventView(damus: damus_state, event: ev, pubkey: model.pubkey, options: options) .onTapGesture { - self.model.open_dm_by_model(model) + self.model.set_active_dm_model(model) + navigationCoordinator.push(route: Route.DMChat(dms: self.model.active_model)) } Divider() diff --git a/damus/Views/FollowingView.swift b/damus/Views/FollowingView.swift index 578974c7..0060d429 100644 --- a/damus/Views/FollowingView.swift +++ b/damus/Views/FollowingView.swift @@ -12,14 +12,8 @@ struct FollowUserView: View { let damus_state: DamusState static let markdown = Markdown() - @State var navigating: Bool = false var body: some View { - let dest = ProfileView(damus_state: damus_state, pubkey: target.pubkey) - NavigationLink(destination: dest, isActive: $navigating) { - EmptyView() - } - HStack { UserViewRow(damus_state: damus_state, pubkey: target.pubkey) diff --git a/damus/Views/Notifications/EventGroupView.swift b/damus/Views/Notifications/EventGroupView.swift index a473381b..2bba92b0 100644 --- a/damus/Views/Notifications/EventGroupView.swift +++ b/damus/Views/Notifications/EventGroupView.swift @@ -192,6 +192,8 @@ struct EventGroupView: View { let state: DamusState let event: NostrEvent? let group: EventGroupType + + @EnvironmentObject var navigationCoordinator: NavigationCoordinator func GroupDescription(_ pubkeys: [String]) -> some View { Text(verbatim: "\(reacting_to_text(profiles: state.profiles, our_pubkey: state.pubkey, group: group, ev: event, pubkeys: pubkeys))") @@ -237,6 +239,7 @@ struct EventGroupView: View { let unique_pubkeys = event_group_unique_pubkeys(profiles: state.profiles, group: group) ProfilePicturesView(state: state, pubkeys: unique_pubkeys) + .environmentObject(navigationCoordinator) if let event { let thread = ThreadModel(event: event, damus_state: state) diff --git a/damus/Views/Notifications/NotificationItemView.swift b/damus/Views/Notifications/NotificationItemView.swift index 7eaa8586..e4e87bd8 100644 --- a/damus/Views/Notifications/NotificationItemView.swift +++ b/damus/Views/Notifications/NotificationItemView.swift @@ -30,6 +30,8 @@ func notification_item_event(events: EventCache, notif: NotificationItem) -> Sho struct NotificationItemView: View { let state: DamusState let item: NotificationItem + + @EnvironmentObject var navigationCoordinator: NavigationCoordinator var show_item: ShowItem { notification_item_event(events: state.events, notif: item) @@ -48,15 +50,19 @@ struct NotificationItemView: View { switch item { case .repost(_, let evgrp): EventGroupView(state: state, event: ev, group: .repost(evgrp)) + .environmentObject(navigationCoordinator) case .event_zap(_, let zapgrp): EventGroupView(state: state, event: ev, group: .zap(zapgrp)) + .environmentObject(navigationCoordinator) case .profile_zap(let grp): EventGroupView(state: state, event: nil, group: .profile_zap(grp)) + .environmentObject(navigationCoordinator) case .reaction(_, let evgrp): EventGroupView(state: state, event: ev, group: .reaction(evgrp)) + .environmentObject(navigationCoordinator) case .reply(let ev): NavigationLink(value: Route.Thread(thread: ThreadModel(event: ev, damus_state: state))) { diff --git a/damus/Views/Notifications/NotificationsView.swift b/damus/Views/Notifications/NotificationsView.swift index 417acfc7..c3f14980 100644 --- a/damus/Views/Notifications/NotificationsView.swift +++ b/damus/Views/Notifications/NotificationsView.swift @@ -89,6 +89,7 @@ struct NotificationsView: View { @SceneStorage("NotificationsView.filter_state") var filter_state: NotificationFilterState = .all @Environment(\.colorScheme) var colorScheme + @EnvironmentObject var navigationCoordinator: NavigationCoordinator var mystery: some View { VStack(spacing: 20) { @@ -173,6 +174,7 @@ struct NotificationsView: View { .frame(height: 5) ForEach(filter.filter(contacts: state.contacts, items: notifications.notifications), id: \.id) { item in NotificationItemView(state: state, item: item) + .environmentObject(navigationCoordinator) } } .background(GeometryReader { proxy -> Color in diff --git a/damus/Views/Notifications/ProfilePicturesView.swift b/damus/Views/Notifications/ProfilePicturesView.swift index 5250d60a..50f3f46e 100644 --- a/damus/Views/Notifications/ProfilePicturesView.swift +++ b/damus/Views/Notifications/ProfilePicturesView.swift @@ -11,19 +11,14 @@ struct ProfilePicturesView: View { let state: DamusState let pubkeys: [String] - @State var nav_target: String? = nil - @State var navigating: Bool = false + @EnvironmentObject var navigationCoordinator: NavigationCoordinator var body: some View { - NavigationLink(destination: ProfileView(damus_state: state, pubkey: nav_target ?? ""), isActive: $navigating) { - EmptyView() - } HStack { ForEach(pubkeys.prefix(8), id: \.self) { pubkey in ProfilePicView(pubkey: pubkey, size: 32.0, highlight: .none, profiles: state.profiles, disable_animation: state.settings.disable_animation) .onTapGesture { - nav_target = pubkey - navigating = true + navigationCoordinator.push(route: Route.ProfileByKey(pubkey: pubkey)) } } } diff --git a/damus/Views/Profile/ProfileView.swift b/damus/Views/Profile/ProfileView.swift index a4a0cfb3..3c64221d 100644 --- a/damus/Views/Profile/ProfileView.swift +++ b/damus/Views/Profile/ProfileView.swift @@ -132,6 +132,8 @@ struct ProfileView: View { @StateObject var followers: FollowersModel @StateObject var zap_button_model: ZapButtonModel = ZapButtonModel() + @EnvironmentObject var navigationCoordinator: NavigationCoordinator + init(damus_state: DamusState, profile: ProfileModel, followers: FollowersModel) { self.damus_state = damus_state self._profile = StateObject(wrappedValue: profile) diff --git a/damus/Views/SearchHomeView.swift b/damus/Views/SearchHomeView.swift index 7b31ed86..3e439ee4 100644 --- a/damus/Views/SearchHomeView.swift +++ b/damus/Views/SearchHomeView.swift @@ -14,6 +14,7 @@ struct SearchHomeView: View { @StateObject var model: SearchHomeModel @State var search: String = "" @FocusState private var isFocused: Bool + @EnvironmentObject var navigationCoordinator: NavigationCoordinator let preferredLanguages = Set(Locale.preferredLanguages.map { localeToLanguage($0) }) @@ -67,6 +68,7 @@ struct SearchHomeView: View { return preferredLanguages.contains(note_lang) } ) + .environmentObject(navigationCoordinator) .refreshable { // Fetch new information by unsubscribing and resubscribing to the relay model.unsubscribe() diff --git a/damus/Views/SearchView.swift b/damus/Views/SearchView.swift index b828cba8..668b2e06 100644 --- a/damus/Views/SearchView.swift +++ b/damus/Views/SearchView.swift @@ -11,9 +11,11 @@ struct SearchView: View { let appstate: DamusState @StateObject var search: SearchModel @Environment(\.dismiss) var dismiss + @EnvironmentObject var navigationCoordinator: NavigationCoordinator var body: some View { TimelineView(events: search.events, loading: $search.loading, damus: appstate, show_friend_icon: true, filter: { _ in true }) + .environmentObject(navigationCoordinator) .navigationBarTitle(describe_search(search.search)) .onReceive(handle_notify(.switched_timeline)) { obj in dismiss() diff --git a/damus/Views/Timeline/InnerTimelineView.swift b/damus/Views/Timeline/InnerTimelineView.swift index 0d33c1a6..b8e90619 100644 --- a/damus/Views/Timeline/InnerTimelineView.swift +++ b/damus/Views/Timeline/InnerTimelineView.swift @@ -12,8 +12,8 @@ struct InnerTimelineView: View { @ObservedObject var events: EventHolder let state: DamusState let filter: (NostrEvent) -> Bool - @State var nav_target: NostrEvent - @State var navigating: Bool = false + + @EnvironmentObject var navigationCoordinator: NavigationCoordinator static var count: Int = 0 @@ -23,8 +23,6 @@ struct InnerTimelineView: View { self.filter = filter print("rendering InnerTimelineView \(InnerTimelineView.count)") InnerTimelineView.count += 1 - // dummy event to avoid MaybeThreadView - self._nav_target = State(initialValue: test_event) } var event_options: EventViewOptions { @@ -36,11 +34,6 @@ struct InnerTimelineView: View { } var body: some View { - let thread = ThreadModel(event: nav_target, damus_state: state) - let dest = ThreadView(state: state, thread: thread) - NavigationLink(destination: dest, isActive: $navigating) { - EmptyView() - } LazyVStack(spacing: 0) { let events = self.events.events if events.isEmpty { @@ -53,8 +46,9 @@ struct InnerTimelineView: View { let ind = tup.1 EventView(damus: state, event: ev, options: event_options) .onTapGesture { - nav_target = ev.get_inner_event(cache: state.events) ?? ev - navigating = true + let event = ev.get_inner_event(cache: state.events) ?? ev + let thread = ThreadModel(event: event, damus_state: state) + navigationCoordinator.push(route: Route.Thread(thread: thread)) } .padding(.top, 7) .onAppear { diff --git a/damus/Views/TimelineView.swift b/damus/Views/TimelineView.swift index 326ae8bc..0ed1f555 100644 --- a/damus/Views/TimelineView.swift +++ b/damus/Views/TimelineView.swift @@ -8,6 +8,7 @@ import SwiftUI struct TimelineView: View { + @EnvironmentObject var navigationCoordinator: NavigationCoordinator @ObservedObject var events: EventHolder @Binding var loading: Bool @@ -27,6 +28,7 @@ struct TimelineView: View { .frame(height: 1) InnerTimelineView(events: events, damus: damus, filter: loading ? { _ in true } : filter) + .environmentObject(navigationCoordinator) .redacted(reason: loading ? .placeholder : []) .shimmer(loading) .disabled(loading)