diff --git a/Packages/Timeline/Sources/Timeline/TimelineUnreadStatusesObserver.swift b/Packages/Timeline/Sources/Timeline/TimelineUnreadStatusesObserver.swift index 7e4fb8240..6fdb5bebc 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineUnreadStatusesObserver.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineUnreadStatusesObserver.swift @@ -32,13 +32,17 @@ import SwiftUI } struct TimelineUnreadStatusesView: View { - @State var observer: TimelineUnreadStatusesObserver @Environment(UserPreferences.self) private var preferences @Environment(Theme.self) private var theme + @State var observer: TimelineUnreadStatusesObserver + let onButtonTap: (String?) -> Void + var body: some View { if observer.pendingStatusesCount > 0 || observer.isLoadingNewStatuses { - Button { } label: { + Button { + onButtonTap(observer.pendingStatuses.last) + } label: { HStack(spacing: 8) { if observer.isLoadingNewStatuses { ProgressView() diff --git a/Packages/Timeline/Sources/Timeline/View/TimelineView.swift b/Packages/Timeline/Sources/Timeline/View/TimelineView.swift index 762155851..4fc1e7865 100644 --- a/Packages/Timeline/Sources/Timeline/View/TimelineView.swift +++ b/Packages/Timeline/Sources/Timeline/View/TimelineView.swift @@ -20,6 +20,8 @@ public struct TimelineView: View { @State private var viewModel = TimelineViewModel() @State private var contentFilter = TimelineContentFilter.shared + + @State private var scrollToIdAnimated: String? = nil @State private var wasBackgrounded: Bool = false @@ -45,9 +47,7 @@ public struct TimelineView: View { public var body: some View { ZStack(alignment: .top) { listView - if viewModel.timeline.supportNewestPagination { - TimelineUnreadStatusesView(observer: viewModel.pendingStatusesObserver) - } + statusesObserver } .safeAreaInset(edge: .top, spacing: 0) { if canFilterTimeline, !pinnedFilters.isEmpty { @@ -188,6 +188,14 @@ public struct TimelineView: View { viewModel.scrollToId = nil } } + .onChange(of: scrollToIdAnimated) { _, newValue in + if let newValue { + withAnimation { + proxy.scrollTo(newValue, anchor: .top) + scrollToIdAnimated = nil + } + } + } .onChange(of: selectedTabScrollToTop) { _, newValue in if newValue == 0, routerPath.path.isEmpty { withAnimation { @@ -197,6 +205,17 @@ public struct TimelineView: View { } } } + + @ViewBuilder + private var statusesObserver: some View { + if viewModel.timeline.supportNewestPagination { + TimelineUnreadStatusesView(observer: viewModel.pendingStatusesObserver) { statusId in + if let statusId { + scrollToIdAnimated = statusId + } + } + } + } @ToolbarContentBuilder private var toolbarTitleView: some ToolbarContent {