IceCubesApp/Packages/StatusKit/Sources/StatusKit/Row/Subviews/StatusRowHeaderView.swift

103 lines
3.5 KiB
Swift
Raw Normal View History

import DesignSystem
2023-02-21 06:23:42 +00:00
import Env
import Models
2023-02-18 06:26:48 +00:00
import SwiftUI
2023-12-27 15:07:16 +00:00
import Network
2023-09-18 19:03:52 +00:00
@MainActor
struct StatusRowHeaderView: View {
2023-02-19 14:29:07 +00:00
@Environment(\.isInCaptureMode) private var isInCaptureMode: Bool
@Environment(\.isStatusFocused) private var isFocused
2023-12-27 15:07:16 +00:00
@Environment(\.redactionReasons) private var redactionReasons
2023-09-18 19:03:52 +00:00
@Environment(Theme.self) private var theme
2023-02-18 06:26:48 +00:00
let viewModel: StatusRowViewModel
var body: some View {
2023-12-27 15:07:16 +00:00
HStack(alignment: theme.avatarPosition == .top ? .center : .top) {
2024-02-14 09:48:17 +00:00
accountView
.hoverEffect()
.accessibilityAddTraits(.isButton)
.onTapGesture {
viewModel.navigateToAccountDetail(account: viewModel.finalStatus.account)
}
Spacer()
2023-12-27 18:28:16 +00:00
if !redactionReasons.contains(.placeholder) {
dateView
}
}
Timeline & Timeline detail accessibility uplift (#1323) * Improve accessibility of StatusPollView Previously, this view did not provide the proper context to indicate that it represented a poll. Now, we’ve added - A container that will stay “Active poll” or “Poll results” when the cursor first hits one of the options; - A prefix to say “Option X of Y” before each option; - A Selected trait on the selected option(s), if present - Consolidating and adding an `.updatesFrequently` trait to the footer view with the countdown. * Add poll description in StatusRowView combinedAccessibilityLabel This largely duplicates the logic in `StatusPollView`. * Improve accessibility of media attachments Previously, the media attachments without alt text would not show up in the consolidated `StatusRowView`, nor would they be meaningfully explained on the status detail screen. Now, they are presented with their attachment type. * Change accessibilityRepresentation of AppAcountsSelectorView * Change Notifications tab title view accessibility representation to Menu Previously it would present as a button * Hide layout `Rectangle`s from accessibility * Consolidate `StatusRowDetailView` accessibility representation * Improve readability of Poll accessibility label * Ensure poll options don’t present as interactive when the poll is finished * Improve accessibility of StatusRowCardView Previously, it would present as four separate elements, including an image without a description, all interactive, none with an interactive trait. Now, it presents as a single element with the `.link` trait * Improve accessibility of StatusRowHeaderView Previously, it had no traits and no actions except inherited ones. Now it presents as a button, triggering its primary action. It also has custom actions corresponding to its context menu * Avoid applying the StatusRowView custom actions to every view when contained * Provide context for the application name * Add pauses to StatusRowView combinedAccessibilityLabel * Hide `TimelineView.scrollToTopView` from accessibility * Set appropriate font style on Notification header After the change the Text needed a `.headline` style to match the prior appearance. * Fix bug in accessibilityRepresentation of TimelineView nav bar title Previously, it would not display the proper label for .remoteLocal filter options. * Ensure that pop-up button nav bar titles are interactive * Ensure TextView responds to Environment.sizeCategory This resolves #1309 * Fix button --------- Co-authored-by: Thomas Ricouard <ricouard77@gmail.com>
2023-03-28 16:48:58 +00:00
.accessibilityElement(children: .combine)
.accessibilityLabel(Text("\(viewModel.finalStatus.account.safeDisplayName)") + Text(", ") + Text(viewModel.finalStatus.createdAt.relativeFormatted))
.accessibilityAction {
viewModel.navigateToAccountDetail(account: viewModel.finalStatus.account)
}
}
2023-02-18 06:26:48 +00:00
@ViewBuilder
2023-03-02 05:56:25 +00:00
private var accountView: some View {
HStack(alignment: .center) {
if theme.avatarPosition == .top {
AvatarView(viewModel.finalStatus.account.avatar)
2024-01-24 15:22:44 +00:00
#if targetEnvironment(macCatalyst)
.accountPopover(viewModel.finalStatus.account)
2024-01-24 15:22:44 +00:00
#endif
}
2023-02-19 18:51:37 +00:00
VStack(alignment: .leading, spacing: 2) {
HStack(alignment: .firstTextBaseline, spacing: 2) {
Group {
2024-01-24 15:22:44 +00:00
EmojiTextApp(viewModel.finalStatus.account.cachedDisplayName,
2023-03-02 05:56:25 +00:00
emojis: viewModel.finalStatus.account.emojis)
2023-12-18 07:22:59 +00:00
.font(.scaledSubheadline)
.foregroundColor(theme.labelColor)
2024-02-05 07:55:24 +00:00
.emojiText.size(Font.scaledSubheadlineFont.emojiSize)
.emojiText.baselineOffset(Font.scaledSubheadlineFont.emojiBaselineOffset)
2023-12-18 07:22:59 +00:00
.fontWeight(.semibold)
.lineLimit(1)
2024-01-24 15:22:44 +00:00
#if targetEnvironment(macCatalyst)
2023-12-18 07:22:59 +00:00
.accountPopover(viewModel.finalStatus.account)
2024-01-24 15:22:44 +00:00
#endif
2023-12-27 16:12:48 +00:00
if !redactionReasons.contains(.placeholder) {
2023-12-27 15:07:16 +00:00
accountBadgeView
.font(.footnote)
}
}
.layoutPriority(1)
}
2023-12-27 17:16:59 +00:00
if !redactionReasons.contains(.placeholder) {
if (theme.displayFullUsername && theme.avatarPosition == .leading) ||
theme.avatarPosition == .top {
Text("@\(theme.displayFullUsername ? viewModel.finalStatus.account.acct : viewModel.finalStatus.account.username)")
.font(.scaledFootnote)
.foregroundStyle(.secondary)
.lineLimit(1)
2024-01-24 15:22:44 +00:00
#if targetEnvironment(macCatalyst)
2023-12-27 17:16:59 +00:00
.accountPopover(viewModel.finalStatus.account)
2024-01-24 15:22:44 +00:00
#endif
2023-12-27 17:16:59 +00:00
}
}
}
}
}
2023-02-26 05:45:57 +00:00
private var accountBadgeView: Text {
2023-02-24 16:16:39 +00:00
if (viewModel.status.reblogAsAsStatus ?? viewModel.status).account.bot {
2023-02-26 16:33:16 +00:00
return Text(Image(systemName: "poweroutlet.type.b.fill")) + Text(" ")
2023-02-24 16:16:39 +00:00
} else if (viewModel.status.reblogAsAsStatus ?? viewModel.status).account.locked {
return Text(Image(systemName: "lock.fill")) + Text(" ")
}
return Text("")
}
2023-02-21 06:23:42 +00:00
2023-12-27 15:07:16 +00:00
private var dateView: some View {
Group {
2023-12-27 18:28:16 +00:00
Text(Image(systemName: viewModel.finalStatus.visibility.iconName)) +
Text("") +
Text(viewModel.finalStatus.createdAt.relativeFormatted)
2023-12-27 15:07:16 +00:00
}
.font(.scaledFootnote)
.foregroundStyle(.secondary)
.lineLimit(1)
}
}