From 2a5616d52c21cc65098b8bd67db3ddb32b435ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Santos?= Date: Tue, 26 Nov 2024 16:31:42 +0000 Subject: [PATCH 1/3] Improve test options --- .../values/strings-common.xml | 6 +- .../ooni/probe/config/BuildTypesDefaults.kt | 8 ++ .../config/OrganizationConfigInterface.kt | 26 ---- .../ooni/probe/config/OrganizationConfig.kt | 21 +++ .../ooni/probe/data/models/PreferenceItem.kt | 76 ++++++++++ .../{PreferenceModel.kt => SettingsKey.kt} | 72 ---------- .../ooni/probe/domain/BootstrapPreferences.kt | 2 +- .../org/ooni/probe/domain/GetSettings.kt | 135 ++++++++++++++---- .../ooni/probe/ui/navigation/Navigation.kt | 12 +- .../category/SettingsCategoryScreen.kt | 122 ++++++++-------- .../ooni/probe/config/BuildTypeDefaults.kt | 8 ++ .../config/OrganizationConfigInterface.kt | 25 ---- .../ooni/probe/config/OrganizationConfig.kt | 1 + .../domain/OrganizationPreferenceDefaults.kt | 8 ++ .../ooni/probe/domain/OrganizationSettings.kt | 16 --- .../ooni/probe/config/OrganizationConfig.kt | 1 + .../domain/OrganizationPreferenceDefaults.kt | 13 ++ .../ooni/probe/domain/OrganizationSettings.kt | 73 ---------- 18 files changed, 318 insertions(+), 307 deletions(-) create mode 100644 composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt delete mode 100644 composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt create mode 100644 composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceItem.kt rename composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/{PreferenceModel.kt => SettingsKey.kt} (50%) create mode 100644 composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt delete mode 100644 composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt create mode 100644 composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt delete mode 100644 composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt create mode 100644 composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt delete mode 100644 composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt diff --git a/composeApp/src/commonMain/composeResources/values/strings-common.xml b/composeApp/src/commonMain/composeResources/values/strings-common.xml index 39dc3d3e..0650d913 100644 --- a/composeApp/src/commonMain/composeResources/values/strings-common.xml +++ b/composeApp/src/commonMain/composeResources/values/strings-common.xml @@ -76,8 +76,8 @@ Only while charging By enabling automatic testing, OONI Probe tests will run automatically multiple times per day. Your test results will automatically get published on OONI Explorer: https://explorer.ooni.org/ \n\nImportant: If you have a VPN enabled, OONI Probe will not run tests automatically. Please turn off your VPN for automated OONI Probe testing. Learn more: https://ooni.org/support/faq/#can-i-run-ooni-probe-over-a-vpn - Limit test duration - Test duration + Limit Websites test duration + Maximum Websites test duration Website categories to test %1$s categories enabled @@ -291,4 +291,6 @@ Only the last %1$d results are shown Skip after this amount of results failed to upload Unsupported URL + Results are automatically uploaded to OONI explorer + Tests will run every hour in the background diff --git a/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt b/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt new file mode 100644 index 00000000..a255ad36 --- /dev/null +++ b/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt @@ -0,0 +1,8 @@ +package org.ooni.probe.config + +object BuildTypesDefaults : BuildTypesDefaultsInterface { + override val ooniApiBaseUrl = "https://api.dev.ooni.io" + override val ooniRunDomain = "run.test.ooni.org" + override val ooniRunDashboardUrl = "https://run.test.ooni.org" + override val explorerUrl = "https://explorer.test.ooni.org" +} diff --git a/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt b/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt deleted file mode 100644 index 9024c2ac..00000000 --- a/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt +++ /dev/null @@ -1,26 +0,0 @@ -package org.ooni.probe.config - - -interface OrganizationConfigInterface { - val baseSoftwareName: String - - val ooniApiBaseUrl: String - get() = "https://api.dev.ooni.io" - - val ooniRunDomain: String - get() = "run.test.ooni.org" - - val ooniRunDashboardUrl: String - get() = "https://run.test.ooni.org" - - val explorerUrl: String - get() = "https://explorer.ooni.org" - - val testDisplayMode: TestDisplayMode - - val autorunTaskId: String - - val onboardingImages: OnboardingImages - - val updateDescriptorTaskId: String -} diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt index f722bf11..ffe14918 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt @@ -2,6 +2,27 @@ package org.ooni.probe.config import org.jetbrains.compose.resources.DrawableResource +interface OrganizationConfigInterface { + val baseSoftwareName: String + val testDisplayMode: TestDisplayMode + val autorunTaskId: String + val onboardingImages: OnboardingImages + val updateDescriptorTaskId: String + val hasWebsitesDescriptor: Boolean + + val ooniApiBaseUrl get() = BuildTypesDefaults.ooniApiBaseUrl + val ooniRunDomain get() = BuildTypesDefaults.ooniRunDomain + val ooniRunDashboardUrl get() = BuildTypesDefaults.ooniRunDashboardUrl + val explorerUrl get() = BuildTypesDefaults.explorerUrl +} + +interface BuildTypesDefaultsInterface { + val ooniApiBaseUrl: String + val ooniRunDomain: String + val ooniRunDashboardUrl: String + val explorerUrl: String +} + data class OnboardingImages( val image1: DrawableResource, val image2: DrawableResource, diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceItem.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceItem.kt new file mode 100644 index 00000000..a0b93168 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceItem.kt @@ -0,0 +1,76 @@ +package org.ooni.probe.data.models + +import androidx.compose.runtime.Composable +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.StringResource + +open class PreferenceItem( + open val title: StringResource, + open val icon: DrawableResource? = null, + open val type: PreferenceItemType, + open val key: SettingsKey, + open val supportingContent: @Composable (() -> Unit)? = null, + open val trailingContent: @Composable (() -> Unit)? = null, + open val enabled: Boolean = true, + open val indentation: Int = 0, +) + +data class SettingsItem( + override val icon: DrawableResource? = null, + override val title: StringResource, + override val type: PreferenceItemType, + override val key: SettingsKey, + override val supportingContent: @Composable (() -> Unit)? = null, + override val trailingContent: @Composable (() -> Unit)? = null, + override val enabled: Boolean = true, + override val indentation: Int = 0, +) : PreferenceItem( + title = title, + icon = icon, + supportingContent = supportingContent, + type = type, + key = key, + enabled = enabled, + ) + +data class SettingsCategoryItem( + override val icon: DrawableResource? = null, + override val title: StringResource, + val route: PreferenceCategoryKey, + val settings: List? = emptyList(), + override val supportingContent: @Composable (() -> Unit)? = null, + val footerContent: @Composable (() -> Unit)? = null, + override val indentation: Int = 0, +) : PreferenceItem( + title = title, + icon = icon, + supportingContent = supportingContent, + type = PreferenceItemType.ROUTE, + key = SettingsKey.ROUTE, + ) + +enum class PreferenceItemType { + SWITCH, + INT, + BUTTON, + SELECT, + ROUTE, +} + +enum class PreferenceCategoryKey(val value: String) { + NOTIFICATIONS("notifications"), + TEST_OPTIONS("test_options"), + PRIVACY("privacy"), + PROXY("proxy"), + ADVANCED("advanced"), + SEND_EMAIL("send_email"), + ABOUT_OONI("about_ooni"), + + WEBSITES_CATEGORIES("websites_categories"), + SEE_RECENT_LOGS("see_recent_logs"), + ; + + companion object { + fun fromValue(value: String?) = value?.let { entries.firstOrNull { it.value == value } } + } +} diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceModel.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/SettingsKey.kt similarity index 50% rename from composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceModel.kt rename to composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/SettingsKey.kt index 7a4e3d95..b87c3884 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/PreferenceModel.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/data/models/SettingsKey.kt @@ -1,77 +1,5 @@ package org.ooni.probe.data.models -import androidx.compose.runtime.Composable -import org.jetbrains.compose.resources.DrawableResource -import org.jetbrains.compose.resources.StringResource - -open class PreferenceItem( - open val title: StringResource, - open val icon: DrawableResource? = null, - open val type: PreferenceItemType, - open val key: SettingsKey, - open val supportingContent: @Composable (() -> Unit)? = null, - open val trailingContent: @Composable (() -> Unit)? = null, - open val enabled: Boolean = true, -) - -data class SettingsItem( - override val icon: DrawableResource? = null, - override val title: StringResource, - override val type: PreferenceItemType, - override val key: SettingsKey, - override val supportingContent: @Composable (() -> Unit)? = null, - override val trailingContent: @Composable (() -> Unit)? = null, - override val enabled: Boolean = true, -) : PreferenceItem( - title = title, - icon = icon, - supportingContent = supportingContent, - type = type, - key = key, - enabled = enabled, - ) - -data class SettingsCategoryItem( - override val icon: DrawableResource? = null, - override val title: StringResource, - val route: PreferenceCategoryKey, - val settings: List? = emptyList(), - override val supportingContent: @Composable (() -> Unit)? = null, - val footerContent: @Composable (() -> Unit)? = null, -) : PreferenceItem( - title = title, - icon = icon, - supportingContent = supportingContent, - type = PreferenceItemType.ROUTE, - key = SettingsKey.ROUTE, - ) - -enum class PreferenceItemType { - SWITCH, - INT, - BUTTON, - SELECT, - ROUTE, -} - -enum class PreferenceCategoryKey(val value: String) { - NOTIFICATIONS("notifications"), - TEST_OPTIONS("test_options"), - PRIVACY("privacy"), - PROXY("proxy"), - ADVANCED("advanced"), - SEND_EMAIL("send_email"), - ABOUT_OONI("about_ooni"), - - WEBSITES_CATEGORIES("websites_categories"), - SEE_RECENT_LOGS("see_recent_logs"), - ; - - companion object { - fun fromValue(value: String) = entries.first { it.value == value } - } -} - enum class SettingsKey(val value: String) { // Notifications NOTIFICATIONS_ENABLED("notifications_enabled"), diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/BootstrapPreferences.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/BootstrapPreferences.kt index 91dfbdf7..d54523d9 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/BootstrapPreferences.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/BootstrapPreferences.kt @@ -33,7 +33,7 @@ class BootstrapPreferences( SettingsKey.AUTOMATED_TESTING_CHARGING to true, SettingsKey.AUTOMATED_TESTING_NOT_UPLOADED_LIMIT to NOT_UPLOADED_LIMIT_DEFAULT, ) + - preferenceDefaults(), + organizationPreferenceDefaults(), ) } diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt index 3ef7f165..11eb869e 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt @@ -28,6 +28,7 @@ import ooniprobe.composeapp.generated.resources.Settings_Advanced_Label import ooniprobe.composeapp.generated.resources.Settings_Advanced_RecentLogs import ooniprobe.composeapp.generated.resources.Settings_AutomatedTesting_RunAutomatically import ooniprobe.composeapp.generated.resources.Settings_AutomatedTesting_RunAutomatically_ChargingOnly +import ooniprobe.composeapp.generated.resources.Settings_AutomatedTesting_RunAutomatically_Description import ooniprobe.composeapp.generated.resources.Settings_AutomatedTesting_RunAutomatically_Footer import ooniprobe.composeapp.generated.resources.Settings_AutomatedTesting_RunAutomatically_WiFiOnly import ooniprobe.composeapp.generated.resources.Settings_Notifications_Enabled @@ -37,10 +38,15 @@ import ooniprobe.composeapp.generated.resources.Settings_Privacy_SendCrashReport import ooniprobe.composeapp.generated.resources.Settings_Proxy_Label import ooniprobe.composeapp.generated.resources.Settings_SendEmail_Label import ooniprobe.composeapp.generated.resources.Settings_Sharing_UploadResults +import ooniprobe.composeapp.generated.resources.Settings_Sharing_UploadResults_Description import ooniprobe.composeapp.generated.resources.Settings_Storage_Clear import ooniprobe.composeapp.generated.resources.Settings_Storage_Label import ooniprobe.composeapp.generated.resources.Settings_TestOptions_Label import ooniprobe.composeapp.generated.resources.Settings_WarmVPNInUse_Label +import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Description +import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Label +import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntime +import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled import ooniprobe.composeapp.generated.resources.advanced import ooniprobe.composeapp.generated.resources.auto_test_not_uploaded_limit import ooniprobe.composeapp.generated.resources.ic_settings @@ -51,6 +57,7 @@ import ooniprobe.composeapp.generated.resources.proxy import ooniprobe.composeapp.generated.resources.send_email import org.jetbrains.compose.resources.stringResource import org.ooni.engine.models.WebConnectivityCategory +import org.ooni.probe.config.OrganizationConfig import org.ooni.probe.data.models.PreferenceCategoryKey import org.ooni.probe.data.models.PreferenceItemType import org.ooni.probe.data.models.SettingsCategoryItem @@ -59,6 +66,8 @@ import org.ooni.probe.data.models.SettingsKey import org.ooni.probe.data.repositories.PreferenceRepository import org.ooni.probe.ui.settings.category.SettingsDescription import org.ooni.probe.ui.shared.formatDataUsage +import org.ooni.probe.ui.shared.shortFormat +import kotlin.time.Duration.Companion.seconds class GetSettings( private val preferencesRepository: PreferenceRepository, @@ -82,6 +91,7 @@ class GetSettings( val enabledCategoriesCount = WebConnectivityCategory.entries.count { preferences[it.settingsKey] == true } buildSettings( + hasWebsitesDescriptor = OrganizationConfig.hasWebsitesDescriptor, uploadResultsEnabled = preferences[SettingsKey.UPLOAD_RESULTS] == true, autoRunEnabled = preferences[SettingsKey.AUTOMATED_TESTING_ENABLED] == true, autoRunNotUploadedLimit = preferences[SettingsKey.AUTOMATED_TESTING_NOT_UPLOADED_LIMIT] as? Int, @@ -95,6 +105,7 @@ class GetSettings( } private fun buildSettings( + hasWebsitesDescriptor: Boolean, uploadResultsEnabled: Boolean, autoRunEnabled: Boolean, autoRunNotUploadedLimit: Int?, @@ -131,43 +142,111 @@ class GetSettings( title = Res.string.Settings_Sharing_UploadResults, key = SettingsKey.UPLOAD_RESULTS, type = PreferenceItemType.SWITCH, + supportingContent = { + Text( + stringResource(Res.string.Settings_Sharing_UploadResults_Description), + style = MaterialTheme.typography.labelLarge, + ) + }, ), SettingsItem( title = Res.string.Settings_AutomatedTesting_RunAutomatically, key = SettingsKey.AUTOMATED_TESTING_ENABLED, type = PreferenceItemType.SWITCH, enabled = uploadResultsEnabled, - ), - SettingsItem( - title = Res.string.Settings_AutomatedTesting_RunAutomatically_WiFiOnly, - key = SettingsKey.AUTOMATED_TESTING_WIFIONLY, - type = PreferenceItemType.SWITCH, - enabled = autoRunEnabled && uploadResultsEnabled, - ), - SettingsItem( - title = Res.string.Settings_AutomatedTesting_RunAutomatically_ChargingOnly, - key = SettingsKey.AUTOMATED_TESTING_CHARGING, - type = PreferenceItemType.SWITCH, - enabled = autoRunEnabled && uploadResultsEnabled, - ), - SettingsItem( - title = Res.string.auto_test_not_uploaded_limit, - key = SettingsKey.AUTOMATED_TESTING_NOT_UPLOADED_LIMIT, - type = PreferenceItemType.INT, - enabled = autoRunEnabled && uploadResultsEnabled, supportingContent = { - val value = ( - autoRunNotUploadedLimit - ?: BootstrapPreferences.NOT_UPLOADED_LIMIT_DEFAULT - ).coerceAtLeast(1) - Text(value.toString()) + Text( + stringResource(Res.string.Settings_AutomatedTesting_RunAutomatically_Description), + style = MaterialTheme.typography.labelLarge, + ) }, ), - ) + webConnectivityPreferences( - enabledCategoriesCount, - maxRuntimeEnabled, - maxRuntime, - ), + ) + if (autoRunEnabled) { + listOf( + SettingsItem( + title = Res.string.Settings_AutomatedTesting_RunAutomatically_WiFiOnly, + key = SettingsKey.AUTOMATED_TESTING_WIFIONLY, + type = PreferenceItemType.SWITCH, + enabled = autoRunEnabled && uploadResultsEnabled, + indentation = 1, + ), + SettingsItem( + title = Res.string.Settings_AutomatedTesting_RunAutomatically_ChargingOnly, + key = SettingsKey.AUTOMATED_TESTING_CHARGING, + type = PreferenceItemType.SWITCH, + enabled = autoRunEnabled && uploadResultsEnabled, + indentation = 1, + ), + SettingsItem( + title = Res.string.auto_test_not_uploaded_limit, + key = SettingsKey.AUTOMATED_TESTING_NOT_UPLOADED_LIMIT, + type = PreferenceItemType.INT, + enabled = autoRunEnabled && uploadResultsEnabled, + supportingContent = { + val value = ( + autoRunNotUploadedLimit + ?: BootstrapPreferences.NOT_UPLOADED_LIMIT_DEFAULT + ).coerceAtLeast(1) + Text(value.toString()) + }, + indentation = 1, + ), + ) + if (hasWebsitesDescriptor) { + listOfNotNull( + SettingsItem( + title = Res.string.Settings_Websites_MaxRuntimeEnabled, + key = SettingsKey.MAX_RUNTIME_ENABLED, + type = PreferenceItemType.SWITCH, + indentation = 1, + ), + if (maxRuntimeEnabled) { + SettingsItem( + title = Res.string.Settings_Websites_MaxRuntime, + key = SettingsKey.MAX_RUNTIME, + type = PreferenceItemType.INT, + supportingContent = { + maxRuntime?.let { + Text(it.coerceAtLeast(0).seconds.shortFormat()) + } + }, + indentation = 2, + ) + } else { + null + }, + ) + } else { + emptyList() + } + } else { + emptyList() + } + if (hasWebsitesDescriptor) { + listOf( + SettingsCategoryItem( + title = Res.string.Settings_Websites_Categories_Label, + route = PreferenceCategoryKey.WEBSITES_CATEGORIES, + supportingContent = { + Text( + stringResource( + Res.string.Settings_Websites_Categories_Description, + enabledCategoriesCount, + ), + ) + }, + settings = WebConnectivityCategory.entries.mapNotNull { cat -> + SettingsItem( + icon = cat.icon, + title = cat.title, + supportingContent = { Text(stringResource(cat.description)) }, + key = cat.settingsKey ?: return@mapNotNull null, + type = PreferenceItemType.SWITCH, + ) + }, + ), + ) + } else { + emptyList() + }, footerContent = { SettingsDescription( Res.string.Settings_AutomatedTesting_RunAutomatically_Footer, diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/navigation/Navigation.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/navigation/Navigation.kt index a3064879..f39b19c6 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/navigation/Navigation.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/navigation/Navigation.kt @@ -161,9 +161,11 @@ fun Navigation( route = Screen.SettingsCategory.NAV_ROUTE, arguments = Screen.SettingsCategory.ARGUMENTS, ) { entry -> - val category = entry.arguments?.getString("category") ?: return@composable + val category = PreferenceCategoryKey.fromValue( + entry.arguments?.getString("category"), + ) ?: return@composable when (category) { - PreferenceCategoryKey.ABOUT_OONI.value -> { + PreferenceCategoryKey.ABOUT_OONI -> { val viewModel = viewModel { dependencies.aboutViewModel(onBack = { navController.goBack() }) } @@ -174,7 +176,7 @@ fun Navigation( ) } - PreferenceCategoryKey.PROXY.value -> { + PreferenceCategoryKey.PROXY -> { val viewModel = viewModel { dependencies.proxyViewModel(onBack = { navController.goBack() }) } @@ -182,7 +184,7 @@ fun Navigation( ProxyScreen(state, viewModel::onEvent) } - PreferenceCategoryKey.SEE_RECENT_LOGS.value -> { + PreferenceCategoryKey.SEE_RECENT_LOGS -> { val viewModel = viewModel { dependencies.logViewModel(onBack = { navController.goBack() }) } @@ -193,7 +195,7 @@ fun Navigation( else -> { val viewModel = viewModel { dependencies.settingsCategoryViewModel( - categoryKey = category, + categoryKey = category.value, goToSettingsForCategory = { navController.safeNavigate(Screen.SettingsCategory(it)) }, diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/settings/category/SettingsCategoryScreen.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/settings/category/SettingsCategoryScreen.kt index e0c07bcb..f685ef84 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/settings/category/SettingsCategoryScreen.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/ui/settings/category/SettingsCategoryScreen.kt @@ -78,69 +78,73 @@ fun SettingsCategoryScreen( val category = state.category ?: return Column { category.settings?.forEach { preferenceItem -> - when (preferenceItem.type) { - PreferenceItemType.SWITCH -> - SwitchSettingsView( - icon = preferenceItem.icon, - title = preferenceItem.title, - key = preferenceItem.key, - checked = state.preferences[preferenceItem.key] == true, - enabled = preferenceItem.enabled, - supportingContent = preferenceItem.supportingContent, - onCheckedChange = { key, value -> - onEvent( - SettingsCategoryViewModel.Event.CheckedChangeClick( - key, - value, - ), - ) - }, - ) + Box( + modifier = Modifier.padding(start = 32.dp * preferenceItem.indentation), + ) { + when (preferenceItem.type) { + PreferenceItemType.SWITCH -> + SwitchSettingsView( + icon = preferenceItem.icon, + title = preferenceItem.title, + key = preferenceItem.key, + checked = state.preferences[preferenceItem.key] == true, + enabled = preferenceItem.enabled, + supportingContent = preferenceItem.supportingContent, + onCheckedChange = { key, value -> + onEvent( + SettingsCategoryViewModel.Event.CheckedChangeClick( + key, + value, + ), + ) + }, + ) - PreferenceItemType.INT -> - NumberPickerItem( - title = preferenceItem.title, - supportingContent = preferenceItem.supportingContent, - enabled = preferenceItem.enabled, - value = state.preferences[preferenceItem.key] as? Int, - onChanged = { - onEvent( - SettingsCategoryViewModel.Event.IntChanged( - preferenceItem.key, - it, - ), - ) - }, - ) + PreferenceItemType.INT -> + NumberPickerItem( + title = preferenceItem.title, + supportingContent = preferenceItem.supportingContent, + enabled = preferenceItem.enabled, + value = state.preferences[preferenceItem.key] as? Int, + onChanged = { + onEvent( + SettingsCategoryViewModel.Event.IntChanged( + preferenceItem.key, + it, + ), + ) + }, + ) - PreferenceItemType.BUTTON -> - RouteSettingsView( - title = preferenceItem.title, - supportingContent = preferenceItem.supportingContent, - trailingContent = preferenceItem.trailingContent, - ) + PreferenceItemType.BUTTON -> + RouteSettingsView( + title = preferenceItem.title, + supportingContent = preferenceItem.supportingContent, + trailingContent = preferenceItem.trailingContent, + ) - PreferenceItemType.ROUTE -> - RouteSettingsView( - title = preferenceItem.title, - supportingContent = preferenceItem.supportingContent, - modifier = - Modifier.clickable { - if (preferenceItem is SettingsCategoryItem) { - onEvent( - SettingsCategoryViewModel.Event.SettingsCategoryClick( - preferenceItem.route, - ), - ) - } - }, - ) + PreferenceItemType.ROUTE -> + RouteSettingsView( + title = preferenceItem.title, + supportingContent = preferenceItem.supportingContent, + modifier = + Modifier.clickable { + if (preferenceItem is SettingsCategoryItem) { + onEvent( + SettingsCategoryViewModel.Event.SettingsCategoryClick( + preferenceItem.route, + ), + ) + } + }, + ) - PreferenceItemType.SELECT -> - RouteSettingsView( - title = preferenceItem.title, - supportingContent = preferenceItem.supportingContent, - ) + PreferenceItemType.SELECT -> + RouteSettingsView( + title = preferenceItem.title, + supportingContent = preferenceItem.supportingContent, + ) + } } } category.footerContent?.let { diff --git a/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt b/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt new file mode 100644 index 00000000..f36060c0 --- /dev/null +++ b/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt @@ -0,0 +1,8 @@ +package org.ooni.probe.config + +object BuildTypesDefaults : BuildTypesDefaultsInterface { + override val ooniApiBaseUrl = "https://api.ooni.org" + override val ooniRunDomain = "run.ooni.org" + override val ooniRunDashboardUrl = "https://run.ooni.org" + override val explorerUrl = "https://explorer.test.ooni.org" +} diff --git a/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt b/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt deleted file mode 100644 index 6838b82d..00000000 --- a/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/OrganizationConfigInterface.kt +++ /dev/null @@ -1,25 +0,0 @@ -package org.ooni.probe.config - -interface OrganizationConfigInterface { - val baseSoftwareName: String - - val ooniApiBaseUrl: String - get() = "https://api.ooni.org" - - val ooniRunDomain: String - get() = "run.ooni.org" - - val ooniRunDashboardUrl: String - get() = "https://run.ooni.org" - - val explorerUrl: String - get() = "https://explorer.ooni.org" - - val testDisplayMode: TestDisplayMode - - val autorunTaskId: String - - val onboardingImages: OnboardingImages - - val updateDescriptorTaskId: String -} diff --git a/composeApp/src/dwMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt b/composeApp/src/dwMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt index 6237f0cf..fa7326fb 100644 --- a/composeApp/src/dwMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt +++ b/composeApp/src/dwMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt @@ -13,4 +13,5 @@ object OrganizationConfig : OrganizationConfigInterface { image2 = Res.drawable.onboarding, image3 = Res.drawable.onboarding, ) + override val hasWebsitesDescriptor = false } diff --git a/composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt b/composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt new file mode 100644 index 00000000..284516ed --- /dev/null +++ b/composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt @@ -0,0 +1,8 @@ +package org.ooni.probe.domain + +import org.ooni.probe.data.models.PreferenceItem +import org.ooni.probe.data.models.SettingsKey + +fun organizationPreferenceDefaults(): List> { + return emptyList() +} diff --git a/composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt b/composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt deleted file mode 100644 index 98fb257b..00000000 --- a/composeApp/src/dwMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt +++ /dev/null @@ -1,16 +0,0 @@ -package org.ooni.probe.domain - -import org.ooni.probe.data.models.PreferenceItem -import org.ooni.probe.data.models.SettingsKey - -fun webConnectivityPreferences( - enabledCategoriesCount: Int, - maxRuntimeEnabled: Boolean, - maxRuntime: Int?, -): List { - return emptyList() -} - -fun preferenceDefaults(): List> { - return emptyList() -} diff --git a/composeApp/src/ooniMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt b/composeApp/src/ooniMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt index e8ec35c7..87dc2ff9 100644 --- a/composeApp/src/ooniMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt +++ b/composeApp/src/ooniMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt @@ -15,4 +15,5 @@ object OrganizationConfig : OrganizationConfigInterface { image2 = Res.drawable.onboarding2, image3 = Res.drawable.onboarding3, ) + override val hasWebsitesDescriptor = true } diff --git a/composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt b/composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt new file mode 100644 index 00000000..31de858b --- /dev/null +++ b/composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationPreferenceDefaults.kt @@ -0,0 +1,13 @@ +package org.ooni.probe.domain + +import org.ooni.engine.models.WebConnectivityCategory +import org.ooni.probe.data.models.SettingsKey + +fun organizationPreferenceDefaults(): List> { + return listOf( + SettingsKey.MAX_RUNTIME_ENABLED to true, + SettingsKey.MAX_RUNTIME to 90, + ) + WebConnectivityCategory.entries + .mapNotNull { it.settingsKey } + .map { it to true } +} diff --git a/composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt b/composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt deleted file mode 100644 index d6112600..00000000 --- a/composeApp/src/ooniMain/kotlin/org/ooni/probe/domain/OrganizationSettings.kt +++ /dev/null @@ -1,73 +0,0 @@ -package org.ooni.probe.domain - -import androidx.compose.material3.Text -import ooniprobe.composeapp.generated.resources.Res -import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Description -import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Label -import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntime -import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled -import org.jetbrains.compose.resources.stringResource -import org.ooni.engine.models.WebConnectivityCategory -import org.ooni.probe.data.models.PreferenceCategoryKey -import org.ooni.probe.data.models.PreferenceItem -import org.ooni.probe.data.models.PreferenceItemType -import org.ooni.probe.data.models.SettingsCategoryItem -import org.ooni.probe.data.models.SettingsItem -import org.ooni.probe.data.models.SettingsKey -import org.ooni.probe.ui.shared.shortFormat -import kotlin.time.Duration.Companion.seconds - -fun webConnectivityPreferences( - enabledCategoriesCount: Int, - maxRuntimeEnabled: Boolean, - maxRuntime: Int?, -): List { - return listOf( - SettingsCategoryItem( - title = Res.string.Settings_Websites_Categories_Label, - route = PreferenceCategoryKey.WEBSITES_CATEGORIES, - supportingContent = { - Text( - stringResource( - Res.string.Settings_Websites_Categories_Description, - enabledCategoriesCount, - ), - ) - }, - settings = WebConnectivityCategory.entries.mapNotNull { cat -> - SettingsItem( - icon = cat.icon, - title = cat.title, - supportingContent = { Text(stringResource(cat.description)) }, - key = cat.settingsKey ?: return@mapNotNull null, - type = PreferenceItemType.SWITCH, - ) - }, - ), - SettingsItem( - title = Res.string.Settings_Websites_MaxRuntimeEnabled, - key = SettingsKey.MAX_RUNTIME_ENABLED, - type = PreferenceItemType.SWITCH, - ), - SettingsItem( - title = Res.string.Settings_Websites_MaxRuntime, - key = SettingsKey.MAX_RUNTIME, - type = PreferenceItemType.INT, - enabled = maxRuntimeEnabled, - supportingContent = { - maxRuntime?.let { - Text(it.coerceAtLeast(0).seconds.shortFormat()) - } - }, - ), - ) -} - -fun preferenceDefaults(): List> { - return listOf( - SettingsKey.MAX_RUNTIME_ENABLED to true, - SettingsKey.MAX_RUNTIME to 90, - ) + WebConnectivityCategory.entries - .mapNotNull { it.settingsKey } - .map { it to true } -} From 261f9acc49de8b1fb2d8882a279f06a4801d65f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Santos?= Date: Tue, 26 Nov 2024 18:58:18 +0000 Subject: [PATCH 2/3] Fix limit website --- .../values/strings-common.xml | 1 + .../org/ooni/probe/domain/GetSettings.kt | 57 +++++++++++-------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/composeApp/src/commonMain/composeResources/values/strings-common.xml b/composeApp/src/commonMain/composeResources/values/strings-common.xml index 0650d913..299e38db 100644 --- a/composeApp/src/commonMain/composeResources/values/strings-common.xml +++ b/composeApp/src/commonMain/composeResources/values/strings-common.xml @@ -293,4 +293,5 @@ Unsupported URL Results are automatically uploaded to OONI explorer Tests will run every hour in the background + Only for manual runs diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt index 11eb869e..2db3816c 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt @@ -47,6 +47,7 @@ import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Des import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Label import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntime import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled +import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled_Description import ooniprobe.composeapp.generated.resources.advanced import ooniprobe.composeapp.generated.resources.auto_test_not_uploaded_limit import ooniprobe.composeapp.generated.resources.ic_settings @@ -191,33 +192,39 @@ class GetSettings( }, indentation = 1, ), - ) + if (hasWebsitesDescriptor) { - listOfNotNull( - SettingsItem( - title = Res.string.Settings_Websites_MaxRuntimeEnabled, - key = SettingsKey.MAX_RUNTIME_ENABLED, - type = PreferenceItemType.SWITCH, - indentation = 1, - ), - if (maxRuntimeEnabled) { - SettingsItem( - title = Res.string.Settings_Websites_MaxRuntime, - key = SettingsKey.MAX_RUNTIME, - type = PreferenceItemType.INT, - supportingContent = { - maxRuntime?.let { - Text(it.coerceAtLeast(0).seconds.shortFormat()) - } - }, - indentation = 2, + ) + } else { + emptyList() + } + if (hasWebsitesDescriptor) { + listOfNotNull( + SettingsItem( + title = Res.string.Settings_Websites_MaxRuntimeEnabled, + key = SettingsKey.MAX_RUNTIME_ENABLED, + type = PreferenceItemType.SWITCH, + supportingContent = { + Text( + stringResource(Res.string.Settings_Websites_MaxRuntimeEnabled_Description), + style = MaterialTheme.typography.labelLarge, ) - } else { - null }, - ) - } else { - emptyList() - } + indentation = 0, + ), + if (maxRuntimeEnabled) { + SettingsItem( + title = Res.string.Settings_Websites_MaxRuntime, + key = SettingsKey.MAX_RUNTIME, + type = PreferenceItemType.INT, + supportingContent = { + maxRuntime?.let { + Text(it.coerceAtLeast(0).seconds.shortFormat()) + } + }, + indentation = 1, + ) + } else { + null + }, + ) } else { emptyList() } + if (hasWebsitesDescriptor) { From d8194cb589fc3f3469880e9a7ba2f4b6f0880634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Santos?= Date: Wed, 27 Nov 2024 10:33:56 +0000 Subject: [PATCH 3/3] Use new string resources --- .../composeResources/values/strings-common.xml | 6 ++++-- .../{BuildTypesDefaults.kt => BuildTypeDefaults.kt} | 4 ++-- .../kotlin/org/ooni/probe/config/OrganizationConfig.kt | 10 +++++----- .../kotlin/org/ooni/probe/domain/GetSettings.kt | 8 ++++---- .../kotlin/org/ooni/probe/config/BuildTypeDefaults.kt | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) rename composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/{BuildTypesDefaults.kt => BuildTypeDefaults.kt} (63%) diff --git a/composeApp/src/commonMain/composeResources/values/strings-common.xml b/composeApp/src/commonMain/composeResources/values/strings-common.xml index 299e38db..2199b650 100644 --- a/composeApp/src/commonMain/composeResources/values/strings-common.xml +++ b/composeApp/src/commonMain/composeResources/values/strings-common.xml @@ -76,8 +76,8 @@ Only while charging By enabling automatic testing, OONI Probe tests will run automatically multiple times per day. Your test results will automatically get published on OONI Explorer: https://explorer.ooni.org/ \n\nImportant: If you have a VPN enabled, OONI Probe will not run tests automatically. Please turn off your VPN for automated OONI Probe testing. Learn more: https://ooni.org/support/faq/#can-i-run-ooni-probe-over-a-vpn - Limit Websites test duration - Maximum Websites test duration + Limit test duration + Test duration Website categories to test %1$s categories enabled @@ -292,6 +292,8 @@ Skip after this amount of results failed to upload Unsupported URL Results are automatically uploaded to OONI explorer + Limit Websites test duration + Maximum Websites test duration Tests will run every hour in the background Only for manual runs diff --git a/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt b/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt similarity index 63% rename from composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt rename to composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt index a255ad36..4aca2826 100644 --- a/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypesDefaults.kt +++ b/composeApp/src/commonMain/debug/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt @@ -1,8 +1,8 @@ package org.ooni.probe.config -object BuildTypesDefaults : BuildTypesDefaultsInterface { +object BuildTypeDefaults : BuildTypeDefaultsInterface { override val ooniApiBaseUrl = "https://api.dev.ooni.io" override val ooniRunDomain = "run.test.ooni.org" override val ooniRunDashboardUrl = "https://run.test.ooni.org" - override val explorerUrl = "https://explorer.test.ooni.org" + override val explorerUrl = "https://explorer.ooni.org" } diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt index ffe14918..4393c783 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/config/OrganizationConfig.kt @@ -10,13 +10,13 @@ interface OrganizationConfigInterface { val updateDescriptorTaskId: String val hasWebsitesDescriptor: Boolean - val ooniApiBaseUrl get() = BuildTypesDefaults.ooniApiBaseUrl - val ooniRunDomain get() = BuildTypesDefaults.ooniRunDomain - val ooniRunDashboardUrl get() = BuildTypesDefaults.ooniRunDashboardUrl - val explorerUrl get() = BuildTypesDefaults.explorerUrl + val ooniApiBaseUrl get() = BuildTypeDefaults.ooniApiBaseUrl + val ooniRunDomain get() = BuildTypeDefaults.ooniRunDomain + val ooniRunDashboardUrl get() = BuildTypeDefaults.ooniRunDashboardUrl + val explorerUrl get() = BuildTypeDefaults.explorerUrl } -interface BuildTypesDefaultsInterface { +interface BuildTypeDefaultsInterface { val ooniApiBaseUrl: String val ooniRunDomain: String val ooniRunDashboardUrl: String diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt index 2db3816c..b73a1ce4 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/domain/GetSettings.kt @@ -45,9 +45,9 @@ import ooniprobe.composeapp.generated.resources.Settings_TestOptions_Label import ooniprobe.composeapp.generated.resources.Settings_WarmVPNInUse_Label import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Description import ooniprobe.composeapp.generated.resources.Settings_Websites_Categories_Label -import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntime -import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled_Description +import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntimeEnabled_New +import ooniprobe.composeapp.generated.resources.Settings_Websites_MaxRuntime_New import ooniprobe.composeapp.generated.resources.advanced import ooniprobe.composeapp.generated.resources.auto_test_not_uploaded_limit import ooniprobe.composeapp.generated.resources.ic_settings @@ -198,7 +198,7 @@ class GetSettings( } + if (hasWebsitesDescriptor) { listOfNotNull( SettingsItem( - title = Res.string.Settings_Websites_MaxRuntimeEnabled, + title = Res.string.Settings_Websites_MaxRuntimeEnabled_New, key = SettingsKey.MAX_RUNTIME_ENABLED, type = PreferenceItemType.SWITCH, supportingContent = { @@ -211,7 +211,7 @@ class GetSettings( ), if (maxRuntimeEnabled) { SettingsItem( - title = Res.string.Settings_Websites_MaxRuntime, + title = Res.string.Settings_Websites_MaxRuntime_New, key = SettingsKey.MAX_RUNTIME, type = PreferenceItemType.INT, supportingContent = { diff --git a/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt b/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt index f36060c0..ce360acd 100644 --- a/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt +++ b/composeApp/src/commonMain/release/kotlin/org/ooni/probe/config/BuildTypeDefaults.kt @@ -1,8 +1,8 @@ package org.ooni.probe.config -object BuildTypesDefaults : BuildTypesDefaultsInterface { +object BuildTypeDefaults : BuildTypeDefaultsInterface { override val ooniApiBaseUrl = "https://api.ooni.org" override val ooniRunDomain = "run.ooni.org" override val ooniRunDashboardUrl = "https://run.ooni.org" - override val explorerUrl = "https://explorer.test.ooni.org" + override val explorerUrl = "https://explorer.ooni.org" }