Fixes #614 - Add the user and device identifiers to rageshakes (#620)

* Fixes #614 - Add the user and device identifiers to rageshakes

* Add `base_bundle_identifier` to rageshakes
This commit is contained in:
Stefan Ceriu
2023-02-24 14:51:36 +02:00
committed by GitHub
parent a1300d0b82
commit 0aca8c25c1
15 changed files with 79 additions and 23 deletions

View File

@@ -235,7 +235,7 @@ class AppCoordinator: AppCoordinatorProtocol {
let credentials = SoftLogoutCredentials(userId: userSession.userID,
homeserverName: userSession.homeserver,
userDisplayName: displayName,
deviceId: userSession.deviceId)
deviceId: userSession.deviceID)
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore)
_ = await authenticationService.configure(for: userSession.homeserver)

View File

@@ -23,6 +23,9 @@ enum BugReportCoordinatorResult {
struct BugReportCoordinatorParameters {
let bugReportService: BugReportServiceProtocol
let userID: String
let deviceID: String?
weak var userIndicatorController: UserIndicatorControllerProtocol?
let screenshot: UIImage?
let isModallyPresented: Bool
@@ -38,6 +41,8 @@ final class BugReportCoordinator: CoordinatorProtocol {
self.parameters = parameters
viewModel = BugReportViewModel(bugReportService: parameters.bugReportService,
userID: parameters.userID,
deviceID: parameters.deviceID,
screenshot: parameters.screenshot,
isModallyPresented: parameters.isModallyPresented)
}

View File

@@ -19,14 +19,21 @@ import SwiftUI
typealias BugReportViewModelType = StateStoreViewModel<BugReportViewState, BugReportViewAction>
class BugReportViewModel: BugReportViewModelType, BugReportViewModelProtocol {
let bugReportService: BugReportServiceProtocol
private let bugReportService: BugReportServiceProtocol
private let userID: String
private let deviceID: String?
var callback: ((BugReportViewModelAction) -> Void)?
init(bugReportService: BugReportServiceProtocol,
userID: String,
deviceID: String?,
screenshot: UIImage?,
isModallyPresented: Bool) {
self.bugReportService = bugReportService
self.userID = userID
self.deviceID = deviceID
let bindings = BugReportViewStateBindings(reportText: "", sendingLogsEnabled: true)
super.init(initialViewState: BugReportViewState(screenshot: screenshot,
bindings: bindings,
@@ -61,7 +68,9 @@ class BugReportViewModel: BugReportViewModelType, BugReportViewModelProtocol {
try pngData?.write(to: imageURL)
files.append(imageURL)
}
let bugReport = BugReport(text: context.reportText,
let bugReport = BugReport(userID: userID,
deviceID: deviceID,
text: context.reportText,
includeLogs: context.sendingLogsEnabled,
includeCrashLog: true,
githubLabels: [],

View File

@@ -173,12 +173,16 @@ struct BugReportScreen: View {
struct BugReport_Previews: PreviewProvider {
static let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
userID: "@mock.client.com",
deviceID: nil,
screenshot: nil,
isModallyPresented: false)
static var previews: some View {
NavigationStack {
BugReportScreen(context: BugReportViewModel(bugReportService: MockBugReportService(),
userID: "@mock.client.com",
deviceID: nil,
screenshot: nil,
isModallyPresented: false).context)
.previewDisplayName("Without Screenshot")
@@ -186,6 +190,8 @@ struct BugReport_Previews: PreviewProvider {
NavigationStack {
BugReportScreen(context: BugReportViewModel(bugReportService: MockBugReportService(),
userID: "@mock.client.com",
deviceID: nil,
screenshot: Asset.Images.appLogo.image,
isModallyPresented: false).context)
.previewDisplayName("With Screenshot")

View File

@@ -78,6 +78,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
private func presentBugReportScreen() {
let params = BugReportCoordinatorParameters(bugReportService: parameters.bugReportService,
userID: parameters.userSession.userID,
deviceID: parameters.userSession.deviceID,
userIndicatorController: parameters.userIndicatorController,
screenshot: nil,
isModallyPresented: false)

View File

@@ -28,7 +28,7 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
self.userSession = userSession
let bindings = SettingsScreenViewStateBindings(timelineStyle: ServiceLocator.shared.settings.timelineStyle)
super.init(initialViewState: .init(bindings: bindings,
deviceID: userSession.deviceId,
deviceID: userSession.deviceID,
userID: userSession.userID,
showSessionVerificationSection: !(userSession.sessionVerificationController?.isVerified ?? false),
showDeveloperOptions: ServiceLocator.shared.settings.canShowDeveloperOptions),

View File

@@ -78,10 +78,19 @@ class BugReportService: NSObject, BugReportServiceProtocol {
SentrySDK.crash()
}
func submitBugReport(_ bugReport: BugReport,
progressListener: ProgressListener?) async throws -> SubmitBugReportResponse {
var params = [MultipartFormData(key: "text", type: .text(value: bugReport.text))]
// swiftlint:disable:next function_body_length
func submitBugReport(_ bugReport: BugReport, progressListener: ProgressListener?) async throws -> SubmitBugReportResponse {
var params = [
MultipartFormData(key: "user_id", type: .text(value: bugReport.userID)),
MultipartFormData(key: "text", type: .text(value: bugReport.text))
]
if let deviceID = bugReport.deviceID {
params.append(.init(key: "device_id", type: .text(value: deviceID)))
}
params.append(contentsOf: defaultParams)
for label in bugReport.githubLabels {
params.append(MultipartFormData(key: "label", type: .text(value: label)))
}
@@ -155,7 +164,8 @@ class BugReportService: NSObject, BugReportServiceProtocol {
MultipartFormData(key: "user_language", type: .text(value: Bundle.elementLanguage ?? "null")),
MultipartFormData(key: "fallback_language", type: .text(value: Bundle.elementFallbackLanguage ?? "null")),
MultipartFormData(key: "local_time", type: .text(value: localTime)),
MultipartFormData(key: "utc_time", type: .text(value: utcTime))
MultipartFormData(key: "utc_time", type: .text(value: utcTime)),
MultipartFormData(key: "base_bundle_identifier", type: .text(value: InfoPlistReader.main.baseBundleIdentifier))
]
}

View File

@@ -18,6 +18,8 @@ import Foundation
import UIKit
struct BugReport {
let userID: String
let deviceID: String?
let text: String
let includeLogs: Bool
let includeCrashLog: Bool

View File

@@ -21,7 +21,7 @@ struct MockUserSession: UserSessionProtocol {
let sessionVerificationController: SessionVerificationControllerProxyProtocol? = nil
var userID: String { clientProxy.userID }
var isSoftLogout: Bool { clientProxy.isSoftLogout }
var deviceId: String? { clientProxy.deviceId }
var deviceID: String? { clientProxy.deviceId }
var homeserver: String { clientProxy.homeserver }
let clientProxy: ClientProxyProtocol
let mediaProvider: MediaProviderProtocol

View File

@@ -25,7 +25,7 @@ class UserSession: UserSessionProtocol {
var userID: String { clientProxy.userID }
var isSoftLogout: Bool { clientProxy.isSoftLogout }
var deviceId: String? { clientProxy.deviceId }
var deviceID: String? { clientProxy.deviceId }
var homeserver: String { clientProxy.homeserver }
let clientProxy: ClientProxyProtocol

View File

@@ -25,10 +25,11 @@ enum UserSessionCallback {
}
protocol UserSessionProtocol {
var userID: String { get }
var isSoftLogout: Bool { get }
var deviceId: String? { get }
var homeserver: String { get }
var userID: String { get }
var deviceID: String? { get }
var isSoftLogout: Bool { get }
var clientProxy: ClientProxyProtocol { get }
var mediaProvider: MediaProviderProtocol { get }

View File

@@ -244,6 +244,8 @@ class UserSessionFlowCoordinator: CoordinatorProtocol {
let userIndicatorController = UserIndicatorController(rootCoordinator: feedbackNavigationStackCoordinator)
let parameters = BugReportCoordinatorParameters(bugReportService: bugReportService,
userID: userSession.userID,
deviceID: userSession.deviceID,
userIndicatorController: userIndicatorController,
screenshot: image,
isModallyPresented: true)

View File

@@ -121,6 +121,8 @@ class MockScreen: Identifiable {
case .bugReport:
let navigationStackCoordinator = NavigationStackCoordinator()
let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
userID: "@mock:client.com",
deviceID: nil,
userIndicatorController: nil,
screenshot: nil,
isModallyPresented: true))
@@ -129,6 +131,8 @@ class MockScreen: Identifiable {
case .bugReportWithScreenshot:
let navigationStackCoordinator = NavigationStackCoordinator()
let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
userID: "@mock:client.com",
deviceID: nil,
userIndicatorController: nil,
screenshot: Asset.Images.appLogo.image,
isModallyPresented: false))

View File

@@ -26,7 +26,9 @@ class BugReportServiceTests: XCTestCase {
}
func testSubmitBugReportWithMockService() async throws {
let bugReport = BugReport(text: "i cannot send message",
let bugReport = BugReport(userID: "@mock:client.com",
deviceID: nil,
text: "i cannot send message",
includeLogs: true,
includeCrashLog: true,
githubLabels: [],
@@ -49,7 +51,9 @@ class BugReportServiceTests: XCTestCase {
applicationId: "mock_app_id",
session: .mock)
let bugReport = BugReport(text: "i cannot send message",
let bugReport = BugReport(userID: "@mock:client.com",
deviceID: nil,
text: "i cannot send message",
includeLogs: true,
includeCrashLog: true,
githubLabels: [],

View File

@@ -21,25 +21,36 @@ import XCTest
@MainActor
class BugReportViewModelTests: XCTestCase {
func testInitialState() {
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: nil, isModallyPresented: false)
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
userID: "@mock.client.com",
deviceID: nil,
screenshot: nil,
isModallyPresented: false)
let context = viewModel.context
XCTAssertEqual(context.reportText, "")
XCTAssertNil(context.viewState.screenshot)
XCTAssertTrue(context.sendingLogsEnabled)
}
func testClearScreenshot() async throws {
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: UIImage.actions, isModallyPresented: false)
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
userID: "@mock.client.com",
deviceID: nil,
screenshot: UIImage.actions,
isModallyPresented: false)
let context = viewModel.context
context.send(viewAction: .removeScreenshot)
try await Task.sleep(nanoseconds: 100_000_000)
XCTAssertNil(context.viewState.screenshot)
}
func testAttachScreenshot() async throws {
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(), screenshot: nil, isModallyPresented: false)
let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
userID: "@mock.client.com",
deviceID: nil,
screenshot: nil, isModallyPresented: false)
let context = viewModel.context
XCTAssertNil(context.viewState.screenshot)
context.send(viewAction: .attachScreenshot(UIImage.actions))