Restore ScrollToTop on timeline tab
This commit is contained in:
parent
594fb3ea07
commit
122e57d8ac
|
@ -26,6 +26,7 @@ struct AppView: View {
|
||||||
|
|
||||||
@State var iosTabs = iOSTabs.shared
|
@State var iosTabs = iOSTabs.shared
|
||||||
@State var sidebarTabs = SidebarTabs.shared
|
@State var sidebarTabs = SidebarTabs.shared
|
||||||
|
@State var selectedTabScrollToTop: Int = -1
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
#if os(visionOS)
|
#if os(visionOS)
|
||||||
|
@ -75,6 +76,7 @@ struct AppView: View {
|
||||||
}
|
}
|
||||||
.id(appAccountsManager.currentClient.id)
|
.id(appAccountsManager.currentClient.id)
|
||||||
.withSheetDestinations(sheetDestinations: $appRouterPath.presentedSheet)
|
.withSheetDestinations(sheetDestinations: $appRouterPath.presentedSheet)
|
||||||
|
.environment(\.selectedTabScrollToTop, selectedTabScrollToTop)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateTab(with newTab: AppTab) {
|
private func updateTab(with newTab: AppTab) {
|
||||||
|
@ -90,6 +92,15 @@ struct AppView: View {
|
||||||
HapticManager.shared.fireHaptic(.tabSelection)
|
HapticManager.shared.fireHaptic(.tabSelection)
|
||||||
SoundEffectManager.shared.playSound(.tabSelection)
|
SoundEffectManager.shared.playSound(.tabSelection)
|
||||||
|
|
||||||
|
if selectedTab == newTab {
|
||||||
|
selectedTabScrollToTop = newTab.rawValue
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
|
selectedTabScrollToTop = -1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectedTabScrollToTop = -1
|
||||||
|
}
|
||||||
|
|
||||||
selectedTab = newTab
|
selectedTab = newTab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,5 @@ extension EnvironmentValues {
|
||||||
@Entry public var isStatusFocused: Bool = false
|
@Entry public var isStatusFocused: Bool = false
|
||||||
@Entry public var isHomeTimeline: Bool = false
|
@Entry public var isHomeTimeline: Bool = false
|
||||||
@Entry public var indentationLevel: UInt = 0
|
@Entry public var indentationLevel: UInt = 0
|
||||||
|
@Entry public var selectedTabScrollToTop: Int = -1
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import SwiftUIIntrospect
|
||||||
@MainActor
|
@MainActor
|
||||||
public struct TimelineView: View {
|
public struct TimelineView: View {
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
|
@Environment(\.selectedTabScrollToTop) private var selectedTabScrollToTop
|
||||||
|
|
||||||
@Environment(Theme.self) private var theme
|
@Environment(Theme.self) private var theme
|
||||||
@Environment(CurrentAccount.self) private var account
|
@Environment(CurrentAccount.self) private var account
|
||||||
@Environment(StreamWatcher.self) private var watcher
|
@Environment(StreamWatcher.self) private var watcher
|
||||||
|
@ -45,33 +47,42 @@ public struct TimelineView: View {
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
List {
|
ScrollViewReader { proxy in
|
||||||
scrollToTopView
|
List {
|
||||||
TimelineTagGroupheaderView(group: $selectedTagGroup, timeline: $timeline)
|
scrollToTopView
|
||||||
TimelineTagHeaderView(tag: $viewModel.tag)
|
TimelineTagGroupheaderView(group: $selectedTagGroup, timeline: $timeline)
|
||||||
switch viewModel.timeline {
|
TimelineTagHeaderView(tag: $viewModel.tag)
|
||||||
case .remoteLocal:
|
switch viewModel.timeline {
|
||||||
StatusesListView(fetcher: viewModel, client: client, routerPath: routerPath, isRemote: true)
|
case .remoteLocal:
|
||||||
default:
|
StatusesListView(fetcher: viewModel, client: client, routerPath: routerPath, isRemote: true)
|
||||||
StatusesListView(fetcher: viewModel, client: client, routerPath: routerPath)
|
default:
|
||||||
.environment(\.isHomeTimeline, timeline == .home)
|
StatusesListView(fetcher: viewModel, client: client, routerPath: routerPath)
|
||||||
}
|
.environment(\.isHomeTimeline, timeline == .home)
|
||||||
}
|
|
||||||
.id(client.id)
|
|
||||||
.environment(\.defaultMinListRowHeight, 1)
|
|
||||||
.listStyle(.plain)
|
|
||||||
#if !os(visionOS)
|
|
||||||
.scrollContentBackground(.hidden)
|
|
||||||
.background(theme.primaryBackgroundColor)
|
|
||||||
#endif
|
|
||||||
.introspect(.list, on: .iOS(.v17, .v18)) { (collectionView: UICollectionView) in
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.collectionView = collectionView
|
|
||||||
}
|
}
|
||||||
prefetcher.viewModel = viewModel
|
|
||||||
collectionView.isPrefetchingEnabled = true
|
|
||||||
collectionView.prefetchDataSource = prefetcher
|
|
||||||
}
|
}
|
||||||
|
.id(client.id)
|
||||||
|
.environment(\.defaultMinListRowHeight, 1)
|
||||||
|
.listStyle(.plain)
|
||||||
|
.onChange(of: selectedTabScrollToTop) { _, newValue in
|
||||||
|
if newValue == 0, routerPath.path.isEmpty {
|
||||||
|
withAnimation {
|
||||||
|
proxy.scrollTo(ScrollToView.Constants.scrollToTop, anchor: .top)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if !os(visionOS)
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
.background(theme.primaryBackgroundColor)
|
||||||
|
#endif
|
||||||
|
.introspect(.list, on: .iOS(.v17, .v18)) { (collectionView: UICollectionView) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.collectionView = collectionView
|
||||||
|
}
|
||||||
|
prefetcher.viewModel = viewModel
|
||||||
|
collectionView.isPrefetchingEnabled = true
|
||||||
|
collectionView.prefetchDataSource = prefetcher
|
||||||
|
}
|
||||||
|
}
|
||||||
if viewModel.timeline.supportNewestPagination {
|
if viewModel.timeline.supportNewestPagination {
|
||||||
TimelineUnreadStatusesView(observer: viewModel.pendingStatusesObserver)
|
TimelineUnreadStatusesView(observer: viewModel.pendingStatusesObserver)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue