import SwiftUI import DSKit /// Capture-first treatment: quick-capture box + list distinguishing note vs audio. struct MemoListView: View { @Environment(AppModel.self) private var model @State private var draft: String = "" var body: some View { VStack(alignment: .leading, spacing: 0) { HStack(spacing: 8) { TextField("빠른 메모 캡처", text: $draft) .textFieldStyle(.roundedBorder) Button("저장") { let content = draft draft = "" Task { _ = try? await model.client.createMemo(MemoCreate(content: content)) } } .buttonStyle(.bordered) .disabled(draft.isEmpty) } .padding(12) let selection = Binding( get: { model.selectedMemoID }, set: { if let id = $0 { Task { await model.openMemo(id) } } } ) List(model.memoList, selection: selection) { memo in VStack(alignment: .leading, spacing: 3) { HStack(spacing: 6) { if memo.isAudio { Chip("음성", Sage.formatColor("audio")) } if memo.aiEventKind == "task" { Chip("할 일", Sage.amber) } Text(memo.title ?? "메모 \(memo.id)") .font(.callout.weight(.medium)).foregroundStyle(Sage.ink).lineLimit(1) Spacer() if memo.isPinned { Text("고정").font(.caption2).foregroundStyle(Sage.amber) } } Text(memo.content ?? "").font(.caption).foregroundStyle(Sage.muted).lineLimit(2) } .padding(.vertical, 3) } .listStyle(.inset) } .background(Sage.surface) } } struct MemoDetailView: View { let memo: MemoResponse var body: some View { ScrollView { VStack(alignment: .leading, spacing: 12) { Text(memo.title ?? "메모").font(.title2.weight(.bold)).foregroundStyle(Sage.ink) if memo.isAudio { HStack(spacing: 8) { Image(systemName: "waveform") Text("원본 재생 (스캐폴드에서는 비활성)").foregroundStyle(Sage.muted) } .padding(10) .frame(maxWidth: .infinity, alignment: .leading) .background(Sage.surface, in: RoundedRectangle(cornerRadius: 8)) } if let tags = memo.aiTags, !tags.isEmpty { HStack(spacing: 6) { ForEach(tags, id: \.self) { Chip($0, Sage.brand) } } } MarkdownView(memo.content ?? "") } .padding(20) } .background(Sage.surface) } }