Skip to content

Commit 4875b5f

Browse files
authored
Merge pull request #82 from jevonmao/develop
Merge from develop into main
2 parents b0ca1a3 + 6afdbf5 commit 4875b5f

File tree

62 files changed

+965
-714
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+965
-714
lines changed

Package.swift

Lines changed: 142 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,151 @@
33

44
import PackageDescription
55

6+
let permissionsTargets: [Target] = [
7+
.target(
8+
name: "CorePermissionsSwiftUI", //Internal module for shared code
9+
dependencies: ["Introspect"],
10+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
11+
),
12+
.target(
13+
name: "PermissionsSwiftUI", //Maintain backward compatibility - access to all permissions
14+
dependencies: ["Introspect", "CorePermissionsSwiftUI", "PermissionsSwiftUITracking", "PermissionsSwiftUIBluetooth", "PermissionsSwiftUICalendar", "PermissionsSwiftUICamera", "PermissionsSwiftUIContacts", "PermissionsSwiftUILocation", "PermissionsSwiftUILocationAlways", "PermissionsSwiftUIMicrophone", "PermissionsSwiftUIMotion", "PermissionsSwiftUIMusic", "PermissionsSwiftUINotification", "PermissionsSwiftUIPhoto", "PermissionsSwiftUIReminder", "PermissionsSwiftUISpeech", "PermissionsSwiftUIHealth"],
15+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
16+
),
17+
.target(
18+
name: "PermissionsSwiftUIBluetooth",
19+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
20+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
21+
),
22+
.target(
23+
name: "PermissionsSwiftUICalendar",
24+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
25+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
26+
),
27+
.target(
28+
name: "PermissionsSwiftUICamera",
29+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
30+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
31+
),
32+
.target(
33+
name: "PermissionsSwiftUIContacts",
34+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
35+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
36+
),
37+
.target(
38+
name: "PermissionsSwiftUIHealth",
39+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
40+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
41+
),
42+
.target(
43+
name: "PermissionsSwiftUILocationAlways",
44+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
45+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
46+
),
47+
.target(
48+
name: "PermissionsSwiftUILocation",
49+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
50+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
51+
),
52+
.target(
53+
name: "PermissionsSwiftUIMicrophone",
54+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
55+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
56+
),
57+
.target(
58+
name: "PermissionsSwiftUIMotion",
59+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
60+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
61+
),
62+
.target(
63+
name: "PermissionsSwiftUIMusic",
64+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
65+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
66+
),
67+
.target(
68+
name: "PermissionsSwiftUINotification",
69+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
70+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
71+
),
72+
.target(
73+
name: "PermissionsSwiftUIPhoto",
74+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
75+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
76+
),
77+
.target(
78+
name: "PermissionsSwiftUIReminder",
79+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
80+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
81+
),
82+
.target(
83+
name: "PermissionsSwiftUISpeech",
84+
dependencies: ["Introspect", "CorePermissionsSwiftUI"],
85+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
86+
),
87+
.target(
88+
name: "PermissionsSwiftUITracking",
89+
dependencies: ["Introspect", .target(name: "CorePermissionsSwiftUI")],
90+
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
91+
),]
92+
693
let package = Package(
794
name: "PermissionsSwiftUI",
895
platforms: [.iOS(.v11)],
996
products: [
1097
// Products define the executables and libraries a package produces, and make them visible to other packages.
1198
.library(
12-
name: "PermissionsSwiftUI",
13-
targets: ["PermissionsSwiftUI"]
99+
name: "PermissionsSwiftUIBluetooth",
100+
targets: ["PermissionsSwiftUIBluetooth"]
101+
),
102+
.library(
103+
name: "PermissionsSwiftUICalendar",
104+
targets: ["PermissionsSwiftUICalendar"]
105+
),
106+
.library(
107+
name: "PermissionsSwiftUICamera",
108+
targets: ["PermissionsSwiftUICamera"]
109+
),
110+
.library(
111+
name: "PermissionsSwiftUIContacts",
112+
targets: ["PermissionsSwiftUIContacts"]
113+
),
114+
.library(name: "PermissionsSwiftUIHealth",
115+
targets: ["PermissionsSwiftUIHealth"]
116+
),
117+
.library(name: "PermissionsSwiftUILocationAlways",
118+
targets: ["PermissionsSwiftUILocationAlways"]
119+
),
120+
.library(name: "PermissionsSwiftUILocation",
121+
targets: ["PermissionsSwiftUILocation"]
14122
),
123+
.library(name: "PermissionsSwiftUIMicrophone",
124+
targets: ["PermissionsSwiftUIMicrophone"]
125+
),
126+
.library(name: "PermissionsSwiftUIMotion",
127+
targets: ["PermissionsSwiftUIMotion"]
128+
),
129+
.library(name: "PermissionsSwiftUIMusic",
130+
targets: ["PermissionsSwiftUIMusic"]
131+
),
132+
.library(name: "PermissionsSwiftUINotification",
133+
targets: ["PermissionsSwiftUINotification"]
134+
),
135+
.library(name: "PermissionsSwiftUIPhoto",
136+
targets: ["PermissionsSwiftUIPhoto"]
137+
),
138+
.library(name: "PermissionsSwiftUIReminder",
139+
targets: ["PermissionsSwiftUIReminder"]
140+
),
141+
.library(name: "PermissionsSwiftUISpeech",
142+
targets: ["PermissionsSwiftUISpeech"]
143+
),
144+
.library(name: "PermissionsSwiftUITracking",
145+
targets: ["PermissionsSwiftUITracking"]
146+
),
147+
.library(name: "PermissionSwiftUI",
148+
targets: ["PermissionsSwiftUI"]),
149+
.library(name: "CorePermissionsSwiftUI",
150+
targets: ["CorePermissionsSwiftUI"]),
15151
],
16152
dependencies: [
17153
// Dependencies declare other packages that this package depends on.
@@ -21,20 +157,16 @@ let package = Package(
21157
targets: [
22158
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
23159
// Targets can depend on other targets in this package, and on products in packages this package depends on.
24-
.target(
25-
name: "PermissionsSwiftUI",
26-
dependencies: ["Introspect"],
27-
exclude: ["../../Tests/PermissionsSwiftUITests/__Snapshots__"]
28-
),
29160
.testTarget(name: "PermissionsSwiftUITests",
30-
dependencies: ["PermissionsSwiftUI","SnapshotTesting"],
161+
dependencies: ["SnapshotTesting", "PermissionsSwiftUI", "CorePermissionsSwiftUI"],
31162
exclude: [],
32163
resources: [.process("__Snapshots__")]),
33164
.testTarget(
34165
name: "PermissionsSwiftUISmallScreenTests",
35-
dependencies: ["PermissionsSwiftUI","SnapshotTesting"],
166+
dependencies: ["SnapshotTesting"] + permissionsTargets
167+
.map{Target.Dependency(stringLiteral: $0.name)},
36168
exclude: [],
37169
resources: [.process("__Snapshots__")]
38170
),
39-
]
171+
] + permissionsTargets
40172
)

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

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
/**
1111
The authorization status for any iOS system permission
1212
*/
13-
public enum AuthorizationStatus {
13+
public enum AuthorizationStatus: String, Hashable, Equatable {
1414
///The explicitly allowed or `authorized` permission state
1515
case authorized
1616
///The explicitly denied permission state
@@ -23,20 +23,4 @@ public enum AuthorizationStatus {
2323
case notDetermined
2424
}
2525

26-
protocol PermissionManager {
27-
var permissionType: PermissionType? {get set}
28-
var authorizationStatus: AuthorizationStatus {get}
29-
30-
init(permissionType: PermissionType?)
31-
32-
33-
func requestPermission(_ completion: @escaping (Bool, Error?) -> Void)
34-
35-
}
36-
37-
extension PermissionManager {
38-
var permissionType: PermissionType? {
39-
get {nil}
40-
set{}
41-
}}
4226

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//
2+
// PermissionModel.swift
3+
//
4+
//
5+
// Created by Jevon Mao on 1/30/21.
6+
//
7+
8+
import Foundation
9+
import SwiftUI
10+
import HealthKit
11+
12+
/**
13+
The types of iOS system permission for show in the JMPermissions view
14+
15+
Pass this as a parameter into JMPermissions View Modifier will display 3 UI elements–location, photo, and microphone.
16+
```
17+
[.location, photo, microphone]
18+
```
19+
*/
20+
@available(iOS 13.0, tvOS 13.0, *)
21+
public enum PermissionType: Hashable, Equatable {
22+
public static func == (lhs: PermissionType, rhs: PermissionType) -> Bool {
23+
lhs.rawValue == rhs.rawValue ? true : false
24+
}
25+
26+
/**
27+
A Permission Manager object that contains properties and functions related to a specific permission. Will be subclassed by any permission type.
28+
29+
- warning: `PermissionManager` shoud never be referenced directly and used. It serves as an abstract interface for PermissionsSwiftUI's many permission modules.
30+
*/
31+
open class PermissionManager: NSObject, Identifiable {
32+
///Holds the permission UI component, containing UI elements like text and image
33+
open var permissionComponent: JMPermission {
34+
get {
35+
preconditionFailure("This property must be overridden.")
36+
}
37+
}
38+
///Holds the health permission subcategories, in case of health permission type subclass
39+
open var healthPermissionCategories: Set<HKSampleType>?
40+
41+
///The type of permission
42+
open var permissionType: PermissionType {
43+
preconditionFailure("This property must be overridden.")
44+
}
45+
46+
///The authorization status of the permission
47+
open var authorizationStatus: AuthorizationStatus {
48+
get {
49+
preconditionFailure("This property must be overridden.")
50+
}
51+
}
52+
53+
/**
54+
Creates a new `PermissionManager` for health permission.
55+
56+
- parameters:
57+
- healthPermissionCategories: Subcategory permissions of health permission to request
58+
*/
59+
public init(_ healthPermissionCategories: Set<HKSampleType>? = nil) {
60+
self.healthPermissionCategories = healthPermissionCategories
61+
}
62+
63+
/**
64+
Requests authorization for the current implemented type of permission.
65+
66+
- parameters:
67+
- completion: Returns back whether the permission authorization is granted, and any errors
68+
*/
69+
open func requestPermission(completion: @escaping (Bool, Error?) -> Void) {
70+
preconditionFailure("This method must be overridden.")
71+
}
72+
}
73+
///The `location` permission allows the device's positoin to be tracked
74+
case location
75+
76+
///Used to access the user's photo library
77+
case photo
78+
79+
///The `notification` permission allows the iOS system to receive notification from app
80+
case notification
81+
82+
///Permission that allows app to access device's bluetooth technologies
83+
case bluetooth
84+
85+
///In order for app to track user's data across apps and websites, the tracking permission is needed
86+
@available(iOS 14, tvOS 14, *) case tracking
87+
#if !os(tvOS)
88+
/**
89+
Permission that allows app to access healthkit information
90+
91+
- 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
92+
93+
For example, passing in a `Set` of `HKSampleType`:
94+
```
95+
[.health(categories: .init(readAndWrite: Set([HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!])))]
96+
```
97+
*/
98+
case health
99+
#endif
100+
101+
///The `locationAlways` permission provides location data even if app is in background
102+
@available(tvOS, unavailable) case locationAlways
103+
104+
///Permission allows developers to interact with the device microphone
105+
@available(tvOS, unavailable) case microphone
106+
107+
///Permission that allows developers to interact with on-device camera
108+
@available(tvOS, unavailable) case camera
109+
110+
///A permission that allows developers to read & write to device contacts
111+
@available(tvOS, unavailable) case contacts
112+
113+
///Permission that give app access to motion and fitness related sensor data
114+
@available(tvOS, unavailable) case motion
115+
116+
///The `reminders` permission is needed to interact with device reminders
117+
@available(tvOS, unavailable) case reminders
118+
119+
///Permission that allows app to read & write to device calendar
120+
@available(tvOS, unavailable) case calendar
121+
122+
///Permission that allows app to use speech recognition
123+
@available(tvOS, unavailable) case speech
124+
125+
///Permission that allows app to control audio playback of the device
126+
@available(tvOS, unavailable) case music
127+
128+
}
129+
130+
131+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// PermissionModelGet.swift
3+
//
4+
//
5+
// Created by Jevon Mao on 2/6/21.
6+
//
7+
8+
import Foundation
9+
import SwiftUI
10+
11+
@available(iOS 13.0, tvOS 13.0, *)
12+
extension PermissionType {
13+
var rawValue: String {
14+
guard let label = Mirror(reflecting: self).children.first?.label else {
15+
return .init(describing: self)
16+
}
17+
return label
18+
}
19+
}

Sources/PermissionsSwiftUI/Model/Structs/FilterPermissions.swift renamed to Sources/CorePermissionsSwiftUI/Model/Structs/FilterPermissions.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77

88
import Foundation
99

10+
@available(iOS 13.0, tvOS 13.0, *)
1011
struct FilterPermissions {
1112
// Based on struct boolean property, dependent on memory
12-
@available(iOS 13.0, tvOS 13.0, *)
13-
static func filterForUnauthorized(with permissions: [PermissionType], store: PermissionSchemaStore) -> [PermissionType] {
13+
static func filterForUnauthorized(with permissions: [PermissionType.PermissionManager],
14+
store: PermissionSchemaStore) -> [PermissionType.PermissionManager] {
1415
let filteredPermissions = permissions.filter {
15-
store.permissionComponentsStore.getPermissionComponent(for: $0, modify: {_ in}).authorized == false
16+
store.permissionComponentsStore.getPermissionComponent(for: $0.permissionType).authorized == false
1617
}
1718
return filteredPermissions
1819
}
@@ -24,11 +25,11 @@ struct FilterPermissions {
2425
// }
2526
// }
2627
// Based on system API query, independent from memory
27-
static func filterForShouldAskPermission(for permissions: [PermissionType]) -> [PermissionType] {
28-
var filteredPermissions = [PermissionType]()
28+
static func filterForShouldAskPermission(for permissions: [PermissionType.PermissionManager]) -> [PermissionType.PermissionManager] {
29+
var filteredPermissions = [PermissionType.PermissionManager]()
2930

3031
for permission in permissions {
31-
if permission.getPermissionManager()?.init(permissionType: permission).authorizationStatus == .notDetermined {
32+
if permission.authorizationStatus == .notDetermined {
3233
filteredPermissions.append(permission)
3334
}
3435
}

0 commit comments

Comments
 (0)