AppStore Link Preview (#1756)

* Custom layout for App Store links

* generalize the logic to include links known to be associated with square icons

- such as Apple Music and Spotify
This commit is contained in:
sh95014 2023-12-17 22:01:46 -08:00 committed by GitHub
parent d755396119
commit 2145bd5971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 90 additions and 37 deletions

View File

@ -46,44 +46,12 @@ public struct StatusRowCardView: View {
} label: {
if let title = card.title, let url = URL(string: card.url) {
VStack(alignment: .leading) {
if let imageURL = card.image, !isInCaptureMode {
LazyResizableImage(url: imageURL) { state, proxy in
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)
let sitesWithIcons = [ "apps.apple.com", "music.apple.com", "open.spotify.com" ]
if let host = url.host(), sitesWithIcons.contains(host) {
iconLinkPreview(title, url)
} else {
defaultLinkPreview(title, url)
}
HStack {
VStack(alignment: .leading, spacing: 6) {
Text(title)
.font(.scaledHeadline)
.lineLimit(3)
if let description = card.description, !description.isEmpty {
Text(description)
.font(.scaledBody)
.foregroundStyle(.secondary)
.lineLimit(3)
}
Text(url.host() ?? url.absoluteString)
.font(.scaledFootnote)
.foregroundColor(theme.tintColor)
.lineLimit(1)
}
Spacer()
}.padding(16)
}
.frame(maxWidth: maxWidth)
.fixedSize(horizontal: false, vertical: true)
@ -114,4 +82,89 @@ public struct StatusRowCardView: View {
}
.buttonStyle(.plain)
}
@MainActor
private func defaultLinkPreview(_ title: String, _ url: URL) -> some View {
Group {
if let imageURL = card.image, !isInCaptureMode {
LazyResizableImage(url: imageURL) { state, proxy in
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)
}
HStack {
VStack(alignment: .leading, spacing: 6) {
Text(title)
.font(.scaledHeadline)
.lineLimit(3)
if let description = card.description, !description.isEmpty {
Text(description)
.font(.scaledBody)
.foregroundStyle(.secondary)
.lineLimit(3)
}
Text(url.host() ?? url.absoluteString)
.font(.scaledFootnote)
.foregroundColor(theme.tintColor)
.lineLimit(1)
}
Spacer()
}.padding(16)
}
}
@MainActor
private func iconLinkPreview(_ title: String, _ url: URL) -> some View {
// ..where the image is known to be a square icon
HStack {
if let imageURL = card.image, !isInCaptureMode {
LazyResizableImage(url: imageURL) { state, proxy in
if let image = state.image {
image
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: imageHeight, height: imageHeight)
.clipped()
} else if state.isLoading {
Rectangle()
.fill(Color.gray)
.frame(width: imageHeight, height: imageHeight)
}
}
// This image is decorative
.accessibilityHidden(true)
.frame(width: imageHeight, height: imageHeight)
}
VStack(alignment: .leading, spacing: 6) {
Text(title)
.font(.scaledHeadline)
.lineLimit(3)
if let description = card.description, !description.isEmpty {
Text(description)
.font(.scaledBody)
.foregroundStyle(.secondary)
.lineLimit(3)
}
Text(url.host() ?? url.absoluteString)
.font(.scaledFootnote)
.foregroundColor(theme.tintColor)
.lineLimit(1)
}.padding(16)
}
}
}