mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
* 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,
|
let credentials = SoftLogoutCredentials(userId: userSession.userID,
|
||||||
homeserverName: userSession.homeserver,
|
homeserverName: userSession.homeserver,
|
||||||
userDisplayName: displayName,
|
userDisplayName: displayName,
|
||||||
deviceId: userSession.deviceId)
|
deviceId: userSession.deviceID)
|
||||||
|
|
||||||
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore)
|
let authenticationService = AuthenticationServiceProxy(userSessionStore: userSessionStore)
|
||||||
_ = await authenticationService.configure(for: userSession.homeserver)
|
_ = await authenticationService.configure(for: userSession.homeserver)
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ enum BugReportCoordinatorResult {
|
|||||||
|
|
||||||
struct BugReportCoordinatorParameters {
|
struct BugReportCoordinatorParameters {
|
||||||
let bugReportService: BugReportServiceProtocol
|
let bugReportService: BugReportServiceProtocol
|
||||||
|
let userID: String
|
||||||
|
let deviceID: String?
|
||||||
|
|
||||||
weak var userIndicatorController: UserIndicatorControllerProtocol?
|
weak var userIndicatorController: UserIndicatorControllerProtocol?
|
||||||
let screenshot: UIImage?
|
let screenshot: UIImage?
|
||||||
let isModallyPresented: Bool
|
let isModallyPresented: Bool
|
||||||
@@ -38,6 +41,8 @@ final class BugReportCoordinator: CoordinatorProtocol {
|
|||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
||||||
viewModel = BugReportViewModel(bugReportService: parameters.bugReportService,
|
viewModel = BugReportViewModel(bugReportService: parameters.bugReportService,
|
||||||
|
userID: parameters.userID,
|
||||||
|
deviceID: parameters.deviceID,
|
||||||
screenshot: parameters.screenshot,
|
screenshot: parameters.screenshot,
|
||||||
isModallyPresented: parameters.isModallyPresented)
|
isModallyPresented: parameters.isModallyPresented)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,21 @@ import SwiftUI
|
|||||||
typealias BugReportViewModelType = StateStoreViewModel<BugReportViewState, BugReportViewAction>
|
typealias BugReportViewModelType = StateStoreViewModel<BugReportViewState, BugReportViewAction>
|
||||||
|
|
||||||
class BugReportViewModel: BugReportViewModelType, BugReportViewModelProtocol {
|
class BugReportViewModel: BugReportViewModelType, BugReportViewModelProtocol {
|
||||||
let bugReportService: BugReportServiceProtocol
|
private let bugReportService: BugReportServiceProtocol
|
||||||
|
private let userID: String
|
||||||
|
private let deviceID: String?
|
||||||
|
|
||||||
var callback: ((BugReportViewModelAction) -> Void)?
|
var callback: ((BugReportViewModelAction) -> Void)?
|
||||||
|
|
||||||
init(bugReportService: BugReportServiceProtocol,
|
init(bugReportService: BugReportServiceProtocol,
|
||||||
|
userID: String,
|
||||||
|
deviceID: String?,
|
||||||
screenshot: UIImage?,
|
screenshot: UIImage?,
|
||||||
isModallyPresented: Bool) {
|
isModallyPresented: Bool) {
|
||||||
self.bugReportService = bugReportService
|
self.bugReportService = bugReportService
|
||||||
|
self.userID = userID
|
||||||
|
self.deviceID = deviceID
|
||||||
|
|
||||||
let bindings = BugReportViewStateBindings(reportText: "", sendingLogsEnabled: true)
|
let bindings = BugReportViewStateBindings(reportText: "", sendingLogsEnabled: true)
|
||||||
super.init(initialViewState: BugReportViewState(screenshot: screenshot,
|
super.init(initialViewState: BugReportViewState(screenshot: screenshot,
|
||||||
bindings: bindings,
|
bindings: bindings,
|
||||||
@@ -61,7 +68,9 @@ class BugReportViewModel: BugReportViewModelType, BugReportViewModelProtocol {
|
|||||||
try pngData?.write(to: imageURL)
|
try pngData?.write(to: imageURL)
|
||||||
files.append(imageURL)
|
files.append(imageURL)
|
||||||
}
|
}
|
||||||
let bugReport = BugReport(text: context.reportText,
|
let bugReport = BugReport(userID: userID,
|
||||||
|
deviceID: deviceID,
|
||||||
|
text: context.reportText,
|
||||||
includeLogs: context.sendingLogsEnabled,
|
includeLogs: context.sendingLogsEnabled,
|
||||||
includeCrashLog: true,
|
includeCrashLog: true,
|
||||||
githubLabels: [],
|
githubLabels: [],
|
||||||
|
|||||||
@@ -173,12 +173,16 @@ struct BugReportScreen: View {
|
|||||||
|
|
||||||
struct BugReport_Previews: PreviewProvider {
|
struct BugReport_Previews: PreviewProvider {
|
||||||
static let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
|
static let viewModel = BugReportViewModel(bugReportService: MockBugReportService(),
|
||||||
|
userID: "@mock.client.com",
|
||||||
|
deviceID: nil,
|
||||||
screenshot: nil,
|
screenshot: nil,
|
||||||
isModallyPresented: false)
|
isModallyPresented: false)
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
BugReportScreen(context: BugReportViewModel(bugReportService: MockBugReportService(),
|
BugReportScreen(context: BugReportViewModel(bugReportService: MockBugReportService(),
|
||||||
|
userID: "@mock.client.com",
|
||||||
|
deviceID: nil,
|
||||||
screenshot: nil,
|
screenshot: nil,
|
||||||
isModallyPresented: false).context)
|
isModallyPresented: false).context)
|
||||||
.previewDisplayName("Without Screenshot")
|
.previewDisplayName("Without Screenshot")
|
||||||
@@ -186,6 +190,8 @@ struct BugReport_Previews: PreviewProvider {
|
|||||||
|
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
BugReportScreen(context: BugReportViewModel(bugReportService: MockBugReportService(),
|
BugReportScreen(context: BugReportViewModel(bugReportService: MockBugReportService(),
|
||||||
|
userID: "@mock.client.com",
|
||||||
|
deviceID: nil,
|
||||||
screenshot: Asset.Images.appLogo.image,
|
screenshot: Asset.Images.appLogo.image,
|
||||||
isModallyPresented: false).context)
|
isModallyPresented: false).context)
|
||||||
.previewDisplayName("With Screenshot")
|
.previewDisplayName("With Screenshot")
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ final class SettingsScreenCoordinator: CoordinatorProtocol {
|
|||||||
|
|
||||||
private func presentBugReportScreen() {
|
private func presentBugReportScreen() {
|
||||||
let params = BugReportCoordinatorParameters(bugReportService: parameters.bugReportService,
|
let params = BugReportCoordinatorParameters(bugReportService: parameters.bugReportService,
|
||||||
|
userID: parameters.userSession.userID,
|
||||||
|
deviceID: parameters.userSession.deviceID,
|
||||||
userIndicatorController: parameters.userIndicatorController,
|
userIndicatorController: parameters.userIndicatorController,
|
||||||
screenshot: nil,
|
screenshot: nil,
|
||||||
isModallyPresented: false)
|
isModallyPresented: false)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
|
|||||||
self.userSession = userSession
|
self.userSession = userSession
|
||||||
let bindings = SettingsScreenViewStateBindings(timelineStyle: ServiceLocator.shared.settings.timelineStyle)
|
let bindings = SettingsScreenViewStateBindings(timelineStyle: ServiceLocator.shared.settings.timelineStyle)
|
||||||
super.init(initialViewState: .init(bindings: bindings,
|
super.init(initialViewState: .init(bindings: bindings,
|
||||||
deviceID: userSession.deviceId,
|
deviceID: userSession.deviceID,
|
||||||
userID: userSession.userID,
|
userID: userSession.userID,
|
||||||
showSessionVerificationSection: !(userSession.sessionVerificationController?.isVerified ?? false),
|
showSessionVerificationSection: !(userSession.sessionVerificationController?.isVerified ?? false),
|
||||||
showDeveloperOptions: ServiceLocator.shared.settings.canShowDeveloperOptions),
|
showDeveloperOptions: ServiceLocator.shared.settings.canShowDeveloperOptions),
|
||||||
|
|||||||
@@ -78,10 +78,19 @@ class BugReportService: NSObject, BugReportServiceProtocol {
|
|||||||
SentrySDK.crash()
|
SentrySDK.crash()
|
||||||
}
|
}
|
||||||
|
|
||||||
func submitBugReport(_ bugReport: BugReport,
|
// swiftlint:disable:next function_body_length
|
||||||
progressListener: ProgressListener?) async throws -> SubmitBugReportResponse {
|
func submitBugReport(_ bugReport: BugReport, progressListener: ProgressListener?) async throws -> SubmitBugReportResponse {
|
||||||
var params = [MultipartFormData(key: "text", type: .text(value: bugReport.text))]
|
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)
|
params.append(contentsOf: defaultParams)
|
||||||
|
|
||||||
for label in bugReport.githubLabels {
|
for label in bugReport.githubLabels {
|
||||||
params.append(MultipartFormData(key: "label", type: .text(value: label)))
|
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: "user_language", type: .text(value: Bundle.elementLanguage ?? "null")),
|
||||||
MultipartFormData(key: "fallback_language", type: .text(value: Bundle.elementFallbackLanguage ?? "null")),
|
MultipartFormData(key: "fallback_language", type: .text(value: Bundle.elementFallbackLanguage ?? "null")),
|
||||||
MultipartFormData(key: "local_time", type: .text(value: localTime)),
|
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
|
import UIKit
|
||||||
|
|
||||||
struct BugReport {
|
struct BugReport {
|
||||||
|
let userID: String
|
||||||
|
let deviceID: String?
|
||||||
let text: String
|
let text: String
|
||||||
let includeLogs: Bool
|
let includeLogs: Bool
|
||||||
let includeCrashLog: Bool
|
let includeCrashLog: Bool
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct MockUserSession: UserSessionProtocol {
|
|||||||
let sessionVerificationController: SessionVerificationControllerProxyProtocol? = nil
|
let sessionVerificationController: SessionVerificationControllerProxyProtocol? = nil
|
||||||
var userID: String { clientProxy.userID }
|
var userID: String { clientProxy.userID }
|
||||||
var isSoftLogout: Bool { clientProxy.isSoftLogout }
|
var isSoftLogout: Bool { clientProxy.isSoftLogout }
|
||||||
var deviceId: String? { clientProxy.deviceId }
|
var deviceID: String? { clientProxy.deviceId }
|
||||||
var homeserver: String { clientProxy.homeserver }
|
var homeserver: String { clientProxy.homeserver }
|
||||||
let clientProxy: ClientProxyProtocol
|
let clientProxy: ClientProxyProtocol
|
||||||
let mediaProvider: MediaProviderProtocol
|
let mediaProvider: MediaProviderProtocol
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class UserSession: UserSessionProtocol {
|
|||||||
|
|
||||||
var userID: String { clientProxy.userID }
|
var userID: String { clientProxy.userID }
|
||||||
var isSoftLogout: Bool { clientProxy.isSoftLogout }
|
var isSoftLogout: Bool { clientProxy.isSoftLogout }
|
||||||
var deviceId: String? { clientProxy.deviceId }
|
var deviceID: String? { clientProxy.deviceId }
|
||||||
var homeserver: String { clientProxy.homeserver }
|
var homeserver: String { clientProxy.homeserver }
|
||||||
|
|
||||||
let clientProxy: ClientProxyProtocol
|
let clientProxy: ClientProxyProtocol
|
||||||
|
|||||||
@@ -25,10 +25,11 @@ enum UserSessionCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protocol UserSessionProtocol {
|
protocol UserSessionProtocol {
|
||||||
var userID: String { get }
|
|
||||||
var isSoftLogout: Bool { get }
|
|
||||||
var deviceId: String? { get }
|
|
||||||
var homeserver: String { get }
|
var homeserver: String { get }
|
||||||
|
var userID: String { get }
|
||||||
|
var deviceID: String? { get }
|
||||||
|
|
||||||
|
var isSoftLogout: Bool { get }
|
||||||
|
|
||||||
var clientProxy: ClientProxyProtocol { get }
|
var clientProxy: ClientProxyProtocol { get }
|
||||||
var mediaProvider: MediaProviderProtocol { get }
|
var mediaProvider: MediaProviderProtocol { get }
|
||||||
|
|||||||
@@ -244,6 +244,8 @@ class UserSessionFlowCoordinator: CoordinatorProtocol {
|
|||||||
let userIndicatorController = UserIndicatorController(rootCoordinator: feedbackNavigationStackCoordinator)
|
let userIndicatorController = UserIndicatorController(rootCoordinator: feedbackNavigationStackCoordinator)
|
||||||
|
|
||||||
let parameters = BugReportCoordinatorParameters(bugReportService: bugReportService,
|
let parameters = BugReportCoordinatorParameters(bugReportService: bugReportService,
|
||||||
|
userID: userSession.userID,
|
||||||
|
deviceID: userSession.deviceID,
|
||||||
userIndicatorController: userIndicatorController,
|
userIndicatorController: userIndicatorController,
|
||||||
screenshot: image,
|
screenshot: image,
|
||||||
isModallyPresented: true)
|
isModallyPresented: true)
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ class MockScreen: Identifiable {
|
|||||||
case .bugReport:
|
case .bugReport:
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
|
let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
|
||||||
|
userID: "@mock:client.com",
|
||||||
|
deviceID: nil,
|
||||||
userIndicatorController: nil,
|
userIndicatorController: nil,
|
||||||
screenshot: nil,
|
screenshot: nil,
|
||||||
isModallyPresented: true))
|
isModallyPresented: true))
|
||||||
@@ -129,6 +131,8 @@ class MockScreen: Identifiable {
|
|||||||
case .bugReportWithScreenshot:
|
case .bugReportWithScreenshot:
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
|
let coordinator = BugReportCoordinator(parameters: .init(bugReportService: MockBugReportService(),
|
||||||
|
userID: "@mock:client.com",
|
||||||
|
deviceID: nil,
|
||||||
userIndicatorController: nil,
|
userIndicatorController: nil,
|
||||||
screenshot: Asset.Images.appLogo.image,
|
screenshot: Asset.Images.appLogo.image,
|
||||||
isModallyPresented: false))
|
isModallyPresented: false))
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ class BugReportServiceTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSubmitBugReportWithMockService() async throws {
|
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,
|
includeLogs: true,
|
||||||
includeCrashLog: true,
|
includeCrashLog: true,
|
||||||
githubLabels: [],
|
githubLabels: [],
|
||||||
@@ -49,7 +51,9 @@ class BugReportServiceTests: XCTestCase {
|
|||||||
applicationId: "mock_app_id",
|
applicationId: "mock_app_id",
|
||||||
session: .mock)
|
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,
|
includeLogs: true,
|
||||||
includeCrashLog: true,
|
includeCrashLog: true,
|
||||||
githubLabels: [],
|
githubLabels: [],
|
||||||
|
|||||||
@@ -21,25 +21,36 @@ import XCTest
|
|||||||
@MainActor
|
@MainActor
|
||||||
class BugReportViewModelTests: XCTestCase {
|
class BugReportViewModelTests: XCTestCase {
|
||||||
func testInitialState() {
|
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
|
let context = viewModel.context
|
||||||
|
|
||||||
XCTAssertEqual(context.reportText, "")
|
XCTAssertEqual(context.reportText, "")
|
||||||
XCTAssertNil(context.viewState.screenshot)
|
XCTAssertNil(context.viewState.screenshot)
|
||||||
XCTAssertTrue(context.sendingLogsEnabled)
|
XCTAssertTrue(context.sendingLogsEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testClearScreenshot() async throws {
|
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
|
let context = viewModel.context
|
||||||
|
|
||||||
context.send(viewAction: .removeScreenshot)
|
context.send(viewAction: .removeScreenshot)
|
||||||
try await Task.sleep(nanoseconds: 100_000_000)
|
try await Task.sleep(nanoseconds: 100_000_000)
|
||||||
XCTAssertNil(context.viewState.screenshot)
|
XCTAssertNil(context.viewState.screenshot)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAttachScreenshot() async throws {
|
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
|
let context = viewModel.context
|
||||||
XCTAssertNil(context.viewState.screenshot)
|
XCTAssertNil(context.viewState.screenshot)
|
||||||
context.send(viewAction: .attachScreenshot(UIImage.actions))
|
context.send(viewAction: .attachScreenshot(UIImage.actions))
|
||||||
|
|||||||
Reference in New Issue
Block a user