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 {
VStack(alignment: .leading, spacing: 4) {
Text("Refresh at these times (comma-separated, 24h):")
VStack(alignment: .leading, spacing: 6) {
Text("Refresh at these times:")
.font(.caption)
.foregroundStyle(.secondary)
TextField("08:00, 14:00", text: dailyTimesBinding)
.font(.caption)
.textFieldStyle(.roundedBorder)
Text("Example: 08:00, 14:00, 20:00")
.font(.caption2)
.foregroundStyle(.secondary)
ForEach(dailyTimeBindings.indices, id: \.self) { index in
HStack {
DatePicker("", selection: dailyTimeBindings[index],
displayedComponents: .hourAndMinute)
.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)
}
// MARK: - Daily times binding
// MARK: - Daily times
private var dailyTimesBinding: Binding<String> {
Binding<String>(
get: { config.dailyRefreshTimes.joined(separator: ", ") },
set: { newValue in
config.dailyRefreshTimes = newValue
.components(separatedBy: ",")
.map { $0.trimmingCharacters(in: .whitespaces) }
.filter { !$0.isEmpty }
}
)
/// Reference date for time-only DatePickers
private var timeRef: Date {
Calendar.current.date(from: DateComponents(year: 2000, month: 1, day: 1))!
}
private var dailyTimeBindings: [Binding<Date>] {
config.dailyRefreshTimes.indices.map { index in
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