Optimisations: Autoclosure for StatusRowViewModel

This commit is contained in:
Thomas Ricouard 2023-02-24 13:25:21 +01:00
parent 401bd7afb5
commit 29aaa7c5cb
9 changed files with 43 additions and 39 deletions

View file

@ -19,7 +19,7 @@ struct DisplaySettingsView: View {
var body: some View { var body: some View {
Form { Form {
Section("settings.display.example-toot") { Section("settings.display.example-toot") {
StatusRowView(viewModel: previewStatusViewModel) StatusRowView(viewModel: { previewStatusViewModel })
.allowsHitTesting(false) .allowsHitTesting(false)
} }

View file

@ -275,7 +275,7 @@ public struct AccountDetailView: View {
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
ForEach(viewModel.pinned) { status in ForEach(viewModel.pinned) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
} }
Rectangle() Rectangle()
.fill(theme.secondaryBackgroundColor) .fill(theme.secondaryBackgroundColor)

View file

@ -81,7 +81,7 @@ public struct ExploreView: View {
private var loadingView: some View { private var loadingView: some View {
ForEach(Status.placeholders()) { status in ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
.padding(.vertical, 8) .padding(.vertical, 8)
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
@ -112,7 +112,7 @@ public struct ExploreView: View {
if !results.statuses.isEmpty { if !results.statuses.isEmpty {
Section("explore.section.posts") { Section("explore.section.posts") {
ForEach(results.statuses) { status in ForEach(results.statuses) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
.padding(.vertical, 8) .padding(.vertical, 8)
} }
@ -184,7 +184,7 @@ public struct ExploreView: View {
Section("explore.section.trending.posts") { Section("explore.section.trending.posts") {
ForEach(viewModel.trendingStatuses ForEach(viewModel.trendingStatuses
.prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count)) { status in .prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count)) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
.padding(.vertical, 8) .padding(.vertical, 8)
} }
@ -192,7 +192,7 @@ public struct ExploreView: View {
NavigationLink { NavigationLink {
List { List {
ForEach(viewModel.trendingStatuses) { status in ForEach(viewModel.trendingStatuses) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
.padding(.vertical, 8) .padding(.vertical, 8)
} }

View file

@ -135,15 +135,15 @@ struct NotificationRowView: View {
if let status = notification.status { if let status = notification.status {
HStack { HStack {
if type == .mention { if type == .mention {
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: { .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
showActions: true)) showActions: true) })
} else { } else {
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: { .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
showActions: false)) showActions: false) })
.lineLimit(4) .lineLimit(4)
.foregroundColor(.gray) .foregroundColor(.gray)
} }

View file

@ -124,7 +124,7 @@ public struct StatusDetailView: View {
makeCurrentStatusView(status: status) makeCurrentStatusView(status: status)
.environment(\.extraLeadingInset, isReplyToPrevious ? 10 : 0) .environment(\.extraLeadingInset, isReplyToPrevious ? 10 : 0)
} else { } else {
StatusRowView(viewModel: viewModel) StatusRowView(viewModel: { viewModel })
.environment(\.extraLeadingInset, isReplyToPrevious ? 10 : 0) .environment(\.extraLeadingInset, isReplyToPrevious ? 10 : 0)
} }
} }
@ -137,10 +137,10 @@ public struct StatusDetailView: View {
} }
private func makeCurrentStatusView(status: Status) -> some View { private func makeCurrentStatusView(status: Status) -> some View {
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: { .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
isFocused: !viewModel.isLoadingContext)) isFocused: !viewModel.isLoadingContext) })
.overlay { .overlay {
GeometryReader { reader in GeometryReader { reader in
VStack {} VStack {}
@ -166,7 +166,7 @@ public struct StatusDetailView: View {
private var loadingDetailView: some View { private var loadingDetailView: some View {
ForEach(Status.placeholders()) { status in ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
} }
} }

View file

@ -23,10 +23,10 @@ public struct StatusEmbeddedView: View {
HStack { HStack {
VStack(alignment: .leading) { VStack(alignment: .leading) {
makeAccountView(account: status.reblog?.account ?? status.account) makeAccountView(account: status.reblog?.account ?? status.account)
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: { .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
showActions: false)) showActions: false) })
.environment(\.isCompact, true) .environment(\.isCompact, true)
} }
Spacer() Spacer()

View file

@ -24,7 +24,7 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
switch fetcher.statusesState { switch fetcher.statusesState {
case .loading: case .loading:
ForEach(Status.placeholders()) { status in ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) })
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
} }
case .error: case .error:
@ -40,17 +40,19 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
case let .display(statuses, nextPageState): case let .display(statuses, nextPageState):
ForEach(statuses, id: \.viewId) { status in ForEach(statuses, id: \.viewId) { status in
let viewModel = StatusRowViewModel(status: status, client: client, routerPath: routerPath, isRemote: isRemote) StatusRowView(viewModel: { StatusRowViewModel(status: status,
if viewModel.filter?.filter.filterAction != .hide { client: client,
StatusRowView(viewModel: viewModel) routerPath: routerPath,
.id(status.id) isRemote: isRemote)
.onAppear {
fetcher.statusDidAppear(status: status) })
} .id(status.id)
.onDisappear { .onAppear {
fetcher.statusDidDisappear(status: status) fetcher.statusDidAppear(status: status)
} }
} .onDisappear {
fetcher.statusDidDisappear(status: status)
}
} }
switch nextPageState { switch nextPageState {
case .hasNextPage: case .hasNextPage:

View file

@ -15,8 +15,9 @@ public struct StatusRowView: View {
@StateObject var viewModel: StatusRowViewModel @StateObject var viewModel: StatusRowViewModel
public init(viewModel: StatusRowViewModel) { // StateObject accepts an @autoclosure which only allocates the view model once when the view gets on screen.
_viewModel = StateObject(wrappedValue: viewModel) public init(viewModel: @escaping () -> StatusRowViewModel) {
_viewModel = StateObject(wrappedValue: viewModel())
} }
var contextMenu: some View { var contextMenu: some View {
@ -32,6 +33,7 @@ public struct StatusRowView: View {
case .hide: case .hide:
EmptyView() EmptyView()
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
.listRowInsets(.init())
} }
} else { } else {
let status: AnyStatus = viewModel.status.reblog ?? viewModel.status let status: AnyStatus = viewModel.status.reblog ?? viewModel.status

View file

@ -92,7 +92,7 @@ struct StatusRowContextMenu: View {
Button { Button {
let view = HStack { let view = HStack {
StatusRowView(viewModel: viewModel) StatusRowView(viewModel: { viewModel })
.padding(16) .padding(16)
} }
.environment(\.isInCaptureMode, true) .environment(\.isInCaptureMode, true)