1
0
mirror of git://jb55.com/damus synced 2024-09-30 00:40:45 +00:00

Convert to NavigationStack

- Fixes linking issues on SideMenu and tab switching issues
- I currently bumped to iOS 16+ to get iterate and get this working.
This commit is contained in:
Scott Penrose 2023-04-29 14:38:28 -04:00 committed by William Casarin
parent 5bac6405b9
commit f0b0eade37
5 changed files with 149 additions and 21 deletions

View File

@ -304,6 +304,7 @@
9CA876E229A00CEA0003B9A3 /* AttachMediaUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CA876E129A00CE90003B9A3 /* AttachMediaUtility.swift */; };
BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; };
BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; };
D2277EEA2A089BD5006C3807 /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2277EE92A089BD5006C3807 /* Router.swift */; };
DD597CBD2963D85A00C64D32 /* MarkdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD597CBC2963D85A00C64D32 /* MarkdownTests.swift */; };
E4FA1C032A24BB7F00482697 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FA1C022A24BB7F00482697 /* SearchSettingsView.swift */; };
E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E990020E2955F837003BBC5A /* EditMetadataView.swift */; };
@ -753,6 +754,7 @@
9CA876E129A00CE90003B9A3 /* AttachMediaUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachMediaUtility.swift; sourceTree = "<group>"; };
BA693073295D649800ADDB87 /* UserSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsStore.swift; sourceTree = "<group>"; };
BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectWalletView.swift; sourceTree = "<group>"; };
D2277EE92A089BD5006C3807 /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = "<group>"; };
DD597CBC2963D85A00C64D32 /* MarkdownTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownTests.swift; sourceTree = "<group>"; };
E4FA1C022A24BB7F00482697 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = "<group>"; };
E990020E2955F837003BBC5A /* EditMetadataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMetadataView.swift; sourceTree = "<group>"; };
@ -1155,6 +1157,7 @@
50B5685229F97CB400A23243 /* CredentialHandler.swift */,
4C7D09582A05BEAD00943473 /* KeyboardVisible.swift */,
3A8CC6CB2A2CFEF900940F5F /* StringUtil.swift */,
D2277EE92A089BD5006C3807 /* Router.swift */,
);
path = Util;
sourceTree = "<group>";
@ -1307,7 +1310,9 @@
4CE6DEE427F7A08100C66700 /* Products */,
4CEE2AE62804F57B00AB5EEF /* Frameworks */,
);
indentWidth = 4;
sourceTree = "<group>";
tabWidth = 4;
};
4CE6DEE427F7A08100C66700 /* Products */ = {
isa = PBXGroup;
@ -1861,6 +1866,7 @@
5C6E1DAD2A193EC2008FC15A /* GradientButtonStyle.swift in Sources */,
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */,
3A4647CF2A413ADC00386AD8 /* CondensedProfilePicturesView.swift in Sources */,
D2277EEA2A089BD5006C3807 /* Router.swift in Sources */,
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */,
4CE1399429F0669900AC6A0B /* BigButton.swift in Sources */,
7C60CAEF298471A1009C80D6 /* CoreSVG.swift in Sources */,
@ -2254,6 +2260,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = Launch.storyboard;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -2302,6 +2309,7 @@
INFOPLIST_KEY_UILaunchStoryboardName = Launch.storyboard;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View File

@ -97,6 +97,7 @@ struct ContentView: View {
@SceneStorage("ContentView.filter_state") var filter_state : FilterState = .posts_and_replies
@State private var isSideBarOpened = false
var home: HomeModel = HomeModel()
@StateObject var navigationCoordinator: NavigationCoordinator = NavigationCoordinator()
let sub_id = UUID().description
@ -287,7 +288,7 @@ struct ContentView: View {
var body: some View {
VStack(alignment: .leading, spacing: 0) {
if let damus = self.damus_state {
NavigationView {
NavigationStack(path: $navigationCoordinator.path) {
TabView { // Prevents navbar appearance change on scroll
MainContent(damus: damus)
.toolbar() {
@ -327,6 +328,12 @@ struct ContentView: View {
.overlay(
SideMenuView(damus_state: damus, isSidebarVisible: $isSideBarOpened.animation())
)
.navigationDestination(for: Route.self) { route in
route.view(navigationCordinator: navigationCoordinator)
}
.onReceive(handle_notify(.switched_timeline)) { _ in
navigationCoordinator.popToRoot()
}
}
.navigationViewStyle(.stack)

115
damus/Util/Router.swift Normal file
View File

@ -0,0 +1,115 @@
//
// Router.swift
// damus
//
// Created by Scott Penrose on 5/7/23.
//
import SwiftUI
enum Route: Hashable {
case Profile(damusSate: DamusState, profile: ProfileModel, followers: FollowersModel)
case Followers(damusState: DamusState, environmentObject: FollowersModel)
case Relay(damusState: DamusState, relay: String, showActionButtons: Binding<Bool>)
case Following(damusState: DamusState, following: FollowingModel)
case MuteList(damusState: DamusState, users: [String])
case RelayConfig(damusState: DamusState)
case Bookmarks(damusState: DamusState)
case Config(damusState: DamusState)
case EditMetadata(damusState: DamusState)
case DMChat(damusState: DamusState, dms: DirectMessageModel)
case UserRelays(damusState: DamusState, relays: [String])
@ViewBuilder
func view(navigationCordinator: NavigationCoordinator) -> some View {
switch self {
case .Profile (let damusState, let profile, let followers):
ProfileView(damus_state: damusState, profile: profile, followers: followers)
case .Followers (let damusState, let environmentObject):
FollowersView(damus_state: damusState)
.environmentObject(environmentObject)
case .Relay (let damusState, let relay, let showActionButtons):
RelayView(state: damusState, relay: relay, showActionButtons: showActionButtons)
case .Following(let damusState, let following):
FollowingView(damus_state: damusState, following: following)
case .MuteList(let damusState, let users):
MutelistView(damus_state: damusState, users: users)
case .RelayConfig(let damusState):
RelayConfigView(state: damusState)
case .Bookmarks(let damusState):
BookmarksView(state: damusState)
case .Config(let damusState):
ConfigView(state: damusState)
case .EditMetadata(let damusState):
EditMetadataView(damus_state: damusState)
case .DMChat(let damusState, let dms):
DMChatView(damus_state: damusState, dms: dms)
case .UserRelays(let damusState, let relays):
UserRelaysView(state: damusState, relays: relays)
}
}
static func == (lhs: Route, rhs: Route) -> Bool {
switch (lhs, rhs) {
case (.Profile (_, let lhs_profile, _), .Profile(_, let rhs_profile, _)):
return lhs_profile == rhs_profile
case (.Followers (_, _), .Followers (_, _)):
return true
case (.Relay (_, let lhs_relay, _), .Relay (_, let rhs_relay, _)):
return lhs_relay == rhs_relay
case (.Following(_, _), .Following(_, _)):
return true
case (.MuteList(_, let lhs_users), .MuteList(_, let rhs_users)):
return lhs_users == rhs_users
case (.RelayConfig(_), .RelayConfig(_)):
return true
case (.Bookmarks(_), .Bookmarks(_)):
return true
case (.Config(_), .Config(_)):
return true
case (.EditMetadata(_), .EditMetadata(_)):
return true
case (.DMChat(_, let lhs_dms), .DMChat(_, let rhs_dms)):
return lhs_dms.our_pubkey == rhs_dms.our_pubkey
case (.UserRelays(_, let lhs_relays), .UserRelays(_, let rhs_relays)):
return lhs_relays == rhs_relays
default:
return false
}
}
func hash(into hasher: inout Hasher) {
switch self {
case .Profile(_, let profile, _):
hasher.combine(profile.pubkey)
case .Followers(_, _):
hasher.combine("followers")
case .Relay(_, let relay, _):
hasher.combine(relay)
case .Following(_, _):
hasher.combine("following")
case .MuteList(_, let users):
hasher.combine(users)
case .RelayConfig(_):
hasher.combine("relayConfig")
case .Bookmarks(_):
hasher.combine("bookmarks")
case .Config(_):
hasher.combine("config")
case .EditMetadata(_):
hasher.combine("editMetadata")
case .DMChat(_, let dms):
hasher.combine(dms.our_pubkey)
case .UserRelays(_, let relays):
hasher.combine(relays)
}
}
}
class NavigationCoordinator: ObservableObject {
@Published var path = [Route]()
func popToRoot() {
path = []
}
}

View File

@ -77,7 +77,7 @@ struct EditButton: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
NavigationLink(destination: EditMetadataView(damus_state: damus_state)) {
NavigationLink(value: Route.EditMetadata(damusState: damus_state)) {
Text("Edit", comment: "Button to edit user's profile.")
.frame(height: 30)
.padding(.horizontal,25)
@ -300,8 +300,7 @@ struct ProfileView: View {
var dmButton: some View {
let dm_model = damus_state.dms.lookup_or_create(profile.pubkey)
let dmview = DMChatView(damus_state: damus_state, dms: dm_model)
return NavigationLink(destination: dmview) {
return NavigationLink(value: Route.DMChat(damusState: damus_state, dms: dm_model)) {
Image("messages")
.profile_button_style(scheme: colorScheme)
}
@ -325,7 +324,7 @@ struct ProfileView: View {
follow_state: damus_state.contacts.follow_state(profile.pubkey)
)
} else if damus_state.keypair.privkey != nil {
NavigationLink(destination: EditMetadataView(damus_state: damus_state)) {
NavigationLink(value: Route.EditMetadata(damusState: damus_state)) {
EditButton(damus_state: damus_state)
}
}
@ -404,7 +403,7 @@ struct ProfileView: View {
if let contact = profile.contacts {
let contacts = contact.referenced_pubkeys.map { $0.ref_id }
let following_model = FollowingModel(damus_state: damus_state, contacts: contacts)
NavigationLink(destination: FollowingView(damus_state: damus_state, following: following_model)) {
NavigationLink(value: Route.Following(damusState: damus_state, following: following_model)) {
HStack {
let noun_text = Text(verbatim: "\(followingCountString(profile.following))").font(.subheadline).foregroundColor(.gray)
Text("\(Text(verbatim: profile.following.formatted()).font(.subheadline.weight(.medium))) \(noun_text)", comment: "Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.")
@ -412,10 +411,9 @@ struct ProfileView: View {
}
.buttonStyle(PlainButtonStyle())
}
let fview = FollowersView(damus_state: damus_state)
.environmentObject(followers)
if followers.contacts != nil {
NavigationLink(destination: fview) {
NavigationLink(value: Route.Followers(damusState: damus_state, environmentObject: followers)) {
followersCount
}
.buttonStyle(PlainButtonStyle())
@ -433,12 +431,12 @@ struct ProfileView: View {
let noun_text = Text(verbatim: relaysCountString(relays.keys.count)).font(.subheadline).foregroundColor(.gray)
let relay_text = Text("\(Text(verbatim: relays.keys.count.formatted()).font(.subheadline.weight(.medium))) \(noun_text)", comment: "Sentence composed of 2 variables to describe how many relay servers a user is connected. In source English, the first variable is the number of relay servers, and the second variable is 'Relay' or 'Relays'.")
if profile.pubkey == damus_state.pubkey && damus_state.is_privkey_user {
NavigationLink(destination: RelayConfigView(state: damus_state)) {
NavigationLink(value: Route.RelayConfig(damusState: damus_state)) {
relay_text
}
.buttonStyle(PlainButtonStyle())
} else {
NavigationLink(destination: UserRelaysView(state: damus_state, relays: Array(relays.keys).sorted())) {
NavigationLink(value: Route.UserRelays(damusState: damus_state, relays: Array(relays.keys).sorted())) {
relay_text
}
.buttonStyle(PlainButtonStyle())

View File

@ -45,7 +45,7 @@ struct SideMenuView: View {
func SidemenuItems(profile_model: ProfileModel, followers: FollowersModel) -> some View {
return VStack(spacing: verticalSpacing) {
NavigationLink(destination: ProfileView(damus_state: damus_state, profile: profile_model, followers: followers)) {
NavigationLink(value: Route.Profile(damusSate: damus_state, profile: profile_model, followers: followers)) {
navLabel(title: NSLocalizedString("Profile", comment: "Sidebar menu label for Profile view."), img: "user")
}
@ -64,19 +64,19 @@ struct SideMenuView: View {
}*/
}
NavigationLink(destination: MutelistView(damus_state: damus_state, users: get_mutelist_users(damus_state.contacts.mutelist) )) {
NavigationLink(value: Route.MuteList(damusState: damus_state, users: get_mutelist_users(damus_state.contacts.mutelist))) {
navLabel(title: NSLocalizedString("Muted", comment: "Sidebar menu label for muted users view."), img: "mute")
}
NavigationLink(destination: RelayConfigView(state: damus_state)) {
NavigationLink(value: Route.RelayConfig(damusState: damus_state)) {
navLabel(title: NSLocalizedString("Relays", comment: "Sidebar menu label for Relays view."), img: "world-relays")
}
NavigationLink(destination: BookmarksView(state: damus_state)) {
NavigationLink(value: Route.Bookmarks(damusState: damus_state)) {
navLabel(title: NSLocalizedString("Bookmarks", comment: "Sidebar menu label for Bookmarks view."), img: "bookmark")
}
NavigationLink(destination: ConfigView(state: damus_state)) {
NavigationLink(value: Route.Config(damusState: damus_state)) {
navLabel(title: NSLocalizedString("Settings", comment: "Sidebar menu label for accessing the app settings"), img: "settings")
}
}