// // WaterView.swift // 摸鱼侠 plugin v0.1 // // 喝水 — 8 cup target with progress dots, tap big cup to log a sip. // import SwiftUI struct WaterView: View { @ObservedObject var store: WorkerStore var body: some View { ScrollView { VStack(spacing: 14) { statusBadge cupHero controls Divider() .background(WorkerTheme.overlay08) .padding(.horizontal, 24) goalRow toggleRows tipText Spacer(minLength: 0) } .padding(.top, 8) .padding(.bottom, 8) } } // MARK: - Toggle rows (auto-from-pomodoro + hourly reminder) private var toggleRows: some View { VStack(spacing: 8) { togglePill( icon: "timer", label: "番茄完成 +1 杯", isOn: store.waterAutoFromPomodoro, tint: WorkerTheme.tomato, action: { store.waterSetAutoFromPomodoro(!store.waterAutoFromPomodoro) } ) togglePill( icon: "bell.fill", label: "整点提醒(9–18 点)", isOn: store.waterHourlyReminder, tint: WorkerTheme.water, action: { store.waterSetHourlyReminder(!store.waterHourlyReminder) } ) } .padding(.horizontal, 16) } private func togglePill(icon: String, label: String, isOn: Bool, tint: Color, action: @escaping () -> Void) -> some View { Button(action: action) { HStack(spacing: 8) { Image(systemName: icon) .font(.system(size: 11, weight: .semibold)) .foregroundColor(isOn ? tint : WorkerTheme.fg55) .frame(width: 18) Text(label) .font(.system(size: 11.5, weight: .medium)) .foregroundColor(isOn ? WorkerTheme.fgPrimary : WorkerTheme.fg70) Spacer() // Slim track-style toggle indicator. ZStack(alignment: isOn ? .trailing : .leading) { Capsule() .fill(isOn ? tint.opacity(0.35) : WorkerTheme.overlay08) .frame(width: 28, height: 16) Circle() .fill(isOn ? tint : WorkerTheme.fg55) .frame(width: 12, height: 12) .padding(2) } } .padding(.horizontal, 12) .frame(height: 32) .background( RoundedRectangle(cornerRadius: 10) .fill(WorkerTheme.overlay04) .overlay( RoundedRectangle(cornerRadius: 10) .stroke(isOn ? tint.opacity(0.35) : WorkerTheme.overlay08, lineWidth: 0.5) ) ) } .buttonStyle(.plain) } // MARK: - Status private var statusBadge: some View { HStack(spacing: 8) { Circle() .fill(WorkerTheme.water) .frame(width: 8, height: 8) .shadow(color: WorkerTheme.water.opacity(0.7), radius: 4) Text(badgeText) .font(.system(size: 12.5, weight: .semibold)) .foregroundColor(WorkerTheme.fg85) } .padding(.horizontal, 12) .frame(height: 26) .background(Capsule().fill(WorkerTheme.overlay06)) } private var badgeText: String { if store.waterCupsToday >= store.waterGoal { return "今日目标已达成 ✨" } return "今日 \(store.waterCupsToday) / \(store.waterGoal) 杯" } // MARK: - Cup hero (tappable) private var cupHero: some View { VStack(spacing: 12) { Button(action: { store.waterAddCup() }) { ZStack { // Water-fill cup illustration. cupShape .frame(width: 130, height: 160) } } .buttonStyle(.plain) .help("点击杯子记录一杯水") // Progress dots HStack(spacing: 6) { ForEach(0..= store.waterGoal ? "今天的水喝够了,给自己鼓个掌 👏" : "保持每小时一杯,工作更高效。") .font(.system(size: 11)) .foregroundColor(WorkerTheme.fg45) .padding(.horizontal, 20) .multilineTextAlignment(.center) .frame(maxWidth: .infinity) } } // MARK: - Cup outline shape private struct CupOutline: Shape { func path(in rect: CGRect) -> Path { // Slight trapezoid: narrower at the bottom. Straight rim with // a 4pt rounded base. var p = Path() let topInset: CGFloat = 0 let bottomInset: CGFloat = rect.width * 0.08 let radius: CGFloat = 8 // Start top-left. p.move(to: CGPoint(x: rect.minX + topInset, y: rect.minY)) // Top edge. p.addLine(to: CGPoint(x: rect.maxX - topInset, y: rect.minY)) // Right side (sloping inward). p.addLine(to: CGPoint(x: rect.maxX - bottomInset, y: rect.maxY - radius)) // Bottom-right curve. p.addQuadCurve( to: CGPoint(x: rect.maxX - bottomInset - radius, y: rect.maxY), control: CGPoint(x: rect.maxX - bottomInset, y: rect.maxY) ) // Bottom edge. p.addLine(to: CGPoint(x: rect.minX + bottomInset + radius, y: rect.maxY)) // Bottom-left curve. p.addQuadCurve( to: CGPoint(x: rect.minX + bottomInset, y: rect.maxY - radius), control: CGPoint(x: rect.minX + bottomInset, y: rect.maxY) ) // Left side back to top. p.addLine(to: CGPoint(x: rect.minX + topInset, y: rect.minY)) p.closeSubpath() return p } }