Skip to content

Commit fbb88cf

Browse files
authored
Release 1.5.8 (#138)
* Add API boilerplate for new calendar and reminder Addresses iOS 17 API changes * Abstract calendar/reminder into event manager * Fix obsolete API mark and revise message * Squashed commit of the following: commit 5ecef99e3b2ef04a2a05b34509e8a449031d92c4 Author: Jevon Mao <woodburyjevonmao@gmail.com> Date: Tue Aug 8 20:13:01 2023 -0400 Add documentation snippet for permission managers commit 44e3f41 Author: Jevon Mao <woodburyjevonmao@gmail.com> Date: Mon Aug 7 14:41:46 2023 -0400 Implement custom permission description color (#137) commit f3ed32c Author: Jevon Mao <woodburyjevonmao@gmail.com> Date: Mon Aug 7 12:58:42 2023 -0400 Disable stale check CICD * Erase type for custom foreground color * Add NSLog warning deprecated EventKit permissisons * Remove available limitation
1 parent 44e3f41 commit fbb88cf

File tree

32 files changed

+325
-230
lines changed

32 files changed

+325
-230
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ let permissionsTargets: [Target] = [
112112
let package = Package(
113113
name: "PermissionsSwiftUI",
114114
defaultLocalization: "en",
115-
platforms: [.iOS(.v13)],
115+
platforms: [.iOS(.v13), .macOS(.v10_15)],
116116
products: permissionsTargets.map{Product.library(name: $0.name, targets: [$0.name])},
117117
dependencies: [
118118
// Dependencies declare other packages that this package depends on.

Sources/CorePermissionsSwiftUI/Model/PermissionManagers/PermissionManagerProctocol.swift renamed to Sources/CorePermissionsSwiftUI/Model/PermissionManagers/AuthorizationStatus.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//
2-
// PermissionManagerProctocol.swift
3-
//
2+
// AuthorizationStatus.swift
3+
//
44
//
55
// Created by Jevon Mao on 2/18/21.
66
//
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// EventPermissionManager.swift
3+
// PermissionsSwiftUI-Example
4+
//
5+
// Created by Jevon Mao on 8/26/23.
6+
//
7+
8+
import Foundation
9+
import EventKit
10+
11+
open class EventPermissionManager: PermissionManager {
12+
public init(requestedAccessLevel: AccessLevel = .legacy) {
13+
self.requestedAccessLevel = requestedAccessLevel
14+
if requestedAccessLevel == .legacy {
15+
NSLog("[PermissionsSwiftUI]: WARNING! Using legacy calendar or reminder permission, which will NOT work in iOS 17 and always return denied due to Apple EventKit API changes. Learn more: https://developer.apple.com/documentation/eventkit/accessing_the_event_store")
16+
}
17+
}
18+
19+
20+
public var requestedAccessLevel: AccessLevel
21+
public let eventStore = EKEventStore()
22+
open var entityType: EKEntityType {
23+
get {
24+
preconditionFailure("This property must be overridden.")
25+
}
26+
}
27+
28+
public enum AccessLevel {
29+
case writeOnly
30+
case full
31+
case legacy
32+
}
33+
34+
public override var authorizationStatus: AuthorizationStatus {
35+
switch EKEventStore.authorizationStatus(for: entityType){
36+
case .authorized:
37+
return .authorized
38+
case .notDetermined:
39+
return .notDetermined
40+
default:
41+
return .denied
42+
}
43+
}
44+
45+
public func requestLegacyPermission( _ completion: @escaping (Bool, Error?) -> Void) {
46+
eventStore.requestAccess(to: entityType, completion: {
47+
(accessGranted: Bool, error: Error?) in
48+
DispatchQueue.main.async {
49+
completion(accessGranted, error)
50+
}
51+
})
52+
}
53+
54+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//
2+
// PermissionManager.swift
3+
// PermissionsSwiftUI-Example
4+
//
5+
// Created by Jevon Mao on 8/26/23.
6+
//
7+
8+
import Foundation
9+
10+
/**
11+
A Permission Manager object that contains properties and functions related to a specific permission. Will be subclassed by any permission type.
12+
13+
- warning: `PermissionManager` shoud never be referenced directly and used. It serves as an abstract interface for PermissionsSwiftUI's many permission modules.
14+
*/
15+
open class PermissionManager: NSObject, Identifiable {
16+
///Holds the permission UI component, containing UI elements like text and image
17+
open var permissionComponent: JMPermission {
18+
get {
19+
preconditionFailure("This property must be overridden.")
20+
}
21+
}
22+
///The type of permission
23+
open var permissionType: PermissionType {
24+
preconditionFailure("This property must be overridden.")
25+
}
26+
27+
///The authorization status of the permission
28+
open var authorizationStatus: AuthorizationStatus {
29+
get {
30+
preconditionFailure("This property must be overridden.")
31+
}
32+
}
33+
34+
#if PERMISSIONSWIFTUI_HEALTH
35+
36+
///Holds the health permission subcategories, in case of health permission type subclass
37+
open var healthPermissionCategories: Set<HKSampleType>?
38+
39+
/**
40+
Creates a new `PermissionManager` for health permission.
41+
42+
- parameters:
43+
- healthPermissionCategories: Subcategory permissions of health permission to request
44+
*/
45+
public init(_ healthPermissionCategories: Set<HKSampleType>? = nil) {
46+
self.healthPermissionCategories = healthPermissionCategories
47+
}
48+
#else
49+
///Creates a new `PermissionManager` for any type of child implemented permission
50+
public override init() {}
51+
#endif
52+
53+
/**
54+
Requests authorization for the current implemented type of permission.
55+
56+
- parameters:
57+
- completion: Returns back whether the permission authorization is granted, and any errors
58+
*/
59+
open func requestPermission(completion: @escaping (Bool, Error?) -> Void) {
60+
preconditionFailure("This method must be overridden.")
61+
}
62+
}

Sources/CorePermissionsSwiftUI/Model/PermissionType/PermissionType.swift

Lines changed: 57 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -25,117 +25,65 @@ public enum PermissionType: Hashable, Equatable {
2525
lhs.rawValue == rhs.rawValue ? true : false
2626
}
2727

28+
///The `location` permission allows the device's positoin to be tracked
29+
case location
30+
31+
///Used to access the user's photo library
32+
case photo
33+
34+
///The `notification` permission allows the iOS system to receive notification from app
35+
case notification
36+
37+
///Permission that allows app to access device's bluetooth technologies
38+
case bluetooth
39+
40+
///Permission that allows Siri and Maps to communicate with your app
41+
case siri
42+
43+
///In order for app to track user's data across apps and websites, the tracking permission is needed
44+
@available(iOS 14, tvOS 14, *) case tracking
45+
#if !os(tvOS)
2846
/**
29-
A Permission Manager object that contains properties and functions related to a specific permission. Will be subclassed by any permission type.
30-
31-
- warning: `PermissionManager` shoud never be referenced directly and used. It serves as an abstract interface for PermissionsSwiftUI's many permission modules.
47+
Permission that allows app to access healthkit information
48+
49+
- Note: Extensive Info.plist values and configurations are required for HealthKit authorization. Please see Apple Developer [website](https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data) for details. \n
50+
51+
For example, passing in a `Set` of `HKSampleType`:
52+
```
53+
[.health(categories: .init(readAndWrite: Set([HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!])))]
54+
```
3255
*/
33-
open class PermissionManager: NSObject, Identifiable {
34-
///Holds the permission UI component, containing UI elements like text and image
35-
open var permissionComponent: JMPermission {
36-
get {
37-
preconditionFailure("This property must be overridden.")
38-
}
39-
}
40-
///The type of permission
41-
open var permissionType: PermissionType {
42-
preconditionFailure("This property must be overridden.")
43-
}
44-
45-
///The authorization status of the permission
46-
open var authorizationStatus: AuthorizationStatus {
47-
get {
48-
preconditionFailure("This property must be overridden.")
49-
}
50-
}
51-
52-
#if PERMISSIONSWIFTUI_HEALTH
53-
54-
///Holds the health permission subcategories, in case of health permission type subclass
55-
open var healthPermissionCategories: Set<HKSampleType>?
56-
57-
/**
58-
Creates a new `PermissionManager` for health permission.
59-
60-
- parameters:
61-
- healthPermissionCategories: Subcategory permissions of health permission to request
62-
*/
63-
public init(_ healthPermissionCategories: Set<HKSampleType>? = nil) {
64-
self.healthPermissionCategories = healthPermissionCategories
65-
}
66-
#else
67-
///Creates a new `PermissionManager` for any type of child implemented permission
68-
public override init() {}
69-
#endif
70-
71-
/**
72-
Requests authorization for the current implemented type of permission.
73-
74-
- parameters:
75-
- completion: Returns back whether the permission authorization is granted, and any errors
76-
*/
77-
open func requestPermission(completion: @escaping (Bool, Error?) -> Void) {
78-
preconditionFailure("This method must be overridden.")
79-
}
80-
}
81-
///The `location` permission allows the device's positoin to be tracked
82-
case location
83-
84-
///Used to access the user's photo library
85-
case photo
86-
87-
///The `notification` permission allows the iOS system to receive notification from app
88-
case notification
89-
90-
///Permission that allows app to access device's bluetooth technologies
91-
case bluetooth
92-
93-
///Permission that allows Siri and Maps to communicate with your app
94-
case siri
95-
96-
///In order for app to track user's data across apps and websites, the tracking permission is needed
97-
@available(iOS 14, tvOS 14, *) case tracking
98-
#if !os(tvOS)
99-
/**
100-
Permission that allows app to access healthkit information
101-
102-
- Note: Extensive Info.plist values and configurations are required for HealthKit authorization. Please see Apple Developer [website](https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data) for details. \n
103-
104-
For example, passing in a `Set` of `HKSampleType`:
105-
```
106-
[.health(categories: .init(readAndWrite: Set([HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!])))]
107-
```
108-
*/
109-
case health
110-
#endif
111-
112-
///The `locationAlways` permission provides location data even if app is in background
113-
@available(tvOS, unavailable) case locationAlways
114-
115-
///Permission allows developers to interact with the device microphone
116-
@available(tvOS, unavailable) case microphone
117-
118-
///Permission that allows developers to interact with on-device camera
119-
@available(tvOS, unavailable) case camera
120-
121-
///A permission that allows developers to read & write to device contacts
122-
@available(tvOS, unavailable) case contacts
123-
124-
///Permission that give app access to motion and fitness related sensor data
125-
@available(tvOS, unavailable) case motion
126-
127-
///The `reminders` permission is needed to interact with device reminders
128-
@available(tvOS, unavailable) case reminders
129-
130-
///Permission that allows app to read & write to device calendar
131-
@available(tvOS, unavailable) case calendar
132-
133-
///Permission that allows app to use speech recognition
134-
@available(tvOS, unavailable) case speech
135-
136-
///Permission that allows app to control audio playback of the device
137-
@available(tvOS, unavailable) case music
138-
56+
case health
57+
#endif
58+
59+
///The `locationAlways` permission provides location data even if app is in background
60+
@available(tvOS, unavailable) case locationAlways
61+
62+
///Permission allows developers to interact with the device microphone
63+
@available(tvOS, unavailable) case microphone
64+
65+
///Permission that allows developers to interact with on-device camera
66+
@available(tvOS, unavailable) case camera
67+
68+
///A permission that allows developers to read & write to device contacts
69+
@available(tvOS, unavailable) case contacts
70+
71+
///Permission that give app access to motion and fitness related sensor data
72+
@available(tvOS, unavailable) case motion
73+
74+
///Permission that allows app to read & write to device reminder before iOS 17
75+
@available(tvOS, unavailable, deprecated: 16.0, obsoleted: 17.0)
76+
case reminders
77+
78+
///Permission that allows app to read & write to device calendar before iOS 17
79+
@available(tvOS, unavailable, deprecated: 16.0, obsoleted: 17.0)
80+
case calendar
81+
82+
///Permission that allows app to use speech recognition
83+
@available(tvOS, unavailable) case speech
84+
85+
///Permission that allows app to control audio playback of the device
86+
@available(tvOS, unavailable) case music
13987
}
14088

14189

Sources/CorePermissionsSwiftUI/Model/Structs/FilterPermissions.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import Foundation
1010
@available(iOS 13.0, tvOS 13.0, *)
1111
struct FilterPermissions {
1212
// Based on struct boolean property, dependent on memory
13-
static func filterForUnauthorized(with permissions: [PermissionType.PermissionManager],
14-
store: PermissionSchemaStore) -> [PermissionType.PermissionManager] {
13+
static func filterForUnauthorized(with permissions: [PermissionManager],
14+
store: PermissionSchemaStore) -> [PermissionManager] {
1515
let filteredPermissions = permissions.filter {
1616
store.permissionComponentsStore.getPermissionComponent(for: $0.permissionType).authorized == false
1717
}
@@ -25,8 +25,8 @@ struct FilterPermissions {
2525
// }
2626
// }
2727
// Based on system API query, independent from memory
28-
static func filterForShouldAskPermission(for permissions: [PermissionType.PermissionManager]) -> [PermissionType.PermissionManager] {
29-
var filteredPermissions = [PermissionType.PermissionManager]()
28+
static func filterForShouldAskPermission(for permissions: [PermissionManager]) -> [PermissionManager] {
29+
var filteredPermissions = [PermissionManager]()
3030

3131
for permission in permissions {
3232
if permission.authorizationStatus == .notDetermined {

Sources/CorePermissionsSwiftUI/Modifiers/Internal/ViewModifiers.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ extension View {
2525
@ViewBuilder
2626
func compatibleForegroundStyle(_ style: any ShapeStyle) -> some View {
2727
if #available(iOS 15, *) {
28-
self.foregroundStyle(style)
28+
self.foregroundStyle(style).typeErased()
2929
}
3030
else {
31-
self.foregroundColor(style as? Color)
31+
self.foregroundColor(style as? Color).typeErased()
3232
}
3333
}
3434
}

Sources/CorePermissionsSwiftUI/Store/PermissionSchemaStore.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ import Combine
1515
public class PermissionSchemaStore: ObservableObject {
1616

1717
//MARK: Filtered permission arrays
18-
var undeterminedPermissions: [PermissionType.PermissionManager] {
18+
var undeterminedPermissions: [PermissionManager] {
1919
FilterPermissions.filterForShouldAskPermission(for: permissions)
2020
}
21-
var interactedPermissions: [PermissionType.PermissionManager] {
21+
var interactedPermissions: [PermissionManager] {
2222
//Filter for permissions that are not interacted
2323
permissions.filter {
2424
permissionComponentsStore.getPermissionComponent(for: $0.permissionType).interacted
@@ -43,7 +43,7 @@ public class PermissionSchemaStore: ObservableObject {
4343
//MARK: Initialized configuration properties
4444
var configStore: ConfigStore
4545
var store: PermissionStore
46-
@Published var permissions: [PermissionType.PermissionManager]
46+
@Published var permissions: [PermissionManager]
4747
var permissionViewStyle: PermissionViewStyle
4848
@usableFromInline var permissionComponentsStore: PermissionComponentsStore
4949
init(store: PermissionStore, permissionViewStyle: PermissionViewStyle) {

Sources/CorePermissionsSwiftUI/Store/PermissionStore/PermissionStore.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class PermissionStore: ObservableObject {
3131
public init(){}
3232

3333
///An array of permissions that configures the permissions to request
34-
public var permissions: [PermissionType.PermissionManager] = []
34+
public var permissions: [PermissionManager] = []
3535

3636
//MARK: Configuration store
3737
///Custom configurations that alters PermissionsSwiftUI view's behaviors

0 commit comments

Comments
 (0)