feat: iOS Datenebene + Ersteller-Anzeige + Privat-Flag
- Modelle: CalEvent (creator, isPrivate, owner, isGroupEvent, displayColor), LocalCalendar (owned/sharedBy/permission/group), AppSettings (privateEventVisibility, groupVisibleCalendarId), UserProfile (displayName); neue Modelle CalGroup/GroupMember/DirectoryUser/CalendarShare. - API: Profil-Update (Name/Login), Sharing-CRUD, Gruppen-CRUD + combined, Mitglieder-Farbe, iCal Import (multipart) & Export, private-Flag bei Events. - Event-Detail zeigt "Erstellt von" (wenn != ich) + Privat-Hinweis; Editor hat Privat-Toggle (nur lokale Kalender). Login speichert userId. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,11 @@ struct EventDetailSheet: View {
|
||||
|
||||
private var canDelete: Bool { canEdit }
|
||||
|
||||
private var currentUserId: Int? {
|
||||
let id = UserDefaults.standard.integer(forKey: "userId")
|
||||
return id == 0 ? nil : id
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
@@ -91,6 +96,18 @@ struct EventDetailSheet: View {
|
||||
Text(event.source.capitalized)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
if let creator = event.creator, creator.id != currentUserId {
|
||||
HStack {
|
||||
Label("Erstellt von", systemImage: "person")
|
||||
Spacer()
|
||||
Text(creator.displayName)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
if event.isPrivate {
|
||||
Label("Privat", systemImage: "lock")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
if !store.writableCalendars.isEmpty {
|
||||
|
||||
@@ -18,6 +18,7 @@ struct EventEditorSheet: View {
|
||||
@State private var notes = ""
|
||||
@State private var selectedCalendarId: String = ""
|
||||
@State private var color = ""
|
||||
@State private var isPrivate = false
|
||||
@State private var isSaving = false
|
||||
@State private var error = ""
|
||||
|
||||
@@ -75,6 +76,13 @@ struct EventEditorSheet: View {
|
||||
}
|
||||
}
|
||||
|
||||
if selectedCal?.source == "local" {
|
||||
Section {
|
||||
Toggle(L10n.t("event.private", appLang), isOn: $isPrivate)
|
||||
.tint(Color.accentColor)
|
||||
}
|
||||
}
|
||||
|
||||
Section(L10n.t("event.color_section", appLang)) {
|
||||
HStack {
|
||||
Text(L10n.t("event.color", appLang))
|
||||
@@ -140,6 +148,7 @@ struct EventEditorSheet: View {
|
||||
location = ev.location
|
||||
notes = ev.notes
|
||||
color = ev.color ?? ""
|
||||
isPrivate = ev.isPrivate
|
||||
// HA events use "homeassistant-42" in CalEvent but "ha-42" in WritableCalendar
|
||||
if ev.source == "homeassistant" {
|
||||
let num = ev.calendarId.replacingOccurrences(of: "homeassistant-", with: "")
|
||||
@@ -157,6 +166,7 @@ struct EventEditorSheet: View {
|
||||
location = ev.location
|
||||
notes = ev.notes
|
||||
color = ev.color ?? ""
|
||||
isPrivate = ev.isPrivate
|
||||
selectedCalendarId = store.writableCalendars.first?.id ?? ""
|
||||
} else {
|
||||
let cal = Calendar.current
|
||||
@@ -182,7 +192,8 @@ struct EventEditorSheet: View {
|
||||
switch ev.source {
|
||||
case "local":
|
||||
try await api.updateLocalEvent(uid: ev.id, title: title, start: start, end: end,
|
||||
isAllDay: isAllDay, location: location, description: notes, color: colorVal)
|
||||
isAllDay: isAllDay, location: location, description: notes, color: colorVal,
|
||||
isPrivate: isPrivate)
|
||||
case "homeassistant":
|
||||
// No update API exists – delete the old event and recreate with new data.
|
||||
let rawId = ev.calendarId.replacingOccurrences(of: "homeassistant-", with: "")
|
||||
@@ -202,7 +213,8 @@ struct EventEditorSheet: View {
|
||||
case "local":
|
||||
_ = try await api.createLocalEvent(calendarId: cal.numericId, title: title,
|
||||
start: start, end: end, isAllDay: isAllDay,
|
||||
location: location, description: notes, color: colorVal)
|
||||
location: location, description: notes, color: colorVal,
|
||||
isPrivate: isPrivate)
|
||||
case "google":
|
||||
try await api.createGoogleEvent(calendarDbId: cal.numericId, title: title,
|
||||
start: start, end: end, isAllDay: isAllDay,
|
||||
|
||||
Reference in New Issue
Block a user