diff --git a/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift b/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift index b1d52861..36d6c6fb 100644 --- a/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift +++ b/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift @@ -105,7 +105,7 @@ struct AccountSettingsView: View { .toolbar { ToolbarItem(placement: .principal) { HStack { - AvatarView(url: account.avatar, size: .embed) + AvatarView(account: account, config: .embed) Text(account.safeDisplayName) .font(.headline) } diff --git a/Packages/Account/Sources/Account/AccountDetailHeaderView.swift b/Packages/Account/Sources/Account/AccountDetailHeaderView.swift index 77d3c009..376a22f3 100644 --- a/Packages/Account/Sources/Account/AccountDetailHeaderView.swift +++ b/Packages/Account/Sources/Account/AccountDetailHeaderView.swift @@ -99,7 +99,7 @@ struct AccountDetailHeaderView: View { private var accountAvatarView: some View { HStack { ZStack(alignment: .topTrailing) { - AvatarView(url: account.avatar, size: .account) + AvatarView(account: account, config: .account) .accessibilityLabel("accessibility.tabs.profile.user-avatar.label") if viewModel.isCurrentUser, isSupporter { Image(systemName: "checkmark.seal.fill") diff --git a/Packages/Account/Sources/Account/AccountDetailView.swift b/Packages/Account/Sources/Account/AccountDetailView.swift index 7bd8fafd..8626acba 100644 --- a/Packages/Account/Sources/Account/AccountDetailView.swift +++ b/Packages/Account/Sources/Account/AccountDetailView.swift @@ -214,7 +214,7 @@ public struct AccountDetailView: View { Button { routerPath.navigate(to: .accountDetailWithAccount(account: account)) } label: { - AvatarView(url: account.avatar, size: .badge) + AvatarView(account: account, config: .badge) .padding(.leading, -4) .accessibilityLabel(account.safeDisplayName) diff --git a/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift b/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift index dd1b7df4..9e821cd7 100644 --- a/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift +++ b/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift @@ -44,7 +44,7 @@ public struct AccountsListRow: View { public var body: some View { HStack(alignment: .top) { - AvatarView(url: viewModel.account.avatar, size: .status) + AvatarView(account: viewModel.account, config: .status) VStack(alignment: .leading, spacing: 2) { EmojiTextApp(.init(stringValue: viewModel.account.safeDisplayName), emojis: viewModel.account.emojis) .font(.scaledSubheadline) diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift index 574a2d3a..ebdf899c 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift @@ -35,7 +35,7 @@ public struct AppAccountView: View { private var compactView: some View { HStack { if let account = viewModel.account { - AvatarView(url: account.avatar) + AvatarView(account: account) } else { ProgressView() } @@ -61,7 +61,7 @@ public struct AppAccountView: View { HStack { if let account = viewModel.account { ZStack(alignment: .topTrailing) { - AvatarView(url: account.avatar) + AvatarView(account: account) if viewModel.appAccount.id == appAccounts.currentAccount.id { Image(systemName: "checkmark.circle.fill") .foregroundStyle(.white, .green) diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift index 1553ab9e..de16c5ae 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift @@ -15,7 +15,7 @@ public struct AppAccountsSelectorView: View { @State private var isPresented: Bool = false private let accountCreationEnabled: Bool - private let avatarSize: AvatarView.Size + private let avatarConfig: AvatarView.FrameConfig private var showNotificationBadge: Bool { accountsViewModel @@ -33,11 +33,11 @@ public struct AppAccountsSelectorView: View { public init(routerPath: RouterPath, accountCreationEnabled: Bool = true, - avatarSize: AvatarView.Size = .badge) + avatarConfig: AvatarView.FrameConfig = .badge) { self.routerPath = routerPath self.accountCreationEnabled = accountCreationEnabled - self.avatarSize = avatarSize + self.avatarConfig = avatarConfig } public var body: some View { @@ -71,10 +71,10 @@ public struct AppAccountsSelectorView: View { @ViewBuilder private var labelView: some View { Group { - if let avatar = currentAccount.account?.avatar, !currentAccount.isLoadingAccount { - AvatarView(url: avatar, size: avatarSize) + if let account = currentAccount.account, !currentAccount.isLoadingAccount { + AvatarView(account: account, config: avatarConfig) } else { - AvatarView(url: nil, size: avatarSize) + AvatarView(account: nil, config: avatarConfig) .redacted(reason: .placeholder) .allowsHitTesting(false) } diff --git a/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift b/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift index 6abd0ec7..31f0eb80 100644 --- a/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift +++ b/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift @@ -27,7 +27,7 @@ struct ConversationMessageView: View { if isOwnMessage { Spacer() } else { - AvatarView(url: message.account.avatar, size: .status) + AvatarView(account: message.account, config: .status) .onTapGesture { routerPath.navigate(to: .accountDetailWithAccount(account: message.account)) } diff --git a/Packages/Conversations/Sources/Conversations/List/ConversationsListRow.swift b/Packages/Conversations/Sources/Conversations/List/ConversationsListRow.swift index 3d5ecc86..74a3aa56 100644 --- a/Packages/Conversations/Sources/Conversations/List/ConversationsListRow.swift +++ b/Packages/Conversations/Sources/Conversations/List/ConversationsListRow.swift @@ -24,7 +24,7 @@ struct ConversationsListRow: View { } label: { VStack(alignment: .leading) { HStack(alignment: .top, spacing: 8) { - AvatarView(url: conversation.accounts.first!.avatar) + AvatarView(account: conversation.accounts.first!) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 4) { HStack { diff --git a/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift b/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift index 6bde7001..454dfc5f 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift @@ -2,104 +2,315 @@ import Nuke import NukeUI import Shimmer import SwiftUI +import Models @MainActor public struct AvatarView: View { - @Environment(\.redactionReasons) private var reasons @Environment(Theme.self) private var theme - public enum Size { - case account, status, embed, badge, list, boost + @State private var showPopup = false + @State private var autoDismiss = true + @State private var toggleTask: Task = Task {} - public var size: CGSize { - switch self { - case .account: - return .init(width: 80, height: 80) - case .status: - if ProcessInfo.processInfo.isMacCatalystApp { - return .init(width: 48, height: 48) - } - return .init(width: 40, height: 40) - case .embed: - return .init(width: 34, height: 34) - case .badge: - return .init(width: 28, height: 28) - case .list: - return .init(width: 20, height: 20) - case .boost: - return .init(width: 12, height: 12) - } - } - - var cornerRadius: CGFloat { - switch self { - case .badge, .boost, .list: - size.width / 2 - default: - 4 - } - } - } - - public let url: URL? - public let size: Size - - public init(url: URL?, size: Size = .status) { - self.url = url - self.size = size - } + public let account: Account? + public let config: FrameConfig + public let hasPopup: Bool public var body: some View { - Group { - if reasons == .placeholder { - RoundedRectangle(cornerRadius: size.cornerRadius) - .fill(.gray) - .frame(width: size.size.width, height: size.size.height) - } else { - LazyImage(request: url.map { makeImageRequest(for: $0) }) { state in - if let image = state.image { - image - .resizable() - .aspectRatio(contentMode: .fit) - } else { - AvatarPlaceholderView(size: size) + if let account = account { + if hasPopup { + AvatarImage(account: account, config: adaptiveConfig) + .onHover { hovering in + if hovering { + toggleTask.cancel() + toggleTask = Task { + try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 2) + guard !Task.isCancelled else { return } + if !showPopup { + showPopup = true + } + } + } else { + if !showPopup { + toggleTask.cancel() + } + } } - } - .frame(width: size.size.width, height: size.size.height) + .hoverEffect(.lift) + .popover(isPresented: $showPopup) { + AccountPopupView( + account: account, + theme: theme, + showPopup: $showPopup, + autoDismiss: $autoDismiss, + toggleTask: $toggleTask + ) + } + } else { + AvatarImage(account: account, config: adaptiveConfig) } + } else { + AvatarPlaceHolder(config: adaptiveConfig) } - .clipShape(clipShape) - .overlay( - clipShape.stroke(Color.primary.opacity(0.25), lineWidth: 1) - ) } - private func makeImageRequest(for url: URL) -> ImageRequest { - ImageRequest(url: url, processors: [.resize(size: size.size)]) + private var adaptiveConfig: FrameConfig { + var cornerRadius: CGFloat + if config == .badge || theme.avatarShape == .circle { + cornerRadius = config.width / 2 + } else { + cornerRadius = config.cornerRadius + } + return FrameConfig(width: config.width, height: config.height, cornerRadius: cornerRadius) } - private var clipShape: some Shape { - switch theme.avatarShape { - case .circle: - AnyShape(Circle()) - case .rounded: - AnyShape(RoundedRectangle(cornerRadius: size.cornerRadius)) + public init(account: Account?, config: FrameConfig = FrameConfig.status, hasPopup: Bool = false) { + self.account = account + self.config = config + self.hasPopup = hasPopup + } + + public struct FrameConfig: Equatable { + public let size: CGSize + public var width: CGFloat { size.width } + public var height: CGFloat { size.height } + let cornerRadius: CGFloat + + init(width: CGFloat, height: CGFloat, cornerRadius: CGFloat = 4) { + self.size = CGSize(width: width, height: height) + self.cornerRadius = cornerRadius } + + public static let account = FrameConfig(width: 80, height: 80) + public static let status = { + if ProcessInfo.processInfo.isMacCatalystApp { + return FrameConfig(width: 48, height: 48) + } + return FrameConfig(width: 40, height: 40) + }() + public static let embed = FrameConfig(width: 34, height: 34) + public static let badge = FrameConfig(width: 28, height: 28, cornerRadius: 14) + public static let list = FrameConfig(width: 20, height: 20, cornerRadius: 10) + public static let boost = FrameConfig(width: 12, height: 12, cornerRadius: 6) } } -private struct AvatarPlaceholderView: View { - let size: AvatarView.Size +struct AvatarView_Previews: PreviewProvider { + static var previews: some View { + PreviewWrapper() + .padding() + .previewLayout(.sizeThatFits) + } +} + +struct PreviewWrapper: View { + @State private var isCircleAvatar = false var body: some View { - if size == .badge { - Circle() - .fill(.gray) - .frame(width: size.size.width, height: size.size.height) + VStack(alignment: .leading) { + AvatarView(account: Self.account, config: .status) + .environment(Theme.shared) + Toggle("Avatar Shape", isOn: $isCircleAvatar) + } + .onChange(of: isCircleAvatar) { + Theme.shared.avatarShape = self.isCircleAvatar ? .circle : .rounded + } + .onAppear { + Theme.shared.avatarShape = self.isCircleAvatar ? .circle : .rounded + } + } + + private static let account = Account( + id: UUID().uuidString, + username: "@clattner_llvm", + displayName: "Chris Lattner", + avatar: URL(string: "https://pbs.twimg.com/profile_images/1484209565788897285/1n6Viahb_400x400.jpg")!, + header: URL(string: "https://pbs.twimg.com/profile_banners/2543588034/1656822255/1500x500")!, + acct: "clattner_llvm@example.com", + note: .init(stringValue: "Building beautiful things @Modular_AI ๐Ÿ”ฅ, lifting the world of production AI/ML software into a new phase of innovation. Weโ€™re hiring! ๐Ÿš€๐Ÿง "), + createdAt: ServerDate(), + followersCount: 77100, + followingCount: 167, + statusesCount: 123, + lastStatusAt: nil, + fields: [], + locked: false, + emojis: [], + url: URL(string: "https://nondot.org/sabre/")!, + source: nil, + bot: false, + discoverable: true) +} + +struct AvatarImage: View { + @Environment(\.redactionReasons) private var reasons + + public let account: Account + public let config: AvatarView.FrameConfig + + var body: some View { + if reasons == .placeholder { + AvatarPlaceHolder(config: config) } else { - RoundedRectangle(cornerRadius: size.cornerRadius) - .fill(.gray) - .frame(width: size.size.width, height: size.size.height) + LazyImage(request: ImageRequest(url: account.avatar, processors: [.resize(size: config.size)]) + ) { state in + if let image = state.image { + image.resizable().scaledToFill() + .frame(width: config.width, height: config.height) + .clipShape(RoundedRectangle(cornerRadius: config.cornerRadius)) + .overlay( + RoundedRectangle(cornerRadius: config.cornerRadius) + .stroke(.primary.opacity(0.25), lineWidth: 1) + ) + } + } } } } + +struct AvatarPlaceHolder: View { + let config: AvatarView.FrameConfig + + var body: some View { + RoundedRectangle(cornerRadius: config.cornerRadius) + .fill(.gray) + .frame(width: config.width, height: config.height) + } +} + +struct AccountPopupView: View { + let account: Account + let theme: Theme // using `@Environment(Theme.self) will crash the SwiftUI preview + private let config: AvatarView.FrameConfig = .account + + @Binding var showPopup: Bool + @Binding var autoDismiss: Bool + @Binding var toggleTask: Task + + var body: some View { + VStack(alignment: .leading) { + LazyImage(request: ImageRequest(url: account.header) + ) { state in + if let image = state.image { + image.resizable().scaledToFill() + } + } + .frame(width: 500, height: 150) + .clipped() + .background(theme.secondaryBackgroundColor) + + VStack(alignment: .leading) { + HStack(alignment: .bottomAvatar) { + AvatarImage(account: account, config: adaptiveConfig) + Spacer() + makeCustomInfoLabel(title: "account.following", count: account.followingCount ?? 0) + makeCustomInfoLabel(title: "account.posts", count: account.statusesCount ?? 0) + makeCustomInfoLabel(title: "account.followers", count: account.followersCount ?? 0) + } + .frame(height: adaptiveConfig.height / 2, alignment: .bottom) + + EmojiTextApp(.init(stringValue: account.safeDisplayName ), emojis: account.emojis) + .font(.headline) + .foregroundColor(theme.labelColor) + .emojiSize(Font.scaledHeadlineFont.emojiSize) + .emojiBaselineOffset(Font.scaledHeadlineFont.emojiBaselineOffset) + .accessibilityAddTraits(.isHeader) + .help(account.safeDisplayName) + + Text("@\(account.acct)") + .font(.callout) + .foregroundColor(.gray) + .textSelection(.enabled) + .accessibilityRespondsToUserInteraction(false) + .help("@\(account.acct)") + + HStack(spacing: 4) { + Image(systemName: "calendar") + .accessibilityHidden(true) + Text("account.joined") + Text(account.createdAt.asDate, style: .date) + } + .foregroundColor(.gray) + .font(.footnote) + .accessibilityElement(children: .combine) + + EmojiTextApp(account.note, emojis: account.emojis, lineLimit: 5) + .font(.body) + .emojiSize(Font.scaledFootnoteFont.emojiSize) + .emojiBaselineOffset(Font.scaledFootnoteFont.emojiBaselineOffset) + .padding(.top, 3) + } + .padding([.leading, .trailing, .bottom]) + } + .frame(width: 500) + .onAppear { + toggleTask.cancel() + toggleTask = Task { + try? await Task.sleep(nanoseconds: NSEC_PER_SEC * 2) + guard !Task.isCancelled else { return } + if autoDismiss { + showPopup = false + } + } + } + .onHover { hovering in + toggleTask.cancel() + toggleTask = Task { + try? await Task.sleep(nanoseconds: NSEC_PER_SEC / 2) + guard !Task.isCancelled else { return } + if hovering { + autoDismiss = false + } else { + showPopup = false + autoDismiss = true + } + } + } + } + + @MainActor + private func makeCustomInfoLabel(title: LocalizedStringKey, count: Int, needsBadge: Bool = false) -> some View { + VStack { + Text(count, format: .number.notation(.compactName)) + .font(.scaledHeadline) + .foregroundColor(theme.tintColor) + .overlay(alignment: .trailing) { + if needsBadge { + Circle() + .fill(Color.red) + .frame(width: 9, height: 9) + .offset(x: 12) + } + } + Text(title) + .font(.scaledFootnote) + .foregroundColor(.gray) + .alignmentGuide(.bottomAvatar, computeValue: { dimension in + dimension[.firstTextBaseline] + }) + } + .accessibilityElement(children: .ignore) + .accessibilityLabel(title) + .accessibilityValue("\(count)") + } + + private var adaptiveConfig: AvatarView.FrameConfig { + var cornerRadius: CGFloat + if config == .badge || theme.avatarShape == .circle { + cornerRadius = config.width / 2 + } else { + cornerRadius = config.cornerRadius + } + return AvatarView.FrameConfig(width: config.width, height: config.height, cornerRadius: cornerRadius) + } +} + +private enum BottomAvatarAlignment: AlignmentID { + static func defaultValue(in context: ViewDimensions) -> CGFloat { + context.height + } +} + +extension VerticalAlignment { + static let bottomAvatar = VerticalAlignment(BottomAvatarAlignment.self) +} diff --git a/Packages/Lists/Sources/Lists/Edit/ListEditView.swift b/Packages/Lists/Sources/Lists/Edit/ListEditView.swift index 126c83fc..8de041e9 100644 --- a/Packages/Lists/Sources/Lists/Edit/ListEditView.swift +++ b/Packages/Lists/Sources/Lists/Edit/ListEditView.swift @@ -30,7 +30,7 @@ public struct ListEditView: View { } else { ForEach(viewModel.accounts) { account in HStack { - AvatarView(url: account.avatar, size: .status) + AvatarView(account: account, config: .status) VStack(alignment: .leading) { EmojiTextApp(.init(stringValue: account.safeDisplayName), emojis: account.emojis) diff --git a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift index 96db1335..ed25a0bd 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift @@ -23,8 +23,8 @@ struct NotificationRowView: View { .accessibilityHidden(true) } else { makeNotificationIconView(type: notification.type) - .frame(width: AvatarView.Size.status.size.width, - height: AvatarView.Size.status.size.height) + .frame(width: AvatarView.FrameConfig.status.width, + height: AvatarView.FrameConfig.status.height) .accessibilityHidden(true) } VStack(alignment: .leading, spacing: 2) { @@ -52,7 +52,7 @@ struct NotificationRowView: View { private func makeAvatarView(type: Models.Notification.NotificationType) -> some View { ZStack(alignment: .topLeading) { - AvatarView(url: notification.accounts[0].avatar) + AvatarView(account: notification.accounts[0], hasPopup: true) makeNotificationIconView(type: type) .offset(x: -8, y: -8) } @@ -83,7 +83,7 @@ struct NotificationRowView: View { ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 8) { ForEach(notification.accounts) { account in - AvatarView(url: account.avatar) + AvatarView(account: account, hasPopup: true) .contentShape(Rectangle()) .onTapGesture { routerPath.navigate(to: .accountDetailWithAccount(account: account)) @@ -91,7 +91,7 @@ struct NotificationRowView: View { } } .padding(.leading, 1) - .frame(height: AvatarView.Size.status.size.height + 2) + .frame(height: AvatarView.FrameConfig.status.size.height + 2) }.offset(y: -1) } HStack(spacing: 0) { diff --git a/Packages/Status/Sources/Status/Editor/Components/StatusEditorAutoCompleteView.swift b/Packages/Status/Sources/Status/Editor/Components/StatusEditorAutoCompleteView.swift index 249976a4..70895433 100644 --- a/Packages/Status/Sources/Status/Editor/Components/StatusEditorAutoCompleteView.swift +++ b/Packages/Status/Sources/Status/Editor/Components/StatusEditorAutoCompleteView.swift @@ -31,7 +31,7 @@ struct StatusEditorAutoCompleteView: View { viewModel.selectMentionSuggestion(account: account) } label: { HStack { - AvatarView(url: account.avatar, size: .badge) + AvatarView(account: account, config: AvatarView.FrameConfig.badge) VStack(alignment: .leading) { EmojiTextApp(.init(stringValue: account.safeDisplayName), emojis: account.emojis) diff --git a/Packages/Status/Sources/Status/Editor/StatusEditorView.swift b/Packages/Status/Sources/Status/Editor/StatusEditorView.swift index 6895d171..aa0e996f 100644 --- a/Packages/Status/Sources/Status/Editor/StatusEditorView.swift +++ b/Packages/Status/Sources/Status/Editor/StatusEditorView.swift @@ -246,9 +246,9 @@ public struct StatusEditorView: View { if viewModel.mode.isInShareExtension { AppAccountsSelectorView(routerPath: RouterPath(), accountCreationEnabled: false, - avatarSize: .status) + avatarConfig: .status) } else { - AvatarView(url: account.avatar, size: .status) + AvatarView(account: account, config: AvatarView.FrameConfig.status) .environment(theme) .accessibilityHidden(true) } diff --git a/Packages/Status/Sources/Status/Embed/StatusEmbeddedView.swift b/Packages/Status/Sources/Status/Embed/StatusEmbeddedView.swift index 89ca241f..8ac6aefc 100644 --- a/Packages/Status/Sources/Status/Embed/StatusEmbeddedView.swift +++ b/Packages/Status/Sources/Status/Embed/StatusEmbeddedView.swift @@ -46,7 +46,7 @@ public struct StatusEmbeddedView: View { private func makeAccountView(account: Account) -> some View { HStack(alignment: .center) { - AvatarView(url: account.avatar, size: .embed) + AvatarView(account: account, config: .embed, hasPopup: true) VStack(alignment: .leading, spacing: 0) { EmojiTextApp(.init(stringValue: account.safeDisplayName), emojis: account.emojis) .font(.scaledFootnote) diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index 2266b571..1610fa94 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -57,7 +57,7 @@ public struct StatusRowView: View { StatusRowReblogView(viewModel: viewModel) StatusRowReplyView(viewModel: viewModel) } - .padding(.leading, AvatarView.Size.status.size.width + .statusColumnsSpacing) + .padding(.leading, AvatarView.FrameConfig.status.width + .statusColumnsSpacing) } HStack(alignment: .top, spacing: .statusColumnsSpacing) { if !isCompact, @@ -66,7 +66,7 @@ public struct StatusRowView: View { Button { viewModel.navigateToAccountDetail(account: viewModel.finalStatus.account) } label: { - AvatarView(url: viewModel.finalStatus.account.avatar, size: .status) + AvatarView(account: viewModel.finalStatus.account, config: .status, hasPopup: true) } } VStack(alignment: .leading) { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift index 710b3007..7702991e 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift @@ -103,7 +103,7 @@ struct StatusRowDetailView: View { ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 0) { ForEach(accounts) { account in - AvatarView(url: account.avatar, size: .list) + AvatarView(account: account, config: .list, hasPopup: true) .padding(.leading, -4) } .transition(.opacity) diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift index 4e3fc5f7..105261f2 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift @@ -42,7 +42,7 @@ struct StatusRowHeaderView: View { private var accountView: some View { HStack(alignment: .center) { if theme.avatarPosition == .top { - AvatarView(url: viewModel.finalStatus.account.avatar, size: .status) + AvatarView(account: viewModel.finalStatus.account, config: .status, hasPopup: true) } VStack(alignment: .leading, spacing: 2) { HStack(alignment: .firstTextBaseline, spacing: 2) { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift index 13e9441b..b7e2780b 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift @@ -31,7 +31,7 @@ public struct StatusRowMediaPreviewView: View { } var appLayoutWidth: CGFloat { - let avatarColumnWidth = theme.avatarPosition == .leading ? AvatarView.Size.status.size.width + .statusColumnsSpacing : 0 + let avatarColumnWidth = theme.avatarPosition == .leading ? AvatarView.FrameConfig.status.width + .statusColumnsSpacing : 0 var sidebarWidth: CGFloat = 0 var secondaryColumnWidth: CGFloat = 0 let layoutPading: CGFloat = .layoutPadding * 2 diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift index ebe1ca2a..c2bd4760 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift @@ -8,7 +8,7 @@ struct StatusRowReblogView: View { if viewModel.status.reblog != nil { HStack(spacing: 2) { Image("Rocket.Fill") - AvatarView(url: viewModel.status.account.avatar, size: .boost) + AvatarView(account: viewModel.status.account, config: .boost, hasPopup: true) EmojiTextApp(.init(stringValue: viewModel.status.account.safeDisplayName), emojis: viewModel.status.account.emojis) Text("status.row.was-boosted") }