mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
refactor(calendar): group calendars by accounts in settings
Calendars in the "Select Calendars" settings section are now grouped by their source account with color indicators, making it possible to distinguish calendars that share the same name across different accounts. Each account group header includes a toggle to select or deselect all calendars in that group.
This commit is contained in:
parent
6bc3af0431
commit
d39c61c475
5 changed files with 74 additions and 10 deletions
|
|
@ -146,6 +146,7 @@ class CalendarService: CalendarServiceProviding {
|
||||||
extension CalendarModel {
|
extension CalendarModel {
|
||||||
init(from calendar: EKCalendar) {
|
init(from calendar: EKCalendar) {
|
||||||
self.init(
|
self.init(
|
||||||
|
accountName: calendar.accountTitle,
|
||||||
id: calendar.calendarIdentifier,
|
id: calendar.calendarIdentifier,
|
||||||
title: calendar.title,
|
title: calendar.title,
|
||||||
color: calendar.color,
|
color: calendar.color,
|
||||||
|
|
@ -267,7 +268,7 @@ extension Priority {
|
||||||
|
|
||||||
// MARK: - Helper Extensions
|
// MARK: - Helper Extensions
|
||||||
|
|
||||||
private extension EKCalendar {
|
extension EKCalendar {
|
||||||
var accountTitle: String {
|
var accountTitle: String {
|
||||||
switch source.sourceType {
|
switch source.sourceType {
|
||||||
case .local, .subscribed, .birthdays:
|
case .local, .subscribed, .birthdays:
|
||||||
|
|
|
||||||
|
|
@ -2905,18 +2905,48 @@ struct CalendarSettings: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Section(header: Text("Select Calendars")) {
|
Section(header: Text("Select Calendars")) {
|
||||||
ForEach(calendarManager.allCalendars, id: \.id) { calendar in
|
let grouped = Dictionary(grouping: calendarManager.allCalendars, by: \.accountName)
|
||||||
Toggle(isOn: Binding(
|
let sortedAccounts = grouped.keys.sorted()
|
||||||
get: { calendarManager.getCalendarSelected(calendar) },
|
|
||||||
set: { isSelected in
|
ForEach(sortedAccounts, id: \.self) { account in
|
||||||
Task {
|
let accountCalendars = grouped[account] ?? []
|
||||||
await calendarManager.setCalendarSelected(calendar, isSelected: isSelected)
|
let allAccountSelected = accountCalendars.allSatisfy { calendarManager.getCalendarSelected($0) }
|
||||||
|
|
||||||
|
Section(header: HStack {
|
||||||
|
Text(account)
|
||||||
|
Spacer()
|
||||||
|
Toggle("", isOn: Binding(
|
||||||
|
get: { allAccountSelected },
|
||||||
|
set: { isSelected in
|
||||||
|
Task {
|
||||||
|
await calendarManager.setCalendarsSelected(accountCalendars, isSelected: isSelected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
))
|
||||||
|
.labelsHidden()
|
||||||
|
.toggleStyle(.switch)
|
||||||
|
.controlSize(.mini)
|
||||||
|
.disabled(!showCalendar)
|
||||||
|
}) {
|
||||||
|
ForEach(accountCalendars, id: \.id) { calendar in
|
||||||
|
Toggle(isOn: Binding(
|
||||||
|
get: { calendarManager.getCalendarSelected(calendar) },
|
||||||
|
set: { isSelected in
|
||||||
|
Task {
|
||||||
|
await calendarManager.setCalendarSelected(calendar, isSelected: isSelected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)) {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
Circle()
|
||||||
|
.fill(Color(calendar.color))
|
||||||
|
.frame(width: 8, height: 8)
|
||||||
|
Text(calendar.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(!showCalendar)
|
||||||
}
|
}
|
||||||
)) {
|
|
||||||
Text(calendar.title)
|
|
||||||
}
|
}
|
||||||
.disabled(!showCalendar)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,36 @@ class CalendarManager: ObservableObject {
|
||||||
lastEventsFetchDate = Date()
|
lastEventsFetchDate = Date()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setCalendarsSelected(_ calendars: [CalendarModel], isSelected: Bool) async {
|
||||||
|
var selectionState = Defaults[.calendarSelectionState]
|
||||||
|
let ids = Set(calendars.map { $0.id })
|
||||||
|
|
||||||
|
switch selectionState {
|
||||||
|
case .all:
|
||||||
|
if !isSelected {
|
||||||
|
let identifiers = Set(allCalendars.map { $0.id }).subtracting(ids)
|
||||||
|
selectionState = .selected(identifiers)
|
||||||
|
}
|
||||||
|
case .selected(var identifiers):
|
||||||
|
if isSelected {
|
||||||
|
identifiers.formUnion(ids)
|
||||||
|
} else {
|
||||||
|
identifiers.subtract(ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
if identifiers.isEmpty || identifiers.count == allCalendars.count {
|
||||||
|
selectionState = .all
|
||||||
|
} else {
|
||||||
|
selectionState = .selected(identifiers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Defaults[.calendarSelectionState] = selectionState
|
||||||
|
updateSelectedCalendars()
|
||||||
|
await updateEvents(force: true)
|
||||||
|
await updateLockScreenEvents(force: true)
|
||||||
|
}
|
||||||
|
|
||||||
func setReminderCompleted(reminderID: String, completed: Bool) async {
|
func setReminderCompleted(reminderID: String, completed: Bool) async {
|
||||||
await calendarService.setReminderCompleted(reminderID: reminderID, completed: completed)
|
await calendarService.setReminderCompleted(reminderID: reminderID, completed: completed)
|
||||||
await updateEvents(force: true)
|
await updateEvents(force: true)
|
||||||
|
|
|
||||||
|
|
@ -302,6 +302,7 @@ final class LockScreenWidgetPreviewManager: ObservableObject {
|
||||||
private func applyCalendarPreviewEvents() {
|
private func applyCalendarPreviewEvents() {
|
||||||
let now = Date()
|
let now = Date()
|
||||||
let reminderCalendar = CalendarModel(
|
let reminderCalendar = CalendarModel(
|
||||||
|
accountName: "Preview",
|
||||||
id: "preview.reminders",
|
id: "preview.reminders",
|
||||||
title: "Reminders",
|
title: "Reminders",
|
||||||
color: .systemBlue,
|
color: .systemBlue,
|
||||||
|
|
@ -327,6 +328,7 @@ final class LockScreenWidgetPreviewManager: ObservableObject {
|
||||||
)
|
)
|
||||||
|
|
||||||
let eventCalendar = CalendarModel(
|
let eventCalendar = CalendarModel(
|
||||||
|
accountName: "Preview",
|
||||||
id: "preview.calendar",
|
id: "preview.calendar",
|
||||||
title: "Calendar",
|
title: "Calendar",
|
||||||
color: .systemOrange,
|
color: .systemOrange,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
struct CalendarModel: Identifiable, Hashable {
|
struct CalendarModel: Identifiable, Hashable {
|
||||||
|
let accountName: String
|
||||||
let id: String
|
let id: String
|
||||||
let title: String
|
let title: String
|
||||||
let color: NSColor
|
let color: NSColor
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue