diff --git a/Packages/Models/Sources/Models/Card.swift b/Packages/Models/Sources/Models/Card.swift new file mode 100644 index 00000000..44d511c2 --- /dev/null +++ b/Packages/Models/Sources/Models/Card.swift @@ -0,0 +1,9 @@ +import Foundation + +public struct Card: Codable { + public let url: URL + public let title: String? + public let description: String? + public let type: String + public let image: URL? +} diff --git a/Packages/Models/Sources/Models/Status.swift b/Packages/Models/Sources/Models/Status.swift index 6cd784dd..f4bf4334 100644 --- a/Packages/Models/Sources/Models/Status.swift +++ b/Packages/Models/Sources/Models/Status.swift @@ -10,6 +10,7 @@ public protocol AnyStatus { var repliesCount: Int { get } var reblogsCount: Int { get } var favouritesCount: Int { get } + var card: Card? { get } } public struct Status: AnyStatus, Codable, Identifiable { @@ -23,6 +24,7 @@ public struct Status: AnyStatus, Codable, Identifiable { public let repliesCount: Int public let reblogsCount: Int public let favouritesCount: Int + public let card: Card? public static func placeholder() -> Status { .init(id: UUID().uuidString, @@ -34,7 +36,8 @@ public struct Status: AnyStatus, Codable, Identifiable { mentions: [], repliesCount: 0, reblogsCount: 0, - favouritesCount: 0) + favouritesCount: 0, + card: nil) } public static func placeholders() -> [Status] { @@ -52,4 +55,5 @@ public struct ReblogStatus: AnyStatus, Codable, Identifiable { public let repliesCount: Int public let reblogsCount: Int public let favouritesCount: Int + public let card: Card? } diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index d2e66159..9a4f6032 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -5,6 +5,7 @@ import DesignSystem import Network public struct StatusRowView: View { + @Environment(\.openURL) private var openURL @Environment(\.redactionReasons) private var reasons @EnvironmentObject private var client: Client @EnvironmentObject private var routeurPath: RouterPath @@ -63,6 +64,7 @@ public struct StatusRowView: View { StatusMediaPreviewView(attachements: status.mediaAttachments) .padding(.vertical, 4) } + makeCardView(status: status) } } @@ -83,4 +85,54 @@ public struct StatusRowView: View { } } } + + @ViewBuilder + private func makeCardView(status: AnyStatus) -> some View { + if let card = status.card, let title = card.title { + VStack(alignment: .leading) { + if let imageURL = card.image { + AsyncImage( + url: imageURL, + content: { image in + image.resizable() + .aspectRatio(contentMode: .fill) + }, + placeholder: { + ProgressView() + .frame(maxWidth: 40, maxHeight: 40) + } + ) + } + Spacer() + HStack { + VStack(alignment: .leading, spacing: 6) { + Text(title) + .font(.headline) + .lineLimit(3) + if let description = card.description, !description.isEmpty { + Text(description) + .font(.body) + .foregroundColor(.gray) + .lineLimit(3) + } else { + Text(card.url.absoluteString) + .font(.body) + .foregroundColor(.gray) + .lineLimit(3) + } + } + Spacer() + }.padding(8) + } + .background(Color.gray.opacity(0.15)) + .cornerRadius(16) + .overlay( + RoundedRectangle(cornerRadius: 16) + .stroke(.gray.opacity(0.35), lineWidth: 1) + ) + .onTapGesture { + openURL(card.url) + } + } + } }