Allow reporting a problem from the onboarding screen

This commit is contained in:
Stefan Ceriu 2024-01-20 17:10:12 +02:00
parent 261258dd0a
commit 0fe52fe54b
16 changed files with 71 additions and 23 deletions

View File

@ -398,11 +398,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
encryptionKeyProvider: EncryptionKeyProvider(),
appSettings: appSettings)
authenticationCoordinator = AuthenticationCoordinator(authenticationService: authenticationService,
appLockService: appLockFlowCoordinator.appLockService,
bugReportService: ServiceLocator.shared.bugReportService,
navigationStackCoordinator: authenticationNavigationStackCoordinator,
appSettings: appSettings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appLockService: appLockFlowCoordinator.appLockService)
userIndicatorController: ServiceLocator.shared.userIndicatorController)
authenticationCoordinator?.delegate = self
authenticationCoordinator?.start()

View File

@ -24,11 +24,12 @@ protocol AuthenticationCoordinatorDelegate: AnyObject {
class AuthenticationCoordinator: CoordinatorProtocol {
private let authenticationService: AuthenticationServiceProxyProtocol
private let appLockService: AppLockServiceProtocol
private let bugReportService: BugReportServiceProtocol
private let navigationStackCoordinator: NavigationStackCoordinator
private let appSettings: AppSettings
private let analytics: AnalyticsService
private let userIndicatorController: UserIndicatorControllerProtocol
private let appLockService: AppLockServiceProtocol
private var cancellables = Set<AnyCancellable>()
@ -39,17 +40,19 @@ class AuthenticationCoordinator: CoordinatorProtocol {
weak var delegate: AuthenticationCoordinatorDelegate?
init(authenticationService: AuthenticationServiceProxyProtocol,
appLockService: AppLockServiceProtocol,
bugReportService: BugReportServiceProtocol,
navigationStackCoordinator: NavigationStackCoordinator,
appSettings: AppSettings,
analytics: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol,
appLockService: AppLockServiceProtocol) {
userIndicatorController: UserIndicatorControllerProtocol) {
self.authenticationService = authenticationService
self.appLockService = appLockService
self.bugReportService = bugReportService
self.navigationStackCoordinator = navigationStackCoordinator
self.appSettings = appSettings
self.analytics = analytics
self.userIndicatorController = userIndicatorController
self.appLockService = appLockService
}
func start() {
@ -81,6 +84,8 @@ class AuthenticationCoordinator: CoordinatorProtocol {
switch action {
case .login:
Task { await self.startAuthentication() }
case .reportProblem:
showReportProblemScreen()
}
}
.store(in: &cancellables)
@ -88,6 +93,27 @@ class AuthenticationCoordinator: CoordinatorProtocol {
navigationStackCoordinator.setRootCoordinator(coordinator)
}
private func showReportProblemScreen() {
let feedbackNavigationStackCoordinator = NavigationStackCoordinator()
let parameters = BugReportScreenCoordinatorParameters(bugReportService: bugReportService,
userID: nil,
deviceID: nil,
userIndicatorController: ServiceLocator.shared.userIndicatorController,
screenshot: nil,
isModallyPresented: true)
let coordinator = BugReportScreenCoordinator(parameters: parameters)
coordinator.completion = { [weak self] _ in
self?.navigationStackCoordinator.setSheetCoordinator(nil)
}
feedbackNavigationStackCoordinator.setRootCoordinator(coordinator)
navigationStackCoordinator.setSheetCoordinator(feedbackNavigationStackCoordinator, animated: true)
}
private func startAuthentication() async {
startLoading()

View File

@ -24,7 +24,7 @@ enum BugReportScreenCoordinatorResult {
struct BugReportScreenCoordinatorParameters {
let bugReportService: BugReportServiceProtocol
let userID: String
let userID: String?
let deviceID: String?
let userIndicatorController: UserIndicatorControllerProtocol?

View File

@ -21,7 +21,7 @@ typealias BugReportScreenViewModelType = StateStoreViewModel<BugReportScreenView
class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenViewModelProtocol {
private let bugReportService: BugReportServiceProtocol
private let userID: String
private let userID: String?
private let deviceID: String?
private let actionsSubject: PassthroughSubject<BugReportScreenViewModelAction, Never> = .init()
// periphery:ignore - when set to nil this is automatically cancelled
@ -32,7 +32,7 @@ class BugReportScreenViewModel: BugReportScreenViewModelType, BugReportScreenVie
}
init(bugReportService: BugReportServiceProtocol,
userID: String,
userID: String?,
deviceID: String?,
screenshot: UIImage?,
isModallyPresented: Bool) {

View File

@ -40,6 +40,8 @@ final class OnboardingScreenCoordinator: CoordinatorProtocol {
switch action {
case .login:
actionsSubject.send(.login)
case .reportProblem:
actionsSubject.send(.reportProblem)
}
}
.store(in: &cancellables)

View File

@ -20,14 +20,17 @@ import SwiftUI
enum OnboardingScreenCoordinatorAction {
case login
case reportProblem
}
enum OnboardingScreenViewModelAction {
case login
case reportProblem
}
struct OnboardingScreenViewState: BindableState { }
enum OnboardingScreenViewAction {
case login
case reportProblem
}

View File

@ -34,6 +34,8 @@ class OnboardingScreenViewModel: OnboardingScreenViewModelType, OnboardingScreen
switch viewAction {
case .login:
actionsSubject.send(.login)
case .reportProblem:
actionsSubject.send(.reportProblem)
}
}
}

View File

@ -42,6 +42,16 @@ struct OnboardingScreen: View {
.frame(height: UIConstants.spacerHeight(in: geometry))
}
.frame(maxHeight: .infinity)
.safeAreaInset(edge: .bottom) {
Button {
context.send(viewAction: .reportProblem)
} label: {
Text(L10n.commonReportAProblem)
.font(.compound.bodySM)
.foregroundColor(.compound.textSecondary)
}
.frame(width: geometry.size.width)
}
}
.navigationBarHidden(true)
.background {

View File

@ -119,11 +119,14 @@ class BugReportService: NSObject, BugReportServiceProtocol {
func submitBugReport(_ bugReport: BugReport,
progressListener: CurrentValueSubject<Double, Never>) async -> Result<SubmitBugReportResponse, BugReportServiceError> {
var params = [
MultipartFormData(key: "user_id", type: .text(value: bugReport.userID)),
MultipartFormData(key: "text", type: .text(value: bugReport.text)),
MultipartFormData(key: "can_contact", type: .text(value: "\(bugReport.canContact)"))
]
if let userID = bugReport.userID {
params.append(.init(key: "user_id", type: .text(value: userID)))
}
if let deviceID = bugReport.deviceID {
params.append(.init(key: "device_id", type: .text(value: deviceID)))
}

View File

@ -19,7 +19,7 @@ import Foundation
import UIKit
struct BugReport: Equatable {
let userID: String
let userID: String?
let deviceID: String?
let text: String
let includeLogs: Bool

View File

@ -137,11 +137,12 @@ class MockScreen: Identifiable {
case .authenticationFlow:
let navigationStackCoordinator = NavigationStackCoordinator()
let coordinator = AuthenticationCoordinator(authenticationService: MockAuthenticationServiceProxy(),
appLockService: AppLockServiceMock(),
bugReportService: BugReportServiceMock(),
navigationStackCoordinator: navigationStackCoordinator,
appSettings: ServiceLocator.shared.settings,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appLockService: AppLockServiceMock())
userIndicatorController: ServiceLocator.shared.userIndicatorController)
retainedState.append(coordinator)
navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator

Binary file not shown.