-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ABW-737] Improve camera permissions UX (#191)
Co-authored-by: David Roman <2538074+davdroman@users.noreply.github.com>
- Loading branch information
1 parent
963add6
commit 1251159
Showing
26 changed files
with
518 additions
and
232 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
Sources/Clients/CameraPermissionClient/CameraPermissionClient+Interface.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import Foundation | ||
|
||
// MARK: - UserDefaultsClient | ||
public struct CameraPermissionClient: Sendable { | ||
public var getCameraAccess: @Sendable () async -> Bool | ||
} |
16 changes: 16 additions & 0 deletions
16
Sources/Clients/CameraPermissionClient/CameraPermissionClient+Live.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import AVKit | ||
import Dependencies | ||
import Foundation | ||
|
||
// MARK: - UserDefaultsClient + DependencyKey | ||
extension CameraPermissionClient: DependencyKey { | ||
public static let liveValue = Self( | ||
getCameraAccess: { | ||
await withCheckedContinuation { continuation in | ||
AVCaptureDevice.requestAccess(for: .video) { access in | ||
continuation.resume(returning: access) | ||
} | ||
} | ||
} | ||
) | ||
} |
25 changes: 25 additions & 0 deletions
25
Sources/Clients/CameraPermissionClient/CameraPermissionClient+Test.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import Dependencies | ||
import Foundation | ||
import XCTestDynamicOverlay | ||
|
||
public extension DependencyValues { | ||
var cameraPermissionClient: CameraPermissionClient { | ||
get { self[CameraPermissionClient.self] } | ||
set { self[CameraPermissionClient.self] = newValue } | ||
} | ||
} | ||
|
||
// MARK: - CameraPermissionClient + TestDependencyKey | ||
extension CameraPermissionClient: TestDependencyKey { | ||
public static let previewValue = Self.noop | ||
|
||
public static let testValue = Self( | ||
getCameraAccess: unimplemented("\(Self.self).getCameraAccess") | ||
) | ||
} | ||
|
||
public extension CameraPermissionClient { | ||
static let noop = Self( | ||
getCameraAccess: { false } | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
...ces/Features/NewConnectionFeature/Children/CameraPermission/CameraPermission+Action.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import ComposableArchitecture | ||
import ConverseCommon | ||
import Foundation | ||
|
||
// MARK: - CameraPermission.Action | ||
public extension CameraPermission { | ||
enum Action: Sendable, Equatable { | ||
static func view(_ action: ViewAction) -> Self { .internal(.view(action)) } | ||
case `internal`(InternalAction) | ||
case delegate(DelegateAction) | ||
} | ||
} | ||
|
||
// MARK: - CameraPermission.Action.ViewAction | ||
public extension CameraPermission.Action { | ||
enum ViewAction: Sendable, Equatable { | ||
public enum PermissionDeniedAlertAction: Sendable, Equatable { | ||
case dismissed | ||
case cancelButtonTapped | ||
case openSettingsButtonTapped | ||
} | ||
|
||
case appeared | ||
case permissionDeniedAlert(PermissionDeniedAlertAction) | ||
} | ||
} | ||
|
||
// MARK: - CameraPermission.Action.InternalAction | ||
public extension CameraPermission.Action { | ||
enum InternalAction: Sendable, Equatable { | ||
case view(ViewAction) | ||
case system(SystemAction) | ||
} | ||
} | ||
|
||
// MARK: - CameraPermission.Action.SystemAction | ||
public extension CameraPermission.Action { | ||
enum SystemAction: Sendable, Equatable { | ||
case displayPermissionDeniedAlert | ||
} | ||
} | ||
|
||
// MARK: - CameraPermission.Action.DelegateAction | ||
public extension CameraPermission.Action { | ||
enum DelegateAction: Sendable, Equatable { | ||
case permissionResponse(Bool) | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...es/Features/NewConnectionFeature/Children/CameraPermission/CameraPermission+Reducer.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import CameraPermissionClient | ||
import Common | ||
import ComposableArchitecture | ||
#if os(iOS) | ||
import class UIKit.UIApplication | ||
#endif | ||
|
||
// MARK: - CameraPermission | ||
public struct CameraPermission: Sendable, ReducerProtocol { | ||
@Dependency(\.cameraPermissionClient) var cameraPermissionClient | ||
@Dependency(\.openURL) var openURL | ||
|
||
public init() {} | ||
} | ||
|
||
public extension CameraPermission { | ||
func reduce(into state: inout State, action: Action) -> EffectTask<Action> { | ||
switch action { | ||
case .internal(.view(.appeared)): | ||
return .run { send in | ||
let allowed = await cameraPermissionClient.getCameraAccess() | ||
if allowed { | ||
await send(.delegate(.permissionResponse(true))) | ||
} else { | ||
await send(.internal(.system(.displayPermissionDeniedAlert))) | ||
} | ||
} | ||
|
||
case .internal(.system(.displayPermissionDeniedAlert)): | ||
state.permissionDeniedAlert = .init( | ||
title: { TextState(L10n.NewConnection.CameraPermission.DeniedAlert.title) }, | ||
actions: { | ||
ButtonState( | ||
role: .cancel, | ||
action: .send(.cancelButtonTapped), | ||
label: { TextState(L10n.NewConnection.CameraPermission.DeniedAlert.cancelButtonTitle) } | ||
) | ||
ButtonState( | ||
role: .none, | ||
action: .send(.openSettingsButtonTapped), | ||
label: { TextState(L10n.NewConnection.CameraPermission.DeniedAlert.settingsButtonTitle) } | ||
) | ||
}, | ||
message: { TextState(L10n.NewConnection.CameraPermission.DeniedAlert.message) } | ||
) | ||
return .none | ||
|
||
case let .internal(.view(.permissionDeniedAlert(action))): | ||
state.permissionDeniedAlert = nil | ||
switch action { | ||
case .dismissed, .cancelButtonTapped: | ||
return .run { send in | ||
await send(.delegate(.permissionResponse(false))) | ||
} | ||
case .openSettingsButtonTapped: | ||
return .run { send in | ||
await send(.delegate(.permissionResponse(false))) | ||
#if os(iOS) | ||
await openURL(URL(string: UIApplication.openSettingsURLString)!) | ||
#endif | ||
} | ||
} | ||
|
||
case .delegate: | ||
return .none | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
Sources/Features/NewConnectionFeature/Children/CameraPermission/CameraPermission+State.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import ComposableArchitecture | ||
import Foundation | ||
|
||
// MARK: - CameraPermission.State | ||
public extension CameraPermission { | ||
struct State: Sendable, Equatable { | ||
var permissionDeniedAlert: AlertState<Action.ViewAction.PermissionDeniedAlertAction>? | ||
|
||
init() { | ||
self.permissionDeniedAlert = nil | ||
} | ||
} | ||
} | ||
|
||
#if DEBUG | ||
public extension CameraPermission.State { | ||
static let previewValue: Self = .init() | ||
} | ||
#endif |
Oops, something went wrong.