* Fixes #614 - Add the user and device identifiers to rageshakes * Add `base_bundle_identifier` to rageshakes
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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))
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user