Refactor TimelineView

This commit is contained in:
Thomas Ricouard 2023-12-30 12:30:02 +01:00
parent 6ea4888ae5
commit 631707a798
5 changed files with 105 additions and 82 deletions

View File

@ -0,0 +1,22 @@
import SwiftUI
import DesignSystem
struct TimelineHeaderView<Content: View>: View {
@Environment(Theme.self) private var theme
var content: () -> Content
var body: some View {
VStack(alignment: .leading) {
Spacer()
content()
Spacer()
}
.listRowBackground(theme.secondaryBackgroundColor)
.listRowSeparator(.hidden)
.listRowInsets(.init(top: 8,
leading: .layoutPadding,
bottom: 8,
trailing: .layoutPadding))
}
}

View File

@ -0,0 +1,39 @@
import SwiftUI
import Models
import Env
struct TimelineTagGroupheaderView: View {
@Environment(RouterPath.self) private var routerPath
@Binding var group: TagGroup?
@Binding var timeline: TimelineFilter
var body: some View {
if let group {
TimelineHeaderView {
HStack {
ScrollView(.horizontal) {
HStack(spacing: 4) {
ForEach(group.tags, id: \.self) { tag in
Button {
routerPath.navigate(to: .hashTag(tag: tag, account: nil))
} label: {
Text("#\(tag)")
.font(.scaledHeadline)
}
.buttonStyle(.plain)
}
}
}
.scrollIndicators(.hidden)
Button("status.action.edit") {
routerPath.presentedSheet = .editTagGroup(tagGroup: group, onSaved: { group in
timeline = .tagGroup(title: group.title, tags: group.tags)
})
}
.buttonStyle(.bordered)
}
}
}
}
}

View File

@ -0,0 +1,42 @@
import SwiftUI
import Models
import DesignSystem
import Env
struct TimelineTagHeaderView: View {
@Environment(CurrentAccount.self) private var account
@Binding var tag: Tag?
var body: some View {
if let tag {
TimelineHeaderView {
HStack {
TagChartView(tag: tag)
.padding(.top, 12)
VStack(alignment: .leading, spacing: 4) {
Text("#\(tag.name)")
.font(.scaledHeadline)
Text("timeline.n-recent-from-n-participants \(tag.totalUses) \(tag.totalAccounts)")
.font(.scaledFootnote)
.foregroundStyle(.secondary)
}
.accessibilityElement(children: .combine)
Spacer()
Button {
Task {
if tag.following {
self.tag = await account.unfollowTag(id: tag.name)
} else {
self.tag = await account.followTag(id: tag.name)
}
}
} label: {
Text(tag.following ? "account.follow.following" : "account.follow.follow")
}.buttonStyle(.bordered)
}
}
}
}
}

View File

@ -48,8 +48,8 @@ public struct TimelineView: View {
ZStack(alignment: .top) {
List {
scrollToTopView
tagGroupHeaderView
tagHeaderView
TimelineTagGroupheaderView(group: $selectedTagGroup, timeline: $viewModel.timeline)
TimelineTagHeaderView(tag: $viewModel.tag)
switch viewModel.timeline {
case .remoteLocal:
StatusesListView(fetcher: viewModel, client: client, routerPath: routerPath, isRemote: true)
@ -157,86 +157,6 @@ public struct TimelineView: View {
}
}
@ViewBuilder
private var tagHeaderView: some View {
if let tag = viewModel.tag {
headerView {
HStack {
TagChartView(tag: tag)
.padding(.top, 12)
VStack(alignment: .leading, spacing: 4) {
Text("#\(tag.name)")
.font(.scaledHeadline)
Text("timeline.n-recent-from-n-participants \(tag.totalUses) \(tag.totalAccounts)")
.font(.scaledFootnote)
.foregroundStyle(.secondary)
}
.accessibilityElement(children: .combine)
Spacer()
Button {
Task {
if tag.following {
viewModel.tag = await account.unfollowTag(id: tag.name)
} else {
viewModel.tag = await account.followTag(id: tag.name)
}
}
} label: {
Text(tag.following ? "account.follow.following" : "account.follow.follow")
}.buttonStyle(.bordered)
}
}
}
}
@ViewBuilder
private var tagGroupHeaderView: some View {
if let group = selectedTagGroup {
headerView {
HStack {
ScrollView(.horizontal) {
HStack(spacing: 4) {
ForEach(group.tags, id: \.self) { tag in
Button {
routerPath.navigate(to: .hashTag(tag: tag, account: nil))
} label: {
Text("#\(tag)")
.font(.scaledHeadline)
}
.buttonStyle(.plain)
}
}
}
.scrollIndicators(.hidden)
Button("status.action.edit") {
routerPath.presentedSheet = .editTagGroup(tagGroup: group, onSaved: { group in
viewModel.timeline = .tagGroup(title: group.title, tags: group.tags)
})
}
.buttonStyle(.bordered)
}
}
}
}
@ViewBuilder
private func headerView(
@ViewBuilder content: () -> some View
) -> some View {
VStack(alignment: .leading) {
Spacer()
content()
Spacer()
}
.listRowBackground(theme.secondaryBackgroundColor)
.listRowSeparator(.hidden)
.listRowInsets(.init(top: 8,
leading: .layoutPadding,
bottom: 8,
trailing: .layoutPadding))
}
@ToolbarContentBuilder
private var toolbarTitleView: some ToolbarContent {
ToolbarItem(placement: .principal) {