diff --git a/Cami.xcodeproj/project.pbxproj b/Cami.xcodeproj/project.pbxproj index 3ca8fa3..4ba7478 100644 --- a/Cami.xcodeproj/project.pbxproj +++ b/Cami.xcodeproj/project.pbxproj @@ -26,7 +26,7 @@ 461817AE2B10BBBD004D692A /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 461817AD2B10BBBD004D692A /* OrderedCollections */; }; 4619D6D62B0CB7740046A7B5 /* DateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4619D6D52B0CB7740046A7B5 /* DateComponents.swift */; }; 4619D6E02B0CDFD10046A7B5 /* DateComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4619D6D52B0CB7740046A7B5 /* DateComponents.swift */; }; - 461CF4A02B035F15003D9293 /* AuthorizationSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461CF49F2B035F15003D9293 /* AuthorizationSet.swift */; }; + 461CF4A02B035F15003D9293 /* PermissionSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461CF49F2B035F15003D9293 /* PermissionSet.swift */; }; 461D69112B0DF2B000A600D7 /* EventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461D69102B0DF2B000A600D7 /* EventView.swift */; }; 461D69132B0E1D6E00A600D7 /* Dates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461D69122B0E1D6E00A600D7 /* Dates.swift */; }; 461D69162B0E22A700A600D7 /* Weeks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461D69152B0E22A700A600D7 /* Weeks.swift */; }; @@ -45,6 +45,11 @@ 46589F2E2B77E86100DB9211 /* EventHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46589F2C2B77E86100DB9211 /* EventHelper.swift */; }; 46688DA02B07658400AD28F4 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46688D9F2B07658400AD28F4 /* Events.swift */; }; 46688DA42B07ACB800AD28F4 /* Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46688DA32B07ACB800AD28F4 /* Bool.swift */; }; + 467344982B79055300470979 /* PermissionAccessButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467344972B79055300470979 /* PermissionAccessButton.swift */; }; + 4673449A2B7905E000470979 /* PermissionSettingsFallbackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467344992B7905E000470979 /* PermissionSettingsFallbackButton.swift */; }; + 4673449C2B79071600470979 /* PermissionAccessSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4673449B2B79071600470979 /* PermissionAccessSection.swift */; }; + 4673449E2B7907F400470979 /* PermissionStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4673449D2B7907F400470979 /* PermissionStatus.swift */; }; + 4673449F2B7907FE00470979 /* PermissionStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4673449D2B7907F400470979 /* PermissionStatus.swift */; }; 467F3DCB2B04C49200F10899 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467F3DCA2B04C49200F10899 /* SettingsView.swift */; }; 467F3DCD2B04C50B00F10899 /* CalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467F3DCC2B04C50B00F10899 /* CalendarView.swift */; }; 467F3DCF2B04C76400F10899 /* ContactHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467F3DCE2B04C76400F10899 /* ContactHelper.swift */; }; @@ -88,7 +93,7 @@ 46B160932B07D90D00A44FBF /* CamiHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46968DB72B0518AB00EA1C8D /* CamiHelper.swift */; }; 46B160942B07D90D00A44FBF /* ReminderHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46968DB42B05188A00EA1C8D /* ReminderHelper.swift */; }; 46B160952B07D91000A44FBF /* TypeAliases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46BDFBFA2AFA8AED00B4C7CB /* TypeAliases.swift */; }; - 46B160962B07D91000A44FBF /* AuthorizationSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461CF49F2B035F15003D9293 /* AuthorizationSet.swift */; }; + 46B160962B07D91000A44FBF /* PermissionSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461CF49F2B035F15003D9293 /* PermissionSet.swift */; }; 46B160972B07D91000A44FBF /* WidgetFamilySet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 460CAB142B0652470059B2F7 /* WidgetFamilySet.swift */; }; 46B160992B07D92F00A44FBF /* CamiWidgetLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 465533282AF4EA7A000B537B /* CamiWidgetLiveActivity.swift */; }; 46B1609C2B07D9A100A44FBF /* CamiWidgetBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 465533262AF4EA7A000B537B /* CamiWidgetBundle.swift */; }; @@ -102,7 +107,6 @@ 46B160A52B07D9A100A44FBF /* CamiWidgetHeaderBirthdays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4675FC622B0379800050F0FC /* CamiWidgetHeaderBirthdays.swift */; }; 46B160A62B07D9A100A44FBF /* CamiWidgetEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461CF4A32B036A80003D9293 /* CamiWidgetEvents.swift */; }; 46B160A72B07D9A100A44FBF /* CamiWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 462861FE2AF7E616004FDC9E /* CamiWidgetView.swift */; }; - 46B5C4672B0EE6E200FAC90A /* SettingsAdditionalInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46B5C4662B0EE6E200FAC90A /* SettingsAdditionalInformation.swift */; }; 46BDFBEF2AFA2CC600B4C7CB /* RoundedBorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46BDFBEE2AFA2CC600B4C7CB /* RoundedBorder.swift */; }; 46BDFBFB2AFA8AED00B4C7CB /* TypeAliases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46BDFBFA2AFA8AED00B4C7CB /* TypeAliases.swift */; }; 46CC7E142AF7944800607AAF /* EKEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46CC7E132AF7944800607AAF /* EKEvent.swift */; }; @@ -156,7 +160,7 @@ 461649392B09B57400F7E7E1 /* MonthWeekRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonthWeekRow.swift; sourceTree = ""; }; 4616493B2B09B58900F7E7E1 /* MonthDayCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonthDayCell.swift; sourceTree = ""; }; 4619D6D52B0CB7740046A7B5 /* DateComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateComponents.swift; sourceTree = ""; }; - 461CF49F2B035F15003D9293 /* AuthorizationSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorizationSet.swift; sourceTree = ""; }; + 461CF49F2B035F15003D9293 /* PermissionSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionSet.swift; sourceTree = ""; }; 461CF4A32B036A80003D9293 /* CamiWidgetEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CamiWidgetEvents.swift; sourceTree = ""; }; 461D69102B0DF2B000A600D7 /* EventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventView.swift; sourceTree = ""; }; 461D69122B0E1D6E00A600D7 /* Dates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dates.swift; sourceTree = ""; }; @@ -180,6 +184,10 @@ 46589F2C2B77E86100DB9211 /* EventHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventHelper.swift; sourceTree = ""; }; 46688D9F2B07658400AD28F4 /* Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Events.swift; sourceTree = ""; }; 46688DA32B07ACB800AD28F4 /* Bool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bool.swift; sourceTree = ""; }; + 467344972B79055300470979 /* PermissionAccessButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionAccessButton.swift; sourceTree = ""; }; + 467344992B7905E000470979 /* PermissionSettingsFallbackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionSettingsFallbackButton.swift; sourceTree = ""; }; + 4673449B2B79071600470979 /* PermissionAccessSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionAccessSection.swift; sourceTree = ""; }; + 4673449D2B7907F400470979 /* PermissionStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionStatus.swift; sourceTree = ""; }; 4675FC5C2B0370520050F0FC /* CamiWidgetEventsByDate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CamiWidgetEventsByDate.swift; sourceTree = ""; }; 4675FC5F2B0370CB0050F0FC /* CamiWidgetEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CamiWidgetEvent.swift; sourceTree = ""; }; 4675FC622B0379800050F0FC /* CamiWidgetHeaderBirthdays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CamiWidgetHeaderBirthdays.swift; sourceTree = ""; }; @@ -207,7 +215,6 @@ 46B1606A2B07D87100A44FBF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 46B1606C2B07D87100A44FBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46B1606D2B07D87100A44FBF /* CamiWidget.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CamiWidget.entitlements; sourceTree = ""; }; - 46B5C4662B0EE6E200FAC90A /* SettingsAdditionalInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsAdditionalInformation.swift; sourceTree = ""; }; 46BDFBED2AF8536700B4C7CB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 46BDFBEE2AFA2CC600B4C7CB /* RoundedBorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedBorder.swift; sourceTree = ""; }; 46BDFBF72AFA607A00B4C7CB /* RemainingTimeComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemainingTimeComponent.swift; sourceTree = ""; }; @@ -408,9 +415,10 @@ children = ( 46BDFBFA2AFA8AED00B4C7CB /* TypeAliases.swift */, 46152C7F2B12463800EF7F39 /* Generics.swift */, - 461CF49F2B035F15003D9293 /* AuthorizationSet.swift */, + 461CF49F2B035F15003D9293 /* PermissionSet.swift */, 460CAB142B0652470059B2F7 /* WidgetFamilySet.swift */, 469853152B0C9B4100A1F35B /* Day.swift */, + 4673449D2B7907F400470979 /* PermissionStatus.swift */, ); path = "Custom Types"; sourceTree = ""; @@ -493,8 +501,10 @@ isa = PBXGroup; children = ( 467F3DCA2B04C49200F10899 /* SettingsView.swift */, - 46B5C4662B0EE6E200FAC90A /* SettingsAdditionalInformation.swift */, 465159292B7133830073544A /* SettingsLinkView.swift */, + 467344972B79055300470979 /* PermissionAccessButton.swift */, + 467344992B7905E000470979 /* PermissionSettingsFallbackButton.swift */, + 4673449B2B79071600470979 /* PermissionAccessSection.swift */, ); path = Settings; sourceTree = ""; @@ -651,6 +661,7 @@ files = ( 469E05932B0919A000F3263D /* CamiWidgetIntent.swift in Sources */, 467F3DCF2B04C76400F10899 /* ContactHelper.swift in Sources */, + 4673449E2B7907F400470979 /* PermissionStatus.swift in Sources */, 467F3DCD2B04C50B00F10899 /* CalendarView.swift in Sources */, 4619D6D62B0CB7740046A7B5 /* DateComponents.swift in Sources */, 46BDFBEF2AFA2CC600B4C7CB /* RoundedBorder.swift in Sources */, @@ -659,7 +670,6 @@ 4616493A2B09B57500F7E7E1 /* MonthWeekRow.swift in Sources */, 46F331422B7812D70060FA8B /* Notifications.swift in Sources */, 460CAB122B0650370059B2F7 /* Rounded.swift in Sources */, - 46B5C4672B0EE6E200FAC90A /* SettingsAdditionalInformation.swift in Sources */, 46968DB52B05188A00EA1C8D /* ReminderHelper.swift in Sources */, 460CAB1E2B06602E0059B2F7 /* Pad.swift in Sources */, 469E05992B0922B600F3263D /* CamiWidgetConfiguration.swift in Sources */, @@ -680,15 +690,17 @@ 46225B012B58970900765185 /* EditEventViewController.swift in Sources */, 46E58C752B75A4E7003B48A0 /* FAQInformationModel.swift in Sources */, 469E058A2B086C3100F3263D /* WidgetCalendarEntity.swift in Sources */, + 4673449C2B79071600470979 /* PermissionAccessSection.swift in Sources */, 46589F2D2B77E86100DB9211 /* EventHelper.swift in Sources */, 46E58C712B75A468003B48A0 /* InformationModalView.swift in Sources */, 469E05832B0848AE00F3263D /* Seconds.swift in Sources */, 460CAB152B0652470059B2F7 /* WidgetFamilySet.swift in Sources */, + 467344982B79055300470979 /* PermissionAccessButton.swift in Sources */, 4651592C2B7134DA0073544A /* ButtonInnerBody.swift in Sources */, 46BDFBFB2AFA8AED00B4C7CB /* TypeAliases.swift in Sources */, 4655330D2AF4EA69000B537B /* CamiApp.swift in Sources */, 460CAB272B06C2EC0059B2F7 /* MiniBadge.swift in Sources */, - 461CF4A02B035F15003D9293 /* AuthorizationSet.swift in Sources */, + 461CF4A02B035F15003D9293 /* PermissionSet.swift in Sources */, 46E58C732B75A4A1003B48A0 /* FAQInformation.swift in Sources */, 46498EC22B76C19C00FC480C /* OnboardingView.swift in Sources */, 469E05802B08172700F3263D /* AllDayStyleEnum.swift in Sources */, @@ -699,6 +711,7 @@ 46688DA42B07ACB800AD28F4 /* Bool.swift in Sources */, 46688DA02B07658400AD28F4 /* Events.swift in Sources */, 4616493C2B09B58900F7E7E1 /* MonthDayCell.swift in Sources */, + 4673449A2B7905E000470979 /* PermissionSettingsFallbackButton.swift in Sources */, 4651592A2B7133830073544A /* SettingsLinkView.swift in Sources */, 460CAB212B0669900059B2F7 /* EdgeInsets.swift in Sources */, 46F331402B7811470060FA8B /* PermissionModel.swift in Sources */, @@ -722,7 +735,7 @@ 46F331442B781B170060FA8B /* PermissionModel.swift in Sources */, 46B160892B07D90A00A44FBF /* Events.swift in Sources */, 46B160A62B07D9A100A44FBF /* CamiWidgetEvents.swift in Sources */, - 46B160962B07D91000A44FBF /* AuthorizationSet.swift in Sources */, + 46B160962B07D91000A44FBF /* PermissionSet.swift in Sources */, 469E05942B0919A800F3263D /* CamiWidgetIntent.swift in Sources */, 46B160932B07D90D00A44FBF /* CamiHelper.swift in Sources */, 46B160992B07D92F00A44FBF /* CamiWidgetLiveActivity.swift in Sources */, @@ -742,6 +755,7 @@ 46B1608F2B07D90A00A44FBF /* Calendars.swift in Sources */, 46B160832B07D90500A44FBF /* Pad.swift in Sources */, 469E059D2B0956B500F3263D /* EventDict.swift in Sources */, + 4673449F2B7907FE00470979 /* PermissionStatus.swift in Sources */, 46589F2E2B77E86100DB9211 /* EventHelper.swift in Sources */, 46B160942B07D90D00A44FBF /* ReminderHelper.swift in Sources */, 46B160842B07D90500A44FBF /* MiniBadge.swift in Sources */, diff --git a/Cami/CamiApp.swift b/Cami/CamiApp.swift index ccc0f9d..34a5fbb 100644 --- a/Cami/CamiApp.swift +++ b/Cami/CamiApp.swift @@ -18,14 +18,11 @@ struct CamiApp: App { var body: some Scene { WindowGroup { - ContentView( - model: model, - perms: perms - ) - .environment(model) - .environmentObject(model) - .environment(perms) - .environmentObject(perms) + ContentView() + .environment(model) + .environmentObject(model) + .environment(perms) + .environmentObject(perms) } } } diff --git a/Cami/Model/FAQInformationModel.swift b/Cami/Model/FAQInformationModel.swift index 2be91fa..eed6b05 100644 --- a/Cami/Model/FAQInformationModel.swift +++ b/Cami/Model/FAQInformationModel.swift @@ -4,7 +4,6 @@ // // Created by Guillaume Coquard on 09/02/24. // -// swiftlint:disable line_length import Foundation @@ -12,11 +11,13 @@ class FAQInformationModel { static let shared: FAQInformationModel = .init() + // swiftlint:disable line_length public let list: [FAQInformation] = [ .init(title: "Why does Cami request full access to Calendars?", description: "iOS requires applications to either request access to calendars in order to be able to edit events OR read and edit events. We need to read every events from every calendars, hence the request for \"Full Access\"."), .init(title: "Why does Cami request access to Contacts?", description: "Cami presents by default the next birthday from your contacts in the top right corner of the widget, therefore Cami needs to access your contacts. If you disable contact access, next birthday won't be displayed."), .init(title: "Why does my widget content seem outdated?", description: "Cami relies completely on iOS features and mechanisms. According to documentation provided by Apple, a widget can be updated every five minutes at most. If you want to force the update of your actual widgets, you just have to open the app and close it right after. This automatically refreshes widgets. If it does not work, you can try long pressing the \"Everything is fine.\" green box on the welcome screen of Cami and then tap on \"Refresh widgets\".") ] + // swiftlint:enable line_length private init() {} } diff --git a/Cami/Model/PermissionModel.swift b/Cami/Model/PermissionModel.swift index 93f9a95..9eb00ed 100644 --- a/Cami/Model/PermissionModel.swift +++ b/Cami/Model/PermissionModel.swift @@ -16,23 +16,23 @@ final class PermissionModel: ObservableObject { private let center: NotificationCenter = .default - private var events: AuthorizationSet = .none { + private var events: PermissionSet = .none { didSet { self.center.post(name: .eventsAccessUpdated, object: nil) } } - private var contacts: AuthorizationSet = .none { + private var contacts: PermissionSet = .none { didSet { self.center.post(name: .contactsAccessUpdated, object: nil) } } - private var reminders: AuthorizationSet = .none { + private var reminders: PermissionSet = .none { didSet { self.center.post(name: .remindersAccessUpdated, object: nil) } } - var global: AuthorizationSet = .none { + var global: PermissionSet = .none { didSet { self.center.post(name: .accessUpdated, object: nil) } @@ -67,7 +67,7 @@ final class PermissionModel: ObservableObject { AuthSet.restrictedReminders } - self.global = AuthorizationSet([ + self.global = PermissionSet([ self.events, self.contacts, self.reminders @@ -110,7 +110,7 @@ extension PermissionModel { } @objc private func updateAccess() { - self.global = AuthorizationSet([ + self.global = PermissionSet([ self.events, self.contacts, self.reminders diff --git a/Cami/View/Calendar/CalendarView.swift b/Cami/View/Calendar/CalendarView.swift index 8b27697..5a15255 100644 --- a/Cami/View/Calendar/CalendarView.swift +++ b/Cami/View/Calendar/CalendarView.swift @@ -21,8 +21,8 @@ struct CalendarView: View { @State private var wasNotAuthorized: Bool = true - @State - private var isSettingsViewPresented: Bool = !Bool(PermissionModel.shared.global.status) + @Binding + var areSettingsPresented: Bool @State private var isCalendarSelectionViewPresented: Bool = false @@ -40,15 +40,8 @@ struct CalendarView: View { .scrollIndicators(.hidden) .scrollPosition(id: $model.position) .sheet(isPresented: $isCalendarSelectionViewPresented) { - CalendarSelectionView().presentationDragIndicator(.visible) - } - .sheet(isPresented: $isSettingsViewPresented) { - SettingsView() - .environmentObject(model) - .environmentObject(perms) - .presentationDragIndicator(Bool(perms.global.status) ? .visible : .hidden) - .presentationDetents([.medium]) - .interactiveDismissDisabled(!Bool(perms.global.status)) + CalendarSelectionView() + .presentationDragIndicator(.visible) } .toolbar { ToolbarItemGroup(placement: .navigation) { @@ -89,7 +82,7 @@ struct CalendarView: View { .labelStyle(.iconOnly) } Button { - isSettingsViewPresented.toggle() + areSettingsPresented.toggle() } label: { Label("Settings", systemImage: "gear") .labelStyle(.iconOnly) @@ -107,7 +100,7 @@ struct CalendarView: View { .labelStyle(.iconOnly) } Button { - isSettingsViewPresented.toggle() + areSettingsPresented.toggle() } label: { Label("Settings", systemImage: "gear") .labelStyle(.iconOnly) diff --git a/Cami/View/Calendar/MonthDayCell.swift b/Cami/View/Calendar/MonthDayCell.swift index 54d6445..1849bb5 100644 --- a/Cami/View/Calendar/MonthDayCell.swift +++ b/Cami/View/Calendar/MonthDayCell.swift @@ -13,9 +13,19 @@ struct MonthDayCell: View { @Environment(ViewModel.self) private var model: ViewModel + @EnvironmentObject + private var perms: PermissionModel + @State private var colors: [Generic]? + private func updateColors() async { + let calendars: Set = await day.lazyInitCalendars() + self.colors = Array(model.calendars.intersection( calendars )) + .asEKCalendars() + .map { Generic(Color(cgColor: $0.cgColor)) } + } + let day: Day var body: some View { @@ -51,10 +61,14 @@ struct MonthDayCell: View { .onAppear { DispatchQueue.main.async { Task { - let calendars: Set = await day.lazyInitCalendars() - colors = Array(model.calendars.intersection( calendars )) - .asEKCalendars() - .map { Generic(Color(cgColor: $0.cgColor)) } + await self.updateColors() + } + } + } + .onChange(of: perms.global) { _, _ in + DispatchQueue.main.async { + Task { + await self.updateColors() } } } diff --git a/Cami/View/ContentView.swift b/Cami/View/ContentView.swift index 6a68696..b939c32 100644 --- a/Cami/View/ContentView.swift +++ b/Cami/View/ContentView.swift @@ -4,7 +4,6 @@ // // Created by Guillaume Coquard on 03/11/23. // -// swiftlint:disable line_length import SwiftUI import EventKit @@ -15,26 +14,27 @@ struct ContentView: View { @Environment(\.scenePhase) var scenePhase: ScenePhase - @Bindable - var model: ViewModel + @EnvironmentObject + private var perms: PermissionModel - @Bindable - var perms: PermissionModel + @EnvironmentObject + private var model: ViewModel @State - private var isModalPresented: Bool = false + private var areSettingsPresented: Bool = false @State - private var isInformationModalPresented: Bool = false + private var areInformationsPresented: Bool = false - @State - private var wasNotAuthorized: Bool = true + private var wasNotAuthorized: Bool = PermissionModel.shared.global.status == .restricted - @State - private var authorized: Bool = PermissionModel.shared.global.status == .authorized + private var authorized: Bool { + PermissionModel.shared.global == .authorized + } - @State - private var restricted: Bool = PermissionModel.shared.global.status != .authorized + private var restricted: Bool { + PermissionModel.shared.global == .restricted + } @AppStorage("accessWorkInProgressFeatures") private var accessWorkInProgressFeatures: Bool = false @@ -43,53 +43,39 @@ struct ContentView: View { Group { if accessWorkInProgressFeatures { NavigationStack(path: $model.path) { - CalendarView() - .navigationDestination(for: Day.self, destination: DayView.init) - .navigationDestination(for: EKEvent.self, destination: EventView.init) + CalendarView( + areSettingsPresented: $areSettingsPresented + ) + .navigationDestination(for: Day.self, destination: DayView.init) + .navigationDestination(for: EKEvent.self, destination: EventView.init) } } else { OnboardingView( - authorized: $authorized, - restricted: $restricted, - isModalPresented: $isModalPresented, - isInformationModalPresented: $isInformationModalPresented + areSettingsPresented: $areSettingsPresented, + areInformationsPresented: $areInformationsPresented ) .frame(maxWidth: 720) } } - .onAppear { - wasNotAuthorized = perms.global.status != .authorized - authorized = perms.global.calendars.status == .authorized - && perms.global.contacts.status == .authorized - restricted = perms.global.calendars.status == .restricted - && perms.global.contacts.status == .restricted + .onChange(of: scenePhase) { _, _ in WidgetCenter.shared.reloadAllTimelines() } - .onChange(of: scenePhase) { _, _ in + .onChange(of: perms.global) { _, _ in + model.reset() WidgetCenter.shared.reloadAllTimelines() } - .sheet(isPresented: $isModalPresented) { + .sheet(isPresented: $areSettingsPresented) { SettingsView() .environmentObject(model) .environmentObject(perms) .presentationDragIndicator(.visible) - .presentationDetents([.large]) + .presentationDetents([.medium, .large]) .presentationContentInteraction(.scrolls) - .onDisappear { - authorized = perms.global.calendars.status == .authorized - && perms.global.contacts.status == .authorized - restricted = perms.global.calendars.status == .restricted - && perms.global.contacts.status == .restricted - if wasNotAuthorized && authorized { - model.reset() - } - } } - .sheet(isPresented: $isInformationModalPresented) { + .sheet(isPresented: $areInformationsPresented) { InformationModalView() .environmentObject(model) - .environmentObject(perms) - .presentationDetents([.large]) + .presentationDetents([.medium, .large]) .presentationDragIndicator(.visible) .presentationContentInteraction(.scrolls) } diff --git a/Cami/View/InformationModalView.swift b/Cami/View/InformationModalView.swift index a30aac7..cd87011 100644 --- a/Cami/View/InformationModalView.swift +++ b/Cami/View/InformationModalView.swift @@ -4,7 +4,6 @@ // // Created by Guillaume Coquard on 09/02/24. // -// swiftlint:disable identifier_name import SwiftUI @@ -24,6 +23,7 @@ struct InformationModalView: View { forKey: information.id ) } + // swiftlint:disable identifier_name let sortedWeights = weights.sorted(by: { a, b in a.value < b.value }) return sortedWeights @@ -31,6 +31,7 @@ struct InformationModalView: View { .map { information in FAQInformationModel.shared.list.first(where: { i in information.key == i.id })! } + // swiftlint:enable identifier_name } } diff --git a/Cami/View/OnboardingView.swift b/Cami/View/OnboardingView.swift index 9802368..eee0789 100644 --- a/Cami/View/OnboardingView.swift +++ b/Cami/View/OnboardingView.swift @@ -11,19 +11,35 @@ import WidgetKit struct OnboardingView: View { @Environment(ViewModel.self) - private var viewModel: ViewModel + private var model: ViewModel - @Binding - var authorized: Bool + @Environment(PermissionModel.self) + private var perms: PermissionModel @Binding - var restricted: Bool + var areSettingsPresented: Bool @Binding - var isModalPresented: Bool + var areInformationsPresented: Bool - @Binding - var isInformationModalPresented: Bool + @AppStorage("accessWorkInProgressFeatures") + private var accessWorkInProgressFeatures = false + + private var authorized: Bool { + return if accessWorkInProgressFeatures { + perms.global == ._beta_authorized + } else { + perms.global.isSuperset(of: .authorized) + } + } + + private var restricted: Bool { + return if accessWorkInProgressFeatures { + !perms.global.isDisjoint(with: .restricted) + } else { + !perms.global.isDisjoint(with: [.restrictedCalendars, .restrictedContacts]) + } + } var body: some View { ScrollView(.vertical) { @@ -46,7 +62,6 @@ struct OnboardingView: View { """) Spacer(minLength: 32) if !authorized { - if restricted { Button { if let url = URL(string: UIApplication.openSettingsURLString) { @@ -64,8 +79,9 @@ struct OnboardingView: View { } } else { Button { - isModalPresented.toggle() + areSettingsPresented.toggle() } label: { + // swiftlint:disable line_length ButtonInnerBody( label: "Grant Access", description: "Cami needs you to grant it access to your calendar and contacts information to work properly.", @@ -74,9 +90,9 @@ struct OnboardingView: View { border: true ) .tint(.orange) + // swiftlint:enable line_length } } - } else { ButtonInnerBody( label: "Everything is fine.", @@ -105,7 +121,7 @@ struct OnboardingView: View { ) Button { - isInformationModalPresented.toggle() + areInformationsPresented.toggle() }label: { ButtonInnerBody( label: "Information", diff --git a/Cami/View/Settings/PermissionAccessButton.swift b/Cami/View/Settings/PermissionAccessButton.swift new file mode 100644 index 0000000..962ba61 --- /dev/null +++ b/Cami/View/Settings/PermissionAccessButton.swift @@ -0,0 +1,29 @@ +// +// PermissionAccessButton.swift +// Cami +// +// Created by Guillaume Coquard on 11/02/24. +// + +import SwiftUI + +struct PermissionAccessButton: View { + + var name: Notification.Name? + + var body: some View { + Button { + if let name = self.name { + NotificationCenter.default.post(name: name, object: nil) + } + } label: { + ButtonInnerBody( + label: "Authorize", + radius: 8, + border: true, + noIcon: true + ) + .tint(.blue) + } + } +} diff --git a/Cami/View/Settings/PermissionAccessSection.swift b/Cami/View/Settings/PermissionAccessSection.swift new file mode 100644 index 0000000..4c9b4f3 --- /dev/null +++ b/Cami/View/Settings/PermissionAccessSection.swift @@ -0,0 +1,82 @@ +// +// PermissionAccessSection.swift +// Cami +// +// Created by Guillaume Coquard on 11/02/24. +// + +import SwiftUI + +struct PermissionAccessSection: View { + + var status: PermissionSet + var title: String + var label: String + var notificationName: Notification.Name + var description: String + var restrictedDescription: String + var radius: Double = 12 + + @AppStorage("accessWorkInProgressFeatures") + private var accessWorkInProgressFeatures: Bool = false + + private var consideringReminders: Bool { + accessWorkInProgressFeatures && !status.isDisjoint(with: [.reminders, .restrictedReminders]) + } + private var areRemindersAuthorized: Bool { + accessWorkInProgressFeatures && status.contains(.reminders) + } + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + HStack(spacing: 8) { + Group { + Text(title) + .font(.title2) + + if status.status == .authorized || areRemindersAuthorized { + Label( + label, + systemImage: "checkmark.circle.fill" + ) + .foregroundStyle(.green) + .labelStyle(.iconOnly) + } + } + .fontWeight(.semibold) + + Spacer() + } + + VStack(alignment: .leading, spacing: 8) { + Text(description) + } + .frame(maxHeight: .infinity) + .font(.caption) + .fontWeight(.medium) + .foregroundStyle(.foreground.secondary) + .multilineTextAlignment(.leading) + + switch status.status { + case .notDetermined: + if consideringReminders { + EmptyView() + } else { + PermissionAccessButton( + name: notificationName + ) + } + case .authorized: + EmptyView() + case .restricted: + PermissionSettingsFallbackButton( + description: restrictedDescription + ) + } + } + .frame(maxHeight: .infinity) + .padding() + .background(.regularMaterial) + .clipShape(RoundedRectangle(cornerRadius: radius)) + } +} diff --git a/Cami/View/Settings/PermissionSettingsFallbackButton.swift b/Cami/View/Settings/PermissionSettingsFallbackButton.swift new file mode 100644 index 0000000..c55b64e --- /dev/null +++ b/Cami/View/Settings/PermissionSettingsFallbackButton.swift @@ -0,0 +1,31 @@ +// +// PermissionSettingsFallbackButton.swift +// Cami +// +// Created by Guillaume Coquard on 11/02/24. +// + +import SwiftUI + +struct PermissionSettingsFallbackButton: View { + + var description: String = "" + var radius: Double? = 8.0 + + var body: some View { + Button { + if let url = URL(string: UIApplication.openSettingsURLString) { + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } + } label: { + ButtonInnerBody( + label: "Restricted", + description: description, + systemImage: "gear", + radius: radius, + border: true + ) + .tint(.red) + } + } +} diff --git a/Cami/View/Settings/SettingsAdditionalInformation.swift b/Cami/View/Settings/SettingsAdditionalInformation.swift deleted file mode 100644 index 20e0c0b..0000000 --- a/Cami/View/Settings/SettingsAdditionalInformation.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// SettingsAdditionalInformation.swift -// Cami -// -// Created by Guillaume Coquard on 23/11/23. -// - -import SwiftUI - -struct SettingsAdditionalInformation: View { - - var title: String - var content: () -> any View - - init(_ title: String, content: @escaping () -> any View ) { - self.title = title - self.content = content - } - - var body: some View { - ScrollView(.vertical) { - VStack(alignment: .leading, spacing: 4) { - Text(title) - .font(.title) - AnyView(content()) - } - } - } -} - -// #Preview { -// SettingsAdditionalInformation() -// } diff --git a/Cami/View/Settings/SettingsView.swift b/Cami/View/Settings/SettingsView.swift index 186e18c..cf32c4b 100644 --- a/Cami/View/Settings/SettingsView.swift +++ b/Cami/View/Settings/SettingsView.swift @@ -12,12 +12,17 @@ struct SettingsView: View { @Environment(\.dismiss) private var dismiss: DismissAction - @Environment(PermissionModel.self) + @EnvironmentObject private var perms: PermissionModel - @State private var calInfo: Bool = false - @State private var remInfo: Bool = false - @State private var conInfo: Bool = false + @State + private var calInfo: Bool = false + + @State + private var remInfo: Bool = false + + @State + private var conInfo: Bool = false @AppStorage("accessWorkInProgressFeatures") private var accessWorkInProgressFeatures = false @@ -25,190 +30,39 @@ struct SettingsView: View { var body: some View { ScrollView(.vertical) { VStack(alignment: .leading, spacing: 16) { - VStack(alignment: .leading, spacing: 16) { - HStack(spacing: 8) { - Group { - Text("Calendars") - .font(.title2) - - if perms.global.calendars.status == .authorized { - Label("Access to calendars authorized", systemImage: "checkmark.circle.fill") - .foregroundStyle(.green) - .labelStyle(.iconOnly) - } - } - .fontWeight(.semibold) - Spacer() - } - - VStack(alignment: .leading, spacing: 8) { - Text("Cami ONLY uses your on-device calendar information to display events in widgets.") - Text("Cami DOES NOT edit or delete or send those information away.") - } - .frame(maxHeight: .infinity) - .font(.caption) - .fontWeight(.medium) - .foregroundStyle(.foreground.secondary) - .multilineTextAlignment(.leading) + // swiftlint:disable line_length + PermissionAccessSection( + status: perms.global.calendars, + title: "Calendars", + label: "Access to calendars authorized", + notificationName: .requestEventsAccess, + description: "Cami ONLY uses your calendars informations to display events in widgets.", + restrictedDescription: "Review Cami access to your calendars." + ) - switch perms.global.calendars.status { - case .notDetermined: - Button { - NotificationCenter.default.post(name: .requestEventsAccess, object: nil) - } label: { - ButtonInnerBody(label: "Authorize", radius: 8, border: true, noIcon: true) - .tint(.blue) - } - case .authorized: - EmptyView() - case .restricted: - Button { - if let url = URL(string: UIApplication.openSettingsURLString) { - UIApplication.shared.open(url, options: [:], completionHandler: nil) - } - } label: { - ButtonInnerBody( - label: "Restricted", - description: "Review Cami access to your calendars.", - systemImage: "gear", - radius: 8, - border: true - ) - .tint(.red) - } - } - } - .frame(maxHeight: .infinity) - .padding() - .background(.regularMaterial) - .clipShape(RoundedRectangle(cornerRadius: 12)) + PermissionAccessSection( + status: perms.global.contacts, + title: "Contacts", + label: "Access to contacts authorized", + notificationName: .requestContactsAccess, + description: "Cami ONLY uses your contacts informations to display birthday information in widgets.", + restrictedDescription: "Review Cami access to your contacts." + ) if accessWorkInProgressFeatures { - VStack(alignment: .leading, spacing: 16) { - HStack(spacing: 8) { - Group { - Text("Reminders") - .font(.title2) - - if perms.global.reminders.status == .authorized { - Label("Access to reminders authorized", systemImage: "checkmark.circle.fill") - .foregroundStyle(.green) - .labelStyle(.iconOnly) - } - } - .fontWeight(.semibold) - - Spacer() - } - - Text("Used to display reminders in the calendar and the widget.") - .font(.caption) - .fontWeight(.medium) - .foregroundStyle(.foreground.secondary) - - switch perms.global.reminders.status { - case .notDetermined: - Button { - NotificationCenter.default.post(name: .requestRemindersAccess, object: nil) - } label: { - ButtonInnerBody(label: "Authorize", radius: 8, border: true, noIcon: true) - .tint(.blue) - } - case .authorized: - EmptyView() - case .restricted: - Button { - if let url = URL(string: UIApplication.openSettingsURLString) { - UIApplication.shared.open(url, options: [:], completionHandler: nil) - } - } label: { - ButtonInnerBody( - label: "Restricted", - description: "Review Cami access to your reminders.", - systemImage: "gear", - radius: 8, - border: true - ) - .tint(.red) - } - } - } - .padding() - .background(.regularMaterial) - .clipShape(RoundedRectangle(cornerRadius: 12)) - } - - VStack(alignment: .leading, spacing: 16) { - HStack(spacing: 8) { - Group { - Text("Contacts") - .font(.title2) - - if perms.global.contacts.status == .authorized { - Label("Access to contacts authorized", systemImage: "checkmark.circle.fill") - .foregroundStyle(.green) - .labelStyle(.iconOnly) - } - } - .fontWeight(.semibold) - - Spacer() - } - - VStack(alignment: .leading, spacing: 8) { - Text("Cami ONLY uses your on-device contacts information to display birthday information in widgets.") - Text("Cami DOES NOT edit or delete or send those information away.") - } - .frame(maxHeight: .infinity) - .font(.caption) - .fontWeight(.medium) - .foregroundStyle(.foreground.secondary) - .multilineTextAlignment(.leading) - - switch perms.global.contacts.status { - case .notDetermined: - Button { - NotificationCenter.default.post(name: .requestContactsAccess, object: nil) - } label: { - ButtonInnerBody( - label: "Authorize", - radius: 8, - border: true, - noIcon: true - ) - .tint(.blue) - } - case .authorized: - EmptyView() - case .restricted: - Button { - if let url = URL(string: UIApplication.openSettingsURLString) { - UIApplication.shared.open( - url, - options: [:], - completionHandler: nil - ) - } - } label: { - ButtonInnerBody( - label: "Restricted", - description: "Review Cami access to your contacts.", - systemImage: "gear", - radius: 8, - border: true - ) - .tint(.red) - } - } + PermissionAccessSection( + status: perms.global.reminders, + title: "Reminders", + label: "Access to reminders authorized", + notificationName: .requestRemindersAccess, + description: "Cami ONLY uses your reminders informations to display them in widgets.", + restrictedDescription: "Review Cami access to your reminders." + ) } - .frame(maxHeight: .infinity) - .padding() - .background(.regularMaterial) - .clipShape(RoundedRectangle(cornerRadius: 12)) + // swiftlint:enable line_length - if perms.global.calendars.status == .authorized - && perms.global.contacts.status == .authorized { + if perms.global.isDisjoint(with: .restricted) { SettingsLinkView(radius: 12) } diff --git a/Multiplatform/Custom Types/AuthorizationSet.swift b/Multiplatform/Custom Types/AuthorizationSet.swift deleted file mode 100644 index 3623732..0000000 --- a/Multiplatform/Custom Types/AuthorizationSet.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// AuthorizationSet.swift -// Cami -// -// Created by Guillaume Coquard on 14/11/23. -// - -import Foundation - -struct AuthorizationSet: Observable, OptionSet { - - let rawValue: Int - - enum Status: Int { - case authorized = 1 - case restricted = 0 - case notDetermined = -1 - } - - static let calendars = AuthorizationSet(rawValue: 1 << 0) - static let reminders = AuthorizationSet(rawValue: 1 << 1) - static let contacts = AuthorizationSet(rawValue: 1 << 2) - - static let restrictedCalendars = AuthorizationSet(rawValue: 1 << 3) - static let restrictedReminders = AuthorizationSet(rawValue: 1 << 4) - static let restrictedContacts = AuthorizationSet(rawValue: 1 << 5) - - var status: Status { - if !(self.isDisjoint(with: .all)) { - return .authorized - } else if !(self.isDisjoint(with: .restricted)) { - return .restricted - } - return .notDetermined - } - - static private func opposite(_ member: AuthorizationSet) -> AuthorizationSet { - switch member { - case .calendars: - .restrictedCalendars - case .reminders: - .restrictedReminders - case .contacts: - .restrictedContacts - case .restrictedCalendars: - .calendars - case .restrictedReminders: - .reminders - case .restrictedContacts: - .contacts - default: - .none - } - } - - mutating func insert(_ newMember: AuthorizationSet) { - let opposite: AuthorizationSet = AuthorizationSet.opposite(newMember) - self = self.contains(opposite) - ? self.symmetricDifference(opposite).union(newMember) - : self.union(newMember) - } - - var calendars: AuthorizationSet { - self.intersection([.calendars, .restrictedCalendars]) - } - - var reminders: AuthorizationSet { - self.intersection([.reminders, .restrictedReminders]) - } - - var contacts: AuthorizationSet { - self.intersection([.contacts, .restrictedContacts]) - } - - private static let restricted: AuthorizationSet = [ - .restrictedCalendars, - .restrictedReminders, - .restrictedContacts - ] - - static let all: AuthorizationSet = [ - .calendars, - .reminders, - .contacts - ] - - static let none: AuthorizationSet = [] -} diff --git a/Multiplatform/Custom Types/PermissionSet.swift b/Multiplatform/Custom Types/PermissionSet.swift new file mode 100644 index 0000000..0dc2742 --- /dev/null +++ b/Multiplatform/Custom Types/PermissionSet.swift @@ -0,0 +1,95 @@ +// +// AuthorizationSet.swift +// Cami +// +// Created by Guillaume Coquard on 14/11/23. +// + +import Foundation + +struct PermissionSet: Observable, OptionSet { + + let rawValue: Int + + static let calendars = PermissionSet(rawValue: 1 << 0) + static let reminders = PermissionSet(rawValue: 1 << 1) + static let contacts = PermissionSet(rawValue: 1 << 2) + + static let restrictedCalendars = PermissionSet(rawValue: 1 << 3) + static let restrictedReminders = PermissionSet(rawValue: 1 << 4) + static let restrictedContacts = PermissionSet(rawValue: 1 << 5) + + var status: PermissionStatus { + if !(self.isDisjoint(with: .authorized)) { + return .authorized + } else if !(self.isDisjoint(with: .restricted)) { + return .restricted + } + return .notDetermined + } + + static private func opposite(_ member: PermissionSet) -> PermissionSet { + switch member { + case .calendars: + .restrictedCalendars + case .reminders: + .restrictedReminders + case .contacts: + .restrictedContacts + case .restrictedCalendars: + .calendars + case .restrictedReminders: + .reminders + case .restrictedContacts: + .contacts + default: + .none + } + } + + mutating func insert(_ newMember: PermissionSet) { + let opposite: PermissionSet = PermissionSet.opposite(newMember) + self = self.contains(opposite) + ? self.symmetricDifference(opposite).union(newMember) + : self.union(newMember) + } + + var calendars: PermissionSet { + self.intersection([.calendars, .restrictedCalendars]) + } + + var reminders: PermissionSet { + self.intersection([.reminders, .restrictedReminders]) + } + + var contacts: PermissionSet { + self.intersection([.contacts, .restrictedContacts]) + } + + static let restricted: PermissionSet = [ + .restrictedCalendars, + .restrictedReminders, + .restrictedContacts + ] + + static let all: PermissionSet = [ + .calendars, + .contacts + ] + + // swiftlint:disable identifier_name + static let _beta_all: PermissionSet = [ + .calendars, + .reminders, + .contacts + ] + // swiftlint:enable identifier_name + + static let authorized: PermissionSet = .all + + // swiftlint:disable identifier_name + static let _beta_authorized: PermissionSet = ._beta_all + // swiftlint:enable identifier_name + + static let none: PermissionSet = [] +} diff --git a/Multiplatform/Custom Types/PermissionStatus.swift b/Multiplatform/Custom Types/PermissionStatus.swift new file mode 100644 index 0000000..8b01b1b --- /dev/null +++ b/Multiplatform/Custom Types/PermissionStatus.swift @@ -0,0 +1,14 @@ +// +// PermissionStatus.swift +// Cami +// +// Created by Guillaume Coquard on 11/02/24. +// + +import Foundation + +enum PermissionStatus: Int { + case authorized = 1 + case restricted = 0 + case notDetermined = -1 +} diff --git a/Multiplatform/Custom Types/TypeAliases.swift b/Multiplatform/Custom Types/TypeAliases.swift index d0b5e4e..0118fc2 100644 --- a/Multiplatform/Custom Types/TypeAliases.swift +++ b/Multiplatform/Custom Types/TypeAliases.swift @@ -14,7 +14,7 @@ typealias Dates = [Date] typealias Weeks = [Dates] typealias Birthdays = Events -typealias AuthSet = AuthorizationSet +typealias AuthSet = PermissionSet typealias Seconds = Int typealias DateRange = ClosedRange diff --git a/Multiplatform/Extensions/Bool.swift b/Multiplatform/Extensions/Bool.swift index a3fd996..bc06417 100644 --- a/Multiplatform/Extensions/Bool.swift +++ b/Multiplatform/Extensions/Bool.swift @@ -12,7 +12,7 @@ extension Bool { self.init(integer > 0) } - init(_ authorizationStatus: AuthorizationSet.Status) { - self.init(authorizationStatus.rawValue) + init(_ permissionStatus: PermissionStatus) { + self.init(permissionStatus.rawValue) } } diff --git a/Multiplatform/Helper/ContactHelper.swift b/Multiplatform/Helper/ContactHelper.swift index c40f5ab..aa646ae 100644 --- a/Multiplatform/Helper/ContactHelper.swift +++ b/Multiplatform/Helper/ContactHelper.swift @@ -17,7 +17,7 @@ struct ContactHelper { /// /// - Returns: The access status as an `AuthorizationSet` object. /// - public static func requestAccess() async -> AuthorizationSet { + public static func requestAccess() async -> PermissionSet { do { return try await Self.store.requestAccess( for: .contacts @@ -34,7 +34,7 @@ struct ContactHelper { /// The status is passed to the callback as an `AuthorizationSet` object. /// public static func requestAccess( - _ callback: @escaping (AuthorizationSet) -> Void + _ callback: @escaping (PermissionSet) -> Void ) { Self.store.requestAccess(for: .contacts) { result, error in if error != nil { diff --git a/Multiplatform/Helper/ReminderHelper.swift b/Multiplatform/Helper/ReminderHelper.swift index 62b5db5..b99afb2 100644 --- a/Multiplatform/Helper/ReminderHelper.swift +++ b/Multiplatform/Helper/ReminderHelper.swift @@ -10,7 +10,7 @@ import EventKit struct ReminderHelper { - public static func requestAccess() async -> AuthorizationSet { + public static func requestAccess() async -> PermissionSet { do { return try await EventHelper.store.requestFullAccessToReminders() ? .reminders @@ -22,7 +22,7 @@ struct ReminderHelper { } public static func requestAccess( - callback: @escaping (AuthorizationSet) -> Void + callback: @escaping (PermissionSet) -> Void ) { EventHelper.store.requestFullAccessToReminders { result, error in if error != nil {