Allow focusing the different avatars making up a DM details cluster separately. (#3341)

This commit is contained in:
Stefan Ceriu
2024-09-27 15:23:20 +03:00
committed by GitHub
parent 9d23dec2e9
commit 8a3994016d
12 changed files with 65 additions and 51 deletions
@@ -26,13 +26,13 @@ struct AvatarHeaderView<Footer: View>: View {
private let avatarSize: AvatarSize
private let mediaProvider: MediaProviderProtocol?
private var onAvatarTap: (() -> Void)?
private var onAvatarTap: ((URL) -> Void)?
@ViewBuilder private var footer: () -> Footer
init(room: RoomDetails,
avatarSize: AvatarSize,
mediaProvider: MediaProviderProtocol? = nil,
onAvatarTap: (() -> Void)? = nil,
onAvatarTap: ((URL) -> Void)? = nil,
@ViewBuilder footer: @escaping () -> Footer) {
avatarInfo = .room(room.avatar)
title = room.name ?? room.id
@@ -54,7 +54,7 @@ struct AvatarHeaderView<Footer: View>: View {
init(accountOwner: RoomMemberDetails,
dmRecipient: RoomMemberDetails,
mediaProvider: MediaProviderProtocol? = nil,
onAvatarTap: (() -> Void)? = nil,
onAvatarTap: ((URL) -> Void)? = nil,
@ViewBuilder footer: @escaping () -> Footer) {
let dmRecipientProfile = UserProfileProxy(member: dmRecipient)
avatarInfo = .room(.heroes([dmRecipientProfile, UserProfileProxy(member: accountOwner)]))
@@ -72,7 +72,7 @@ struct AvatarHeaderView<Footer: View>: View {
init(member: RoomMemberDetails,
avatarSize: AvatarSize,
mediaProvider: MediaProviderProtocol? = nil,
onAvatarTap: (() -> Void)? = nil,
onAvatarTap: ((URL) -> Void)? = nil,
@ViewBuilder footer: @escaping () -> Footer) {
let profile = UserProfileProxy(member: member)
@@ -86,7 +86,7 @@ struct AvatarHeaderView<Footer: View>: View {
init(user: UserProfileProxy,
avatarSize: AvatarSize,
mediaProvider: MediaProviderProtocol? = nil,
onAvatarTap: (() -> Void)? = nil,
onAvatarTap: ((URL) -> Void)? = nil,
@ViewBuilder footer: @escaping () -> Footer) {
avatarInfo = .user(user)
title = user.displayName ?? user.userID
@@ -128,24 +128,22 @@ struct AvatarHeaderView<Footer: View>: View {
case .room(let roomAvatar):
RoomAvatarImage(avatar: roomAvatar,
avatarSize: avatarSize,
mediaProvider: mediaProvider)
mediaProvider: mediaProvider,
onAvatarTap: onAvatarTap)
case .user(let userProfile):
LoadableAvatarImage(url: userProfile.avatarURL,
name: userProfile.displayName,
contentID: userProfile.userID,
avatarSize: avatarSize,
mediaProvider: mediaProvider)
mediaProvider: mediaProvider,
onTap: onAvatarTap)
}
}
var body: some View {
VStack(spacing: 8.0) {
Button {
onAvatarTap?()
} label: {
avatar
}
.buttonStyle(.borderless) // Add a button style to stop the whole row being tappable.
avatar
Spacer()
.frame(height: 9)
@@ -13,20 +13,39 @@ struct LoadableAvatarImage: View {
private let contentID: String?
private let avatarSize: AvatarSize
private let mediaProvider: MediaProviderProtocol?
private let onTap: ((URL) -> Void)?
@ScaledMetric private var frameSize: CGFloat
init(url: URL?, name: String?, contentID: String?, avatarSize: AvatarSize, mediaProvider: MediaProviderProtocol?) {
init(url: URL?, name: String?,
contentID: String?,
avatarSize: AvatarSize,
mediaProvider: MediaProviderProtocol?,
onTap: ((URL) -> Void)? = nil) {
self.url = url
self.name = name
self.contentID = contentID
self.avatarSize = avatarSize
self.mediaProvider = mediaProvider
self.onTap = onTap
_frameSize = ScaledMetric(wrappedValue: avatarSize.value)
}
var body: some View {
if let onTap, let url {
Button {
onTap(url)
} label: {
clippedAvatar
}
.buttonStyle(.borderless) // Add a button style to stop the whole row being tappable.
} else {
clippedAvatar
}
}
private var clippedAvatar: some View {
avatar
.frame(width: frameSize, height: frameSize)
.background(Color.compound.bgCanvasDefault)
@@ -34,7 +53,7 @@ struct LoadableAvatarImage: View {
}
@ViewBuilder
var avatar: some View {
private var avatar: some View {
if let url {
LoadableImage(url: url,
mediaType: .avatar,
@@ -25,6 +25,8 @@ struct RoomAvatarImage: View {
let avatarSize: AvatarSize
let mediaProvider: MediaProviderProtocol?
private(set) var onAvatarTap: ((URL) -> Void)?
var body: some View {
switch avatar {
case .room(let id, let name, let avatarURL):
@@ -32,7 +34,8 @@ struct RoomAvatarImage: View {
name: name,
contentID: id,
avatarSize: avatarSize,
mediaProvider: mediaProvider)
mediaProvider: mediaProvider,
onTap: onAvatarTap)
case .heroes(let users):
// We will expand upon this with more stack sizes in the future.
if users.count == 0 {
@@ -45,14 +48,16 @@ struct RoomAvatarImage: View {
name: users[0].displayName,
contentID: users[0].userID,
avatarSize: avatarSize,
mediaProvider: mediaProvider)
mediaProvider: mediaProvider,
onTap: onAvatarTap)
.scaledFrame(size: clusterSize, alignment: .topTrailing)
LoadableAvatarImage(url: users[1].avatarURL,
name: users[1].displayName,
contentID: users[1].userID,
avatarSize: avatarSize,
mediaProvider: mediaProvider)
mediaProvider: mediaProvider,
onTap: onAvatarTap)
.mask {
Rectangle()
.fill(Color.white)
@@ -74,7 +79,8 @@ struct RoomAvatarImage: View {
name: users[0].displayName,
contentID: users[0].userID,
avatarSize: avatarSize,
mediaProvider: mediaProvider)
mediaProvider: mediaProvider,
onTap: onAvatarTap)
}
}
}