adding ability to opt in to on device logs, disabled by default
This commit is contained in:
parent
31318037a7
commit
43e53261b6
|
@ -42,10 +42,15 @@ class SmallTalkApplication : Application(), ModuleProvider {
|
|||
val notificationsModule = featureModules.notificationsModule
|
||||
val storeModule = appModule.storeModule.value
|
||||
val eventLogStore = storeModule.eventLogStore()
|
||||
val loggingStore = storeModule.loggingStore()
|
||||
|
||||
val logger: (String, String) -> Unit = { tag, message ->
|
||||
Log.e(tag, message)
|
||||
applicationScope.launch { eventLogStore.insert(tag, message) }
|
||||
applicationScope.launch {
|
||||
if (loggingStore.isEnabled()) {
|
||||
eventLogStore.insert(tag, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
attachAppLogger(logger)
|
||||
_appLogger = logger
|
||||
|
|
|
@ -205,6 +205,7 @@ internal class FeatureModules internal constructor(
|
|||
deviceMeta,
|
||||
coroutineDispatchers,
|
||||
coreAndroidModule.themeStore(),
|
||||
storeModule.value.loggingStore(),
|
||||
)
|
||||
}
|
||||
val profileModule by unsafeLazy { ProfileModule(matrixModules.profile, matrixModules.sync, matrixModules.room, trackingModule.errorTracker) }
|
||||
|
|
|
@ -8,7 +8,13 @@ interface Preferences {
|
|||
suspend fun remove(key: String)
|
||||
}
|
||||
|
||||
interface CachedPreferences : Preferences
|
||||
interface CachedPreferences : Preferences {
|
||||
suspend fun readString(key: String, defaultValue: String): String
|
||||
}
|
||||
|
||||
suspend fun CachedPreferences.readBoolean(key: String, defaultValue: Boolean) = this
|
||||
.readString(key, defaultValue.toString())
|
||||
.toBooleanStrict()
|
||||
|
||||
suspend fun Preferences.readBoolean(key: String) = this.readString(key)?.toBooleanStrict()
|
||||
suspend fun Preferences.store(key: String, value: Boolean) = this.store(key, value.toString())
|
|
@ -8,12 +8,20 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
@Composable
|
||||
fun TextRow(title: String, content: String? = null, includeDivider: Boolean = true, onClick: (() -> Unit)? = null, body: @Composable () -> Unit = {}) {
|
||||
fun TextRow(
|
||||
title: String,
|
||||
content: String? = null,
|
||||
includeDivider: Boolean = true,
|
||||
onClick: (() -> Unit)? = null,
|
||||
enabled: Boolean = true,
|
||||
body: @Composable () -> Unit = {}
|
||||
) {
|
||||
val modifier = Modifier.padding(horizontal = 24.dp)
|
||||
Column(
|
||||
Modifier
|
||||
|
@ -21,14 +29,19 @@ fun TextRow(title: String, content: String? = null, includeDivider: Boolean = tr
|
|||
.clickable(enabled = onClick != null) { onClick?.invoke() }) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Column(modifier) {
|
||||
val textModifier = when (enabled) {
|
||||
true -> Modifier
|
||||
false -> Modifier.alpha(0.5f)
|
||||
}
|
||||
when (content) {
|
||||
null -> {
|
||||
Text(text = title, fontSize = 18.sp)
|
||||
Text(text = title, fontSize = 18.sp, modifier = textModifier)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Text(text = title, fontSize = 12.sp)
|
||||
Text(text = title, fontSize = 12.sp, modifier = textModifier)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(text = content, fontSize = 18.sp)
|
||||
Text(text = content, fontSize = 18.sp, modifier = textModifier)
|
||||
}
|
||||
}
|
||||
body()
|
||||
|
@ -56,6 +69,6 @@ fun IconRow(icon: ImageVector, title: String, onClick: (() -> Unit)? = null) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun SettingsTextRow(title: String, subtitle: String?, onClick: (() -> Unit)?) {
|
||||
TextRow(title = title, subtitle, includeDivider = false, onClick)
|
||||
fun SettingsTextRow(title: String, subtitle: String?, onClick: (() -> Unit)?, enabled: Boolean) {
|
||||
TextRow(title = title, subtitle, includeDivider = false, onClick, enabled = enabled)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ class ThemeStore(
|
|||
private val preferences: CachedPreferences
|
||||
) {
|
||||
|
||||
suspend fun isMaterialYouEnabled() = preferences.readBoolean(KEY_MATERIAL_YOU_ENABLED) ?: false.also { storeMaterialYouEnabled(false) }
|
||||
suspend fun isMaterialYouEnabled() = preferences.readBoolean(KEY_MATERIAL_YOU_ENABLED, defaultValue = false)
|
||||
|
||||
suspend fun storeMaterialYouEnabled(isEnabled: Boolean) {
|
||||
preferences.store(KEY_MATERIAL_YOU_ENABLED, isEnabled)
|
||||
|
|
|
@ -6,6 +6,7 @@ import app.dapk.st.core.Preferences
|
|||
import app.dapk.st.core.extensions.ErrorTracker
|
||||
import app.dapk.st.core.extensions.unsafeLazy
|
||||
import app.dapk.st.domain.eventlog.EventLogPersistence
|
||||
import app.dapk.st.domain.eventlog.LoggingStore
|
||||
import app.dapk.st.domain.localecho.LocalEchoPersistence
|
||||
import app.dapk.st.domain.preference.CachingPreferences
|
||||
import app.dapk.st.domain.preference.PropertyCache
|
||||
|
@ -39,7 +40,7 @@ class StoreModule(
|
|||
val localEchoStore: LocalEchoStore by unsafeLazy { LocalEchoPersistence(errorTracker, database) }
|
||||
|
||||
private val cache = PropertyCache()
|
||||
val cachingPreferences = CachingPreferences(cache, preferences)
|
||||
val cachingPreferences = CachingPreferences(cache, preferences)
|
||||
|
||||
fun pushStore() = PushTokenRegistrarPreferences(preferences)
|
||||
|
||||
|
@ -62,6 +63,8 @@ class StoreModule(
|
|||
return EventLogPersistence(database, coroutineDispatchers)
|
||||
}
|
||||
|
||||
fun loggingStore(): LoggingStore = LoggingStore(cachingPreferences)
|
||||
|
||||
fun memberStore(): MemberStore {
|
||||
return MemberPersistence(database, coroutineDispatchers)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package app.dapk.st.domain.eventlog
|
||||
|
||||
import app.dapk.st.core.CachedPreferences
|
||||
import app.dapk.st.core.readBoolean
|
||||
import app.dapk.st.core.store
|
||||
|
||||
private const val KEY_LOGGING_ENABLED = "key_logging_enabled"
|
||||
|
||||
class LoggingStore(private val cachedPreferences: CachedPreferences) {
|
||||
|
||||
suspend fun isEnabled() = cachedPreferences.readBoolean(KEY_LOGGING_ENABLED, defaultValue = false)
|
||||
|
||||
suspend fun setEnabled(isEnabled: Boolean) {
|
||||
cachedPreferences.store(KEY_LOGGING_ENABLED, isEnabled)
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ import app.dapk.st.core.CachedPreferences
|
|||
import app.dapk.st.core.Preferences
|
||||
|
||||
class CachingPreferences(private val cache: PropertyCache, private val preferences: Preferences) : CachedPreferences {
|
||||
|
||||
override suspend fun store(key: String, value: String) {
|
||||
cache.setValue(key, value)
|
||||
preferences.store(key, value)
|
||||
|
@ -16,6 +15,10 @@ class CachingPreferences(private val cache: PropertyCache, private val preferenc
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun readString(key: String, defaultValue: String): String {
|
||||
return readString(key) ?: (defaultValue.also { cache.setValue(key, it) })
|
||||
}
|
||||
|
||||
override suspend fun remove(key: String) {
|
||||
preferences.remove(key)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package app.dapk.st.settings
|
||||
|
||||
import app.dapk.st.core.*
|
||||
import app.dapk.st.core.BuildMeta
|
||||
import app.dapk.st.core.DeviceMeta
|
||||
import app.dapk.st.core.ThemeStore
|
||||
import app.dapk.st.core.isAtLeastS
|
||||
import app.dapk.st.domain.eventlog.LoggingStore
|
||||
import app.dapk.st.push.PushTokenRegistrars
|
||||
|
||||
internal class SettingsItemFactory(
|
||||
|
@ -8,14 +12,14 @@ internal class SettingsItemFactory(
|
|||
private val deviceMeta: DeviceMeta,
|
||||
private val pushTokenRegistrars: PushTokenRegistrars,
|
||||
private val themeStore: ThemeStore,
|
||||
private val loggingStore: LoggingStore,
|
||||
) {
|
||||
|
||||
suspend fun root() = general() + theme() + data() + account() + about()
|
||||
suspend fun root() = general() + theme() + data() + account() + advanced() + about()
|
||||
|
||||
private suspend fun general() = listOf(
|
||||
SettingItem.Header("General"),
|
||||
SettingItem.Text(SettingItem.Id.Encryption, "Encryption"),
|
||||
SettingItem.Text(SettingItem.Id.EventLog, "Event log"),
|
||||
SettingItem.Text(SettingItem.Id.PushProvider, "Push provider", pushTokenRegistrars.currentSelection().id)
|
||||
)
|
||||
|
||||
|
@ -36,6 +40,15 @@ internal class SettingsItemFactory(
|
|||
SettingItem.Text(SettingItem.Id.SignOut, "Sign out"),
|
||||
)
|
||||
|
||||
private suspend fun advanced(): List<SettingItem> {
|
||||
val loggingIsEnabled = loggingStore.isEnabled()
|
||||
return listOf(
|
||||
SettingItem.Header("Advanced"),
|
||||
SettingItem.Toggle(SettingItem.Id.ToggleEnableLogs, "Enable local logging", state = loggingIsEnabled),
|
||||
SettingItem.Text(SettingItem.Id.EventLog, "Event log", enabled = loggingIsEnabled),
|
||||
)
|
||||
}
|
||||
|
||||
private fun about() = listOf(
|
||||
SettingItem.Header("About"),
|
||||
SettingItem.Text(SettingItem.Id.PrivacyPolicy, "Privacy policy"),
|
||||
|
|
|
@ -3,6 +3,7 @@ package app.dapk.st.settings
|
|||
import android.content.ContentResolver
|
||||
import app.dapk.st.core.*
|
||||
import app.dapk.st.domain.StoreModule
|
||||
import app.dapk.st.domain.eventlog.LoggingStore
|
||||
import app.dapk.st.matrix.crypto.CryptoService
|
||||
import app.dapk.st.matrix.sync.SyncService
|
||||
import app.dapk.st.push.PushModule
|
||||
|
@ -18,6 +19,7 @@ class SettingsModule(
|
|||
private val deviceMeta: DeviceMeta,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
private val themeStore: ThemeStore,
|
||||
private val loggingStore: LoggingStore,
|
||||
) : ProvidableModule {
|
||||
|
||||
internal fun settingsViewModel(): SettingsViewModel {
|
||||
|
@ -27,9 +29,10 @@ class SettingsModule(
|
|||
cryptoService,
|
||||
syncService,
|
||||
UriFilenameResolver(contentResolver, coroutineDispatchers),
|
||||
SettingsItemFactory(buildMeta, deviceMeta, pushModule.pushTokenRegistrars(), themeStore),
|
||||
SettingsItemFactory(buildMeta, deviceMeta, pushModule.pushTokenRegistrars(), themeStore, loggingStore),
|
||||
pushModule.pushTokenRegistrars(),
|
||||
themeStore,
|
||||
loggingStore,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.ClipboardManager
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.LocalActivityResultRegistryOwner
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.clickable
|
||||
|
@ -197,11 +196,11 @@ private fun RootSettings(page: Page.Root, onClick: (SettingItem) -> Unit) {
|
|||
items(content.value) { item ->
|
||||
when (item) {
|
||||
is SettingItem.Text -> {
|
||||
val itemOnClick = onClick.takeIf { item.id != SettingItem.Id.Ignored }?.let {
|
||||
{ it.invoke(item) }
|
||||
}
|
||||
val itemOnClick = onClick.takeIf {
|
||||
item.id != SettingItem.Id.Ignored && item.enabled
|
||||
}?.let { { it.invoke(item) } }
|
||||
|
||||
SettingsTextRow(item.content, item.subtitle, itemOnClick)
|
||||
SettingsTextRow(item.content, item.subtitle, itemOnClick, enabled = item.enabled)
|
||||
}
|
||||
|
||||
is SettingItem.AccessToken -> {
|
||||
|
@ -313,6 +312,7 @@ private fun SettingsViewModel.ObserveEvents(onSignOut: () -> Unit) {
|
|||
is OpenUrl -> {
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW).apply { data = it.url.toUri() })
|
||||
}
|
||||
|
||||
RecreateActivity -> {
|
||||
context.getActivity()?.recreate()
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ internal sealed interface SettingItem {
|
|||
val id: Id
|
||||
|
||||
data class Header(val label: String, override val id: Id = Id.Ignored) : SettingItem
|
||||
data class Text(override val id: Id, val content: String, val subtitle: String? = null) : SettingItem
|
||||
data class Text(override val id: Id, val content: String, val subtitle: String? = null, val enabled: Boolean = true) : SettingItem
|
||||
data class Toggle(override val id: Id, val content: String, val state: Boolean) : SettingItem
|
||||
data class AccessToken(override val id: Id, val content: String, val accessToken: String) : SettingItem
|
||||
|
||||
|
@ -57,6 +57,7 @@ internal sealed interface SettingItem {
|
|||
PrivacyPolicy,
|
||||
Ignored,
|
||||
ToggleDynamicTheme,
|
||||
ToggleEnableLogs,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import app.dapk.st.core.Lce
|
|||
import app.dapk.st.core.ThemeStore
|
||||
import app.dapk.st.design.components.SpiderPage
|
||||
import app.dapk.st.domain.StoreCleaner
|
||||
import app.dapk.st.domain.eventlog.LoggingStore
|
||||
import app.dapk.st.matrix.crypto.CryptoService
|
||||
import app.dapk.st.matrix.crypto.ImportResult
|
||||
import app.dapk.st.matrix.sync.SyncService
|
||||
|
@ -32,6 +33,7 @@ internal class SettingsViewModel(
|
|||
private val settingsItemFactory: SettingsItemFactory,
|
||||
private val pushTokenRegistrars: PushTokenRegistrars,
|
||||
private val themeStore: ThemeStore,
|
||||
private val loggingStore: LoggingStore,
|
||||
factory: MutableStateFactory<SettingsScreenState> = defaultStateFactory(),
|
||||
) : DapkViewModel<SettingsScreenState, SettingsEvent>(
|
||||
initialState = SettingsScreenState(SpiderPage(Page.Routes.root, "Settings", null, Page.Root(Lce.Loading()))),
|
||||
|
@ -52,31 +54,23 @@ internal class SettingsViewModel(
|
|||
|
||||
fun onClick(item: SettingItem) {
|
||||
when (item.id) {
|
||||
SignOut -> {
|
||||
viewModelScope.launch {
|
||||
cacheCleaner.cleanCache(removeCredentials = true)
|
||||
_events.emit(SignedOut)
|
||||
}
|
||||
SignOut -> viewModelScope.launch {
|
||||
cacheCleaner.cleanCache(removeCredentials = true)
|
||||
_events.emit(SignedOut)
|
||||
}
|
||||
|
||||
AccessToken -> {
|
||||
viewModelScope.launch {
|
||||
require(item is SettingItem.AccessToken)
|
||||
_events.emit(CopyToClipboard("Token copied", item.accessToken))
|
||||
}
|
||||
AccessToken -> viewModelScope.launch {
|
||||
require(item is SettingItem.AccessToken)
|
||||
_events.emit(CopyToClipboard("Token copied", item.accessToken))
|
||||
}
|
||||
|
||||
ClearCache -> {
|
||||
viewModelScope.launch {
|
||||
cacheCleaner.cleanCache(removeCredentials = false)
|
||||
_events.emit(Toast(message = "Cache deleted"))
|
||||
}
|
||||
ClearCache -> viewModelScope.launch {
|
||||
cacheCleaner.cleanCache(removeCredentials = false)
|
||||
_events.emit(Toast(message = "Cache deleted"))
|
||||
}
|
||||
|
||||
EventLog -> {
|
||||
viewModelScope.launch {
|
||||
_events.emit(OpenEventLog)
|
||||
}
|
||||
EventLog -> viewModelScope.launch {
|
||||
_events.emit(OpenEventLog)
|
||||
}
|
||||
|
||||
Encryption -> {
|
||||
|
@ -85,10 +79,8 @@ internal class SettingsViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
PrivacyPolicy -> {
|
||||
viewModelScope.launch {
|
||||
_events.emit(OpenUrl(PRIVACY_POLICY_URL))
|
||||
}
|
||||
PrivacyPolicy -> viewModelScope.launch {
|
||||
_events.emit(OpenUrl(PRIVACY_POLICY_URL))
|
||||
}
|
||||
|
||||
PushProvider -> {
|
||||
|
@ -100,16 +92,24 @@ internal class SettingsViewModel(
|
|||
Ignored -> {
|
||||
// do nothing
|
||||
}
|
||||
ToggleDynamicTheme -> {
|
||||
viewModelScope.launch {
|
||||
themeStore.storeMaterialYouEnabled(!themeStore.isMaterialYouEnabled())
|
||||
start()
|
||||
_events.emit(RecreateActivity)
|
||||
}
|
||||
|
||||
ToggleDynamicTheme -> viewModelScope.launch {
|
||||
themeStore.storeMaterialYouEnabled(!themeStore.isMaterialYouEnabled())
|
||||
refreshRoot()
|
||||
_events.emit(RecreateActivity)
|
||||
|
||||
}
|
||||
|
||||
ToggleEnableLogs -> viewModelScope.launch {
|
||||
loggingStore.setEnabled(!loggingStore.isEnabled())
|
||||
refreshRoot()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshRoot() {
|
||||
start()
|
||||
}
|
||||
|
||||
fun fetchPushProviders() {
|
||||
updatePageState<Page.PushProviders> { copy(options = Lce.Loading()) }
|
||||
|
@ -146,9 +146,11 @@ internal class SettingsViewModel(
|
|||
is ImportResult.Error -> {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
is ImportResult.Update -> {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
is ImportResult.Success -> {
|
||||
syncService.forceManualRefresh(it.roomIds.toList())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package app.dapk.st.settings
|
||||
|
||||
import app.dapk.st.domain.eventlog.LoggingStore
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.mockk
|
||||
import test.delegateReturn
|
||||
|
||||
class FakeLoggingStore {
|
||||
val instance = mockk<LoggingStore>()
|
||||
|
||||
fun givenLoggingIsEnabled() = coEvery { instance.isEnabled() }.delegateReturn()
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package app.dapk.st.settings
|
||||
|
||||
import app.dapk.st.core.ThemeStore
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import test.delegateReturn
|
||||
|
@ -8,5 +9,5 @@ import test.delegateReturn
|
|||
class FakeThemeStore {
|
||||
val instance = mockk<ThemeStore>()
|
||||
|
||||
fun givenMaterialYouIsEnabled() = every { instance.isMaterialYouEnabled() }.delegateReturn()
|
||||
fun givenMaterialYouIsEnabled() = coEvery { instance.isMaterialYouEnabled() }.delegateReturn()
|
||||
}
|
|
@ -15,6 +15,7 @@ import test.delegateReturn
|
|||
|
||||
private val A_SELECTION = Registrar("A_SELECTION")
|
||||
private const val ENABLED_MATERIAL_YOU = true
|
||||
private const val DISABLED_LOGGING = false
|
||||
|
||||
class SettingsItemFactoryTest {
|
||||
|
||||
|
@ -22,20 +23,27 @@ class SettingsItemFactoryTest {
|
|||
private val deviceMeta = DeviceMeta(apiVersion = 31)
|
||||
private val fakePushTokenRegistrars = FakePushRegistrars()
|
||||
private val fakeThemeStore = FakeThemeStore()
|
||||
private val fakeLoggingStore = FakeLoggingStore()
|
||||
|
||||
private val settingsItemFactory = SettingsItemFactory(buildMeta, deviceMeta, fakePushTokenRegistrars.instance, fakeThemeStore.instance)
|
||||
private val settingsItemFactory = SettingsItemFactory(
|
||||
buildMeta,
|
||||
deviceMeta,
|
||||
fakePushTokenRegistrars.instance,
|
||||
fakeThemeStore.instance,
|
||||
fakeLoggingStore.instance
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `when creating root items, then is expected`() = runTest {
|
||||
fakePushTokenRegistrars.givenCurrentSelection().returns(A_SELECTION)
|
||||
fakeThemeStore.givenMaterialYouIsEnabled().returns(ENABLED_MATERIAL_YOU)
|
||||
fakeLoggingStore.givenLoggingIsEnabled().returns(DISABLED_LOGGING)
|
||||
|
||||
val result = settingsItemFactory.root()
|
||||
|
||||
result shouldBeEqualTo listOf(
|
||||
aSettingHeaderItem("General"),
|
||||
aSettingTextItem(SettingItem.Id.Encryption, "Encryption"),
|
||||
aSettingTextItem(SettingItem.Id.EventLog, "Event log"),
|
||||
aSettingTextItem(SettingItem.Id.PushProvider, "Push provider", A_SELECTION.id),
|
||||
SettingItem.Header("Theme"),
|
||||
SettingItem.Toggle(SettingItem.Id.ToggleDynamicTheme, "Enable Material You", state = ENABLED_MATERIAL_YOU),
|
||||
|
@ -43,6 +51,9 @@ class SettingsItemFactoryTest {
|
|||
aSettingTextItem(SettingItem.Id.ClearCache, "Clear cache"),
|
||||
aSettingHeaderItem("Account"),
|
||||
aSettingTextItem(SettingItem.Id.SignOut, "Sign out"),
|
||||
aSettingHeaderItem("Advanced"),
|
||||
SettingItem.Toggle(SettingItem.Id.ToggleEnableLogs, "Enable local logging", state = DISABLED_LOGGING),
|
||||
aSettingTextItem(SettingItem.Id.EventLog, "Event log", enabled = DISABLED_LOGGING),
|
||||
aSettingHeaderItem("About"),
|
||||
aSettingTextItem(SettingItem.Id.PrivacyPolicy, "Privacy policy"),
|
||||
aSettingTextItem(SettingItem.Id.Ignored, "Version", buildMeta.versionName),
|
||||
|
|
|
@ -41,6 +41,7 @@ internal class SettingsViewModelTest {
|
|||
private val fakePushTokenRegistrars = FakePushRegistrars()
|
||||
private val fakeSettingsItemFactory = FakeSettingsItemFactory()
|
||||
private val fakeThemeStore = FakeThemeStore()
|
||||
private val fakeLoggingStore = FakeLoggingStore()
|
||||
|
||||
private val viewModel = SettingsViewModel(
|
||||
fakeStoreCleaner,
|
||||
|
@ -51,6 +52,7 @@ internal class SettingsViewModelTest {
|
|||
fakeSettingsItemFactory.instance,
|
||||
fakePushTokenRegistrars.instance,
|
||||
fakeThemeStore.instance,
|
||||
fakeLoggingStore.instance,
|
||||
runViewModelTest.testMutableStateFactory(),
|
||||
)
|
||||
|
||||
|
|
|
@ -5,8 +5,9 @@ import app.dapk.st.settings.SettingItem
|
|||
internal fun aSettingTextItem(
|
||||
id: SettingItem.Id = SettingItem.Id.Ignored,
|
||||
content: String = "text-content",
|
||||
subtitle: String? = null
|
||||
) = SettingItem.Text(id, content, subtitle)
|
||||
subtitle: String? = null,
|
||||
enabled: Boolean = true,
|
||||
) = SettingItem.Text(id, content, subtitle, enabled)
|
||||
|
||||
internal fun aSettingHeaderItem(
|
||||
label: String = "header-label",
|
||||
|
|
Loading…
Reference in New Issue