fix: replace daily time text field with native DatePickers

- Daily schedule mode now shows macOS-native hour:minute DatePickers
  instead of a comma-separated text field
- Each time entry has its own picker with a remove button
- '+ Add time' button to add more entries
- Minimum 1 entry enforced (remove disabled when only 1 left)
- No hardcoded defaults — starts empty, user picks their times

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tigerenwork 2026-06-29 21:52:37 +08:00
parent b81d3edf42
commit 9154264ea7
1 changed files with 57 additions and 19 deletions

View File

@ -59,16 +59,31 @@ struct SettingsView: View {
} }
if config.pollIntervalSeconds == -1 { if config.pollIntervalSeconds == -1 {
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 6) {
Text("Refresh at these times (comma-separated, 24h):") Text("Refresh at these times:")
.font(.caption) .font(.caption)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
TextField("08:00, 14:00", text: dailyTimesBinding)
.font(.caption) ForEach(dailyTimeBindings.indices, id: \.self) { index in
.textFieldStyle(.roundedBorder) HStack {
Text("Example: 08:00, 14:00, 20:00") DatePicker("", selection: dailyTimeBindings[index],
.font(.caption2) displayedComponents: .hourAndMinute)
.foregroundStyle(.secondary) .labelsHidden()
Button(action: { removeDailyTime(at: index) }) {
Image(systemName: "minus.circle.fill")
.foregroundStyle(.red)
}
.buttonStyle(.plain)
.disabled(config.dailyRefreshTimes.count <= 1)
}
}
Button(action: addDailyTime) {
Label("Add time", systemImage: "plus.circle")
.font(.caption)
}
.buttonStyle(.plain)
} }
} }
} }
@ -165,18 +180,41 @@ struct SettingsView: View {
.padding(.vertical, 2) .padding(.vertical, 2)
} }
// MARK: - Daily times binding // MARK: - Daily times
private var dailyTimesBinding: Binding<String> { /// Reference date for time-only DatePickers
Binding<String>( private var timeRef: Date {
get: { config.dailyRefreshTimes.joined(separator: ", ") }, Calendar.current.date(from: DateComponents(year: 2000, month: 1, day: 1))!
set: { newValue in }
config.dailyRefreshTimes = newValue
.components(separatedBy: ",") private var dailyTimeBindings: [Binding<Date>] {
.map { $0.trimmingCharacters(in: .whitespaces) } config.dailyRefreshTimes.indices.map { index in
.filter { !$0.isEmpty } Binding<Date>(
} get: {
) let parts = config.dailyRefreshTimes[index].components(separatedBy: ":")
let hour = Int(parts.first ?? "") ?? 0
let minute = Int(parts.last ?? "") ?? 0
return Calendar.current.date(
bySettingHour: hour, minute: minute, second: 0, of: timeRef
) ?? timeRef
},
set: { newDate in
let comps = Calendar.current.dateComponents([.hour, .minute], from: newDate)
let h = String(format: "%02d", comps.hour ?? 0)
let m = String(format: "%02d", comps.minute ?? 0)
config.dailyRefreshTimes[index] = "\(h):\(m)"
}
)
}
}
private func addDailyTime() {
config.dailyRefreshTimes.append("09:00")
}
private func removeDailyTime(at index: Int) {
guard config.dailyRefreshTimes.count > 1 else { return }
config.dailyRefreshTimes.remove(at: index)
} }
// MARK: - Actions // MARK: - Actions