Fix Preview Image Size of StatusRowCardView. (#1904)

* fix preview image size and text spacing

* Fix bg

---------

Co-authored-by: Thomas Ricouard <ricouard77@gmail.com>
This commit is contained in:
Thai D. V 2024-01-19 23:48:52 +07:00 committed by GitHub
parent 328ee2d090
commit 0b7fed2e9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 22 deletions

View file

@ -10,6 +10,8 @@ public struct Card: Codable, Identifiable, Equatable, Hashable {
public let description: String? public let description: String?
public let type: String public let type: String
public let image: URL? public let image: URL?
public let width: CGFloat
public let height: CGFloat
} }
extension Card: Sendable {} extension Card: Sendable {}

View file

@ -45,9 +45,9 @@ public struct StatusRowCardView: View {
} }
} label: { } label: {
if let title = card.title, let url = URL(string: card.url) { if let title = card.title, let url = URL(string: card.url) {
VStack(alignment: .leading) { VStack(alignment: .leading, spacing: 0) {
let sitesWithIcons = ["apps.apple.com", "music.apple.com", "open.spotify.com"] let sitesWithIcons = ["apps.apple.com", "music.apple.com", "open.spotify.com"]
if (UIDevice.current.userInterfaceIdiom == .pad || if (UIDevice.current.userInterfaceIdiom == .pad ||
UIDevice.current.userInterfaceIdiom == .mac || UIDevice.current.userInterfaceIdiom == .mac ||
UIDevice.current.userInterfaceIdiom == .vision), UIDevice.current.userInterfaceIdiom == .vision),
let host = url.host(), sitesWithIcons.contains(host) { let host = url.host(), sitesWithIcons.contains(host) {
@ -94,25 +94,9 @@ public struct StatusRowCardView: View {
@ViewBuilder @ViewBuilder
private func defaultLinkPreview(_ title: String, _ url: URL) -> some View { private func defaultLinkPreview(_ title: String, _ url: URL) -> some View {
if let imageURL = card.image, !isInCaptureMode { if let imageURL = card.image, !isInCaptureMode {
LazyResizableImage(url: imageURL) { state, proxy in DefaultPreviewImage(url: imageURL, originalWidth: card.width, originalHeight: card.height)
let width = imageWidthFor(proxy: proxy)
if let image = state.image {
image
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: imageHeight)
.frame(maxWidth: width)
.clipped()
} else if state.isLoading {
Rectangle()
.fill(Color.gray)
.frame(height: imageHeight)
}
}
// This image is decorative
.accessibilityHidden(true)
.frame(height: imageHeight)
} }
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
Text(title) Text(title)
.font(.scaledHeadline) .font(.scaledHeadline)
@ -129,8 +113,7 @@ public struct StatusRowCardView: View {
.lineLimit(1) .lineLimit(1)
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 10) .padding(10)
.padding(.bottom, 10)
} }
private func iconLinkPreview(_ title: String, _ url: URL) -> some View { private func iconLinkPreview(_ title: String, _ url: URL) -> some View {
@ -173,3 +156,57 @@ public struct StatusRowCardView: View {
} }
} }
} }
struct DefaultPreviewImage: View {
@Environment(Theme.self) private var theme
let url: URL
let originalWidth: CGFloat
let originalHeight: CGFloat
var body: some View {
_Layout(originalWidth: originalWidth, originalHeight: originalHeight) {
LazyResizableImage(url: url) { state, _ in
Rectangle()
.fill(theme.secondaryBackgroundColor)
.overlay {
if let image = state.image {
image.resizable().scaledToFill()
}
}
}
.accessibilityHidden(true) // This image is decorative
.clipped()
}
}
private struct _Layout: Layout {
let originalWidth: CGFloat
let originalHeight: CGFloat
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
guard !subviews.isEmpty else { return CGSize.zero }
return calculateSize(proposal)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
guard let view = subviews.first else { return }
let size = calculateSize(proposal)
view.place(at: bounds.origin, proposal: ProposedViewSize(size))
}
private func calculateSize(_ proposal: ProposedViewSize) -> CGSize {
return switch (proposal.width, proposal.height) {
case (nil, nil):
CGSize(width: originalWidth, height: originalWidth)
case let (nil, .some(height)):
CGSize(width: originalWidth, height: min(height, originalWidth))
case (0, _):
CGSize.zero
case let (.some(width), _):
CGSize(width: width, height: width / originalWidth * originalHeight)
}
}
}
}