Better attachment placeholders
This commit is contained in:
@@ -88,47 +88,29 @@ struct ImageItemView: View
|
|||||||
@State private var img: NSImage?
|
@State private var img: NSImage?
|
||||||
@Environment(\.xpcClient) var xpcClient
|
@Environment(\.xpcClient) var xpcClient
|
||||||
|
|
||||||
private let imageMaxWidth: CGFloat = 340.0
|
|
||||||
@State private var containerWidth: CGFloat? = nil
|
@State private var containerWidth: CGFloat? = nil
|
||||||
|
|
||||||
var aspectRatio: CGFloat {
|
private var aspectRatio: CGFloat {
|
||||||
if let size = attachment.size, size.height > 0 {
|
attachment.size?.aspectRatio ?? 1.0
|
||||||
return size.width / size.height
|
|
||||||
} else {
|
|
||||||
return 1.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var preferredSize: CGSize {
|
private var preferredWidth: CGFloat {
|
||||||
return CGSize(
|
preferredBubbleWidth(forAttachmentSize: attachment.size, containerWidth: containerWidth, maxWidth: .imageMaxWidth)
|
||||||
width: preferredWidth,
|
|
||||||
height: preferredWidth / aspectRatio
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var preferredWidth: CGFloat {
|
|
||||||
if let containerWidth, let attachmentWidth = attachment.size?.width {
|
|
||||||
return CGFloat.minimum(containerWidth, attachmentWidth)
|
|
||||||
} else if let containerWidth {
|
|
||||||
return containerWidth
|
|
||||||
} else {
|
|
||||||
return 200.0 // fallback
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
BubbleView(sender: sender, date: date) {
|
BubbleView(sender: sender, date: date) {
|
||||||
|
let maxWidth = CGFloat.minimum(.imageMaxWidth, containerWidth ?? .imageMaxWidth)
|
||||||
if let img {
|
if let img {
|
||||||
Image(nsImage: img)
|
Image(nsImage: img)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(
|
.frame(maxWidth: maxWidth)
|
||||||
maxWidth: CGFloat.minimum(imageMaxWidth, containerWidth ?? imageMaxWidth)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(.gray)
|
.fill(.gray.opacity(0.4))
|
||||||
|
.frame(width: preferredWidth, height: preferredWidth / aspectRatio)
|
||||||
|
.frame(maxWidth: maxWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onGeometryChange(for: CGFloat.self,
|
.onGeometryChange(for: CGFloat.self,
|
||||||
@@ -159,19 +141,38 @@ struct PlaceholderImageItemView: View
|
|||||||
{
|
{
|
||||||
let sender: Display.Sender
|
let sender: Display.Sender
|
||||||
let date: Date
|
let date: Date
|
||||||
let size: CGSize
|
let size: CGSize?
|
||||||
|
|
||||||
|
@State private var containerWidth: CGFloat? = nil
|
||||||
|
|
||||||
|
private var aspectRatio: CGFloat {
|
||||||
|
size?.aspectRatio ?? 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
private var preferredWidth: CGFloat {
|
||||||
|
preferredBubbleWidth(forAttachmentSize: size, containerWidth: containerWidth, maxWidth: .imageMaxWidth)
|
||||||
|
}
|
||||||
|
|
||||||
init(sender: Display.Sender, date: Date, size: CGSize?) {
|
init(sender: Display.Sender, date: Date, size: CGSize?) {
|
||||||
self.sender = sender
|
self.sender = sender
|
||||||
self.date = date
|
self.date = date
|
||||||
self.size = size ?? CGSize(width: 250.0, height: 100.0)
|
self.size = size
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
BubbleView(sender: sender, date: date) {
|
BubbleView(sender: sender, date: date) {
|
||||||
Color.gray
|
ZStack {
|
||||||
.frame(width: size.width, height: size.height)
|
Rectangle()
|
||||||
|
.fill(.gray.opacity(0.4))
|
||||||
|
.frame(width: preferredWidth, height: preferredWidth / aspectRatio)
|
||||||
|
.frame(maxWidth: .imageMaxWidth)
|
||||||
|
|
||||||
|
ProgressView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.onGeometryChange(for: CGFloat.self,
|
||||||
|
of: { $0.size.width },
|
||||||
|
action: { containerWidth = $0 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,4 +223,19 @@ fileprivate extension CGFloat {
|
|||||||
static let dominantCornerRadius = 16.0
|
static let dominantCornerRadius = 16.0
|
||||||
static let minorCornerRadius = 4.0
|
static let minorCornerRadius = 4.0
|
||||||
static let minimumBubbleHorizontalPadding = 80.0
|
static let minimumBubbleHorizontalPadding = 80.0
|
||||||
|
static let imageMaxWidth = 380.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension CGSize {
|
||||||
|
var aspectRatio: CGFloat { width / height }
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func preferredBubbleWidth(forAttachmentSize attachmentSize: CGSize?, containerWidth: CGFloat?, maxWidth: CGFloat) -> CGFloat {
|
||||||
|
if let containerWidth, let attachmentWidth = attachmentSize?.width {
|
||||||
|
return .minimum(maxWidth, .minimum(containerWidth, attachmentWidth))
|
||||||
|
} else if let containerWidth {
|
||||||
|
return containerWidth
|
||||||
|
} else {
|
||||||
|
return 200.0 // fallback
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user