From 3ec32dbc794f9be2c5ab108a0a56a3452419c385 Mon Sep 17 00:00:00 2001 From: HLCaptain Date: Thu, 27 Apr 2023 18:41:50 +0200 Subject: [PATCH] Refactoring, bug fixing. Fixed bug with offline user preferences not updating. Created `AppSettingsDataSource` to get the app's settings, clientID and offline user preferences. Fixed issue with UI initialization not animating correctly (sheet does not expand, camera animates badly). --- .../main/java/illyan/jay/MainApplication.kt | 3 - .../datasource/AppSettingsDataSource.kt | 61 ++++++++++++ .../illyan/jay/data/resolver/DataResolver.kt | 2 +- .../jay/data/resolver/PreferencesResolver.kt | 70 +++++++++----- .../domain/interactor/SessionInteractor.kt | 7 +- .../domain/interactor/SettingsInteractor.kt | 36 ++----- .../java/illyan/jay/ui/freedrive/FreeDrive.kt | 24 +++-- app/src/main/java/illyan/jay/ui/home/Home.kt | 94 ++++++++----------- .../jay/ui/sessions/SessionsViewModel.kt | 6 +- .../ui/settings/user/UserSettingsViewModel.kt | 2 +- 10 files changed, 173 insertions(+), 132 deletions(-) create mode 100644 app/src/main/java/illyan/jay/data/datastore/datasource/AppSettingsDataSource.kt diff --git a/app/src/main/java/illyan/jay/MainApplication.kt b/app/src/main/java/illyan/jay/MainApplication.kt index fa9eeaf7..e36357a3 100644 --- a/app/src/main/java/illyan/jay/MainApplication.kt +++ b/app/src/main/java/illyan/jay/MainApplication.kt @@ -19,13 +19,11 @@ package illyan.jay import android.app.Application -import androidx.datastore.core.DataStore import com.google.android.gms.ads.MobileAds import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.perf.FirebasePerformance import dagger.hilt.android.HiltAndroidApp -import illyan.jay.data.datastore.model.AppSettings import illyan.jay.di.CoroutineScopeIO import illyan.jay.domain.interactor.AuthInteractor import illyan.jay.domain.interactor.SettingsInteractor @@ -42,7 +40,6 @@ import kotlin.coroutines.cancellation.CancellationException class MainApplication : Application() { @Inject lateinit var crashlyticsTree: CrashlyticsTree @Inject lateinit var debugTree: Timber.DebugTree - @Inject lateinit var appSettingsDataStore: DataStore @Inject lateinit var authInteractor: AuthInteractor @Inject lateinit var crashlytics: FirebaseCrashlytics @Inject lateinit var analytics: FirebaseAnalytics diff --git a/app/src/main/java/illyan/jay/data/datastore/datasource/AppSettingsDataSource.kt b/app/src/main/java/illyan/jay/data/datastore/datasource/AppSettingsDataSource.kt new file mode 100644 index 00000000..b0cdc924 --- /dev/null +++ b/app/src/main/java/illyan/jay/data/datastore/datasource/AppSettingsDataSource.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Balázs Püspök-Kiss (Illyan) + * + * Jay is a driver behaviour analytics app. + * + * This file is part of Jay. + * + * Jay is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * Jay is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Jay. + * If not, see . + */ + +package illyan.jay.data.datastore.datasource + +import androidx.datastore.core.DataStore +import illyan.jay.data.datastore.model.AppSettings +import illyan.jay.domain.model.DomainPreferences +import kotlinx.coroutines.flow.map +import timber.log.Timber +import java.time.ZonedDateTime +import java.util.UUID +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class AppSettingsDataSource @Inject constructor( + private val appSettingsDataStore: DataStore +) { + val appSettings by lazy { + appSettingsDataStore.data.map { settings -> + if (settings.clientUUID == null) { + val newSettings = settings.copy(clientUUID = UUID.randomUUID().toString()) + updateAppSettings { newSettings } + newSettings + } else { + settings + } + } + } + + suspend fun updateAppSettings(transform: (AppSettings) -> AppSettings) { + appSettingsDataStore.updateData { + val newSettings = transform(it) + Timber.v("Changed settings from $it to $newSettings") + newSettings + } + } + + suspend fun updateAppPreferences(transform: (DomainPreferences) -> DomainPreferences) { + Timber.v("Updating App Preferences requested") + updateAppSettings { + it.copy(preferences = transform(it.preferences).copy(lastUpdate = ZonedDateTime.now())) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/illyan/jay/data/resolver/DataResolver.kt b/app/src/main/java/illyan/jay/data/resolver/DataResolver.kt index de2ee5c2..c9ea7b29 100644 --- a/app/src/main/java/illyan/jay/data/resolver/DataResolver.kt +++ b/app/src/main/java/illyan/jay/data/resolver/DataResolver.kt @@ -83,7 +83,7 @@ abstract class DataResolver( localDataLoading, enableSyncedData ) { cloudDataLoading, localDataLoading, enableSyncedData -> - if (enableSyncedData) { + if (!enableSyncedData) { localDataLoading } else { if (cloudDataLoading == null && localDataLoading == null) { diff --git a/app/src/main/java/illyan/jay/data/resolver/PreferencesResolver.kt b/app/src/main/java/illyan/jay/data/resolver/PreferencesResolver.kt index 6ec823bd..3ae3bcfb 100644 --- a/app/src/main/java/illyan/jay/data/resolver/PreferencesResolver.kt +++ b/app/src/main/java/illyan/jay/data/resolver/PreferencesResolver.kt @@ -1,8 +1,25 @@ +/* + * Copyright (c) 2023 Balázs Püspök-Kiss (Illyan) + * + * Jay is a driver behaviour analytics app. + * + * This file is part of Jay. + * + * Jay is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * Jay is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Jay. + * If not, see . + */ + package illyan.jay.data.resolver -import androidx.datastore.core.DataStore import illyan.jay.data.DataStatus -import illyan.jay.data.datastore.model.AppSettings +import illyan.jay.data.datastore.datasource.AppSettingsDataSource import illyan.jay.data.firestore.datasource.PreferencesFirestoreDataSource import illyan.jay.data.room.datasource.PreferencesRoomDataSource import illyan.jay.di.CoroutineScopeIO @@ -14,6 +31,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import timber.log.Timber @@ -22,7 +40,7 @@ import kotlin.coroutines.cancellation.CancellationException class PreferencesResolver @Inject constructor( private val authInteractor: AuthInteractor, - private val appSettingsDataStore: DataStore, + private val appSettingsDataSource: AppSettingsDataSource, private val preferencesFirestoreDataSource: PreferencesFirestoreDataSource, private val preferencesRoomDataSource: PreferencesRoomDataSource, @CoroutineScopeIO private val coroutineScopeIO: CoroutineScope, @@ -35,32 +53,42 @@ class PreferencesResolver @Inject constructor( override val localDataStatus: StateFlow> by lazy { val statusStateFlow = MutableStateFlow(DataStatus()) Timber.v("Refreshing local user preferences data collection") - var dataCollectionJob: Job? = null + var dataCollectionJob: Job? coroutineScopeIO.launch { + dataCollectionJob = refreshLocalPreferences(authInteractor.userUUID, statusStateFlow) authInteractor.userUUIDStateFlow.collectLatest { uuid -> - statusStateFlow.update { DataStatus(data = null, isLoading = true) } dataCollectionJob?.cancel(CancellationException("User Authentication changed, need to cancel jobs depending on User Authentication")) - if (uuid != null) { // User signed in - Timber.v("Collecting signed in user preferences from disk") - dataCollectionJob = coroutineScopeIO.launch { - preferencesRoomDataSource.getPreferences(uuid).collectLatest { preferences -> - statusStateFlow.update { DataStatus(preferences, false) } - } - } - } else { // Offline user - Timber.v("Collecting offline user preferences from disk") - // Simple, we only use the baseline preferences for offline users - dataCollectionJob = coroutineScopeIO.launch { - appSettingsDataStore.data.collectLatest { settings -> - statusStateFlow.update { DataStatus(settings.preferences, false) } - } - } - } + dataCollectionJob = refreshLocalPreferences(uuid, statusStateFlow) } } statusStateFlow.asStateFlow() } + private suspend fun refreshLocalPreferences( + uuid: String?, + statusStateFlow: MutableStateFlow>, + ): Job { + statusStateFlow.update { DataStatus(data = null, isLoading = true) } + return if (uuid != null) { // User signed in + Timber.v("Collecting signed in user preferences from disk") + coroutineScopeIO.launch { + preferencesRoomDataSource.getPreferences(uuid).collectLatest { preferences -> + statusStateFlow.update { DataStatus(preferences, false) } + } + } + } else { // Offline user + Timber.v("Collecting offline user preferences from disk") + // Simple, we only use the baseline preferences for offline users + coroutineScopeIO.launch { + appPreferences.collectLatest { preferences -> + statusStateFlow.update { DataStatus(preferences, false) } + } + } + } + } + + val appPreferences by lazy { appSettingsDataSource.appSettings.map { it.preferences } } + override fun shouldSyncData(localData: DomainPreferences?): Boolean { return localData?.shouldSync ?: DomainPreferences.Default.shouldSync } diff --git a/app/src/main/java/illyan/jay/domain/interactor/SessionInteractor.kt b/app/src/main/java/illyan/jay/domain/interactor/SessionInteractor.kt index 86b201b2..42543043 100644 --- a/app/src/main/java/illyan/jay/domain/interactor/SessionInteractor.kt +++ b/app/src/main/java/illyan/jay/domain/interactor/SessionInteractor.kt @@ -22,6 +22,7 @@ import com.google.firebase.firestore.FirebaseFirestore import com.google.firebase.firestore.WriteBatch import com.mapbox.geojson.Point import com.mapbox.search.ReverseGeoOptions +import illyan.jay.data.datastore.datasource.AppSettingsDataSource import illyan.jay.data.firestore.datasource.PathFirestoreDataSource import illyan.jay.data.firestore.datasource.SessionFirestoreDataSource import illyan.jay.data.room.datasource.LocationRoomDataSource @@ -63,7 +64,7 @@ class SessionInteractor @Inject constructor( private val searchInteractor: SearchInteractor, private val sessionFirestoreDataSource: SessionFirestoreDataSource, private val authInteractor: AuthInteractor, - private val settingsInteractor: SettingsInteractor, + private val appSettingsDataSource: AppSettingsDataSource, private val serviceInteractor: ServiceInteractor, private val pathFirestoreDataSource: PathFirestoreDataSource, private val firestore: FirebaseFirestore, @@ -289,12 +290,12 @@ class SessionInteractor @Inject constructor( getSession(sessionUUID).first { session -> session?.let { Timber.i("Trying to assign client to session $sessionUUID") - settingsInteractor.appSettingsFlow.first { settings -> + appSettingsDataSource.appSettings.first { settings -> Timber.d("Client UUID = ${settings.clientUUID}") if (settings.clientUUID == null) { val clientUUID = UUID.randomUUID().toString() Timber.d("Generating new client UUID: $clientUUID") - settingsInteractor.updateAppSettings { + appSettingsDataSource.updateAppSettings { it.copy(clientUUID = clientUUID) } it.clientUUID = clientUUID diff --git a/app/src/main/java/illyan/jay/domain/interactor/SettingsInteractor.kt b/app/src/main/java/illyan/jay/domain/interactor/SettingsInteractor.kt index 940308f9..4dfd2d6b 100644 --- a/app/src/main/java/illyan/jay/domain/interactor/SettingsInteractor.kt +++ b/app/src/main/java/illyan/jay/domain/interactor/SettingsInteractor.kt @@ -18,38 +18,27 @@ package illyan.jay.domain.interactor -import androidx.datastore.core.DataStore -import illyan.jay.data.datastore.model.AppSettings +import illyan.jay.data.datastore.datasource.AppSettingsDataSource import illyan.jay.data.resolver.PreferencesResolver import illyan.jay.data.room.datasource.PreferencesRoomDataSource import illyan.jay.di.CoroutineScopeIO import illyan.jay.domain.model.DomainPreferences import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import timber.log.Timber import java.time.ZonedDateTime -import java.util.UUID import javax.inject.Inject import javax.inject.Singleton @Singleton class SettingsInteractor @Inject constructor( - private val appSettingsDataStore: DataStore, + private val appSettingsDataSource: AppSettingsDataSource, private val preferencesResolver: PreferencesResolver, private val preferencesRoomDataSource: PreferencesRoomDataSource, private val authInteractor: AuthInteractor, @CoroutineScopeIO private val coroutineScopeIO: CoroutineScope ) { - val appSettingsFlow = appSettingsDataStore.data.map { settings -> - if (settings.clientUUID == null) { - val newSettings = settings.copy(clientUUID = UUID.randomUUID().toString()) - updateAppSettings { newSettings } - newSettings - } else { - settings - } - } + val appSettings = appSettingsDataSource.appSettings var freeDriveAutoStart: Boolean? get() = userPreferences.value?.freeDriveAutoStart @@ -60,7 +49,7 @@ class SettingsInteractor @Inject constructor( if (authInteractor.isUserSignedIn) { preferencesRoomDataSource.setFreeDriveAutoStart(authInteractor.userUUID!!, value) } else { - updateAppPreferences { it.copy(freeDriveAutoStart = value) } + appSettingsDataSource.updateAppPreferences { it.copy(freeDriveAutoStart = value) } } } } @@ -77,7 +66,7 @@ class SettingsInteractor @Inject constructor( preferencesRoomDataSource.setAnalyticsEnabled(authInteractor.userUUID!!, value) } else { Timber.v("Setting Analytics $value for offline user") - updateAppPreferences { + appSettingsDataSource.updateAppPreferences { it.copy( analyticsEnabled = value, lastUpdateToAnalytics = ZonedDateTime.now() @@ -97,7 +86,7 @@ class SettingsInteractor @Inject constructor( if (authInteractor.isUserSignedIn) { preferencesRoomDataSource.setShowAds(authInteractor.userUUID!!, value) } else { - updateAppPreferences { + appSettingsDataSource.updateAppPreferences { it.copy(showAds = value) } } @@ -124,22 +113,9 @@ class SettingsInteractor @Inject constructor( val localUserPreferences = preferencesResolver.localData val userPreferences = preferencesResolver.data - suspend fun updateAppSettings(transform: (AppSettings) -> AppSettings) { - appSettingsDataStore.updateData { - val newSettings = transform(it) - Timber.v("Changed settings from $it to $newSettings") - newSettings - } - } - /** * Automatically updates [DomainPreferences.lastUpdate] */ - suspend fun updateAppPreferences(transform: (DomainPreferences) -> DomainPreferences) { - updateAppSettings { - it.copy(preferences = transform(it.preferences).copy(lastUpdate = ZonedDateTime.now())) - } - } fun deleteLocalUserPreferences() { if (authInteractor.isUserSignedIn) { diff --git a/app/src/main/java/illyan/jay/ui/freedrive/FreeDrive.kt b/app/src/main/java/illyan/jay/ui/freedrive/FreeDrive.kt index b6752a37..516fafed 100644 --- a/app/src/main/java/illyan/jay/ui/freedrive/FreeDrive.kt +++ b/app/src/main/java/illyan/jay/ui/freedrive/FreeDrive.kt @@ -120,20 +120,18 @@ fun FreeDrive( onDispose { viewModel.disposeViewport() viewModel.lastLocation.value?.let { location -> - flyToLocation( - extraCameraOptions = { builder -> - builder - .pitch(0.0) - .bearing(0.0) - .zoom(12.0) - .center( - Point.fromLngLat( - location.longitude, - location.latitude - ) + flyToLocation { + it + .pitch(0.0) + .bearing(0.0) + .zoom(12.0) + .center( + Point.fromLngLat( + location.longitude, + location.latitude ) - } - ) + ) + } } } } diff --git a/app/src/main/java/illyan/jay/ui/home/Home.kt b/app/src/main/java/illyan/jay/ui/home/Home.kt index 796669a2..04064299 100644 --- a/app/src/main/java/illyan/jay/ui/home/Home.kt +++ b/app/src/main/java/illyan/jay/ui/home/Home.kt @@ -77,6 +77,7 @@ import androidx.compose.material.Surface import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Cancel import androidx.compose.material.rememberBottomSheetScaffoldState +import androidx.compose.material.rememberBottomSheetState import androidx.compose.material3.CardDefaults import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ExperimentalMaterial3Api @@ -173,6 +174,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import timber.log.Timber @@ -260,10 +262,7 @@ fun flyToLocation( refreshCameraPadding() mapView.value?.camera?.flyTo( CameraOptions.Builder() - .padding( - cameraPadding.value, - density.value - ) + .padding(cameraPadding.value, density.value) .extraOptions(extraCameraOptions) .build() ) @@ -405,9 +404,9 @@ fun refreshCameraPadding() { val bottomSpace = screenHeight - absoluteBottom.value val topSpace = absoluteTop.value val sheetOffset = sheetState.getOffsetAsDp(density.value) - _cameraPadding.value = PaddingValues( - bottom = max(0.dp, screenHeight + bottomSpace + topSpace - sheetOffset) - ) + _cameraPadding.update { + PaddingValues(bottom = max(0.dp, screenHeight + bottomSpace + topSpace - sheetOffset)) + } } @HomeNavGraph(start = true) @@ -437,8 +436,8 @@ fun HomeScreen( } val density = LocalDensity.current.density val screenHeightDp = LocalConfiguration.current.screenHeightDp.dp - LaunchedEffect(density) { _density.value = density } - LaunchedEffect(screenHeightDp) { _screenHeight.value = screenHeightDp } + LaunchedEffect(density) { _density.update { density } } + LaunchedEffect(screenHeightDp) { _screenHeight.update { screenHeightDp } } ConstraintLayout( modifier = Modifier .fillMaxSize() @@ -446,7 +445,7 @@ fun HomeScreen( var topSet = false val absoluteTopPosition = (coordinates.positionInWindow().y / density).dp if (_absoluteTop.value != absoluteTopPosition) { - _absoluteTop.value = absoluteTopPosition + _absoluteTop.update { absoluteTopPosition } topSet = true } var bottomSet = false @@ -454,23 +453,21 @@ fun HomeScreen( ((coordinates.positionInWindow().y + coordinates.size.height) / density).dp if (_absoluteBottom.value != absoluteBottomPosition) { bottomSet = true - _absoluteBottom.value = absoluteBottomPosition + _absoluteBottom.update { absoluteBottomPosition } } if (topSet || bottomSet) { refreshCameraPadding() Timber.d( "Camera bottom padding: ${ - absoluteBottomPosition - sheetState.getOffsetAsDp( - density - ) + absoluteBottomPosition - sheetState.getOffsetAsDp(density) }" ) } } ) { val (searchBar, scaffold) = createRefs() - val scaffoldState = rememberBottomSheetScaffoldState() - val bottomSheetState = scaffoldState.bottomSheetState + val bottomSheetState = rememberBottomSheetState(initialValue = BottomSheetValue.Expanded) + val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = bottomSheetState) sheetState = bottomSheetState var isTextFieldFocused by remember { mutableStateOf(false) } var roundDp by rememberSaveable( @@ -613,10 +610,11 @@ fun HomeScreen( var didLoadInLocation by rememberSaveable { mutableStateOf(false) } var didLoadInLocationWithoutPermissions by rememberSaveable { mutableStateOf(false) } var isMapInitialized by rememberSaveable { mutableStateOf(false) } + var isMapVisible by rememberSaveable { mutableStateOf(false) } val sheetContentHeight by sheetContentHeight.collectAsStateWithLifecycle() LaunchedEffect( bottomSheetState.getOffsetAsDp(density), - isMapInitialized, + isMapVisible, initialLocationLoaded ) { refreshCameraPadding() @@ -625,10 +623,10 @@ fun HomeScreen( !didLoadInLocation && cameraOptionsBuilder != null && initialLocationLoaded && - isMapInitialized && + isMapVisible && bottomSheetState.progress.to == BottomSheetValue.Expanded && sheetContentHeight >= 20.dp && - _cameraPadding.value.calculateBottomPadding() >= 20.dp + cameraPadding.value.calculateBottomPadding() >= 20.dp ) { Timber.d( "Focusing camera to location\n" + @@ -637,30 +635,22 @@ fun HomeScreen( "Sheet content height = $sheetContentHeight" ) didLoadInLocation = true - mapView.value?.camera?.flyTo( - cameraOptionsBuilder!! - .center( - viewModel.initialLocation.value?.let { - Point.fromLngLat( - it.longitude, - it.latitude - ) - } - ) - .padding( - _cameraPadding.value, context - ) - .build() - ) + flyToLocation { builder -> + builder.center( + viewModel.initialLocation.value?.let { + Point.fromLngLat(it.longitude, it.latitude) + } + ).padding(cameraPadding.value, context) + } } // Permissions not granted if (bottomSheetState.isExpanded && !didLoadInLocationWithoutPermissions && !locationPermissionState.status.isGranted && - isMapInitialized && + isMapVisible && bottomSheetState.progress.to == BottomSheetValue.Expanded && sheetContentHeight >= 20.dp && - _cameraPadding.value.calculateBottomPadding() >= 20.dp + cameraPadding.value.calculateBottomPadding() >= 20.dp ) { Timber.d( "Focusing camera to location" + @@ -669,26 +659,16 @@ fun HomeScreen( "Sheet content height = $sheetContentHeight" ) didLoadInLocationWithoutPermissions = true - mapView.value?.camera?.flyTo( - CameraOptions.Builder() - .zoom(4.0) - .center( - Point.fromLngLat( - BmeK.longitude, - BmeK.latitude - ) - ) - .padding( - _cameraPadding.value, context - ) - .build() - ) + flyToLocation { + it.zoom(4.0) + .center(Point.fromLngLat(BmeK.longitude, BmeK.latitude)) + .padding(cameraPadding.value, context) + } } } if (initialLocationLoaded || cameraOptionsBuilder != null) { ConstraintLayout(modifier = Modifier.fillMaxSize()) { val (foreground, map) = createRefs() - var isMapVisible by rememberSaveable { mutableStateOf(false) } androidx.compose.animation.AnimatedVisibility( modifier = Modifier .zIndex(1f) @@ -732,16 +712,16 @@ fun HomeScreen( .accessToken(BuildConfig.MapboxAccessToken) .build(), onMapFullyLoaded = { isMapVisible = true }, - onMapInitialized = { + onMapInitialized = { view -> isMapInitialized = true - _mapView.value = it + _mapView.update { view } when (locationPermissionState.status) { is PermissionStatus.Granted -> { - it.location.turnOnWithDefaultPuck(context) + view.location.turnOnWithDefaultPuck(context) } is PermissionStatus.Denied -> { - it.location.enabled = false + view.location.enabled = false } } }, @@ -955,7 +935,7 @@ fun BottomSheetScreen( .background(MaterialTheme.colorScheme.surfaceColorAtElevation(0.dp)) .layout { measurable, constraints -> val placeable = measurable.measure(constraints) - _sheetContentHeight.value = (placeable.height / density).dp + _sheetContentHeight.update { (placeable.height / density).dp } layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) } @@ -988,7 +968,7 @@ fun BottomSheetScreen( val density = LocalDensity.current val bottomSheetFraction = 1 - offset / (screenHeight.value * density.density) LaunchedEffect(bottomSheetFraction) { - _bottomSheetFraction.value = bottomSheetFraction + _bottomSheetFraction.update { bottomSheetFraction } } onBottomSheetFractionChange(bottomSheetFraction) ConstraintLayout( diff --git a/app/src/main/java/illyan/jay/ui/sessions/SessionsViewModel.kt b/app/src/main/java/illyan/jay/ui/sessions/SessionsViewModel.kt index 861ccb86..bab59647 100644 --- a/app/src/main/java/illyan/jay/ui/sessions/SessionsViewModel.kt +++ b/app/src/main/java/illyan/jay/ui/sessions/SessionsViewModel.kt @@ -21,11 +21,11 @@ package illyan.jay.ui.sessions import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import illyan.jay.data.datastore.datasource.AppSettingsDataSource import illyan.jay.di.CoroutineDispatcherIO import illyan.jay.domain.interactor.AuthInteractor import illyan.jay.domain.interactor.LocationInteractor import illyan.jay.domain.interactor.SessionInteractor -import illyan.jay.domain.interactor.SettingsInteractor import illyan.jay.domain.model.DomainSession import illyan.jay.ui.sessions.model.UiSession import illyan.jay.ui.sessions.model.toUiModel @@ -55,7 +55,7 @@ class SessionsViewModel @Inject constructor( private val sessionInteractor: SessionInteractor, private val locationInteractor: LocationInteractor, private val authInteractor: AuthInteractor, - private val settingsInteractor: SettingsInteractor, + private val appSettingsDataSource: AppSettingsDataSource, @CoroutineDispatcherIO private val dispatcherIO: CoroutineDispatcher ) : ViewModel() { private val sessionStateFlows = mutableMapOf>() @@ -77,7 +77,7 @@ class SessionsViewModel @Inject constructor( private val _localSessionsLoading = MutableStateFlow(false) val localSessionsLoading = _localSessionsLoading.asStateFlow() - private val clientUUID = settingsInteractor.appSettingsFlow.map { it.clientUUID ?: "" } + private val clientUUID = appSettingsDataSource.appSettings.map { it.clientUUID ?: "" } .stateIn(viewModelScope, SharingStarted.Eagerly, "") private val _syncedSessions = MutableStateFlow(listOf()) diff --git a/app/src/main/java/illyan/jay/ui/settings/user/UserSettingsViewModel.kt b/app/src/main/java/illyan/jay/ui/settings/user/UserSettingsViewModel.kt index 379deb09..e187d8ce 100644 --- a/app/src/main/java/illyan/jay/ui/settings/user/UserSettingsViewModel.kt +++ b/app/src/main/java/illyan/jay/ui/settings/user/UserSettingsViewModel.kt @@ -46,7 +46,7 @@ class UserSettingsViewModel @Inject constructor( val preferences = combine( settingsInteractor.userPreferences, - settingsInteractor.appSettingsFlow + settingsInteractor.appSettings ) { preferences, appSettings -> val uiPreferences = preferences?.toUiModel(clientUUID = appSettings.clientUUID) updateAnalyticsRequestDialogVisibility(uiPreferences)