Skip to content

Commit

Permalink
Make Settings Menu Options Configurable (#3300)
Browse files Browse the repository at this point in the history
* Rename GIZ EIR to EIR

* Ignore debug directory in variants dir

* Add settingsScreenMenuOptions to app config

* Show/hide settings menu options based on app config

* Show all menu options by default in tests

* Add SWITCH_LANGUAGES as a default in the application

* Update documentation

* Update insights strings

* Update strings

* Remove DOWNLOAD_DATABASE settings menu option
  • Loading branch information
qiarie authored Jun 3, 2024
1 parent ee6d05e commit 6bdd3a0
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ data class ApplicationConfiguration(
val showLogo: Boolean = true,
val taskBackgroundWorkerBatchSize: Int = 500,
val eventWorkflows: List<EventWorkflow> = emptyList(),
val settingsScreenMenuOptions: List<SettingsOptions> =
listOf(
SettingsOptions.MANUAL_SYNC,
SettingsOptions.SWITCH_LANGUAGES,
SettingsOptions.RESET_DATA,
SettingsOptions.INSIGHTS,
),
val logGpsLocation: List<LocationLogOptions> = emptyList(),
val usePractitionerAssignedLocationOnSync: Boolean =
true, // TODO This defaults to scheduling periodic sync, otherwise use sync location ids from
Expand All @@ -61,3 +68,12 @@ enum class LocationLogOptions {
QUESTIONNAIRE,
CALCULATE_DISTANCE_RULE_EXECUTOR,
}

enum class SettingsOptions {
MANUAL_SYNC,
OFFLINE_MAPS,
SWITCH_LANGUAGES,
RESET_DATA,
INSIGHTS,
CONTACT_HELP,
}
2 changes: 1 addition & 1 deletion android/engine/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@
<string name="location">Location</string>
<string name="app_version_code">App version code</string>
<string name="build_date">Build date</string>
<string name="manufacture">Manufacture</string>
<string name="manufacture">Manufacturer</string>
<string name="app_versions">App version</string>
<string name="os_version">OS Version</string>
<string name="device_date">Date</string>
Expand Down
1 change: 1 addition & 0 deletions android/quest/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ release/
src/*/assets/configs/
src/androidTest/assets/resources.db
src/benchmark/assets/resources.db
**/debug/
2 changes: 1 addition & 1 deletion android/quest/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ android {
dimension = "apps"
applicationIdSuffix = ".gizeir"
versionNameSuffix = "-gizeir"
manifestPlaceholders["appLabel"] = "GIZ EIR"
manifestPlaceholders["appLabel"] = "EIR"
}

create("engage") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ class UserSettingScreenTest {
isShowDatabaseResetConfirmation: Boolean = false,
isDebugVariant: Boolean = false,
isP2PAvailable: Boolean = false,
showManualSync: Boolean = true,
showAppInsights: Boolean = true,
hasOfflineMaps: Boolean = true,
showContactHelp: Boolean = true,
) {
scenario.onActivity { activity ->
activity.setContent {
Expand All @@ -189,17 +193,21 @@ class UserSettingScreenTest {
fullname = "Jam Kenya",
practitionerLocation = "Gateway Remote Location",
username = userName,
allowSwitchingLanguages = allowSwitchingLanguages,
selectedLanguage = Locale.ENGLISH.toLanguageTag(),
languages = listOf(Language("en", "English"), Language("sw", "Swahili")),
showDatabaseResetConfirmation = isShowDatabaseResetConfirmation,
progressBarState = Pair(isShowProgressBar, R.string.resetting_app),
isDebugVariant = isDebugVariant,
onEvent = {},
mainNavController = rememberNavController(),
allowP2PSync = isP2PAvailable,
lastSyncTime = "05:30 PM, Mar 3",
showProgressIndicatorFlow = MutableStateFlow(false),
enableManualSync = showManualSync,
allowSwitchingLanguages = allowSwitchingLanguages,
showDatabaseResetConfirmation = isShowDatabaseResetConfirmation,
allowP2PSync = isP2PAvailable,
enableAppInsights = showAppInsights,
showOfflineMaps = hasOfflineMaps,
enableHelpContacts = showContactHelp,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import javax.inject.Inject
import kotlinx.coroutines.launch
import org.smartregister.fhircore.engine.BuildConfig
import org.smartregister.fhircore.engine.R
import org.smartregister.fhircore.engine.configuration.app.SettingsOptions
import org.smartregister.fhircore.engine.domain.model.SnackBarMessageConfig
import org.smartregister.fhircore.engine.sync.OnSyncListener
import org.smartregister.fhircore.engine.sync.SyncListenerManager
Expand Down Expand Up @@ -97,19 +98,27 @@ class UserSettingFragment : Fragment(), OnSyncListener {
username = userSettingViewModel.retrieveUsername(),
practitionerLocation = userSettingViewModel.practitionerLocation(),
fullname = userSettingViewModel.retrieveUserInfo()?.name,
allowSwitchingLanguages = userSettingViewModel.allowSwitchingLanguages(),
selectedLanguage = userSettingViewModel.loadSelectedLanguage(),
allowP2PSync = userSettingViewModel.enabledDeviceToDeviceSync(),
languages = userSettingViewModel.languages,
onEvent = userSettingViewModel::onEvent,
showDatabaseResetConfirmation =
userSettingViewModel.showDBResetConfirmationDialog.observeAsState(false).value,
progressBarState =
userSettingViewModel.progressBarState.observeAsState(Pair(false, 0)).value,
isDebugVariant = BuildConfig.DEBUG,
mainNavController = findNavController(),
lastSyncTime = userSettingViewModel.retrieveLastSyncTimestamp(),
showProgressIndicatorFlow = userSettingViewModel.showProgressIndicatorFlow,
enableManualSync =
userSettingViewModel.enableMenuOption(SettingsOptions.MANUAL_SYNC),
allowSwitchingLanguages = userSettingViewModel.allowSwitchingLanguages(),
showDatabaseResetConfirmation =
userSettingViewModel.enableMenuOption(SettingsOptions.RESET_DATA) &&
userSettingViewModel.showDBResetConfirmationDialog.observeAsState(false).value,
enableAppInsights = userSettingViewModel.enableMenuOption(SettingsOptions.INSIGHTS),
showOfflineMaps =
userSettingViewModel.enableMenuOption(SettingsOptions.OFFLINE_MAPS),
allowP2PSync = userSettingViewModel.enabledDeviceToDeviceSync(),
enableHelpContacts =
userSettingViewModel.enableMenuOption(SettingsOptions.CONTACT_HELP),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,22 @@ fun UserSettingScreen(
username: String?,
practitionerLocation: String?,
fullname: String?,
allowSwitchingLanguages: Boolean,
selectedLanguage: String,
languages: List<Language>,
showDatabaseResetConfirmation: Boolean,
progressBarState: Pair<Boolean, Int>,
isDebugVariant: Boolean = false,
onEvent: (UserSettingsEvent) -> Unit,
mainNavController: NavController,
appVersionPair: Pair<Int, String>? = null,
allowP2PSync: Boolean,
lastSyncTime: String?,
showProgressIndicatorFlow: MutableStateFlow<Boolean>,
enableManualSync: Boolean,
allowSwitchingLanguages: Boolean,
showDatabaseResetConfirmation: Boolean,
enableAppInsights: Boolean,
showOfflineMaps: Boolean = false,
allowP2PSync: Boolean = false,
enableHelpContacts: Boolean = false,
) {
val context = LocalContext.current
val (showProgressBar, messageResource) = progressBarState
Expand Down Expand Up @@ -212,20 +216,25 @@ fun UserSettingScreen(
}
}
Divider(color = DividerColor)
UserSettingRow(
icon = Icons.Rounded.Sync,
text = stringResource(id = R.string.sync),
clickListener = { onEvent(UserSettingsEvent.SyncData(context)) },
modifier = modifier.testTag(USER_SETTING_ROW_SYNC),
)

UserSettingRow(
icon = Icons.Rounded.Map,
text = stringResource(id = R.string.offline_map),
clickListener = { onEvent(UserSettingsEvent.OnLaunchOfflineMap(true, context)) },
modifier = modifier.testTag(USER_SETTING_ROW_OFFLINE_MAP),
canSwitchToScreen = true,
)
if (enableManualSync) {
UserSettingRow(
icon = Icons.Rounded.Sync,
text = stringResource(id = R.string.sync),
clickListener = { onEvent(UserSettingsEvent.SyncData(context)) },
modifier = modifier.testTag(USER_SETTING_ROW_SYNC),
)
}

if (showOfflineMaps) {
UserSettingRow(
icon = Icons.Rounded.Map,
text = stringResource(id = R.string.offline_map),
clickListener = { onEvent(UserSettingsEvent.OnLaunchOfflineMap(true, context)) },
modifier = modifier.testTag(USER_SETTING_ROW_OFFLINE_MAP),
canSwitchToScreen = true,
)
}

// Language option
if (allowSwitchingLanguages) {
Expand Down Expand Up @@ -323,23 +332,28 @@ fun UserSettingScreen(
)
}

UserSettingRow(
icon = Icons.Rounded.Insights,
text = stringResource(id = R.string.insights),
clickListener = {
onEvent(UserSettingsEvent.ShowInsightsScreen(navController = mainNavController))
},
modifier = modifier.testTag(USER_SETTING_ROW_INSIGHTS),
showProgressIndicator = showProgressIndicatorFlow.collectAsState().value,
canSwitchToScreen = true,
)
UserSettingRow(
icon = Icons.Rounded.Phone,
text = stringResource(id = R.string.contact_help),
clickListener = { onEvent(UserSettingsEvent.ShowContactView(true, context)) },
modifier = modifier.testTag(USER_SETTING_ROW_CONTACT_HELP),
canSwitchToScreen = true,
)
if (enableAppInsights) {
UserSettingRow(
icon = Icons.Rounded.Insights,
text = stringResource(id = R.string.insights),
clickListener = {
onEvent(UserSettingsEvent.ShowInsightsScreen(navController = mainNavController))
},
modifier = modifier.testTag(USER_SETTING_ROW_INSIGHTS),
showProgressIndicator = showProgressIndicatorFlow.collectAsState().value,
canSwitchToScreen = true,
)
}

if (enableHelpContacts) {
UserSettingRow(
icon = Icons.Rounded.Phone,
text = stringResource(id = R.string.contact_help),
clickListener = { onEvent(UserSettingsEvent.ShowContactView(true, context)) },
modifier = modifier.testTag(USER_SETTING_ROW_CONTACT_HELP),
canSwitchToScreen = true,
)
}

UserSettingRow(
icon = Icons.Rounded.Logout,
Expand Down Expand Up @@ -484,17 +498,21 @@ fun UserSettingPreview() {
username = "Jam",
fullname = "Jam Kenya",
practitionerLocation = "Gateway Remote Location",
allowSwitchingLanguages = true,
selectedLanguage = java.util.Locale.ENGLISH.toLanguageTag(),
languages = listOf(Language("en", "English"), Language("sw", "Swahili")),
showDatabaseResetConfirmation = false,
progressBarState = Pair(false, R.string.resetting_app),
isDebugVariant = true,
onEvent = {},
mainNavController = rememberNavController(),
appVersionPair = Pair(1, "1.0.1"),
allowP2PSync = true,
lastSyncTime = "05:30 PM, Mar 3",
showProgressIndicatorFlow = MutableStateFlow(false),
enableManualSync = true,
allowSwitchingLanguages = true,
showDatabaseResetConfirmation = false,
enableAppInsights = true,
showOfflineMaps = true,
allowP2PSync = true,
enableHelpContacts = true,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.smartregister.fhircore.engine.R
import org.smartregister.fhircore.engine.configuration.ConfigType
import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.configuration.app.ApplicationConfiguration
import org.smartregister.fhircore.engine.configuration.app.SettingsOptions
import org.smartregister.fhircore.engine.data.remote.model.response.UserInfo
import org.smartregister.fhircore.engine.domain.model.SnackBarMessageConfig
import org.smartregister.fhircore.engine.sync.SyncBroadcaster
Expand Down Expand Up @@ -104,7 +105,11 @@ constructor(
fun retrieveLastSyncTimestamp(): String? =
sharedPreferencesHelper.read(SharedPreferenceKey.LAST_SYNC_TIMESTAMP.name, null)

fun allowSwitchingLanguages() = languages.size > 1
fun enableMenuOption(settingOption: SettingsOptions) =
applicationConfiguration.settingsScreenMenuOptions.contains(settingOption)

fun allowSwitchingLanguages() =
enableMenuOption(SettingsOptions.SWITCH_LANGUAGES) && languages.size > 1

fun loadSelectedLanguage(): String =
Locale.forLanguageTag(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import org.robolectric.Shadows
import org.robolectric.shadows.ShadowLooper
import org.smartregister.fhircore.engine.R
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.configuration.app.SettingsOptions
import org.smartregister.fhircore.engine.data.remote.fhir.resource.FhirResourceDataSource
import org.smartregister.fhircore.engine.data.remote.fhir.resource.FhirResourceService
import org.smartregister.fhircore.engine.domain.model.Language
Expand Down Expand Up @@ -180,25 +181,39 @@ class UserSettingViewModelTest : RobolectricTest() {
}

@Test
fun allowSwitchingLanguagesShouldReturnTrueWhenMultipleLanguagesAreConfigured() {
fun allowSwitchingLanguagesShouldReturnFalseWhenSwitchLanguagesOptionIsNotSetAndMultipleLanguagesAreConfigured() {
val languages = listOf(Language("es", "Spanish"), Language("en", "English"))
userSettingViewModel = spyk(userSettingViewModel)

every { userSettingViewModel.enableMenuOption(SettingsOptions.SWITCH_LANGUAGES) } returns false
every { userSettingViewModel.languages } returns languages

Assert.assertTrue(userSettingViewModel.allowSwitchingLanguages())
Assert.assertFalse(userSettingViewModel.allowSwitchingLanguages())
Shadows.shadowOf(Looper.getMainLooper()).idle()
}

@Test
fun allowSwitchingLanguagesShouldReturnFalseWhenConfigurationIsFalse() {
val languages = listOf(Language("es", "Spanish"))
fun allowSwitchingLanguagesShouldReturnTrueWhenSwitchLanguagesOptionIsSetAndMultipleLanguagesAreConfigured() {
val languages = listOf(Language("es", "Spanish"), Language("en", "English"))
userSettingViewModel = spyk(userSettingViewModel)

every { userSettingViewModel.enableMenuOption(SettingsOptions.SWITCH_LANGUAGES) } returns true
every { userSettingViewModel.languages } returns languages

Assert.assertTrue(userSettingViewModel.allowSwitchingLanguages())
Shadows.shadowOf(Looper.getMainLooper()).idle()
}

@Test
fun allowSwitchingLanguagesShouldReturnFalseWhenSwitchLanguagesOptionIsSetAndOnlyOneLanguageIsConfigured() {
val languages = listOf(Language("en", "English"))
userSettingViewModel = spyk(userSettingViewModel)

every { userSettingViewModel.enableMenuOption(SettingsOptions.SWITCH_LANGUAGES) } returns true
every { userSettingViewModel.languages } returns languages

Assert.assertFalse(userSettingViewModel.allowSwitchingLanguages())
Shadows.shadowOf(Looper.getMainLooper()).idle()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,6 @@ The `logGpsLocation` config takes in a list of `LocationLogOptions` to toggle wh
`showLogo` | Toggle whether to show the logo | Yes | `true` |
`taskBackgroundWorkerBatchSize` | Batch size of tasks to be fetched from the server | Yes | `500` |
`eventWorkflows` | A list of `EventWorkflow`s | Yes | `emptyList()` |
`logGpsLocation` | A list of `LocationLogOptions` to toggle whether to capture GPS coordinates | Yes | emptyList() |
`settingsScreenMenuOptions` | A list of `SettingsOptions`s that defines menu options to be displayed on the `Settings` screen | Yes | `listOf(SettingsOptions.MANUAL_SYNC, SettingsOptions.SWITCH_LANGUAGES, SettingsOptions.RESET_DATA, SettingsOptions.INSIGHTS,)` |
`logGpsLocation` | A list of `LocationLogOptions` to toggle whether to capture GPS coordinates | Yes | emptyList() |
`usePractitionerAssignedLocationOnSync` | If `true`, default to using logged in practitioner's location | Yes | `true` |

0 comments on commit 6bdd3a0

Please sign in to comment.