IceCubesApp/IceCubesAppWidgetsExtension/Shared/PostsWidgetView.swift
2024-10-28 10:57:48 +01:00

98 lines
2.3 KiB
Swift

import DesignSystem
import Models
import Network
import SwiftUI
import Timeline
import WidgetKit
struct PostsWidgetEntry: TimelineEntry {
let date: Date
let title: String
let statuses: [Status]
let images: [URL: UIImage]
}
struct PostsWidgetView: View {
var entry: LatestPostsWidgetProvider.Entry
@Environment(\.widgetFamily) var family
@Environment(\.redactionReasons) var redacted
var contentLineLimit: Int {
switch family {
case .systemSmall, .systemMedium:
return 5
default:
return 2
}
}
var body: some View {
VStack(alignment: .leading, spacing: 8) {
headerView
ForEach(entry.statuses) { status in
makeStatusView(status)
}
Spacer()
}
.frame(maxWidth: .infinity)
}
private var headerView: some View {
HStack {
Text(entry.title)
Spacer()
Image(systemName: "cube")
}
.font(.subheadline)
.fontWeight(.bold)
.foregroundStyle(Color("AccentColor"))
}
@ViewBuilder
private func makeStatusView(_ status: Status) -> some View {
if let url = URL(string: status.url ?? "") {
Link(
destination: url,
label: {
VStack(alignment: .leading, spacing: 2) {
makeStatusHeaderView(status)
Text(status.content.asSafeMarkdownAttributedString)
.font(.footnote)
.lineLimit(contentLineLimit)
.fixedSize(horizontal: false, vertical: true)
.padding(.leading, 20)
}
})
}
}
private func makeStatusHeaderView(_ status: Status) -> some View {
HStack(alignment: .center, spacing: 4) {
if let image = entry.images[status.account.avatar] {
Image(uiImage: image)
.resizable()
.frame(width: 16, height: 16)
.clipShape(Circle())
} else {
Circle()
.foregroundStyle(.secondary)
.frame(width: 16, height: 16)
}
HStack(spacing: 0) {
Text(status.account.safeDisplayName)
.foregroundStyle(.primary)
if family != .systemSmall {
Text(" @")
.foregroundStyle(.tertiary)
Text(status.account.username)
.foregroundStyle(.tertiary)
}
Spacer()
}
.font(.footnote)
.fontWeight(.semibold)
.lineLimit(1)
}
}
}