diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt
index 79b05ea32e..631a51a686 100644
--- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt
+++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/reporter/BugReporter.kt
@@ -20,6 +20,7 @@ interface BugReporter {
* @param problemDescription the bug description
* @param canContact true if the user opt in to be contacted directly
* @param sendPushRules true to include the push rules
+ * @param ghIssueNumber it not null, the GitHub issue number to link the bug report to.
* @param listener the listener
*/
suspend fun sendBugReport(
@@ -29,6 +30,7 @@ interface BugReporter {
problemDescription: String,
canContact: Boolean = false,
sendPushRules: Boolean = false,
+ ghIssueNumber: Int? = null,
listener: BugReporterListener
)
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt
index 90751873dd..94897d1bad 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportEvents.kt
@@ -18,4 +18,5 @@ sealed interface BugReportEvents {
data class SetCanContact(val canContact: Boolean) : BugReportEvents
data class SetSendScreenshot(val sendScreenshot: Boolean) : BugReportEvents
data class SetSendPushRules(val sendPushRules: Boolean) : BugReportEvents
+ data class SetGhIssueNumber(val ghIssueNumber: Int?) : BugReportEvents
}
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt
index 4985f9b30e..85731ae959 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenter.kt
@@ -113,6 +113,9 @@ class BugReportPresenter(
sendingProgress.floatValue = 0f
sendingAction.value = AsyncAction.Uninitialized
}
+ is BugReportEvents.SetGhIssueNumber -> updateFormState(formState) {
+ copy(ghIssueNumber = event.ghIssueNumber)
+ }
}
}
@@ -142,7 +145,8 @@ class BugReportPresenter(
problemDescription = formState.description,
canContact = formState.canContact,
sendPushRules = formState.sendPushRules,
- listener = listener
+ ghIssueNumber = formState.ghIssueNumber,
+ listener = listener,
)
}
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt
index 65cc055ec9..8e07b3c4e8 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportState.kt
@@ -32,6 +32,7 @@ data class BugReportFormState(
val canContact: Boolean,
val sendScreenshot: Boolean,
val sendPushRules: Boolean,
+ val ghIssueNumber: Int?,
) : Parcelable {
companion object {
val Default = BugReportFormState(
@@ -40,6 +41,7 @@ data class BugReportFormState(
canContact = false,
sendScreenshot = false,
sendPushRules = false,
+ ghIssueNumber = null,
)
}
}
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
index c2c34835c9..36b407a669 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt
@@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import coil3.request.CachePolicy
import coil3.request.ImageRequest
+import io.element.android.compound.theme.ElementTheme
import io.element.android.features.rageshake.impl.R
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.async.AsyncActionView
@@ -155,6 +156,48 @@ fun BugReportView(
title = stringResource(R.string.screen_bug_report_send_notification_settings_title),
subtitle = stringResource(R.string.screen_bug_report_send_notification_settings_description),
)
+ PreferenceRow {
+ var ghIssueNumberState by textFieldState(
+ stateValue = state.formState.ghIssueNumber?.toString() ?: ""
+ )
+ TextField(
+ value = ghIssueNumberState,
+ modifier = Modifier
+ .fillMaxWidth()
+ .onTabOrEnterKeyFocusNext(LocalFocusManager.current),
+ enabled = isFormEnabled,
+ label = stringResource(id = R.string.screen_bug_report_github_issue_label),
+ placeholder = "1234",
+ supportingText = stringResource(id = R.string.screen_bug_report_github_issue_description),
+ leadingIcon = {
+ Text(
+ text = "#",
+ style = ElementTheme.typography.fontBodyLgMedium,
+ color = ElementTheme.colors.textSecondary,
+ )
+ },
+ onValueChange = {
+ if (it.isEmpty()) {
+ ghIssueNumberState = ""
+ eventSink(BugReportEvents.SetGhIssueNumber(null))
+ } else {
+ val number = it.toIntOrNull()?.takeIf { ghInt -> ghInt in 1..99_999 }
+ number?.let { ghIssueNumber ->
+ ghIssueNumberState = ghIssueNumber.toString()
+ eventSink(BugReportEvents.SetGhIssueNumber(ghIssueNumber))
+ }
+ }
+ },
+ keyboardOptions = KeyboardOptions(
+ keyboardType = KeyboardType.Number,
+ imeAction = ImeAction.Next,
+ ),
+ keyboardActions = KeyboardActions(onNext = {
+ keyboardController?.hide()
+ }),
+ singleLine = true,
+ )
+ }
// Submit
PreferenceRow {
Button(
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
index 2568a6fba9..735bb1cea0 100755
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
@@ -123,6 +123,7 @@ class DefaultBugReporter(
problemDescription: String,
canContact: Boolean,
sendPushRules: Boolean,
+ ghIssueNumber: Int?,
listener: BugReporterListener,
) {
val url = bugReporterUrlProvider.provide().first()
@@ -144,6 +145,9 @@ class DefaultBugReporter(
val crashCallStack = crashDataStore.crashInfo().first()
val bugDescription = buildString {
append(problemDescription)
+ ghIssueNumber?.let {
+ append("\n\nhttps://github.com/element-hq/element-x-android/issues/$it")
+ }
if (crashCallStack.isNotEmpty() && withCrashLogs) {
append("\n\n\n\n--------------------------------- crash call stack ---------------------------------\n")
append(crashCallStack)
diff --git a/features/rageshake/impl/src/main/res/values/localazy.xml b/features/rageshake/impl/src/main/res/values/localazy.xml
index 85af2af4a7..d1dc52f3e4 100644
--- a/features/rageshake/impl/src/main/res/values/localazy.xml
+++ b/features/rageshake/impl/src/main/res/values/localazy.xml
@@ -8,6 +8,8 @@
"Describe the problem…"
"If possible, please write the description in English."
"The description is too short, please provide more details about what happened. Thanks!"
+ "You can enter the number of an associated GitHub issue, if any."
+ "GitHub issue"
"Send crash logs"
"Allow logs"
"Your logs are excessively large so cannot be included in this report, please send them to us another way."
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt
index 148c375e25..afbcc939a6 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt
@@ -107,6 +107,18 @@ class BugReportPresenterTest {
}
}
+ @Test
+ fun `present - set GitHub issue number`() = runTest {
+ val presenter = createPresenter()
+ presenter.test {
+ val initialState = awaitItem()
+ initialState.eventSink.invoke(BugReportEvents.SetGhIssueNumber(1))
+ assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(ghIssueNumber = 1))
+ initialState.eventSink.invoke(BugReportEvents.SetGhIssueNumber(null))
+ assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(ghIssueNumber = null))
+ }
+ }
+
@Test
fun `present - reset all`() = runTest {
val presenter = createPresenter(
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt
index 36cc185e86..659145caa9 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/FakeBugReporter.kt
@@ -28,6 +28,7 @@ class FakeBugReporter(val mode: Mode = Mode.Success) : BugReporter {
problemDescription: String,
canContact: Boolean,
sendPushRules: Boolean,
+ ghIssueNumber: Int?,
listener: BugReporterListener,
) {
delay(100)
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png
index b81b524b86..0599f2300a 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4a10513e98757e17cc3ffb8302807896839a78d036331e79bb207686f3f9db86
-size 47842
+oid sha256:a4b243025f40d5d4a91e32d59a6cac9ec21a273aaddbfac020cb26b3dc86c906
+size 53339
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png
index 0700c94bb7..9e2407229c 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_1_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:05efb0fa45bb6440e75e9280b219cfdac83c372efe9e6d6254b4bbe516f8b998
-size 112842
+oid sha256:e98722e0c21fe6b509b2bdf4a9ce7f78a1c83b606411329d2fd97a676fc4bed3
+size 113728
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png
index 61e347497e..bfd0f366be 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:833d21633cb0f153b660112fcfd0923c588cd26b64005403a007d7782ecfe5d5
-size 45138
+oid sha256:44eed3e8a093977f51d706acbec65cf29d592dcf0af3cdc9fce85d2b8e570eb9
+size 51038
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png
index b81b524b86..0599f2300a 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4a10513e98757e17cc3ffb8302807896839a78d036331e79bb207686f3f9db86
-size 47842
+oid sha256:a4b243025f40d5d4a91e32d59a6cac9ec21a273aaddbfac020cb26b3dc86c906
+size 53339
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png
index 948604dd84..1a5d877a24 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewDay_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ebe22ec065cc6dff2133dcc573a82e003d9061ae0446c2d8c13f4e1fba1f3c19
-size 37056
+oid sha256:781287977ff2637fe6479c3653270783c4374bc10fffb91da8b45d4e4f588a98
+size 41744
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png
index 9b379990c3..3fea4591cd 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_0_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f647e92bf813ead7affcdb6ad07076fe9d739f6a4c0016b9787912f032e27476
-size 46567
+oid sha256:f690c34f97eec23f01bfdc3c2606a229bb12abb91fe86fb79c89da79b08480a0
+size 52049
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png
index fcdfe6ba7d..957e19a4ce 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_1_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cdfbb9f70a97724a1b6687ad4f199efc2c9bcc5f29fe9475a17ee6e52e5ecf8e
-size 110829
+oid sha256:751b442e5aecd9d3938817f8a1af11b7cc1d250c1166c9e8bd3154a85268471d
+size 111765
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png
index 6760c96a86..390d0faf7e 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_2_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:1cfab4886243e6c914f466f5f127ec0347b0ab30ee43fb95c7bc82d2b16325d5
-size 43727
+oid sha256:0719e803112640729fe2b59c40373343db3e9f2e8dded9258d4b6c44547f8fd1
+size 49420
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png
index 9b379990c3..3fea4591cd 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_3_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f647e92bf813ead7affcdb6ad07076fe9d739f6a4c0016b9787912f032e27476
-size 46567
+oid sha256:f690c34f97eec23f01bfdc3c2606a229bb12abb91fe86fb79c89da79b08480a0
+size 52049
diff --git a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png
index 6b7ad4a825..4fd1ecbc0e 100644
--- a/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.rageshake.impl.bugreport_BugReportViewNight_4_en.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8c24515cc18b3c5cc52f2acfcee4faa65c02d8d5c8be847d4b1ec5671a858210
-size 35201
+oid sha256:1cb10ddf4a9dee4a001276554cf32cf874062e1e5d7d0ebb673f6417641530bf
+size 39730