mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Lock the Link New Device flow to portrait and improve Cancel/Try Again handling. (#5094)
* Lock the LinkNewDeviceScreen to portrait. * Add cancel buttons to the QR Code errors and handle cancel/startOver correctly. * Use the shared QRCodeErrorView in the LinkNewDeviceScreen. * Clarify the different QR Error/ErrorStates a bit more. * Update snapshots.
This commit is contained in:
@@ -308,13 +308,14 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
return
|
||||
}
|
||||
switch action {
|
||||
case .startOver:
|
||||
fatalError("QR code login shouldn't request to start over as it's handled within the screen.")
|
||||
case .requestOIDCAuthorisation, .linkedDevice:
|
||||
fatalError("QR code login shouldn't request an OIDC flow or link a device.")
|
||||
case .signInManually:
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
stateMachine.tryEvent(.cancelledLoginWithQR)
|
||||
stateMachine.tryEvent(.confirmServer(.login))
|
||||
case .dismiss:
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
stateMachine.tryEvent(.cancelledLoginWithQR)
|
||||
case .signedIn(let userSession):
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
// Since the qr code login flow includes verification
|
||||
@@ -322,8 +323,9 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {
|
||||
DispatchQueue.main.async {
|
||||
self.stateMachine.tryEvent(.signedIn, userInfo: userSession)
|
||||
}
|
||||
case .requestOIDCAuthorisation, .linkedDevice:
|
||||
fatalError("QR code login shouldn't request an OIDC flow or link a device.")
|
||||
case .cancel:
|
||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||
stateMachine.tryEvent(.cancelledLoginWithQR)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -43,7 +43,8 @@ class LinkNewDeviceFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
|
||||
private func presentLinkNewDeviceScreen() {
|
||||
let coordinator = LinkNewDeviceScreenCoordinator(parameters: .init(clientProxy: flowParameters.userSession.clientProxy))
|
||||
let coordinator = LinkNewDeviceScreenCoordinator(parameters: .init(clientProxy: flowParameters.userSession.clientProxy,
|
||||
orientationManager: flowParameters.appMediator.windowManager))
|
||||
coordinator.actionsPublisher
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
@@ -74,12 +75,14 @@ class LinkNewDeviceFlowCoordinator: FlowCoordinatorProtocol {
|
||||
switch action {
|
||||
case .signInManually, .signedIn:
|
||||
fatalError("QR linking shouldn't send sign-in actions.")
|
||||
case .dismiss:
|
||||
navigationStackCoordinator.pop()
|
||||
case .startOver:
|
||||
navigationStackCoordinator.pop() // Pops back to the LinkNewDeviceScreen.
|
||||
case .requestOIDCAuthorisation(let url, let continuation):
|
||||
actionsSubject.send(.requestOIDCAuthorisation(url, continuation))
|
||||
case .linkedDevice:
|
||||
actionsSubject.send(.dismiss)
|
||||
case .cancel:
|
||||
actionsSubject.send(.dismiss)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -16,10 +16,12 @@ enum LinkNewDeviceScreenCoordinatorAction {
|
||||
|
||||
struct LinkNewDeviceScreenCoordinatorParameters {
|
||||
let clientProxy: ClientProxyProtocol
|
||||
let orientationManager: OrientationManagerProtocol
|
||||
}
|
||||
|
||||
final class LinkNewDeviceScreenCoordinator: CoordinatorProtocol {
|
||||
private let viewModel: LinkNewDeviceScreenViewModelProtocol
|
||||
private let orientationManager: OrientationManagerProtocol
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
@@ -30,6 +32,7 @@ final class LinkNewDeviceScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
init(parameters: LinkNewDeviceScreenCoordinatorParameters) {
|
||||
viewModel = LinkNewDeviceScreenViewModel(clientProxy: parameters.clientProxy)
|
||||
orientationManager = parameters.orientationManager
|
||||
}
|
||||
|
||||
func start() {
|
||||
@@ -47,6 +50,13 @@ final class LinkNewDeviceScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
orientationManager.setOrientation(.portrait)
|
||||
orientationManager.lockOrientation(.portrait)
|
||||
}
|
||||
|
||||
func stop() {
|
||||
orientationManager.lockOrientation(.all)
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
|
||||
@@ -14,7 +14,12 @@ enum LinkNewDeviceScreenViewModelAction {
|
||||
}
|
||||
|
||||
struct LinkNewDeviceScreenViewState: BindableState {
|
||||
enum Mode: Equatable { case loading, readyToLink(isGeneratingCode: Bool), notSupported }
|
||||
enum Mode: Equatable {
|
||||
case loading
|
||||
case readyToLink(isGeneratingCode: Bool)
|
||||
case error(QRCodeLoginState.ErrorState)
|
||||
}
|
||||
|
||||
var mode: Mode = .loading
|
||||
|
||||
let showLinkDesktopComputerButton: Bool
|
||||
@@ -23,5 +28,6 @@ struct LinkNewDeviceScreenViewState: BindableState {
|
||||
enum LinkNewDeviceScreenViewAction {
|
||||
case linkMobileDevice
|
||||
case linkDesktopComputer
|
||||
case errorAction(QRCodeErrorView.Action)
|
||||
case dismiss
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ class LinkNewDeviceScreenViewModel: LinkNewDeviceScreenViewModelType, LinkNewDev
|
||||
Task { await linkMobileDevice() }
|
||||
case .linkDesktopComputer:
|
||||
actionsSubject.send(.linkDesktopComputer)
|
||||
case .errorAction(let action):
|
||||
handleErrorAction(action)
|
||||
case .dismiss:
|
||||
actionsSubject.send(.dismiss)
|
||||
}
|
||||
@@ -50,7 +52,7 @@ class LinkNewDeviceScreenViewModel: LinkNewDeviceScreenViewModelType, LinkNewDev
|
||||
if await clientProxy.isLoginWithQRCodeSupported {
|
||||
state.mode = .readyToLink(isGeneratingCode: false)
|
||||
} else {
|
||||
state.mode = .notSupported
|
||||
state.mode = .error(.notSupported)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +75,22 @@ class LinkNewDeviceScreenViewModel: LinkNewDeviceScreenViewModelType, LinkNewDev
|
||||
actionsSubject.send(.linkMobileDevice(progressPublisher))
|
||||
state.mode = .readyToLink(isGeneratingCode: false)
|
||||
} catch {
|
||||
#warning("Needs some form of re-usable error handling, will handle with the next screen.")
|
||||
state.mode = .notSupported
|
||||
// This is hard to share a mapping from the QRCodeLoginError with the
|
||||
// QRCodeLoginScreen given that some of those are scan errors…
|
||||
state.mode = .error(.unknown)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleErrorAction(_ action: QRCodeErrorView.Action) {
|
||||
switch action {
|
||||
case .startOver:
|
||||
// Reset to ready state to allow trying again.
|
||||
state.mode = .readyToLink(isGeneratingCode: false)
|
||||
case .openSettings, .signInManually:
|
||||
MXLog.error("Unexpected error action: \(action)")
|
||||
actionsSubject.send(.dismiss)
|
||||
case .cancel:
|
||||
actionsSubject.send(.dismiss)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
@@ -12,16 +13,24 @@ struct LinkNewDeviceScreen: View {
|
||||
@Bindable var context: LinkNewDeviceScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
FullscreenDialog(topPadding: 24, horizontalPadding: 24) {
|
||||
mainContent
|
||||
} bottomContent: {
|
||||
buttons
|
||||
switch context.viewState.mode {
|
||||
case .error(let errorState):
|
||||
QRCodeErrorView(errorState: errorState, canSignInManually: false) { action in
|
||||
context.send(viewAction: .errorAction(action))
|
||||
}
|
||||
.backgroundStyle(.compound.bgCanvasDefault)
|
||||
default:
|
||||
FullscreenDialog(topPadding: 24, horizontalPadding: 24) {
|
||||
mainContent
|
||||
} bottomContent: {
|
||||
buttons
|
||||
}
|
||||
.background()
|
||||
.backgroundStyle(.compound.bgSubtleSecondary)
|
||||
.navigationTitle(L10n.commonLinkNewDevice)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
}
|
||||
.background()
|
||||
.backgroundStyle(.compound.bgSubtleSecondary)
|
||||
.navigationTitle(L10n.commonLinkNewDevice)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar { toolbar }
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
@@ -31,11 +40,8 @@ struct LinkNewDeviceScreen: View {
|
||||
TitleAndIcon(title: L10n.screenLinkNewDeviceRootTitle,
|
||||
icon: \.computer,
|
||||
iconStyle: .default)
|
||||
case .notSupported:
|
||||
TitleAndIcon(title: L10n.screenLinkNewDeviceErrorNotSupportedTitle,
|
||||
subtitle: L10n.screenLinkNewDeviceErrorNotSupportedSubtitle,
|
||||
icon: \.errorSolid,
|
||||
iconStyle: .alertSolid)
|
||||
case .error:
|
||||
EmptyView() // Not reachable.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,11 +85,8 @@ struct LinkNewDeviceScreen: View {
|
||||
}
|
||||
}
|
||||
.disabled(isGeneratingCode)
|
||||
case .notSupported:
|
||||
Button(L10n.actionDismiss) {
|
||||
context.send(viewAction: .dismiss)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
case .error:
|
||||
EmptyView() // Not reachable.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +106,8 @@ struct LinkNewDeviceScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = makeViewModel(mode: .readyToLink(isGeneratingCode: false))
|
||||
static let generatingViewModel = makeViewModel(mode: .readyToLink(isGeneratingCode: true))
|
||||
static let loadingViewModel = makeViewModel(mode: .loading)
|
||||
static let unsupportedViewModel = makeViewModel(mode: .notSupported)
|
||||
static let unsupportedViewModel = makeViewModel(mode: .error(.notSupported))
|
||||
static let unknownErrorViewModel = makeViewModel(mode: .error(.unknown))
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
@@ -127,7 +131,13 @@ struct LinkNewDeviceScreen_Previews: PreviewProvider, TestablePreview {
|
||||
LinkNewDeviceScreen(context: unsupportedViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Unsupported")
|
||||
.snapshotPreferences(expect: unsupportedViewModel.context.observe(\.viewState.mode).map { $0 == .notSupported })
|
||||
.snapshotPreferences(expect: unsupportedViewModel.context.observe(\.viewState.mode).map { $0 == .error(.notSupported) })
|
||||
|
||||
NavigationStack {
|
||||
LinkNewDeviceScreen(context: unknownErrorViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Unknown error")
|
||||
.snapshotPreferences(expect: unknownErrorViewModel.context.observe(\.viewState.mode).map { $0 == .error(.unknown) })
|
||||
}
|
||||
|
||||
static func makeViewModel(mode: LinkNewDeviceScreenViewState.Mode) -> LinkNewDeviceScreenViewModel {
|
||||
@@ -137,19 +147,25 @@ struct LinkNewDeviceScreen_Previews: PreviewProvider, TestablePreview {
|
||||
case .loading:
|
||||
try? await Task.sleep(for: .seconds(20))
|
||||
return false
|
||||
case .readyToLink:
|
||||
return true
|
||||
case .notSupported:
|
||||
case .error(.notSupported):
|
||||
return false
|
||||
case .readyToLink, .error:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
let linkMobileProgressSubject = CurrentValueSubject<LinkNewDeviceService.LinkMobileProgress, QRCodeLoginError>(.starting)
|
||||
clientProxy.linkNewDeviceServiceReturnValue = LinkNewDeviceServiceMock(.init(linkMobileProgressPublisher: linkMobileProgressSubject.asCurrentValuePublisher()))
|
||||
|
||||
let viewModel = LinkNewDeviceScreenViewModel(clientProxy: clientProxy)
|
||||
|
||||
Task {
|
||||
try? await Task.sleep(for: .milliseconds(100))
|
||||
if case .readyToLink(isGeneratingCode: true) = mode {
|
||||
viewModel.context.send(viewAction: .linkMobileDevice)
|
||||
} else if case .error = mode {
|
||||
viewModel.context.send(viewAction: .linkMobileDevice)
|
||||
linkMobileProgressSubject.send(completion: .failure(.unknown))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,19 +17,26 @@ struct QRCodeLoginScreenCoordinatorParameters {
|
||||
}
|
||||
|
||||
enum QRCodeLoginScreenCoordinatorAction: CustomStringConvertible {
|
||||
case dismiss
|
||||
/// Restart the flow.
|
||||
///
|
||||
/// This action should only be sent when linking a new device. When logging in it
|
||||
/// is handled internally within the screen.
|
||||
case startOver
|
||||
case signInManually
|
||||
case signedIn(userSession: UserSessionProtocol)
|
||||
case requestOIDCAuthorisation(URL, OIDCAccountSettingsPresenter.Continuation)
|
||||
case linkedDevice
|
||||
/// Cancel the flow (dismiss the modal).
|
||||
case cancel
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .dismiss: "dismiss"
|
||||
case .startOver: "startOver"
|
||||
case .signInManually: "signInManually"
|
||||
case .signedIn: "signedIn"
|
||||
case .requestOIDCAuthorisation: "requestOIDCAuthorisation"
|
||||
case .linkedDevice: "linkedDevice"
|
||||
case .cancel: "cancel"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,14 +67,16 @@ final class QRCodeLoginScreenCoordinator: CoordinatorProtocol {
|
||||
switch action {
|
||||
case .signInManually:
|
||||
actionsSubject.send(.signInManually)
|
||||
case .dismiss:
|
||||
actionsSubject.send(.dismiss)
|
||||
case .startOver:
|
||||
actionsSubject.send(.startOver)
|
||||
case .signedIn(let userSession):
|
||||
actionsSubject.send(.signedIn(userSession: userSession))
|
||||
case .requestOIDCAuthorisation(let url, let continuation):
|
||||
actionsSubject.send(.requestOIDCAuthorisation(url, continuation))
|
||||
case .linkedDevice:
|
||||
actionsSubject.send(.linkedDevice)
|
||||
case .cancel:
|
||||
actionsSubject.send(.cancel)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -9,19 +9,26 @@
|
||||
import SwiftUI
|
||||
|
||||
enum QRCodeLoginScreenViewModelAction: CustomStringConvertible {
|
||||
case dismiss
|
||||
/// Restart the flow.
|
||||
///
|
||||
/// This action should only be sent when linking a new device. When logging in it
|
||||
/// is handled internally within the screen.
|
||||
case startOver
|
||||
case signInManually
|
||||
case signedIn(userSession: UserSessionProtocol)
|
||||
case requestOIDCAuthorisation(URL, OIDCAccountSettingsPresenter.Continuation)
|
||||
case linkedDevice
|
||||
/// Cancel the flow (dismiss the modal).
|
||||
case cancel
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .dismiss: "dismiss"
|
||||
case .startOver: "startOver"
|
||||
case .signInManually: "signInManually"
|
||||
case .signedIn: "signedIn"
|
||||
case .requestOIDCAuthorisation: "requestOIDCAuthorisation"
|
||||
case .linkedDevice: "linkedDevice"
|
||||
case .cancel: "cancel"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,13 +56,13 @@ struct QRCodeLoginScreenViewState: BindableState {
|
||||
switch mode {
|
||||
case .login:
|
||||
switch state {
|
||||
case .loginInstructions, .scan, .error(.noCameraPermission): true
|
||||
case .loginInstructions, .scan: true
|
||||
case .error: false
|
||||
case .linkDesktopInstructions, .displayCode, .displayQR, .confirmCode: false // Unreachable states.
|
||||
}
|
||||
case .linkDesktop, .linkMobile:
|
||||
switch state {
|
||||
case .displayCode, .confirmCode, .scan, .error(.noCameraPermission): true
|
||||
case .displayCode, .confirmCode, .scan: true
|
||||
case .linkDesktopInstructions, .displayQR, .error: false
|
||||
case .loginInstructions: false // Unreachable state.
|
||||
}
|
||||
@@ -81,7 +88,8 @@ struct QRCodeLoginScreenViewStateBindings {
|
||||
}
|
||||
|
||||
enum QRCodeLoginScreenViewAction {
|
||||
case dismiss
|
||||
/// Cancel the entire flow (dismiss the modal).
|
||||
case cancel
|
||||
case startScan
|
||||
case sendCheckCode
|
||||
case errorAction(QRCodeErrorView.Action)
|
||||
@@ -107,13 +115,17 @@ enum QRCodeLoginState: Equatable {
|
||||
case error(ErrorState)
|
||||
|
||||
enum ErrorState: Equatable, CaseIterable {
|
||||
/// The account provider doesn't support the use of QR codes.
|
||||
case notSupported
|
||||
case noCameraPermission
|
||||
case connectionNotSecure
|
||||
case cancelled
|
||||
case declined
|
||||
case expired
|
||||
/// The other device does not support linking Element X by QR code.
|
||||
case linkingNotSupported
|
||||
case deviceNotSupported
|
||||
/// Login cannot be continued due to a lack of Sliding Sync.
|
||||
case slidingSyncNotAvailable
|
||||
/// Expected a QR code for a new device, however the processed code belongs to a device that is already signed in.
|
||||
case deviceAlreadySignedIn
|
||||
case unknown
|
||||
|
||||
@@ -49,8 +49,8 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr
|
||||
|
||||
override func process(viewAction: QRCodeLoginScreenViewAction) {
|
||||
switch viewAction {
|
||||
case .dismiss, .errorAction(.dismiss):
|
||||
actionsSubject.send(.dismiss)
|
||||
case .cancel, .errorAction(.cancel):
|
||||
actionsSubject.send(.cancel)
|
||||
case .startScan:
|
||||
Task { await startScanIfPossible() }
|
||||
case .sendCheckCode:
|
||||
@@ -58,9 +58,12 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr
|
||||
case .errorAction(.startOver):
|
||||
switch state.mode {
|
||||
case .login:
|
||||
Task { await startScanIfPossible() }
|
||||
// Login restarts the flow on this screen.
|
||||
state.bindings.qrResult = nil
|
||||
state.state = .loginInstructions
|
||||
case .linkDesktop, .linkMobile:
|
||||
actionsSubject.send(.dismiss)
|
||||
// Linking a new device starts on the previous screen.
|
||||
actionsSubject.send(.startOver)
|
||||
}
|
||||
case .errorAction(.openSettings):
|
||||
appMediator.openAppSettings()
|
||||
@@ -267,8 +270,8 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr
|
||||
case .success:
|
||||
break // The state will be updated by the status publisher.
|
||||
case .failure(.userCancellation):
|
||||
MXLog.info("User cancelled the WAS, dismissing.")
|
||||
actionsSubject.send(.dismiss)
|
||||
MXLog.info("User cancelled the WAS, the flow must be restarted.")
|
||||
actionsSubject.send(.startOver)
|
||||
case .failure:
|
||||
handleError(.unknown)
|
||||
}
|
||||
@@ -296,8 +299,8 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr
|
||||
state.state = .error(.linkingNotSupported)
|
||||
case .expired:
|
||||
state.state = .error(.expired)
|
||||
case .deviceNotSupported:
|
||||
state.state = .error(.deviceNotSupported)
|
||||
case .slidingSyncNotAvailable:
|
||||
state.state = .error(.slidingSyncNotAvailable)
|
||||
case .deviceAlreadySignedIn:
|
||||
state.state = .error(.deviceAlreadySignedIn)
|
||||
case .unknown:
|
||||
|
||||
@@ -12,11 +12,13 @@ struct QRCodeErrorView: View {
|
||||
let errorState: QRCodeLoginState.ErrorState
|
||||
let canSignInManually: Bool
|
||||
|
||||
enum Action { case openSettings, startOver, signInManually, dismiss }
|
||||
enum Action { case openSettings, startOver, signInManually, cancel }
|
||||
let action: (Action) -> Void
|
||||
|
||||
var title: String {
|
||||
switch errorState {
|
||||
case .notSupported:
|
||||
L10n.screenLinkNewDeviceErrorNotSupportedTitle
|
||||
case .noCameraPermission:
|
||||
L10n.screenQrCodeLoginNoCameraPermissionStateTitle
|
||||
case .connectionNotSecure:
|
||||
@@ -29,7 +31,7 @@ struct QRCodeErrorView: View {
|
||||
L10n.screenQrCodeLoginErrorExpiredTitle
|
||||
case .linkingNotSupported:
|
||||
L10n.screenQrCodeLoginErrorLinkingNotSuportedTitle
|
||||
case .deviceNotSupported:
|
||||
case .slidingSyncNotAvailable:
|
||||
L10n.screenQrCodeLoginErrorSlidingSyncNotSupportedTitle(InfoPlistReader.main.bundleDisplayName)
|
||||
case .deviceAlreadySignedIn:
|
||||
L10n.screenQrCodeLoginErrorDeviceAlreadySignedInTitle
|
||||
@@ -40,6 +42,8 @@ struct QRCodeErrorView: View {
|
||||
|
||||
var subtitle: String {
|
||||
switch errorState {
|
||||
case .notSupported:
|
||||
L10n.screenLinkNewDeviceErrorNotSupportedSubtitle
|
||||
case .noCameraPermission:
|
||||
L10n.screenQrCodeLoginNoCameraPermissionStateDescription(InfoPlistReader.main.productionAppName)
|
||||
case .connectionNotSecure:
|
||||
@@ -52,7 +56,7 @@ struct QRCodeErrorView: View {
|
||||
L10n.screenQrCodeLoginErrorExpiredSubtitle
|
||||
case .linkingNotSupported:
|
||||
L10n.screenQrCodeLoginErrorLinkingNotSuportedSubtitle(InfoPlistReader.main.bundleDisplayName)
|
||||
case .deviceNotSupported:
|
||||
case .slidingSyncNotAvailable:
|
||||
L10n.screenQrCodeLoginErrorSlidingSyncNotSupportedSubtitle(InfoPlistReader.main.bundleDisplayName)
|
||||
case .deviceAlreadySignedIn:
|
||||
L10n.screenQrCodeLoginErrorDeviceAlreadySignedInSubtitle
|
||||
@@ -117,26 +121,30 @@ struct QRCodeErrorView: View {
|
||||
iconStyle: iconStyle)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var buttons: some View {
|
||||
switch errorState {
|
||||
case .noCameraPermission:
|
||||
Button(L10n.screenQrCodeLoginNoCameraPermissionButton) {
|
||||
action(.openSettings)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
case .connectionNotSecure, .unknown, .expired, .declined, .deviceNotSupported:
|
||||
Button(L10n.screenQrCodeLoginStartOverButton) {
|
||||
action(.startOver)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
case .cancelled:
|
||||
Button(L10n.actionTryAgain) {
|
||||
action(.startOver)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
case .linkingNotSupported:
|
||||
VStack(spacing: 16) {
|
||||
VStack(spacing: 16) {
|
||||
switch errorState {
|
||||
case .noCameraPermission:
|
||||
Button(L10n.screenQrCodeLoginNoCameraPermissionButton) {
|
||||
action(.openSettings)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
|
||||
Button(L10n.actionCancel) {
|
||||
action(.cancel)
|
||||
}
|
||||
.buttonStyle(.compound(.secondary))
|
||||
case .connectionNotSecure, .unknown, .expired, .declined, .slidingSyncNotAvailable, .cancelled:
|
||||
Button(L10n.actionTryAgain) {
|
||||
action(.startOver)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
|
||||
Button(L10n.actionCancel) {
|
||||
action(.cancel)
|
||||
}
|
||||
.buttonStyle(.compound(.secondary))
|
||||
case .notSupported, .linkingNotSupported:
|
||||
if canSignInManually {
|
||||
Button(L10n.screenOnboardingSignInManually) {
|
||||
action(.signInManually)
|
||||
@@ -144,16 +152,16 @@ struct QRCodeErrorView: View {
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
|
||||
Button(L10n.actionCancel) {
|
||||
action(.dismiss)
|
||||
Button(L10n.actionDismiss) {
|
||||
action(.cancel)
|
||||
}
|
||||
.buttonStyle(.compound(.tertiary))
|
||||
.buttonStyle(.compound(canSignInManually ? .secondary : .primary))
|
||||
case .deviceAlreadySignedIn:
|
||||
Button(L10n.actionContinue) {
|
||||
action(.cancel)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
case .deviceAlreadySignedIn:
|
||||
Button(L10n.actionContinue) {
|
||||
action(.dismiss)
|
||||
}
|
||||
.buttonStyle(.compound(.primary))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,13 +189,14 @@ struct QRCodeErrorView_Previews: PreviewProvider, TestablePreview {
|
||||
private extension QRCodeLoginState.ErrorState {
|
||||
var previewDisplayName: String {
|
||||
switch self {
|
||||
case .notSupported: "Not supported"
|
||||
case .noCameraPermission: "No Camera Permission"
|
||||
case .connectionNotSecure: "Connection not secure"
|
||||
case .linkingNotSupported: "Linking unsupported"
|
||||
case .cancelled: "Cancelled"
|
||||
case .declined: "Declined"
|
||||
case .expired: "Expired"
|
||||
case .deviceNotSupported: "Device not supported"
|
||||
case .slidingSyncNotAvailable: "Sliding sync not available"
|
||||
case .deviceAlreadySignedIn: "Device already signed in"
|
||||
case .unknown: "Unknown error"
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ struct QRCodeLoginScreen: View {
|
||||
}
|
||||
} bottomContent: {
|
||||
Button(L10n.actionCancel) {
|
||||
context.send(viewAction: .dismiss)
|
||||
context.send(viewAction: .cancel)
|
||||
}
|
||||
.buttonStyle(.compound(.secondary))
|
||||
}
|
||||
@@ -281,7 +281,7 @@ struct QRCodeLoginScreen: View {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
if context.viewState.shouldDisplayCancelButton {
|
||||
Button(L10n.actionCancel) {
|
||||
context.send(viewAction: .dismiss)
|
||||
context.send(viewAction: .cancel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ private extension HumanQrLoginError {
|
||||
case .Expired, .NotFound: // The most likely cause of a .NotFound is that the rendezvous session expired on the server side
|
||||
.qrCodeError(.expired)
|
||||
case .SlidingSyncNotAvailable:
|
||||
.qrCodeError(.deviceNotSupported)
|
||||
.qrCodeError(.slidingSyncNotAvailable)
|
||||
case .OtherDeviceNotSignedIn:
|
||||
.qrCodeError(.deviceNotSignedIn)
|
||||
case .Unknown, .OidcMetadataInvalid, .CheckCodeAlreadySent, .CheckCodeCannotBeSent:
|
||||
|
||||
@@ -103,7 +103,7 @@ enum QRCodeLoginError: Error, Equatable {
|
||||
case declined
|
||||
case linkingNotSupported
|
||||
case expired
|
||||
case deviceNotSupported
|
||||
case slidingSyncNotAvailable
|
||||
case deviceNotSignedIn
|
||||
case deviceAlreadySignedIn
|
||||
case unknown
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3ccc74bdd99363168ab860d90be717836a98e21b2011305582b34959cb7dd13a
|
||||
size 111866
|
||||
oid sha256:592b59289bed364dd2adc7728f3e12347ac94424a624be85bdce69c8e128aae6
|
||||
size 112157
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8e5f2cafc52726da840b03245f0cb66d48d8af7be99f55e4e09bfa192887d4ce
|
||||
size 125605
|
||||
oid sha256:38ff2a2eb43eceb91f9aabfa7a35d928cc6bf39b7a4bce26ef3c81cdd3e36150
|
||||
size 124522
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:45a70d51380f1bb93b25b0f789b0a437fdd5e28450b6680dc96c40a1153b2f3d
|
||||
size 101315
|
||||
oid sha256:9f35e13949126aa35bbc49b9e5dbf0845ca60be7063ee7fc3a0384164f96e856
|
||||
size 102469
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7ecc2829a7b715265cbe825c0fddb7cfb707c29380eb92b3cae23d3f977e4e3d
|
||||
size 111986
|
||||
oid sha256:842cbb773b3cb49647582e37d8a55043e83d3be1dbb0699e301049503b3f3d52
|
||||
size 113151
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:58fafcba5ce430c2b9db2d04d5f08b7fb49f657e7ea766d019aceaba938f5fa4
|
||||
size 112156
|
||||
oid sha256:d8241c970619e687e62815ce3f7abb9fbfdea419aa7253bb72583aca0463b3a3
|
||||
size 112495
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1f1a820798a46a32b2747ea2efd5af67daf883e5cfd566409eb7e4911437afee
|
||||
size 125621
|
||||
oid sha256:3c904990b0d618a09545732264ae620e994259148474dccbf535edf694cc5b7a
|
||||
size 124221
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:865ad5f990f5afef41e924c286aebb8c99d9629577f4d75b237aa9972aa4a167
|
||||
size 96939
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9619af1b33240507268b5b8ff1934e025758aaf23ad8b6d5a42a5e3baaed20d0
|
||||
size 106049
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d59e49988fd995a3af8ec3ed54a951a6f7e6675d135cc8c0ffba780f64535365
|
||||
size 53470
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:84dcb8268c7f3f878ffd5d32beb9991a6e7212894e799b1df509a0e4a314516c
|
||||
size 66759
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5ee9d2b8142ec642ea6f8d606769aaf2b4c1742855e5d67370f8d1b270a6e15a
|
||||
size 108670
|
||||
oid sha256:865ad5f990f5afef41e924c286aebb8c99d9629577f4d75b237aa9972aa4a167
|
||||
size 96939
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2bda2afc3ec1c2a1668a24b60021cf0045a8d6a8da870241e1f6c005f1b1a460
|
||||
size 123442
|
||||
oid sha256:9619af1b33240507268b5b8ff1934e025758aaf23ad8b6d5a42a5e3baaed20d0
|
||||
size 106049
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:df24040677476878fd5ac4a22873177105c26094f74732fedb6af07642b6d44d
|
||||
size 62919
|
||||
oid sha256:d59e49988fd995a3af8ec3ed54a951a6f7e6675d135cc8c0ffba780f64535365
|
||||
size 53470
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:84932548b4b69ad3e0a1ab732cd895863e2a036903429f1febd973dda7cf54b1
|
||||
size 80320
|
||||
oid sha256:84dcb8268c7f3f878ffd5d32beb9991a6e7212894e799b1df509a0e4a314516c
|
||||
size 66759
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1f8cf845823645d2e588ba8a428ea3593202278610a2c80f6d7e1c748fa268c7
|
||||
size 90008
|
||||
oid sha256:99039cfa29c1ad171ccb4f79ead377ad8df08d157832d3d8d95f196d1965ac6a
|
||||
size 96338
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4695ac841ffb2d4e18503526d93ad8830324e39bb7d0066001a3986d339e8ee1
|
||||
size 96486
|
||||
oid sha256:aeca0e8f518801efe79a78796a2cb87e8cb8f910b673882472ee021be2543779
|
||||
size 104068
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:79bdf4106793f8f3d8fb80feac0e0964d709190b9bfeede34cb3bc23493ef001
|
||||
size 47530
|
||||
oid sha256:3bbf39094d65d397119568ff8a6bea9c313bd11e6aa4b2ededd718143b15f480
|
||||
size 53140
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3794b5a8528c3f5548788488df8248d60448aba81d9c3a9e89882ccac6b1e000
|
||||
size 59265
|
||||
oid sha256:07dfb1ddbf0f9db98c5f28d01e5700ece886ea38060b512919ef9c0b8cda0ece
|
||||
size 65950
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0ab5f1cee96b039b902b3907bc714c842eaf5627f61ba8c86bac0b15ae9b1124
|
||||
size 142040
|
||||
oid sha256:4da7776836f54807cfb1d032409cb3e5547fac036ca8ff8fd12d39962a048abd
|
||||
size 148049
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f6bf4551fca5b548bdbd46dc435d24599fb120545f3c38dc301f85d3591a60b8
|
||||
size 187585
|
||||
oid sha256:b45f5822a671edf93fb06b55a446f2b45fb29547ea5e7edd5dd15a01976951dd
|
||||
size 194475
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:becdb1165a086f0330eec535042723adbb7fc6f54c5dbd5ceec89e3c47026996
|
||||
size 100875
|
||||
oid sha256:8af042953fdd7d2dad2aaa7615acfc03e53ecfba021da7b38133e8185acfe91f
|
||||
size 106023
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5de8ec9e0a53a9c96576d4870063b4d7758b23d79bde721e858833ceea741454
|
||||
size 156932
|
||||
oid sha256:eebe6b00f270ff92a737bc669452414fe849405385e4189b98cc01ecf26a3823
|
||||
size 157922
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bfaacefcc921a093540aac44cce94220e00eeb5b8177182add57ec84f3a0686a
|
||||
size 87657
|
||||
oid sha256:0df156666150ef572576f07a015accc9096251b902be50f5833ff9f86c2e94e1
|
||||
size 93666
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eb5fb9dc291ba1f184e9267a8e0abf9abd2b4730b93e3fb62868df0b1658e643
|
||||
size 93414
|
||||
oid sha256:a17d386ccc05cfd597178e48a66e8ae7caed4991862f7db5ce9b28d84b72b521
|
||||
size 100469
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d6c978a5fcbde7333ac77c8c3dc63b275206f8427e24f4bca54dac26eb44c970
|
||||
size 45537
|
||||
oid sha256:f57c645139b41a6405c285cc23d54fc9ea0ec01c166b46096e11545918706951
|
||||
size 50889
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1f8cc9c945184f57b3b9ffb14862738dc82854de36bdcbe77fbcbbee7014df51
|
||||
size 52829
|
||||
oid sha256:16b1c87494e516deefdfab2e71517f8c9e37b795b76294fcfc493bf66004a897
|
||||
size 59081
|
||||
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fc51ca496c5f50060a8750613f9454cf9280ad22276cc42cb92603100937383a
|
||||
size 90595
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7f2c18ea2b2b409ce38ea3c52d93daf1ffdf2f9ace3e8fbe24b1a7e6766a5a9f
|
||||
size 98690
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a3fa9554b1ad1e3e848a983cfac396114f9ef6d9408aaab83e41538242273ecd
|
||||
size 48875
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:052b428d2fd84511082b5801122a5b5d5ddc985b48fb073c21f175fc7ded0545
|
||||
size 62110
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:46530158add2765258605e3ae20c8a69aa7338f7190eab13df38993d5de59aca
|
||||
size 90983
|
||||
oid sha256:3e9f46a2e060cd117a567faff96f56223a5082772c7bd983685371500afc9f76
|
||||
size 96992
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1b9ad00a9444f377f069870058a9cce484200ecf80ddf0993374ba6603f916c1
|
||||
size 99958
|
||||
oid sha256:f1a27690d4564af5e1d5bff2638555a98be4147c6af0434b7cbb641289f5686e
|
||||
size 107013
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ef52548b808b59f966b999650d45fce4b98fbbc6bc4becd11759b84a24bf3e5c
|
||||
size 49878
|
||||
oid sha256:6ef62bd49ad2b7bfba16ce5acb5297d034fc6ee44b248714f31e7b6de0cb3306
|
||||
size 55230
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:abd85913c2264d6276dfa36081826f501edfaef8a669bc9cae0b73e4d7c45052
|
||||
size 63407
|
||||
oid sha256:d6d472aa4f4b88ff4116e8ca78f6401c2182ba563b148f0c53d32cb256d23b09
|
||||
size 69659
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1bb7ee19252c156dbe87f074885f68ca6fc2d58b9a628abc9ae34267fb4bd6a4
|
||||
size 107644
|
||||
oid sha256:1a1956eb383999db5a1a0d49eb2e1f1dcbd6066739463c3e3e1b9afcee68cdbf
|
||||
size 111070
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6fe13470f847b819eebef43f10fc5d670c3d0820f217f48c72f08141da008073
|
||||
size 133115
|
||||
oid sha256:2812be22f47f22db567773722833b96494518ffa260668fcfe9e5c1ed0fb9bfb
|
||||
size 136223
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:939a9c7d6a38eacd8b5636f258e2de8d65ea6a75abb563d2065988557c937d79
|
||||
size 67578
|
||||
oid sha256:596d6d97bc0b59420fb41e3f5d377dea44b87c66584fc8d89b4893b2c541b52a
|
||||
size 70428
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:34ae92445cb12df66949b874ecdb718ef2099261cfa0c3e435051643a395198f
|
||||
size 94076
|
||||
oid sha256:e6825fc0ab0c340f5b78f8d1d8a3f62b38be46ec548385cc12ca271d5afe76a7
|
||||
size 96598
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c59427ee9b1963e79e162fa3e2e666293ed7c557b95f160997d1e9c2437d75f3
|
||||
size 99906
|
||||
oid sha256:f53530dad8ac0e18025303bd5e9f39d9a2c1d4f797b1ab575d5765aec9804902
|
||||
size 102733
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7adf94a154d8969516a4044a6adb7a77b8d936b2dff32572ee4476d9113f222
|
||||
size 123512
|
||||
oid sha256:6284e9b1981fcd873bf2e460ddc837d3a9501724c0e76b85887b71ff8c81d501
|
||||
size 125964
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fda12a17466c9a0ac0b6853f6ec7920b113fc4256bef2661db2c18ea2a304a65
|
||||
size 60872
|
||||
oid sha256:a9a79b94000ef8792fedfd95aea03c8ed40b955f90857acf9eedad1dc7a76413
|
||||
size 63166
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:648db4e91f5b828f25c3a6b121374bc957d2dbae8ad87914e5766a54dfc16e76
|
||||
size 85578
|
||||
oid sha256:a2055ba432f09bf921d04f852e5635bf22b5311affb358cc68b175fee3ccf295
|
||||
size 87594
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a3c4204abe4bf3f79d53baa128e23ab0e64dc92044aa573dd5875e932d5c4c77
|
||||
size 100003
|
||||
oid sha256:cd6aff7c2429ded2e44c7dc7bdac66fbad5f81f502ec5e5f5829bd03dd602bdc
|
||||
size 106290
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:25958be6f832b80dc4d941187bc9b73a04ea65a7f08cbe85b389120a02bb5937
|
||||
size 120131
|
||||
oid sha256:6614cb1f9dcbd51b13e126935bf5c33ccfbfc5b4b7d1086f3a5dc0727ddca0f5
|
||||
size 127732
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0dde38bb16a2bf867a1246e183531b8e0e19ed22a26cfb33ef833746f0b58a06
|
||||
size 60173
|
||||
oid sha256:53c64633e033c97b1ed56887ed77589c89c395bfbb876d5678fd6da27a158b38
|
||||
size 65737
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:61469ce1934f2f8adc28dcb232e703b653ae69480e03a46dfa1ae21e76a37136
|
||||
size 87525
|
||||
oid sha256:209af483bc80d71ca347c4ff84e5b55afc37de4c192363026ea0363dd66591e4
|
||||
size 94066
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ffc09f736bbc07cecad5e93fbbcaa6eb4bdf90020b88446562b497e095d3a494
|
||||
size 101929
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b3e582bae4560bb35730a54b55919550a44e7a645bd3a79139d0beefab19fb75
|
||||
size 116499
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:714c7b55b386f686b943edd992bf855a3d678d6a3ab83c44c03e88de3cea9f49
|
||||
size 60429
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:08706c72bfb0f679d634887cc081a539814d0f2c0461e079985a94bc7c0d96d3
|
||||
size 79243
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d877a090876dd54ca18bf5ec98f21b8d28ecd00ef9a0ff86a2b0b0544bebf89d
|
||||
size 96604
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:74650d5dd76c0e9cd1e20034f3e9eb9dd664078e7057f2eeed621828ee2be32f
|
||||
size 105745
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:35c19a7f7b187a4fd4a0e7af53e7da80f72166c603ad022ec7c182d48bc23cff
|
||||
size 54227
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4eefb6bf9ac16f888fad1988d9b9f05e6f02a3358010a618e8471dcb07845b54
|
||||
size 68362
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:01e8cd4bdedb6a3ade9e4ce142418ea13c6aa7419bc8f756244cb1da9b38d7b3
|
||||
size 90233
|
||||
oid sha256:61956bae4a87d1073ef462e0eeb1bc1ba43b155e99bb24bc428419666902b204
|
||||
size 96242
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cbfd78285154e0a1ffbe6d427a0c90448051c89ed62c28afd1abd09e5d96964f
|
||||
size 96352
|
||||
oid sha256:287eb47327afda08b0fcc6356aed7b49a49bad707d1a063a9286f0c3c0309810
|
||||
size 103407
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:68b5025c6c900caa7af12f0bc6d77c63799efc496452414bba1948a6441e7daf
|
||||
size 47933
|
||||
oid sha256:936c35ac1c5a06a8efe4a94587208f6ff118eba5c83412fb552835cf769103fa
|
||||
size 53285
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:25fca7ccc104f7df8e44df9341a25025dc1cb9900ea698660267eb8ab512690e
|
||||
size 60663
|
||||
oid sha256:9277a9f9be3ee8eb2b36b4738e38810168279ba963aa2504e3dbe1383f9c9166
|
||||
size 66915
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2e66a10d0251fd8d46b38e75a12729d2f37dea6c251ecd1d65c05005d2cdeab5
|
||||
size 88854
|
||||
oid sha256:19b3c9c7130960cadbd4ef8c86e48af9c9129172f4befa195e69bf9942380228
|
||||
size 94696
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:36e4f3b626c67f30d7c5146c8ef62c1377fac2ae79afcb975064d484ac3bd170
|
||||
size 94985
|
||||
oid sha256:f9a007a9348d053ae95005c9b9a37f50e2ea7537abf0f33cbeaf5e3473c8dd5f
|
||||
size 101164
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d6c978a5fcbde7333ac77c8c3dc63b275206f8427e24f4bca54dac26eb44c970
|
||||
size 45537
|
||||
oid sha256:f57c645139b41a6405c285cc23d54fc9ea0ec01c166b46096e11545918706951
|
||||
size 50889
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1f8cc9c945184f57b3b9ffb14862738dc82854de36bdcbe77fbcbbee7014df51
|
||||
size 52829
|
||||
oid sha256:16b1c87494e516deefdfab2e71517f8c9e37b795b76294fcfc493bf66004a897
|
||||
size 59081
|
||||
|
||||
Reference in New Issue
Block a user