Repository: element-hq/element-x-android (language: kotlin)

Issue:
Move the Push history screen to Developer options
The Push history is a developer focused screen. It is very technical and needs good knowledge of the Matrix protocol and push rules to use it. It is expected to have errors there like for unread pushes pushes for example. As developers, we cannot expect non tech people to make a good use of it. We have a dedicated section of the app for this with the Developer options. Tech people knows about it.

On the other hand, the Troubleshooting screen is useful to everyone. It's important to keep it. Everyone can solve their own problem, for example, by allowing notifications.


Discussion hints:
nan

Pull request: Move push history entry point from notification settings to developer settings

<!-- Please read [CONTRIBUTING.md](https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md) before submitting your pull request -->
 
## Content

<!-- Describe shortly what has been changed -->
Move push history entry point from notification settings to developer settings

## Motivation and context

<!-- Provide link to the corresponding issue if applicable or explain the context -->
Closes #5159

## Screenshots / GIFs

<!--
We have screenshot tests in the project, so attaching screenshots to a PR is not mandatory, as far as there
is a Composable Preview covering the changes. In this case, the change will appear in the file diff.
Note that all the UI composables should be covered by a Composable Preview.

Providing a video of the change is still very useful for the reviewer and for the history of the project.

You can use a table like this to show screenshots comparison.
Uncomment this markdown table below and edit the last line `|||`:
|copy screenshot of before here|copy screenshot of after here|

|Before|After|
|-|-|
|||
 -->

## Tests

<!-- Explain how you tested your development -->

- Check the new entry point location of "Push history"

## Tested devices

- [ ] Physical
- [x] Emulator
- OS version(s):

## Checklist

<!-- Depending on the Pull Request content, it can be acceptable if some of the following checkboxes stay unchecked. -->

- [ ] Changes have been tested on an Android device or Android emulator with API 24
- [ ] UI change has been tested on both light and dark themes
- [ ] Accessibility has been taken into account. See https://github.com/element-hq/element-x-android/blob/develop/CONTRIBUTING.md#accessibility
- [ ] Pull request is based on the develop branch
- [ ] Pull request title will be used in the release note, it clearly define what will change for the user
- [ ] Pull request includes screenshots or videos if containing UI changes
- [ ] You've made a self review of your PR


Test command: ./gradlew :features:preferences:impl:testDebugUnitTest --tests "io.element.android.features.preferences.impl.developer.DeveloperSettingsViewTest" --tests "io.element.android.features.preferences.impl.notifications.NotificationSettingsViewTest"

