From 5e5540d9b1c22e0f670ee92c98694876f101acc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E7=BF=94=E5=AE=87?= Date: Wed, 20 May 2026 10:16:57 +0800 Subject: [PATCH] =?UTF-8?q?fix(water):=20remove=20vertical=20scroll=20?= =?UTF-8?q?=E2=80=94=20fit=20toggles=20+=20hero=20in=20580pt=20panel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WaterView added two toggle rows which pushed content past panel height, so it got wrapped in a ScrollView. That introduced a vertical scroll bar — visually noisy for a tab that should fit at a glance. Compaction strategy: - VStack spacing 14 → 10 (saves ~24pt across 4 gaps) - cupShape 130×160 → 100×130 (saves ~30pt + width breathing room) - Big "X" number font 40 → unchanged (still readable in 100pt cup) - toggleRows (vertical 2-stack of 32pt pills) → toggleRow (horizontal 30pt single line with short labels "🍅 +1" / "整点提醒") - Drop tipText (saves ~30pt) — redundant with the badge text Net height now fits inside the panel without scroll. Co-Authored-By: Claude Opus 4.7 (1M context) --- Sources/ui/WaterView.swift | 89 ++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/Sources/ui/WaterView.swift b/Sources/ui/WaterView.swift index eb0b67e..ce233db 100644 --- a/Sources/ui/WaterView.swift +++ b/Sources/ui/WaterView.swift @@ -11,44 +11,43 @@ struct WaterView: View { @ObservedObject var store: WorkerStore var body: some View { - ScrollView { - VStack(spacing: 14) { - statusBadge + // No ScrollView — panel body sits at ~470pt available and we + // tune everything below to fit: tighter VStack spacing, smaller + // cup hero, toggles on a single row, no tipText. + VStack(spacing: 10) { + statusBadge - cupHero + cupHero - controls + controls - Divider() - .background(WorkerTheme.overlay08) - .padding(.horizontal, 24) + Divider() + .background(WorkerTheme.overlay08) + .padding(.horizontal, 24) - goalRow - toggleRows + goalRow + toggleRow - tipText - - Spacer(minLength: 0) - } - .padding(.top, 8) - .padding(.bottom, 8) + Spacer(minLength: 0) } + .padding(.top, 6) } - // MARK: - Toggle rows (auto-from-pomodoro + hourly reminder) + // MARK: - Toggle row (compact horizontal layout — saves vertical + // space so the whole tab fits without a scroll bar). - private var toggleRows: some View { - VStack(spacing: 8) { + private var toggleRow: some View { + HStack(spacing: 8) { togglePill( icon: "timer", - label: "番茄完成 +1 杯", + label: "🍅 +1", isOn: store.waterAutoFromPomodoro, tint: WorkerTheme.tomato, action: { store.waterSetAutoFromPomodoro(!store.waterAutoFromPomodoro) } ) togglePill( icon: "bell.fill", - label: "整点提醒(9–18 点)", + label: "整点提醒", isOn: store.waterHourlyReminder, tint: WorkerTheme.water, action: { store.waterSetHourlyReminder(!store.waterHourlyReminder) } @@ -57,35 +56,38 @@ struct WaterView: View { .padding(.horizontal, 16) } + /// Compact toggle for the horizontal toggleRow. Icon + short label + + /// inline slim toggle track inside a single capsule. Sized to fit + /// 2 across a 380pt panel with 16pt horizontal padding. private func togglePill(icon: String, label: String, isOn: Bool, tint: Color, action: @escaping () -> Void) -> some View { Button(action: action) { - HStack(spacing: 8) { + HStack(spacing: 6) { Image(systemName: icon) - .font(.system(size: 11, weight: .semibold)) + .font(.system(size: 10, weight: .semibold)) .foregroundColor(isOn ? tint : WorkerTheme.fg55) - .frame(width: 18) Text(label) - .font(.system(size: 11.5, weight: .medium)) + .font(.system(size: 11, weight: .medium)) .foregroundColor(isOn ? WorkerTheme.fgPrimary : WorkerTheme.fg70) - Spacer() - // Slim track-style toggle indicator. + .lineLimit(1) + Spacer(minLength: 4) ZStack(alignment: isOn ? .trailing : .leading) { Capsule() .fill(isOn ? tint.opacity(0.35) : WorkerTheme.overlay08) - .frame(width: 28, height: 16) + .frame(width: 24, height: 14) Circle() .fill(isOn ? tint : WorkerTheme.fg55) - .frame(width: 12, height: 12) + .frame(width: 10, height: 10) .padding(2) } } - .padding(.horizontal, 12) - .frame(height: 32) + .padding(.horizontal, 10) + .frame(maxWidth: .infinity) + .frame(height: 30) .background( - RoundedRectangle(cornerRadius: 10) + RoundedRectangle(cornerRadius: 8) .fill(WorkerTheme.overlay04) .overlay( - RoundedRectangle(cornerRadius: 10) + RoundedRectangle(cornerRadius: 8) .stroke(isOn ? tint.opacity(0.35) : WorkerTheme.overlay08, lineWidth: 0.5) ) ) @@ -120,23 +122,24 @@ struct WaterView: View { // MARK: - Cup hero (tappable) private var cupHero: some View { - VStack(spacing: 12) { + VStack(spacing: 8) { Button(action: { store.waterAddCup() }) { ZStack { - // Water-fill cup illustration. + // Water-fill cup — sized down from 130×160 to fit + // the 380×580 panel without scroll. cupShape - .frame(width: 130, height: 160) + .frame(width: 100, height: 130) } } .buttonStyle(.plain) .help("点击杯子记录一杯水") // Progress dots - HStack(spacing: 6) { + HStack(spacing: 5) { ForEach(0..= store.waterGoal - ? "今天的水喝够了,给自己鼓个掌 👏" - : "保持每小时一杯,工作更高效。") - .font(.system(size: 11)) - .foregroundColor(WorkerTheme.fg45) - .padding(.horizontal, 20) - .multilineTextAlignment(.center) - .frame(maxWidth: .infinity) - } } // MARK: - Cup outline shape