Skip to content

Commit

Permalink
Merge branch 'main' into 564/copy-nip05
Browse files Browse the repository at this point in the history
  • Loading branch information
martindsq authored Nov 28, 2023
2 parents 405a911 + a6595cf commit 67d9c3c
Show file tree
Hide file tree
Showing 37 changed files with 149 additions and 103 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

- Added the option to copy the NIP-05 identifier when browsing a profile.
- Tapping on a tab bar icon can let you scroll to top.
- Fixed a bug where a root note could be rendered as a reply
- Added the option to copy the text content while browsing a note.
- Fixed UI bugs when displaying the root note of replies.
Expand Down
2 changes: 1 addition & 1 deletion Nos/NosApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct NosApp: App {
AppView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(relayService)
.environment(router)
.environmentObject(router)
.environment(appController)
.environment(currentUser)
.environmentObject(pushNotificationService)
Expand Down
58 changes: 36 additions & 22 deletions Nos/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,72 @@ import Logger
import Dependencies

// Manages the app's navigation state.
@MainActor @Observable class Router {
var homeFeedPath = NavigationPath()
var discoverPath = NavigationPath()
var notificationsPath = NavigationPath()
var profilePath = NavigationPath()
var sideMenuPath = NavigationPath()
var selectedTab = AppDestination.home
@Dependency(\.persistenceController) @ObservationIgnored private var persistenceController
@MainActor class Router: ObservableObject {

@Published var homeFeedPath = NavigationPath()
@Published var discoverPath = NavigationPath()
@Published var notificationsPath = NavigationPath()
@Published var profilePath = NavigationPath()
@Published var sideMenuPath = NavigationPath()
@Published var selectedTab = AppDestination.home
@Dependency(\.persistenceController) private var persistenceController

var currentPath: Binding<NavigationPath> {
if sideMenuOpened {
return Binding(get: { self.sideMenuPath }, set: { self.sideMenuPath = $0 })
}

return path(for: selectedTab)
}
var userNpubPublicKey = ""
private(set) var sideMenuOpened = false

@Published var userNpubPublicKey = ""

@Published private(set) var sideMenuOpened = false

func toggleSideMenu() {
withAnimation(.easeIn(duration: 0.2)) {
sideMenuOpened.toggle()
}
}

func closeSideMenu() {
withAnimation(.easeIn(duration: 0.2)) {
sideMenuOpened = false
}
}

/// Pushes the given destination item onto the current NavigationPath.
func push<D: Hashable>(_ destination: D) {
currentPath.wrappedValue.append(destination)
}

func pop() {
currentPath.wrappedValue.removeLast()
}

func openOSSettings() {
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}

func showNewNoteView(contents: String?) {
selectedTab = .newNote(contents)
}

func consecutiveTaps(on tab: AppDestination) -> AnyPublisher<Void, Never> {
$selectedTab
.scan((previous: nil, current: selectedTab)) { previousPair, current in
(previous: previousPair.current, current: current)
}
.filter {
$0.previous == $0.current
}
.compactMap {
$0.current == tab ? Void() : nil
}
.eraseToAnyPublisher()
}

func path(for destination: AppDestination) -> Binding<NavigationPath> {
switch destination {
case .home:
Expand All @@ -81,11 +95,11 @@ import Dependencies
}

extension Router {

nonisolated func open(url: URL, with context: NSManagedObjectContext) {
let link = url.absoluteString
let identifier = String(link[link.index(after: link.startIndex)...])

Task { @MainActor in
do {
// handle mentions. mention link will be prefixed with "@" followed by
Expand All @@ -101,7 +115,7 @@ extension Router {
}
} catch {
Log.optional(error)
}
}
}
}
}
9 changes: 4 additions & 5 deletions Nos/Views/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct AppView: View {
@State var newPostContents: String?

@Environment(AppController.self) var appController
@Environment(Router.self) var router
@EnvironmentObject private var router: Router
@EnvironmentObject var pushNotificationService: PushNotificationService
@Environment(\.managedObjectContext) private var viewContext
@Dependency(\.analytics) private var analytics
Expand All @@ -25,7 +25,6 @@ struct AppView: View {
@State private var lastSelectedTab = AppDestination.home

var body: some View {
@Bindable var router = router
ZStack {
if appController.currentState == .onboarding {
OnboardingView(completion: appController.completeOnboarding)
Expand Down Expand Up @@ -176,19 +175,19 @@ struct AppView_Previews: PreviewProvider {
AppView()
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environment(router)
.environmentObject(router)
.environment(loggedInAppController)

AppView()
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environment(router)
.environmentObject(router)
.environment(AppController())

AppView()
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environment(routerWithSideMenuOpened)
.environmentObject(routerWithSideMenuOpened)
.environment(AppController())
}
}
4 changes: 2 additions & 2 deletions Nos/Views/AuthorStoryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct AuthorStoryView: View {

@State private var subscriptionIDs = [String]()

@Environment(Router.self) private var router
@EnvironmentObject private var router: Router
@EnvironmentObject private var relayService: RelayService

init(
Expand Down Expand Up @@ -192,7 +192,7 @@ fileprivate struct BottomOverlay: View {

@Dependency(\.persistenceController) private var persistenceController

@Environment(Router.self) private var router
@EnvironmentObject private var router: Router

@State private var replyCount = 0
@State private var replyAvatarURLs = [URL]()
Expand Down
2 changes: 1 addition & 1 deletion Nos/Views/CompactNoteView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct CompactNoteView: View {
@State private var contentLinks = [URL]()
private var loadLinks: Bool

@Environment(Router.self) var router
@EnvironmentObject private var router: Router
@Dependency(\.persistenceController) private var persistenceController

internal init(note: Event, showFullMessage: Bool = false, loadLinks: Bool = true) {
Expand Down
13 changes: 12 additions & 1 deletion Nos/Views/DiscoverGrid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import SwiftUI
struct DiscoverGrid: View {

@Environment(\.managedObjectContext) private var viewContext
@Environment(Router.self) private var router
@EnvironmentObject private var router: Router
@FetchRequest(fetchRequest: Event.emptyDiscoverRequest()) var events: FetchedResults<Event>
@ObservedObject var searchController: SearchController

Expand Down Expand Up @@ -43,6 +43,12 @@ struct DiscoverGrid: View {
StaggeredGrid(list: events, columns: columns) { note in
NoteButton(note: note, style: .golden)
.matchedGeometryEffect(id: note.identifier, in: animation)
.id(note.id)
}
.doubleTapToPop(tab: .discover) { proxy in
if let firstNote = events.first {
proxy.scrollTo(firstNote.id)
}
}
} else {
// Search results
Expand All @@ -62,6 +68,11 @@ struct DiscoverGrid: View {
}
.padding(.top, 5)
}
.doubleTapToPop(tab: .discover) { proxy in
if let firstAuthor = searchController.authorSuggestions.first {
proxy.scrollTo(firstAuthor.id)
}
}
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions Nos/Views/DiscoverView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct DiscoverView: View {

@Environment(\.managedObjectContext) private var viewContext
@EnvironmentObject private var relayService: RelayService
@Environment(Router.self) var router
@EnvironmentObject private var router: Router
@Environment(CurrentUser.self) var currentUser
@Dependency(\.analytics) private var analytics
@State private var lastRequestDate: Date?
Expand Down Expand Up @@ -112,7 +112,6 @@ struct DiscoverView: View {
}

var body: some View {
@Bindable var router = router
NavigationStack(path: $router.discoverPath) {
ZStack {
if performingInitialLoad && searchController.query.isEmpty {
Expand Down Expand Up @@ -169,7 +168,6 @@ struct DiscoverView: View {
}
}
.animation(.easeInOut, value: columns)
.doubleTapToPop(tab: .discover)
.task {
updatePredicate()
}
Expand Down Expand Up @@ -313,14 +311,14 @@ struct DiscoverView_Previews: PreviewProvider {
DiscoverView(featuredAuthors: [publicKey.npub])
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environment(router)
.environmentObject(router)
.environment(currentUser)
.onAppear { createTestData(in: previewContext) }

DiscoverView(featuredAuthors: [publicKey.npub])
.environment(\.managedObjectContext, previewContext)
.environmentObject(relayService)
.environment(router)
.environmentObject(router)
.environment(currentUser)
.onAppear { createTestData(in: previewContext) }
.previewDevice("iPad Air (5th generation)")
Expand Down
42 changes: 27 additions & 15 deletions Nos/Views/DoubleTapToPopModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,42 @@ import SwiftUI
struct DoubleTapToPopModifier: ViewModifier {

var tab: AppDestination
var onRoot: (@MainActor () -> Void)?
var onRoot: (@MainActor (ScrollViewProxy) -> Void)?

@Environment(Router.self) private var router
@EnvironmentObject private var router: Router
@State private var cancellable: AnyCancellable?

func body(content: Content) -> some View {
content
.onChange(of: router.selectedTab, { oldValue, newValue in
if oldValue != newValue {
let path = router.path(for: tab)
if path.wrappedValue.isEmpty {
if let onRoot {
onRoot()
ScrollViewReader { proxy in
content.task {
if cancellable == nil {
cancellable = router.consecutiveTaps(on: tab)
.sink {
let path = router.path(for: tab)
if path.wrappedValue.isEmpty {
if let onRoot {
onRoot(proxy)
}
} else {
path.wrappedValue.removeLast(path.wrappedValue.count)
}
}
} else {
router.currentPath.wrappedValue.removeLast(router.currentPath.wrappedValue.count)
}
}
})
}
}
}
}

extension View {
func doubleTapToPop(tab: AppDestination, onRoot: (@MainActor () -> Void)? = nil) -> some View {
self.modifier(DoubleTapToPopModifier(tab: tab, onRoot: onRoot))
@ViewBuilder func doubleTapToPop(
tab: AppDestination,
enabled: Bool = true,
onRoot: (@MainActor (ScrollViewProxy) -> Void)? = nil
) -> some View {
if enabled {
self.modifier(DoubleTapToPopModifier(tab: tab, onRoot: onRoot))
} else {
self
}
}
}
2 changes: 1 addition & 1 deletion Nos/Views/FollowCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct FollowCard: View {

var style = CardStyle.compact

@Environment(Router.self) private var router
@EnvironmentObject private var router: Router
@Environment(CurrentUser.self) private var currentUser
@EnvironmentObject private var relayService: RelayService

Expand Down
2 changes: 1 addition & 1 deletion Nos/Views/FollowsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct FollowersDestination: Hashable {
struct FollowsView: View {
@Environment(\.managedObjectContext) private var viewContext
@EnvironmentObject private var relayService: RelayService
@Environment(Router.self) var router
@EnvironmentObject var router: Router

/// Screen title
var title: Localized
Expand Down
2 changes: 1 addition & 1 deletion Nos/Views/GoldenPostView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct GoldenPostView: View {

@Environment(\.managedObjectContext) private var viewContext

@Environment(Router.self) private var router
@EnvironmentObject private var router: Router

@State private var noteContent = LoadingContent<AttributedString>.loading
@State private var contentLinks = [URL]()
Expand Down
Loading

0 comments on commit 67d9c3c

Please sign in to comment.