Widget änderungen, sync änderungen

This commit is contained in:
Scarriffle
2026-05-28 21:43:18 +02:00
parent 4125bfc728
commit e71fd7512f
9 changed files with 726 additions and 57 deletions

View File

@@ -4,11 +4,16 @@ struct EventDetailSheet: View {
let event: CalEvent
let api: CalendarrAPI
let store: CalendarStore
let onDone: (CalEvent?) async -> Void
/// Called when the sheet should close.
/// - `editEvent`: non-nil when the user wants to edit this event
/// - `forceReload`: true when server data changed (create/copy) and the
/// caller must bypass the cache to fetch fresh events
let onDone: (_ editEvent: CalEvent?, _ forceReload: Bool) async -> Void
@Environment(\.dismiss) var dismiss
@State private var showDeleteConfirm = false
@State private var isDeleting = false
@State private var showCopySheet = false
private let timeFmt: DateFormatter = {
let f = DateFormatter()
@@ -92,6 +97,16 @@ struct EventDetailSheet: View {
}
}
if !store.writableCalendars.isEmpty {
Section {
Button {
showCopySheet = true
} label: {
Label("Termin kopieren", systemImage: "doc.on.doc")
}
}
}
if canDelete {
Section {
Button(role: .destructive) {
@@ -110,13 +125,13 @@ struct EventDetailSheet: View {
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Schliessen") {
Task { await onDone(nil) }
Task { await onDone(nil, false) }
}
}
if canEdit {
ToolbarItem(placement: .primaryAction) {
Button("Bearbeiten") {
Task { await onDone(event) }
Task { await onDone(event, false) }
}
}
}
@@ -129,6 +144,18 @@ struct EventDetailSheet: View {
} message: {
Text("\"\(event.title)\" wird dauerhaft gelöscht.")
}
.sheet(isPresented: $showCopySheet) {
EventEditorSheet(
api: api,
store: store,
initialDate: event.startDate,
editingEvent: nil,
copyFrom: event
) {
// Copy created a new server-side event force reload so it appears
await onDone(nil, true)
}
}
}
}
@@ -149,7 +176,7 @@ struct EventDetailSheet: View {
// Optimistically drop it from the cache so it vanishes immediately,
// regardless of how long the source takes to propagate the delete.
store.removeCachedEvent(id: event.id)
await onDone(nil)
await onDone(nil, false)
} catch {
isDeleting = false
}

View File

@@ -5,6 +5,7 @@ struct EventEditorSheet: View {
let store: CalendarStore
let initialDate: Date
let editingEvent: CalEvent?
let copyFrom: CalEvent?
let onSaved: () async -> Void
@Environment(\.dismiss) var dismiss
@@ -21,6 +22,7 @@ struct EventEditorSheet: View {
@State private var error = ""
private var isEditing: Bool { editingEvent != nil }
private var isCopying: Bool { copyFrom != nil && editingEvent == nil }
private var selectedCal: WritableCalendar? {
store.writableCalendars.first { $0.id == selectedCalendarId }
@@ -96,9 +98,11 @@ struct EventEditorSheet: View {
}
}
}
.navigationTitle(isEditing
? L10n.t("event.edit_title", appLang)
: L10n.t("event.new_title", appLang))
.navigationTitle(
isEditing ? L10n.t("event.edit_title", appLang) :
isCopying ? L10n.t("event.copy_title", appLang) :
L10n.t("event.new_title", appLang)
)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
@@ -116,6 +120,12 @@ struct EventEditorSheet: View {
}
}
.onAppear { setup() }
.onChange(of: startDate) { oldStart, newStart in
guard newStart >= endDate else { return }
let duration = endDate.timeIntervalSince(oldStart)
let minDuration: TimeInterval = isAllDay ? 86400 : 3600
endDate = newStart.addingTimeInterval(max(duration, minDuration))
}
}
private func setup() {
@@ -128,6 +138,15 @@ struct EventEditorSheet: View {
notes = ev.notes
color = ev.color ?? ""
selectedCalendarId = ev.calendarId
} else if let ev = copyFrom {
title = ev.title
isAllDay = ev.isAllDay
startDate = ev.startDate
endDate = ev.endDate
location = ev.location
notes = ev.notes
color = ev.color ?? ""
selectedCalendarId = store.writableCalendars.first?.id ?? ""
} else {
let cal = Calendar.current
startDate = cal.date(bySettingHour: cal.component(.hour, from: initialDate),