oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1import SwiftUI
2
3struct SheetPreview: Decodable, Hashable, Sendable {
4 let Rows: Int
5 let Cols: Int
6 let Empty: Bool
7 let Cells: [SheetPreviewCell]?
8}
9struct SheetPreviewCell: Decodable, Hashable, Sendable {
10 let R: Int
11 let C: Int
12 let Fill: String
13 let Bold: Bool
14}
15
16/// Renders shape metadata only: no cell text, web view, or external image fetch.
17struct SheetThumbnail: View {
18 private let preview: SheetPreview?
19 var width: CGFloat = 52
20 var height: CGFloat = 68
21 init(_ preview: SheetPreview?, width: CGFloat = 52, height: CGFloat = 68) { self.preview = preview; self.width = width; self.height = height }
22
23 var body: some View {
24 Canvas { context, size in
25 let border = Path(roundedRect: CGRect(origin: .zero, size: size).insetBy(dx: 0.5, dy: 0.5), cornerRadius: 3)
26 context.fill(border, with: .color(.primary.opacity(0.025)))
27 context.stroke(border, with: .color(.secondary.opacity(0.3)), lineWidth: 1)
28 guard let preview, !preview.Empty, (1...12).contains(preview.Rows),
29 (1...8).contains(preview.Cols) else { return }
30 let width = (size.width - 8) / Double(preview.Cols)
31 let height = (size.height - 8) / Double(preview.Rows)
32 for cell in (preview.Cells ?? []).prefix(96) {
33 guard (0..<preview.Rows).contains(cell.R), (0..<preview.Cols).contains(cell.C) else { continue }
34 let rect = CGRect(x: 4 + Double(cell.C) * width, y: 4 + Double(cell.R) * height, width: width, height: height)
35 if !cell.Fill.isEmpty {
36 let fill = cell.Fill
37 let isHex = fill.count == 7 && fill.hasPrefix("#") && UInt64(fill.dropFirst(), radix: 16) != nil
38 context.fill(Path(rect), with: .color(isHex ? Color(hex: fill) : .accentColor.opacity(0.15)))
39 }
40 let mark = CGRect(x: rect.minX + width * 0.15, y: rect.minY + height * 0.35,
41 width: width * 0.7, height: height * 0.3)
42 context.fill(Path(roundedRect: mark, cornerRadius: 0.5),
43 with: .color(.secondary.opacity(cell.Bold ? 0.8 : 0.4)))
44 }
45 }
46 .frame(width: width, height: height)
47 .accessibilityHidden(true)
48 }
49}
50