Change hierarchy of settings.
This commit is contained in:
parent
ebf775fafd
commit
6699462e06
28 changed files with 598 additions and 61 deletions
|
|
@ -43,13 +43,16 @@ fun AnalyticsPreferencesView(
|
||||||
state.eventSink(AnalyticsOptInEvents.EnableAnalytics(isEnabled = isEnabled))
|
state.eventSink(AnalyticsOptInEvents.EnableAnalytics(isEnabled = isEnabled))
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferenceCategory(title = stringResource(id = CommonStrings.screen_analytics_settings_share_data)) {
|
PreferenceCategory(
|
||||||
|
modifier = modifier,
|
||||||
|
title = stringResource(id = CommonStrings.screen_analytics_settings_share_data)
|
||||||
|
) {
|
||||||
val firstPart = stringResource(id = CommonStrings.screen_analytics_settings_help_us_improve, state.applicationName)
|
val firstPart = stringResource(id = CommonStrings.screen_analytics_settings_help_us_improve, state.applicationName)
|
||||||
val secondPart = buildAnnotatedStringWithColoredPart(
|
val secondPart = buildAnnotatedStringWithColoredPart(
|
||||||
CommonStrings.screen_analytics_settings_read_terms,
|
CommonStrings.screen_analytics_settings_read_terms,
|
||||||
CommonStrings.screen_analytics_settings_read_terms_content_link
|
CommonStrings.screen_analytics_settings_read_terms_content_link
|
||||||
)
|
)
|
||||||
val title = "$firstPart\n\n$secondPart"
|
val title = "$firstPart\n\n$secondPart"
|
||||||
|
|
||||||
PreferenceSwitch(
|
PreferenceSwitch(
|
||||||
title = title,
|
title = title,
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ fun LogoutPreferenceContent(
|
||||||
) {
|
) {
|
||||||
PreferenceText(
|
PreferenceText(
|
||||||
title = stringResource(id = R.string.screen_signout_preference_item),
|
title = stringResource(id = R.string.screen_signout_preference_item),
|
||||||
icon = Icons.Default.Logout,
|
icon = Icons.Filled.Logout,
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.preferences.api.PreferencesEntryPoint
|
import io.element.android.features.preferences.api.PreferencesEntryPoint
|
||||||
|
import io.element.android.features.preferences.impl.about.AboutNode
|
||||||
|
import io.element.android.features.preferences.impl.analytics.AnalyticsSettingsNode
|
||||||
import io.element.android.features.preferences.impl.developer.DeveloperSettingsNode
|
import io.element.android.features.preferences.impl.developer.DeveloperSettingsNode
|
||||||
import io.element.android.features.preferences.impl.root.PreferencesRootNode
|
import io.element.android.features.preferences.impl.root.PreferencesRootNode
|
||||||
import io.element.android.libraries.architecture.BackstackNode
|
import io.element.android.libraries.architecture.BackstackNode
|
||||||
|
|
@ -57,6 +59,12 @@ class PreferencesFlowNode @AssistedInject constructor(
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
object DeveloperSettings : NavTarget
|
object DeveloperSettings : NavTarget
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
object AnalyticsSettings : NavTarget
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
object About : NavTarget
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||||
|
|
@ -67,6 +75,14 @@ class PreferencesFlowNode @AssistedInject constructor(
|
||||||
plugins<PreferencesEntryPoint.Callback>().forEach { it.onOpenBugReport() }
|
plugins<PreferencesEntryPoint.Callback>().forEach { it.onOpenBugReport() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onOpenAnalytics() {
|
||||||
|
backstack.push(NavTarget.AnalyticsSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOpenAbout() {
|
||||||
|
backstack.push(NavTarget.About)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOpenDeveloperSettings() {
|
override fun onOpenDeveloperSettings() {
|
||||||
backstack.push(NavTarget.DeveloperSettings)
|
backstack.push(NavTarget.DeveloperSettings)
|
||||||
}
|
}
|
||||||
|
|
@ -76,6 +92,12 @@ class PreferencesFlowNode @AssistedInject constructor(
|
||||||
NavTarget.DeveloperSettings -> {
|
NavTarget.DeveloperSettings -> {
|
||||||
createNode<DeveloperSettingsNode>(buildContext)
|
createNode<DeveloperSettingsNode>(buildContext)
|
||||||
}
|
}
|
||||||
|
NavTarget.About -> {
|
||||||
|
createNode<AboutNode>(buildContext)
|
||||||
|
}
|
||||||
|
NavTarget.AnalyticsSettings -> {
|
||||||
|
createNode<AnalyticsSettingsNode>(buildContext)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
sealed interface AboutEvents {
|
||||||
|
object MyEvent : AboutEvents
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
import com.bumble.appyx.core.node.Node
|
||||||
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
|
||||||
|
@ContributesNode(SessionScope::class)
|
||||||
|
class AboutNode @AssistedInject constructor(
|
||||||
|
@Assisted buildContext: BuildContext,
|
||||||
|
@Assisted plugins: List<Plugin>,
|
||||||
|
private val presenter: AboutPresenter,
|
||||||
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun View(modifier: Modifier) {
|
||||||
|
val state = presenter.present()
|
||||||
|
AboutView(
|
||||||
|
state = state,
|
||||||
|
onBackPressed = ::navigateUp,
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AboutPresenter @Inject constructor() : Presenter<AboutState> {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun present(): AboutState {
|
||||||
|
|
||||||
|
fun handleEvents(event: AboutEvents) {
|
||||||
|
when (event) {
|
||||||
|
AboutEvents.MyEvent -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AboutState(
|
||||||
|
eventSink = ::handleEvents
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
// TODO add your ui models. Remove the eventSink if you don't have events.
|
||||||
|
// Do not use default value, so no member get forgotten in the presenters.
|
||||||
|
data class AboutState(
|
||||||
|
val eventSink: (AboutEvents) -> Unit
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
|
||||||
|
open class AboutStateProvider : PreviewParameterProvider<AboutState> {
|
||||||
|
override val values: Sequence<AboutState>
|
||||||
|
get() = sequenceOf(
|
||||||
|
aAboutState(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun aAboutState() = AboutState(
|
||||||
|
eventSink = {}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||||
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AboutView(
|
||||||
|
state: AboutState,
|
||||||
|
onBackPressed: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
PreferenceView(
|
||||||
|
modifier = modifier,
|
||||||
|
onBackPressed = onBackPressed,
|
||||||
|
title = stringResource(id = CommonStrings.common_about)
|
||||||
|
) {
|
||||||
|
PreferenceText(title = stringResource(id = CommonStrings.common_copyright))
|
||||||
|
PreferenceText(title = stringResource(id = CommonStrings.common_acceptable_use_policy))
|
||||||
|
PreferenceText(title = stringResource(id = CommonStrings.common_privacy_policy))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun AboutViewLightPreview(@PreviewParameter(AboutStateProvider::class) state: AboutState) =
|
||||||
|
ElementPreviewLight { ContentToPreview(state) }
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun AboutViewDarkPreview(@PreviewParameter(AboutStateProvider::class) state: AboutState) =
|
||||||
|
ElementPreviewDark { ContentToPreview(state) }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ContentToPreview(state: AboutState) {
|
||||||
|
AboutView(
|
||||||
|
state = state,
|
||||||
|
onBackPressed = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
sealed interface AnalyticsSettingsEvents {
|
||||||
|
object MyEvent : AnalyticsSettingsEvents
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
import com.bumble.appyx.core.node.Node
|
||||||
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
|
||||||
|
@ContributesNode(SessionScope::class)
|
||||||
|
class AnalyticsSettingsNode @AssistedInject constructor(
|
||||||
|
@Assisted buildContext: BuildContext,
|
||||||
|
@Assisted plugins: List<Plugin>,
|
||||||
|
private val presenter: AnalyticsSettingsPresenter,
|
||||||
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun View(modifier: Modifier) {
|
||||||
|
val state = presenter.present()
|
||||||
|
AnalyticsSettingsView(
|
||||||
|
state = state,
|
||||||
|
onBackPressed = ::navigateUp,
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesPresenter
|
||||||
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AnalyticsSettingsPresenter @Inject constructor(
|
||||||
|
private val analyticsPresenter: AnalyticsPreferencesPresenter,
|
||||||
|
) : Presenter<AnalyticsSettingsState> {
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun present(): AnalyticsSettingsState {
|
||||||
|
val analyticsState = analyticsPresenter.present()
|
||||||
|
|
||||||
|
fun handleEvents(event: AnalyticsSettingsEvents) {
|
||||||
|
when (event) {
|
||||||
|
AnalyticsSettingsEvents.MyEvent -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AnalyticsSettingsState(
|
||||||
|
analyticsState = analyticsState,
|
||||||
|
eventSink = ::handleEvents
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesState
|
||||||
|
|
||||||
|
// Do not use default value, so no member get forgotten in the presenters.
|
||||||
|
data class AnalyticsSettingsState(
|
||||||
|
val analyticsState: AnalyticsPreferencesState,
|
||||||
|
val eventSink: (AnalyticsSettingsEvents) -> Unit
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
import io.element.android.features.analytics.api.preferences.aAnalyticsPreferencesState
|
||||||
|
|
||||||
|
open class AnalyticsSettingsStateProvider : PreviewParameterProvider<AnalyticsSettingsState> {
|
||||||
|
override val values: Sequence<AnalyticsSettingsState>
|
||||||
|
get() = sequenceOf(
|
||||||
|
aAnalyticsSettingsState(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun aAnalyticsSettingsState() = AnalyticsSettingsState(
|
||||||
|
analyticsState = aAnalyticsPreferencesState(),
|
||||||
|
eventSink = {}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesView
|
||||||
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AnalyticsSettingsView(
|
||||||
|
state: AnalyticsSettingsState,
|
||||||
|
onBackPressed: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
PreferenceView(
|
||||||
|
modifier = modifier,
|
||||||
|
onBackPressed = onBackPressed,
|
||||||
|
title = stringResource(id = CommonStrings.common_analytics)
|
||||||
|
) {
|
||||||
|
AnalyticsPreferencesView(
|
||||||
|
state = state.analyticsState,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun AnalyticsSettingsViewLightPreview(@PreviewParameter(AnalyticsSettingsStateProvider::class) state: AnalyticsSettingsState) =
|
||||||
|
ElementPreviewLight { ContentToPreview(state) }
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun AnalyticsSettingsViewDarkPreview(@PreviewParameter(AnalyticsSettingsStateProvider::class) state: AnalyticsSettingsState) =
|
||||||
|
ElementPreviewDark { ContentToPreview(state) }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ContentToPreview(state: AnalyticsSettingsState) {
|
||||||
|
AnalyticsSettingsView(
|
||||||
|
state = state,
|
||||||
|
onBackPressed = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
||||||
import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase
|
import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase
|
||||||
import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase
|
import io.element.android.features.preferences.impl.tasks.ComputeCacheSizeUseCase
|
||||||
|
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||||
|
|
@ -44,10 +45,12 @@ class DeveloperSettingsPresenter @Inject constructor(
|
||||||
private val featureFlagService: FeatureFlagService,
|
private val featureFlagService: FeatureFlagService,
|
||||||
private val computeCacheSizeUseCase: ComputeCacheSizeUseCase,
|
private val computeCacheSizeUseCase: ComputeCacheSizeUseCase,
|
||||||
private val clearCacheUseCase: ClearCacheUseCase,
|
private val clearCacheUseCase: ClearCacheUseCase,
|
||||||
|
private val rageshakePresenter: RageshakePreferencesPresenter,
|
||||||
) : Presenter<DeveloperSettingsState> {
|
) : Presenter<DeveloperSettingsState> {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): DeveloperSettingsState {
|
override fun present(): DeveloperSettingsState {
|
||||||
|
val rageshakeState = rageshakePresenter.present()
|
||||||
|
|
||||||
val features = remember {
|
val features = remember {
|
||||||
mutableStateMapOf<String, Feature>()
|
mutableStateMapOf<String, Feature>()
|
||||||
|
|
@ -90,6 +93,7 @@ class DeveloperSettingsPresenter @Inject constructor(
|
||||||
features = featureUiModels.toImmutableList(),
|
features = featureUiModels.toImmutableList(),
|
||||||
cacheSize = cacheSize.value,
|
cacheSize = cacheSize.value,
|
||||||
clearCacheAction = clearCacheAction.value,
|
clearCacheAction = clearCacheAction.value,
|
||||||
|
rageshakeState = rageshakeState,
|
||||||
eventSink = ::handleEvents
|
eventSink = ::handleEvents
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.developer
|
package io.element.android.features.preferences.impl.developer
|
||||||
|
|
||||||
|
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
|
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
@ -23,6 +24,7 @@ import kotlinx.collections.immutable.ImmutableList
|
||||||
data class DeveloperSettingsState constructor(
|
data class DeveloperSettingsState constructor(
|
||||||
val features: ImmutableList<FeatureUiModel>,
|
val features: ImmutableList<FeatureUiModel>,
|
||||||
val cacheSize: Async<String>,
|
val cacheSize: Async<String>,
|
||||||
|
val rageshakeState: RageshakePreferencesState,
|
||||||
val clearCacheAction: Async<Unit>,
|
val clearCacheAction: Async<Unit>,
|
||||||
val eventSink: (DeveloperSettingsEvents) -> Unit
|
val eventSink: (DeveloperSettingsEvents) -> Unit
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package io.element.android.features.preferences.impl.developer
|
package io.element.android.features.preferences.impl.developer
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList
|
import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSe
|
||||||
|
|
||||||
fun aDeveloperSettingsState() = DeveloperSettingsState(
|
fun aDeveloperSettingsState() = DeveloperSettingsState(
|
||||||
features = aFeatureUiModelList(),
|
features = aFeatureUiModelList(),
|
||||||
|
rageshakeState = aRageshakePreferencesState(),
|
||||||
cacheSize = Async.Success("1.2 MB"),
|
cacheSize = Async.Success("1.2 MB"),
|
||||||
clearCacheAction = Async.Uninitialized,
|
clearCacheAction = Async.Uninitialized,
|
||||||
eventSink = {}
|
eventSink = {}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||||
|
|
@ -52,6 +53,9 @@ fun DeveloperSettingsView(
|
||||||
onClick = onOpenShowkase
|
onClick = onOpenShowkase
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
RageshakePreferencesView(
|
||||||
|
state = state.rageshakeState,
|
||||||
|
)
|
||||||
val cache = state.cacheSize
|
val cache = state.cacheSize
|
||||||
PreferenceCategory(title = "Cache", showDivider = false) {
|
PreferenceCategory(title = "Cache", showDivider = false) {
|
||||||
PreferenceText(
|
PreferenceText(
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ class PreferencesRootNode @AssistedInject constructor(
|
||||||
|
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun onOpenBugReport()
|
fun onOpenBugReport()
|
||||||
|
fun onOpenAnalytics()
|
||||||
|
fun onOpenAbout()
|
||||||
fun onOpenDeveloperSettings()
|
fun onOpenDeveloperSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,6 +49,14 @@ class PreferencesRootNode @AssistedInject constructor(
|
||||||
plugins<Callback>().forEach { it.onOpenDeveloperSettings() }
|
plugins<Callback>().forEach { it.onOpenDeveloperSettings() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onOpenAnalytics() {
|
||||||
|
plugins<Callback>().forEach { it.onOpenAnalytics() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onOpenAbout() {
|
||||||
|
plugins<Callback>().forEach { it.onOpenAbout() }
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
val state = presenter.present()
|
val state = presenter.present()
|
||||||
|
|
@ -55,8 +65,9 @@ class PreferencesRootNode @AssistedInject constructor(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onBackPressed = this::navigateUp,
|
onBackPressed = this::navigateUp,
|
||||||
onOpenRageShake = this::onOpenBugReport,
|
onOpenRageShake = this::onOpenBugReport,
|
||||||
|
onOpenAnalytics = this::onOpenAnalytics,
|
||||||
|
onOpenAbout = this::onOpenAbout,
|
||||||
onOpenDeveloperSettings = this::onOpenDeveloperSettings
|
onOpenDeveloperSettings = this::onOpenDeveloperSettings
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesPresenter
|
|
||||||
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
||||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
|
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.meta.BuildType
|
import io.element.android.libraries.core.meta.BuildType
|
||||||
import io.element.android.libraries.matrix.api.user.CurrentUserProvider
|
import io.element.android.libraries.matrix.api.user.CurrentUserProvider
|
||||||
|
|
@ -34,8 +32,6 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class PreferencesRootPresenter @Inject constructor(
|
class PreferencesRootPresenter @Inject constructor(
|
||||||
private val logoutPresenter: LogoutPreferencePresenter,
|
private val logoutPresenter: LogoutPreferencePresenter,
|
||||||
private val rageshakePresenter: RageshakePreferencesPresenter,
|
|
||||||
private val analyticsPresenter: AnalyticsPreferencesPresenter,
|
|
||||||
private val currentUserProvider: CurrentUserProvider,
|
private val currentUserProvider: CurrentUserProvider,
|
||||||
private val buildType: BuildType,
|
private val buildType: BuildType,
|
||||||
) : Presenter<PreferencesRootState> {
|
) : Presenter<PreferencesRootState> {
|
||||||
|
|
@ -50,13 +46,9 @@ class PreferencesRootPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
val logoutState = logoutPresenter.present()
|
val logoutState = logoutPresenter.present()
|
||||||
val rageshakeState = rageshakePresenter.present()
|
|
||||||
val analyticsState = analyticsPresenter.present()
|
|
||||||
val showDeveloperSettings = buildType != BuildType.RELEASE
|
val showDeveloperSettings = buildType != BuildType.RELEASE
|
||||||
return PreferencesRootState(
|
return PreferencesRootState(
|
||||||
logoutState = logoutState,
|
logoutState = logoutState,
|
||||||
rageshakeState = rageshakeState,
|
|
||||||
analyticsState = analyticsState,
|
|
||||||
myUser = matrixUser.value,
|
myUser = matrixUser.value,
|
||||||
showDeveloperSettings = showDeveloperSettings
|
showDeveloperSettings = showDeveloperSettings
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,11 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.root
|
package io.element.android.features.preferences.impl.root
|
||||||
|
|
||||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesState
|
|
||||||
import io.element.android.features.logout.api.LogoutPreferenceState
|
import io.element.android.features.logout.api.LogoutPreferenceState
|
||||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
|
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
||||||
data class PreferencesRootState(
|
data class PreferencesRootState(
|
||||||
val logoutState: LogoutPreferenceState,
|
val logoutState: LogoutPreferenceState,
|
||||||
val rageshakeState: RageshakePreferencesState,
|
|
||||||
val analyticsState: AnalyticsPreferencesState,
|
|
||||||
val myUser: MatrixUser?,
|
val myUser: MatrixUser?,
|
||||||
val showDeveloperSettings: Boolean
|
val showDeveloperSettings: Boolean
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,10 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.root
|
package io.element.android.features.preferences.impl.root
|
||||||
|
|
||||||
import io.element.android.features.analytics.api.preferences.aAnalyticsPreferencesState
|
|
||||||
import io.element.android.features.logout.api.aLogoutPreferenceState
|
import io.element.android.features.logout.api.aLogoutPreferenceState
|
||||||
import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState
|
|
||||||
|
|
||||||
fun aPreferencesRootState() = PreferencesRootState(
|
fun aPreferencesRootState() = PreferencesRootState(
|
||||||
logoutState = aLogoutPreferenceState(),
|
logoutState = aLogoutPreferenceState(),
|
||||||
rageshakeState = aRageshakePreferencesState(),
|
|
||||||
analyticsState = aAnalyticsPreferencesState(),
|
|
||||||
myUser = null,
|
myUser = null,
|
||||||
showDeveloperSettings = true
|
showDeveloperSettings = true
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -18,21 +18,21 @@ package io.element.android.features.preferences.impl.root
|
||||||
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.DeveloperMode
|
import androidx.compose.material.icons.filled.DeveloperMode
|
||||||
|
import androidx.compose.material.icons.filled.Help
|
||||||
|
import androidx.compose.material.icons.outlined.BugReport
|
||||||
|
import androidx.compose.material.icons.outlined.InsertChart
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import io.element.android.features.logout.api.LogoutPreferenceView
|
import io.element.android.features.logout.api.LogoutPreferenceView
|
||||||
import io.element.android.features.preferences.impl.user.UserPreferences
|
import io.element.android.features.preferences.impl.user.UserPreferences
|
||||||
import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesView
|
|
||||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView
|
|
||||||
import io.element.android.libraries.architecture.Async
|
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
import io.element.android.libraries.designsystem.preview.LargeHeightPreview
|
import io.element.android.libraries.designsystem.preview.LargeHeightPreview
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.Divider
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import io.element.android.libraries.matrix.ui.components.MatrixUserProvider
|
import io.element.android.libraries.matrix.ui.components.MatrixUserProvider
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
@ -41,11 +41,12 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
fun PreferencesRootView(
|
fun PreferencesRootView(
|
||||||
state: PreferencesRootState,
|
state: PreferencesRootState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onBackPressed: () -> Unit = {},
|
onBackPressed: () -> Unit,
|
||||||
onOpenRageShake: () -> Unit = {},
|
onOpenAnalytics: () -> Unit,
|
||||||
onOpenDeveloperSettings: () -> Unit = {},
|
onOpenRageShake: () -> Unit,
|
||||||
|
onOpenAbout: () -> Unit,
|
||||||
|
onOpenDeveloperSettings: () -> Unit,
|
||||||
) {
|
) {
|
||||||
// TODO Hierarchy!
|
|
||||||
// Include pref from other modules
|
// Include pref from other modules
|
||||||
PreferenceView(
|
PreferenceView(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
@ -53,31 +54,39 @@ fun PreferencesRootView(
|
||||||
title = stringResource(id = CommonStrings.common_settings)
|
title = stringResource(id = CommonStrings.common_settings)
|
||||||
) {
|
) {
|
||||||
UserPreferences(state.myUser)
|
UserPreferences(state.myUser)
|
||||||
AnalyticsPreferencesView(
|
// TODO Verification and eventually divider
|
||||||
state = state.analyticsState,
|
PreferenceText(
|
||||||
|
title = stringResource(id = CommonStrings.common_analytics),
|
||||||
|
icon = Icons.Outlined.InsertChart,
|
||||||
|
onClick = onOpenAnalytics,
|
||||||
)
|
)
|
||||||
RageshakePreferencesView(
|
PreferenceText(
|
||||||
state = state.rageshakeState,
|
title = stringResource(id = CommonStrings.action_report_bug),
|
||||||
onOpenRageshake = onOpenRageShake,
|
icon = Icons.Outlined.BugReport,
|
||||||
|
onClick = onOpenRageShake
|
||||||
)
|
)
|
||||||
LogoutPreferenceView(
|
PreferenceText(
|
||||||
state = state.logoutState,
|
title = stringResource(id = CommonStrings.common_about),
|
||||||
|
icon = Icons.Filled.Help,
|
||||||
|
onClick = onOpenAbout,
|
||||||
)
|
)
|
||||||
if (state.showDeveloperSettings) {
|
if (state.showDeveloperSettings) {
|
||||||
DeveloperPreferencesView(onOpenDeveloperSettings)
|
DeveloperPreferencesView(onOpenDeveloperSettings)
|
||||||
}
|
}
|
||||||
|
Divider()
|
||||||
|
LogoutPreferenceView(
|
||||||
|
state = state.logoutState,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
|
fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) {
|
||||||
PreferenceCategory(title = stringResource(id = CommonStrings.common_developer_options)) {
|
PreferenceText(
|
||||||
PreferenceText(
|
title = stringResource(id = CommonStrings.common_developer_options),
|
||||||
title = stringResource(id = CommonStrings.common_developer_options),
|
icon = Icons.Default.DeveloperMode,
|
||||||
icon = Icons.Default.DeveloperMode,
|
onClick = onOpenDeveloperSettings
|
||||||
onClick = onOpenDeveloperSettings
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@LargeHeightPreview
|
@LargeHeightPreview
|
||||||
|
|
@ -92,5 +101,12 @@ fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContentToPreview(matrixUser: MatrixUser) {
|
private fun ContentToPreview(matrixUser: MatrixUser) {
|
||||||
PreferencesRootView(aPreferencesRootState().copy(myUser = matrixUser))
|
PreferencesRootView(
|
||||||
|
state = aPreferencesRootState().copy(myUser = matrixUser),
|
||||||
|
onBackPressed = {},
|
||||||
|
onOpenAnalytics = {},
|
||||||
|
onOpenRageShake = {},
|
||||||
|
onOpenDeveloperSettings = {},
|
||||||
|
onOpenAbout = {},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.preferences.impl.analytics
|
||||||
|
|
||||||
|
import app.cash.molecule.RecompositionClock
|
||||||
|
import app.cash.molecule.moleculeFlow
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.features.analytics.impl.preferences.DefaultAnalyticsPreferencesPresenter
|
||||||
|
import io.element.android.features.analytics.test.A_BUILD_META
|
||||||
|
import io.element.android.features.analytics.test.FakeAnalyticsService
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class AnalyticsAnalyticsSettingsPresenterTest {
|
||||||
|
@Test
|
||||||
|
fun `present - initial state`() = runTest {
|
||||||
|
val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), A_BUILD_META)
|
||||||
|
val presenter = AnalyticsSettingsPresenter(
|
||||||
|
analyticsPresenter,
|
||||||
|
)
|
||||||
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
|
presenter.present()
|
||||||
|
}.test {
|
||||||
|
val initialState = awaitItem()
|
||||||
|
assertThat(initialState.analyticsState.isEnabled).isFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,9 @@ import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase
|
import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase
|
||||||
import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase
|
import io.element.android.features.preferences.impl.tasks.FakeComputeCacheSizeUseCase
|
||||||
|
import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter
|
||||||
|
import io.element.android.features.rageshake.test.rageshake.FakeRageShake
|
||||||
|
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||||
|
|
@ -31,10 +34,12 @@ import org.junit.Test
|
||||||
class DeveloperSettingsPresenterTest {
|
class DeveloperSettingsPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensures initial state is correct`() = runTest {
|
fun `present - ensures initial state is correct`() = runTest {
|
||||||
|
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService(),
|
FakeFeatureFlagService(),
|
||||||
FakeComputeCacheSizeUseCase(),
|
FakeComputeCacheSizeUseCase(),
|
||||||
FakeClearCacheUseCase(),
|
FakeClearCacheUseCase(),
|
||||||
|
rageshakePresenter
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
|
|
@ -43,16 +48,22 @@ class DeveloperSettingsPresenterTest {
|
||||||
assertThat(initialState.features).isEmpty()
|
assertThat(initialState.features).isEmpty()
|
||||||
assertThat(initialState.clearCacheAction).isEqualTo(Async.Uninitialized)
|
assertThat(initialState.clearCacheAction).isEqualTo(Async.Uninitialized)
|
||||||
assertThat(initialState.cacheSize).isEqualTo(Async.Uninitialized)
|
assertThat(initialState.cacheSize).isEqualTo(Async.Uninitialized)
|
||||||
|
val loadedState = awaitItem()
|
||||||
|
assertThat(loadedState.rageshakeState.isEnabled).isTrue()
|
||||||
|
assertThat(loadedState.rageshakeState.isSupported).isTrue()
|
||||||
|
assertThat(loadedState.rageshakeState.sensitivity).isEqualTo(1.0f)
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensures feature list is loaded`() = runTest {
|
fun `present - ensures feature list is loaded`() = runTest {
|
||||||
|
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService(),
|
FakeFeatureFlagService(),
|
||||||
FakeComputeCacheSizeUseCase(),
|
FakeComputeCacheSizeUseCase(),
|
||||||
FakeClearCacheUseCase(),
|
FakeClearCacheUseCase(),
|
||||||
|
rageshakePresenter,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
|
|
@ -66,10 +77,12 @@ class DeveloperSettingsPresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensures state is updated when enabled feature event is triggered`() = runTest {
|
fun `present - ensures state is updated when enabled feature event is triggered`() = runTest {
|
||||||
|
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService(),
|
FakeFeatureFlagService(),
|
||||||
FakeComputeCacheSizeUseCase(),
|
FakeComputeCacheSizeUseCase(),
|
||||||
FakeClearCacheUseCase(),
|
FakeClearCacheUseCase(),
|
||||||
|
rageshakePresenter,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
|
|
@ -88,11 +101,13 @@ class DeveloperSettingsPresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - clear cache`() = runTest {
|
fun `present - clear cache`() = runTest {
|
||||||
|
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
||||||
val clearCacheUseCase = FakeClearCacheUseCase()
|
val clearCacheUseCase = FakeClearCacheUseCase()
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService(),
|
FakeFeatureFlagService(),
|
||||||
FakeComputeCacheSizeUseCase(),
|
FakeComputeCacheSizeUseCase(),
|
||||||
clearCacheUseCase,
|
clearCacheUseCase,
|
||||||
|
rageshakePresenter,
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,8 @@ class PreferencesRootPresenterTest {
|
||||||
fun `present - initial state`() = runTest {
|
fun `present - initial state`() = runTest {
|
||||||
val matrixClient = FakeMatrixClient()
|
val matrixClient = FakeMatrixClient()
|
||||||
val logoutPresenter = DefaultLogoutPreferencePresenter(matrixClient)
|
val logoutPresenter = DefaultLogoutPreferencePresenter(matrixClient)
|
||||||
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
|
||||||
val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), A_BUILD_META)
|
|
||||||
val presenter = PreferencesRootPresenter(
|
val presenter = PreferencesRootPresenter(
|
||||||
logoutPresenter,
|
logoutPresenter,
|
||||||
rageshakePresenter,
|
|
||||||
analyticsPresenter,
|
|
||||||
CurrentUserProvider(matrixClient),
|
CurrentUserProvider(matrixClient),
|
||||||
A_BUILD_META.buildType
|
A_BUILD_META.buildType
|
||||||
)
|
)
|
||||||
|
|
@ -57,10 +53,6 @@ class PreferencesRootPresenterTest {
|
||||||
assertThat(initialState.myUser).isNull()
|
assertThat(initialState.myUser).isNull()
|
||||||
val loadedState = awaitItem()
|
val loadedState = awaitItem()
|
||||||
assertThat(loadedState.logoutState.logoutAction).isEqualTo(Async.Uninitialized)
|
assertThat(loadedState.logoutState.logoutAction).isEqualTo(Async.Uninitialized)
|
||||||
assertThat(loadedState.analyticsState.isEnabled).isFalse()
|
|
||||||
assertThat(loadedState.rageshakeState.isEnabled).isTrue()
|
|
||||||
assertThat(loadedState.rageshakeState.isSupported).isTrue()
|
|
||||||
assertThat(loadedState.rageshakeState.sensitivity).isEqualTo(1.0f)
|
|
||||||
assertThat(loadedState.myUser).isEqualTo(
|
assertThat(loadedState.myUser).isEqualTo(
|
||||||
MatrixUser(
|
MatrixUser(
|
||||||
userId = matrixClient.sessionId,
|
userId = matrixClient.sessionId,
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
package io.element.android.features.rageshake.api.preferences
|
package io.element.android.features.rageshake.api.preferences
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.BugReport
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -36,7 +34,6 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
fun RageshakePreferencesView(
|
fun RageshakePreferencesView(
|
||||||
state: RageshakePreferencesState,
|
state: RageshakePreferencesState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onOpenRageshake: () -> Unit = {},
|
|
||||||
) {
|
) {
|
||||||
fun onSensitivityChanged(sensitivity: Float) {
|
fun onSensitivityChanged(sensitivity: Float) {
|
||||||
state.eventSink(RageshakePreferencesEvents.SetSensitivity(sensitivity = sensitivity))
|
state.eventSink(RageshakePreferencesEvents.SetSensitivity(sensitivity = sensitivity))
|
||||||
|
|
@ -47,13 +44,6 @@ fun RageshakePreferencesView(
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
PreferenceCategory(title = stringResource(id = CommonStrings.action_report_bug)) {
|
|
||||||
PreferenceText(
|
|
||||||
title = stringResource(id = CommonStrings.action_report_bug),
|
|
||||||
icon = Icons.Default.BugReport,
|
|
||||||
onClick = onOpenRageshake
|
|
||||||
)
|
|
||||||
}
|
|
||||||
PreferenceCategory(title = stringResource(id = CommonStrings.settings_rageshake)) {
|
PreferenceCategory(title = stringResource(id = CommonStrings.settings_rageshake)) {
|
||||||
if (state.isSupported) {
|
if (state.isSupported) {
|
||||||
PreferenceSwitch(
|
PreferenceSwitch(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue