add avtars
This commit is contained in:
parent
520f63f74a
commit
fc7561a9c2
@ -167,6 +167,7 @@ struct ChatProfile: Decodable {
|
|||||||
let bio: String?
|
let bio: String?
|
||||||
let lastSeen: Int?
|
let lastSeen: Int?
|
||||||
let createdAt: Date?
|
let createdAt: Date?
|
||||||
|
let avatars: Avatars?
|
||||||
let stories: [JSONValue]
|
let stories: [JSONValue]
|
||||||
let permissions: ChatPermissions?
|
let permissions: ChatPermissions?
|
||||||
let profilePermissions: ChatProfilePermissions?
|
let profilePermissions: ChatProfilePermissions?
|
||||||
@ -181,6 +182,7 @@ struct ChatProfile: Decodable {
|
|||||||
case bio
|
case bio
|
||||||
case lastSeen
|
case lastSeen
|
||||||
case createdAt
|
case createdAt
|
||||||
|
case avatars
|
||||||
case stories
|
case stories
|
||||||
case permissions
|
case permissions
|
||||||
case profilePermissions
|
case profilePermissions
|
||||||
@ -198,6 +200,7 @@ struct ChatProfile: Decodable {
|
|||||||
self.bio = try container.decodeIfPresent(String.self, forKey: .bio)
|
self.bio = try container.decodeIfPresent(String.self, forKey: .bio)
|
||||||
self.lastSeen = try container.decodeIfPresent(Int.self, forKey: .lastSeen)
|
self.lastSeen = try container.decodeIfPresent(Int.self, forKey: .lastSeen)
|
||||||
self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt)
|
self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt)
|
||||||
|
self.avatars = try container.decodeIfPresent(Avatars.self, forKey: .avatars)
|
||||||
self.stories = try container.decodeIfPresent([JSONValue].self, forKey: .stories) ?? []
|
self.stories = try container.decodeIfPresent([JSONValue].self, forKey: .stories) ?? []
|
||||||
self.permissions = try container.decodeIfPresent(ChatPermissions.self, forKey: .permissions)
|
self.permissions = try container.decodeIfPresent(ChatPermissions.self, forKey: .permissions)
|
||||||
self.profilePermissions = try container.decodeIfPresent(ChatProfilePermissions.self, forKey: .profilePermissions)
|
self.profilePermissions = try container.decodeIfPresent(ChatProfilePermissions.self, forKey: .profilePermissions)
|
||||||
@ -217,6 +220,7 @@ extension ChatProfile {
|
|||||||
bio: String? = nil,
|
bio: String? = nil,
|
||||||
lastSeen: Int? = nil,
|
lastSeen: Int? = nil,
|
||||||
createdAt: Date? = nil,
|
createdAt: Date? = nil,
|
||||||
|
avatars: Avatars? = nil,
|
||||||
stories: [JSONValue] = [],
|
stories: [JSONValue] = [],
|
||||||
permissions: ChatPermissions? = nil,
|
permissions: ChatPermissions? = nil,
|
||||||
profilePermissions: ChatProfilePermissions? = nil,
|
profilePermissions: ChatProfilePermissions? = nil,
|
||||||
@ -230,6 +234,7 @@ extension ChatProfile {
|
|||||||
self.bio = bio
|
self.bio = bio
|
||||||
self.lastSeen = lastSeen
|
self.lastSeen = lastSeen
|
||||||
self.createdAt = createdAt
|
self.createdAt = createdAt
|
||||||
|
self.avatars = avatars
|
||||||
self.stories = stories
|
self.stories = stories
|
||||||
self.permissions = permissions
|
self.permissions = permissions
|
||||||
self.profilePermissions = profilePermissions
|
self.profilePermissions = profilePermissions
|
||||||
@ -238,6 +243,19 @@ extension ChatProfile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AvatarInfo: Decodable {
|
||||||
|
let fileId: String
|
||||||
|
let mime: String?
|
||||||
|
let size: Int?
|
||||||
|
let width: Int?
|
||||||
|
let height: Int?
|
||||||
|
let createdAt: Date?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Avatars: Decodable {
|
||||||
|
let current: AvatarInfo?
|
||||||
|
}
|
||||||
|
|
||||||
struct ChatPermissions: Decodable {
|
struct ChatPermissions: Decodable {
|
||||||
let youCanSendMessage: Bool
|
let youCanSendMessage: Bool
|
||||||
let youCanPublicInvitePermission: Bool
|
let youCanPublicInvitePermission: Bool
|
||||||
|
|||||||
@ -1024,25 +1024,42 @@ private struct ChatRowView: View {
|
|||||||
return message.isViewed == true ? Color.accentColor : Color.secondary
|
return message.isViewed == true ? Color.accentColor : Color.secondary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var avatarUrl: URL? {
|
||||||
|
guard let chatData = chat.chatData,
|
||||||
|
let fileId = chatData.avatars?.current?.fileId else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let userId = chatData.userId
|
||||||
|
return URL(string: "\(AppConfig.API_SERVER)/v1/storage/download/avatar/\(userId)?file_id=\(fileId)")
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Circle()
|
if #available(iOS 15.0, *) {
|
||||||
.fill(avatarBackgroundColor)
|
if let url = avatarUrl {
|
||||||
.frame(width: avatarSize, height: avatarSize)
|
AsyncImage(url: url) { phase in
|
||||||
.overlay(
|
switch phase {
|
||||||
Group {
|
case .empty:
|
||||||
if isDeletedUser {
|
placeholderAvatar
|
||||||
Image(systemName: deletedUserSymbolName)
|
case .success(let image):
|
||||||
.symbolRenderingMode(.hierarchical)
|
image
|
||||||
.font(.system(size: avatarSize * 0.45, weight: .semibold))
|
.resizable()
|
||||||
.foregroundColor(avatarTextColor)
|
.aspectRatio(contentMode: .fill)
|
||||||
} else {
|
.frame(width: avatarSize, height: avatarSize)
|
||||||
Text(initial)
|
.clipShape(Circle())
|
||||||
.font(.system(size: avatarSize * 0.5, weight: .semibold))
|
case .failure:
|
||||||
.foregroundColor(avatarTextColor)
|
placeholderAvatar
|
||||||
|
@unknown default:
|
||||||
|
placeholderAvatar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
.frame(width: avatarSize, height: avatarSize)
|
||||||
|
} else {
|
||||||
|
placeholderAvatar
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
placeholderAvatar
|
||||||
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 4) {
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
if let officialName = officialDisplayName {
|
if let officialName = officialDisplayName {
|
||||||
@ -1066,14 +1083,6 @@ private struct ChatRowView: View {
|
|||||||
.foregroundColor(Color.accentColor)
|
.foregroundColor(Color.accentColor)
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if let login = loginDisplay {
|
|
||||||
// Text(login)
|
|
||||||
// .font(.footnote)
|
|
||||||
// .foregroundColor(.secondary)
|
|
||||||
// .lineLimit(1)
|
|
||||||
// .truncationMode(.tail)
|
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
if #available(iOS 16.0, *) {
|
if #available(iOS 16.0, *) {
|
||||||
Text(title)
|
Text(title)
|
||||||
@ -1131,6 +1140,27 @@ private struct ChatRowView: View {
|
|||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var placeholderAvatar: some View {
|
||||||
|
Circle()
|
||||||
|
.fill(avatarBackgroundColor)
|
||||||
|
.frame(width: avatarSize, height: avatarSize)
|
||||||
|
.overlay(
|
||||||
|
Group {
|
||||||
|
if isDeletedUser {
|
||||||
|
Image(systemName: deletedUserSymbolName)
|
||||||
|
.symbolRenderingMode(.hierarchical)
|
||||||
|
.font(.system(size: avatarSize * 0.45, weight: .semibold))
|
||||||
|
.foregroundColor(avatarTextColor)
|
||||||
|
} else {
|
||||||
|
Text(initial)
|
||||||
|
.font(.system(size: avatarSize * 0.5, weight: .semibold))
|
||||||
|
.foregroundColor(avatarTextColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private static func formattedTimestamp(for date: Date) -> String {
|
private static func formattedTimestamp(for date: Date) -> String {
|
||||||
let calendar = Calendar.current
|
let calendar = Calendar.current
|
||||||
let locale = Locale.current
|
let locale = Locale.current
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user