IceCubesApp/Packages/DesignSystem/Sources/DesignSystem/Views/AvatarView.swift

106 lines
2.5 KiB
Swift
Raw Normal View History

2023-02-19 14:29:07 +00:00
import Nuke
2023-02-21 06:23:42 +00:00
import NukeUI
2023-01-17 10:36:01 +00:00
import Shimmer
import SwiftUI
2022-12-19 11:28:55 +00:00
@MainActor
2022-12-19 11:28:55 +00:00
public struct AvatarView: View {
@Environment(\.redactionReasons) private var reasons
2023-09-18 19:03:52 +00:00
@Environment(Theme.self) private var theme
public enum Size {
case account, status, embed, badge, list, boost
2023-01-17 10:36:01 +00:00
public var size: CGSize {
switch self {
case .account:
return .init(width: 80, height: 80)
case .status:
2023-10-23 17:12:25 +00:00
if ProcessInfo.processInfo.isMacCatalystApp {
return .init(width: 48, height: 48)
}
return .init(width: 40, height: 40)
2022-12-27 06:51:44 +00:00
case .embed:
return .init(width: 34, height: 34)
case .badge:
return .init(width: 28, height: 28)
case .list:
return .init(width: 20, height: 20)
2022-12-29 06:02:10 +00:00
case .boost:
return .init(width: 12, height: 12)
}
}
2023-01-17 10:36:01 +00:00
var cornerRadius: CGFloat {
switch self {
case .badge, .boost, .list:
2023-09-16 12:15:03 +00:00
size.width / 2
default:
2023-09-16 12:15:03 +00:00
4
}
}
}
2023-01-17 10:36:01 +00:00
public let url: URL?
public let size: Size
2023-01-17 10:36:01 +00:00
public init(url: URL?, size: Size = .status) {
2022-12-19 11:28:55 +00:00
self.url = url
self.size = size
2022-12-19 11:28:55 +00:00
}
2023-01-17 10:36:01 +00:00
2022-12-19 11:28:55 +00:00
public var body: some View {
Group {
if reasons == .placeholder {
RoundedRectangle(cornerRadius: size.cornerRadius)
.fill(.gray)
.frame(width: size.size.width, height: size.size.height)
2023-01-17 10:36:01 +00:00
} else {
2023-09-16 12:15:03 +00:00
LazyImage(request: url.map { makeImageRequest(for: $0) }) { state in
if let image = state.image {
image
.resizable()
.aspectRatio(contentMode: .fit)
} else {
AvatarPlaceholderView(size: size)
}
2022-12-19 11:28:55 +00:00
}
.frame(width: size.size.width, height: size.size.height)
2023-01-17 10:36:01 +00:00
}
}
.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 clipShape: some Shape {
switch theme.avatarShape {
case .circle:
2023-09-16 12:15:03 +00:00
AnyShape(Circle())
case .rounded:
2023-09-16 12:15:03 +00:00
AnyShape(RoundedRectangle(cornerRadius: size.cornerRadius))
2022-12-19 11:28:55 +00:00
}
}
}
2023-01-17 10:36:01 +00:00
private struct AvatarPlaceholderView: View {
2023-02-21 06:23:42 +00:00
let size: AvatarView.Size
2023-02-21 06:23:42 +00:00
var body: some View {
if size == .badge {
Circle()
.fill(.gray)
.frame(width: size.size.width, height: size.size.height)
} else {
RoundedRectangle(cornerRadius: size.cornerRadius)
.fill(.gray)
.frame(width: size.size.width, height: size.size.height)
2022-12-23 17:47:19 +00:00
}
2023-02-21 06:23:42 +00:00
}
2022-12-19 11:28:55 +00:00
}