feat(sharing): hidden-profile toggle + hide non-sharing group members

- UserProfile decodes directory_hidden; updateProfile() sends it; Settings has
  a "hide my profile" toggle (excludes you from share/group pickers).
- GroupMember decodes shares_calendar; the group filter list now only shows
  members who actually share a calendar (no phantom empty rows).
- Robust custom decoders (decodeIfPresent) for the new fields.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-06 18:45:49 +02:00
parent 3f5de5cdfa
commit 32cb8e1689
5 changed files with 46 additions and 3 deletions

View File

@@ -223,6 +223,7 @@ struct UserProfile: Codable {
let isAdmin: Bool
let hasAvatar: Bool
let totpEnabled: Bool
var directoryHidden: Bool = false
enum CodingKeys: String, CodingKey {
case id, username, email
@@ -230,6 +231,19 @@ struct UserProfile: Codable {
case isAdmin = "is_admin"
case hasAvatar = "has_avatar"
case totpEnabled = "totp_enabled"
case directoryHidden = "directory_hidden"
}
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
id = try c.decode(Int.self, forKey: .id)
username = try c.decode(String.self, forKey: .username)
displayName = try c.decodeIfPresent(String.self, forKey: .displayName)
email = try c.decodeIfPresent(String.self, forKey: .email)
isAdmin = try c.decodeIfPresent(Bool.self, forKey: .isAdmin) ?? false
hasAvatar = try c.decodeIfPresent(Bool.self, forKey: .hasAvatar) ?? false
totpEnabled = try c.decodeIfPresent(Bool.self, forKey: .totpEnabled) ?? false
directoryHidden = try c.decodeIfPresent(Bool.self, forKey: .directoryHidden) ?? false
}
}
@@ -258,9 +272,20 @@ struct GroupMember: Codable, Identifiable {
let displayName: String?
var role: String
var color: String?
var sharesCalendar: Bool = true
enum CodingKeys: String, CodingKey {
case id, role, color
case displayName = "display_name"
case sharesCalendar = "shares_calendar"
}
init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
id = try c.decode(Int.self, forKey: .id)
displayName = try c.decodeIfPresent(String.self, forKey: .displayName)
role = try c.decodeIfPresent(String.self, forKey: .role) ?? "member"
color = try c.decodeIfPresent(String.self, forKey: .color)
sharesCalendar = try c.decodeIfPresent(Bool.self, forKey: .sharesCalendar) ?? true
}
}