Fix patch:
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt
index 234b4c683b0..b38b835f362 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt
@@ -167,7 +167,12 @@ class PreferencesFlowNode @AssistedInject constructor(
                 createNode<PreferencesRootNode>(buildContext, plugins = listOf(callback))
             }
             NavTarget.DeveloperSettings -> {
-                createNode<DeveloperSettingsNode>(buildContext)
+                val developerSettingsCallback = object : DeveloperSettingsNode.Callback {
+                    override fun onPushHistoryClick() {
+                        backstack.push(NavTarget.PushHistory)
+                    }
+                }
+                createNode<DeveloperSettingsNode>(buildContext, listOf(developerSettingsCallback))
             }
             NavTarget.About -> {
                 val callback = object : AboutNode.Callback {
@@ -189,10 +194,6 @@ class PreferencesFlowNode @AssistedInject constructor(
                     override fun onTroubleshootNotificationsClick() {
                         backstack.push(NavTarget.TroubleshootNotifications)
                     }
-
-                    override fun onPushHistoryClick() {
-                        backstack.push(NavTarget.PushHistory)
-                    }
                 }
                 createNode<NotificationSettingsNode>(buildContext, listOf(notificationSettingsCallback))
             }
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt
index fafe5fc9205..392a6af903d 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsNode.kt
@@ -14,6 +14,7 @@ import com.airbnb.android.showkase.models.Showkase
 import com.bumble.appyx.core.modality.BuildContext
 import com.bumble.appyx.core.node.Node
 import com.bumble.appyx.core.plugin.Plugin
+import com.bumble.appyx.core.plugin.plugins
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedInject
 import io.element.android.anvilannotations.ContributesNode
@@ -26,6 +27,16 @@ class DeveloperSettingsNode @AssistedInject constructor(
     @Assisted plugins: List<Plugin>,
     private val presenter: DeveloperSettingsPresenter,
 ) : Node(buildContext, plugins = plugins) {
+    interface Callback : Plugin {
+        fun onPushHistoryClick()
+    }
+
+    private val callbacks = plugins<Callback>()
+
+    private fun onPushHistoryClick() {
+        callbacks.forEach { it.onPushHistoryClick() }
+    }
+
     @Composable
     override fun View(modifier: Modifier) {
         val activity = requireNotNull(LocalActivity.current)
@@ -39,6 +50,7 @@ class DeveloperSettingsNode @AssistedInject constructor(
             state = state,
             modifier = modifier,
             onOpenShowkase = ::openShowkase,
+            onPushHistoryClick = ::onPushHistoryClick,
             onBackClick = ::navigateUp
         )
     }
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
index 9a9cc61d680..e00b178dee7 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt
@@ -42,6 +42,7 @@ import kotlinx.collections.immutable.toPersistentList
 fun DeveloperSettingsView(
     state: DeveloperSettingsState,
     onOpenShowkase: () -> Unit,
+    onPushHistoryClick: () -> Unit,
     onBackClick: () -> Unit,
     modifier: Modifier = Modifier,
 ) {
@@ -57,6 +58,7 @@ fun DeveloperSettingsView(
         ) {
             FeatureListContent(state)
         }
+        NotificationCategory(onPushHistoryClick)
         ElementCallCategory(state = state)
 
         PreferenceCategory(title = "Rust SDK") {
@@ -159,6 +161,18 @@ private fun ElementCallCategory(
     }
 }
 
+@Composable
+private fun NotificationCategory(onPushHistoryClick: () -> Unit) {
+    PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_title)) {
+        ListItem(
+            headlineContent = {
+                Text(stringResource(R.string.troubleshoot_notifications_entry_point_push_history_title))
+            },
+            onClick = onPushHistoryClick,
+        )
+    }
+}
+
 @Composable
 private fun FeatureListContent(
     state: DeveloperSettingsState,
@@ -179,6 +193,7 @@ internal fun DeveloperSettingsViewPreview(@PreviewParameter(DeveloperSettingsSta
     DeveloperSettingsView(
         state = state,
         onOpenShowkase = {},
+        onPushHistoryClick = {},
         onBackClick = {}
     )
 }
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt
index 75f38f60eeb..15a6afcd89a 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsNode.kt
@@ -27,7 +27,6 @@ class NotificationSettingsNode @AssistedInject constructor(
     interface Callback : Plugin {
         fun editDefaultNotificationMode(isOneToOne: Boolean)
         fun onTroubleshootNotificationsClick()
-        fun onPushHistoryClick()
     }
 
     private val callbacks = plugins<Callback>()
@@ -40,10 +39,6 @@ class NotificationSettingsNode @AssistedInject constructor(
         callbacks.forEach { it.onTroubleshootNotificationsClick() }
     }
 
-    private fun onPushHistoryClick() {
-        callbacks.forEach { it.onPushHistoryClick() }
-    }
-
     @Composable
     override fun View(modifier: Modifier) {
         val state = presenter.present()
@@ -52,7 +47,6 @@ class NotificationSettingsNode @AssistedInject constructor(
             onOpenEditDefault = { openEditDefault(isOneToOne = it) },
             onBackClick = ::navigateUp,
             onTroubleshootNotificationsClick = ::onTroubleshootNotificationsClick,
-            onPushHistoryClick = ::onPushHistoryClick,
             modifier = modifier,
         )
     }
diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
index f73fecaf3c4..26b2de590e3 100644
--- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
+++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt
@@ -51,7 +51,6 @@ fun NotificationSettingsView(
     state: NotificationSettingsState,
     onOpenEditDefault: (isOneToOne: Boolean) -> Unit,
     onTroubleshootNotificationsClick: () -> Unit,
-    onPushHistoryClick: () -> Unit,
     onBackClick: () -> Unit,
     modifier: Modifier = Modifier,
 ) {
@@ -84,7 +83,6 @@ fun NotificationSettingsView(
 //                onCallsNotificationsChanged = { state.eventSink(NotificationSettingsEvents.SetCallNotificationsEnabled(it)) },
                 onInviteForMeNotificationsChange = { state.eventSink(NotificationSettingsEvents.SetInviteForMeNotificationsEnabled(it)) },
                 onTroubleshootNotificationsClick = onTroubleshootNotificationsClick,
-                onPushHistoryClick = onPushHistoryClick,
             )
         }
         AsyncActionView(
@@ -108,7 +106,6 @@ private fun NotificationSettingsContentView(
 //    onCallsNotificationsChanged: (Boolean) -> Unit,
     onInviteForMeNotificationsChange: (Boolean) -> Unit,
     onTroubleshootNotificationsClick: () -> Unit,
-    onPushHistoryClick: () -> Unit,
 ) {
     val context = LocalContext.current
     val systemSettings: NotificationSettingsState.AppSettings = state.appSettings
@@ -207,12 +204,6 @@ private fun NotificationSettingsContentView(
                 },
                 onClick = onTroubleshootNotificationsClick
             )
-            ListItem(
-                headlineContent = {
-                    Text(stringResource(R.string.troubleshoot_notifications_entry_point_push_history_title))
-                },
-                onClick = onPushHistoryClick
-            )
         }
         if (state.showAdvancedSettings) {
             PreferenceCategory(title = stringResource(id = CommonStrings.common_advanced_settings)) {
@@ -313,6 +304,5 @@ internal fun NotificationSettingsViewPreview(@PreviewParameter(NotificationSetti
         onBackClick = {},
         onOpenEditDefault = {},
         onTroubleshootNotificationsClick = {},
-        onPushHistoryClick = {},
     )
 }


Test patch:
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt
index 5d0030af8e0..f10fdc93c46 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsViewTest.kt
@@ -52,6 +52,21 @@ class DeveloperSettingsViewTest {
         }
     }
 
+    @Config(qualifiers = "h1500dp")
+    @Test
+    fun `clicking on push history notification invokes the expected callback`() {
+        val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>(expectEvents = false)
+        ensureCalledOnce {
+            rule.setDeveloperSettingsView(
+                state = aDeveloperSettingsState(
+                    eventSink = eventsRecorder
+                ),
+                onPushHistoryClick = it
+            )
+            rule.clickOn(R.string.troubleshoot_notifications_entry_point_push_history_title)
+        }
+    }
+
     @Config(qualifiers = "h1500dp")
     @Test
     fun `clicking on element call url open the dialogs and submit emits the expected event`() {
@@ -68,7 +83,7 @@ class DeveloperSettingsViewTest {
         eventsRecorder.assertSingle(DeveloperSettingsEvents.SetCustomElementCallBaseUrl("https://call.element.dev"))
     }
 
-    @Config(qualifiers = "h1200dp")
+    @Config(qualifiers = "h2000dp")
     @Test
     fun `clicking on open showkase invokes the expected callback`() {
         val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>(expectEvents = false)
@@ -97,7 +112,7 @@ class DeveloperSettingsViewTest {
         eventsRecorder.assertSingle(DeveloperSettingsEvents.SetTracingLogLevel(LogLevelItem.DEBUG))
     }
 
-    @Config(qualifiers = "h1700dp")
+    @Config(qualifiers = "h2000dp")
     @Test
     fun `clicking on clear cache emits the expected event`() {
         val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
@@ -114,12 +129,14 @@ class DeveloperSettingsViewTest {
 private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setDeveloperSettingsView(
     state: DeveloperSettingsState,
     onOpenShowkase: () -> Unit = EnsureNeverCalled(),
+    onPushHistoryClick: () -> Unit = EnsureNeverCalled(),
     onBackClick: () -> Unit = EnsureNeverCalled()
 ) {
     setContent {
         DeveloperSettingsView(
             state = state,
             onOpenShowkase = onOpenShowkase,
+            onPushHistoryClick = onPushHistoryClick,
             onBackClick = onBackClick,
         )
     }
diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt
index 3b2a2663a51..2aa485a1920 100644
--- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt
+++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsViewTest.kt
@@ -66,22 +66,6 @@ class NotificationSettingsViewTest {
         eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled)
     }
 
-    @Config(qualifiers = "h1024dp")
-    @Test
-    fun `clicking on push history notification invokes the expected callback`() {
-        val eventsRecorder = EventsRecorder<NotificationSettingsEvents>()
-        ensureCalledOnce {
-            rule.setNotificationSettingsView(
-                state = aValidNotificationSettingsState(
-                    eventSink = eventsRecorder
-                ),
-                onPushHistoryClick = it
-            )
-            rule.clickOn(R.string.troubleshoot_notifications_entry_point_push_history_title)
-        }
-        eventsRecorder.assertSingle(NotificationSettingsEvents.RefreshSystemNotificationsEnabled)
-    }
-
     @Config(qualifiers = "h1024dp")
     @Test
     fun `clicking on group chats invokes the expected callback`() {
@@ -300,7 +284,6 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setNotif
     state: NotificationSettingsState,
     onOpenEditDefault: (isOneToOne: Boolean) -> Unit = EnsureNeverCalledWithParam(),
     onTroubleshootNotificationsClick: () -> Unit = EnsureNeverCalled(),
-    onPushHistoryClick: () -> Unit = EnsureNeverCalled(),
     onBackClick: () -> Unit = EnsureNeverCalled(),
 ) {
     setContent {
@@ -308,7 +291,6 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setNotif
             state = state,
             onOpenEditDefault = onOpenEditDefault,
             onTroubleshootNotificationsClick = onTroubleshootNotificationsClick,
-            onPushHistoryClick = onPushHistoryClick,
             onBackClick = onBackClick,
         )
     }
diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png
index 246b5d52eb9..9da2df7e98d 100644
--- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_0_en.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7a028014d94f3aa7c0f2a81f00d9b686df19103ed9c0a0f32f09db27c2bdc742
-size 53850
+oid sha256:e8c417f2c0b856499c3a1733ef6d7415097a324139621fbbfc8fb9d0fe6d1a82
+size 46108
diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png
index 246b5d52eb9..9da2df7e98d 100644
--- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_1_en.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:7a028014d94f3aa7c0f2a81f00d9b686df19103ed9c0a0f32f09db27c2bdc742
-size 53850
+oid sha256:e8c417f2c0b856499c3a1733ef6d7415097a324139621fbbfc8fb9d0fe6d1a82
+size 46108
diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png
index 43edfa29151..68c365da4ca 100644
--- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Day_2_en.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:67cb6c4c1135742ddd2ca9def6580dec715fe92fcf1abcbcee133793d6fc5c9f
-size 52424
+oid sha256:9eda74b1b65aca54f03ed4a07230d49ff6495672747975c5efa1da1c60b29f56
+size 44657
diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png
index 8a161c66e8b..b442c94aa38 100644
--- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_0_en.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:aa42d10fcea58c37f4b4c90fc4b174f31b20abbfd25f926937d58355bbaa89b0
-size 52250
+oid sha256:657b03d76516c88bf748b70287b9270266b82064918463c71dab6df7eae23bd5
+size 44817
diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png
index 8a161c66e8b..b442c94aa38 100644
--- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_1_en.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:aa42d10fcea58c37f4b4c90fc4b174f31b20abbfd25f926937d58355bbaa89b0
-size 52250
+oid sha256:657b03d76516c88bf748b70287b9270266b82064918463c71dab6df7eae23bd5
+size 44817
diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png
index c2de3888ddc..02c1eb313e6 100644
--- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png
+++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.developer_DeveloperSettingsView_Night_2_en.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2822c565f450ff21fab05751db31d4d8d003fca74aff48802c37a45bf8159015
-size 50860
+oid sha256:38f81f8a388f31511ec4b6479e0f188e852d8c5556a38661f5f666e1b191d091
+size 43357