From e008d5d98a2cadd4724fb9b88ce7499c5668b126 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Wed, 15 Jul 2026 06:09:38 +0200 Subject: [PATCH] iOS drawer: compact show/hide-all, single menu button, corner-safe footer Testing feedback: - show-all / hide-all are now side by side (bordered), not two big stacked rows - the busy quick-access strip becomes a single "Einstellungen" button that opens the full menu (which already holds accounts/profile/groups/server/sync/ logout) - extra horizontal + bottom padding so the footer button is not clipped by the iPhone's rounded corners / home indicator Co-Authored-By: Claude Opus 4.8 --- .../Views/Calendar/CalendarDrawer.swift | 49 ++++++------------- .../Views/Calendar/CalendarHostView.swift | 13 +---- .../Views/CalendarFilterContent.swift | 15 ++++-- 3 files changed, 25 insertions(+), 52 deletions(-) diff --git a/Calendarr iOS/Views/Calendar/CalendarDrawer.swift b/Calendarr iOS/Views/Calendar/CalendarDrawer.swift index 65eed21..0fe320e 100644 --- a/Calendarr iOS/Views/Calendar/CalendarDrawer.swift +++ b/Calendarr iOS/Views/Calendar/CalendarDrawer.swift @@ -1,21 +1,14 @@ import SwiftUI -/// Destinations the drawer can open (presented as sheets by the host). -enum DrawerDestination: Int, Identifiable { - case profile, settings, accounts, groups, server - var id: Int { rawValue } -} - -/// The left side drawer: central navigation + calendar visibility + group -/// switching. Replaces the old menu popup and filter sheet. +/// The left side drawer: calendar visibility + group/view switching, plus a +/// single entry into the full menu (Settings/Accounts/Profile/…/Sync/Logout). struct CalendarDrawer: View { let api: CalendarrAPI let store: CalendarStore let groups: [CalGroup] let onSwitchGroup: (CalGroup?) -> Void let onSelectView: (CalViewType) -> Void - let onOpenDestination: (DrawerDestination) -> Void - let onSync: () -> Void + let onOpenMenu: () -> Void let onClose: () -> Void @Environment(AppState.self) private var appState @@ -118,34 +111,20 @@ struct CalendarDrawer: View { .buttonStyle(.plain) } - // MARK: – Nav footer (quick access) + // MARK: – Nav footer (single entry into the full menu) private var navFooter: some View { - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 4) { - navButton(L10n.t("menu.appearance", appLang), "paintpalette") { onOpenDestination(.settings) } - navButton(L10n.t("menu.accounts", appLang), "tray.2") { onOpenDestination(.accounts) } - navButton(L10n.t("menu.profile", appLang), "person.circle") { onOpenDestination(.profile) } - navButton(L10n.t("groups.title", appLang), "person.2") { onOpenDestination(.groups) } - navButton(L10n.t("menu.server", appLang), "server.rack") { onOpenDestination(.server) } - navButton(L10n.t("menu.sync", appLang), "arrow.triangle.2.circlepath") { onSync() } - navButton(L10n.t("menu.logout", appLang), "rectangle.portrait.and.arrow.right", role: .destructive) { - appState.logout() - } - } - .padding(.horizontal, 12).padding(.vertical, 10) - } - } - - private func navButton(_ label: String, _ systemImage: String, role: ButtonRole? = nil, action: @escaping () -> Void) -> some View { - Button(role: role, action: action) { - VStack(spacing: 4) { - Image(systemName: systemImage).font(.system(size: 18)) - Text(label).font(.caption2).lineLimit(1) - } - .frame(width: 64) - .foregroundStyle(role == .destructive ? Color.red : Color.accentColor) + Button { onOpenMenu() } label: { + Label(L10n.t("menu.section.settings", appLang), systemImage: "gearshape") + .font(.body.weight(.medium)) + .frame(maxWidth: .infinity) + .padding(.vertical, 12) } .buttonStyle(.plain) + .foregroundStyle(Color.accentColor) + .padding(.horizontal, 16) + // Extra bottom inset so the button clears the home indicator and the + // screen's rounded corners. + .padding(.bottom, 20) } } diff --git a/Calendarr iOS/Views/Calendar/CalendarHostView.swift b/Calendarr iOS/Views/Calendar/CalendarHostView.swift index 24dd1a3..48e4ae0 100644 --- a/Calendarr iOS/Views/Calendar/CalendarHostView.swift +++ b/Calendarr iOS/Views/Calendar/CalendarHostView.swift @@ -34,7 +34,6 @@ struct CalendarHostView: View { @State private var groups: [CalGroup] = [] @State private var showNewBirthday = false @State private var showDrawer = false - @State private var drawerDestination: DrawerDestination? = nil private var titleString: String { if store.viewType == .month { @@ -63,8 +62,7 @@ struct CalendarHostView: View { api: api, store: store, groups: groups, onSwitchGroup: { g in closeDrawer(); switchGroup(g) }, onSelectView: { vt in store.viewType = vt; closeDrawer() }, - onOpenDestination: { dest in closeDrawer(); drawerDestination = dest }, - onSync: { closeDrawer(); Task { await syncFromServer(force: true) } }, + onOpenMenu: { closeDrawer(); showMenu = true }, onClose: { closeDrawer() } ) .frame(width: drawerWidth) @@ -92,15 +90,6 @@ struct CalendarHostView: View { ) } } - .sheet(item: $drawerDestination) { dest in - switch dest { - case .profile: ProfileView(api: api) - case .settings: SettingsView(api: api) - case .accounts: AccountsView(api: api) - case .groups: GroupsView(api: api) - case .server: ServerView() - } - } } private var drawerWidth: CGFloat { min(UIScreen.main.bounds.width - 40, 360) } diff --git a/Calendarr iOS/Views/CalendarFilterContent.swift b/Calendarr iOS/Views/CalendarFilterContent.swift index b534b79..654e8a2 100644 --- a/Calendarr iOS/Views/CalendarFilterContent.swift +++ b/Calendarr iOS/Views/CalendarFilterContent.swift @@ -33,12 +33,17 @@ struct CalendarFilterContent: View { } else { List { Section { - Button(L10n.t("filter.show_all", appLang)) { - hidden = []; store.setHiddenCalendars(hidden) - } - Button(L10n.t("filter.hide_all", appLang)) { - hidden = allKeys; store.setHiddenCalendars(hidden) + HStack(spacing: 10) { + Button(L10n.t("filter.show_all", appLang)) { + hidden = []; store.setHiddenCalendars(hidden) + } + .buttonStyle(.bordered).frame(maxWidth: .infinity) + Button(L10n.t("filter.hide_all", appLang)) { + hidden = allKeys; store.setHiddenCalendars(hidden) + } + .buttonStyle(.bordered).frame(maxWidth: .infinity) } + .listRowInsets(EdgeInsets(top: 6, leading: 12, bottom: 6, trailing: 12)) } let visibleLocals = localCalendars.filter { !banished.contains(CalendarStore.calendarKey(source: "local", calendarId: "\($0.id)"))