fix(manage): use account-scoped device sync and remove mock device source
Preserve Manage device state across resume while preventing cross-account cache leaks by tracking synced user IDs and clearing stale local device data on account changes. Replace the mock device remote data source with Apollo-backed API queries/mutations using me.locations so Manage only shows devices belonging to the authenticated user. Made-with: Cursor
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package org.db3.airmq.features.manage
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -68,7 +67,6 @@ fun ManageScreen(
|
||||
viewModel: ManageViewModel = hiltViewModel()
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
Log.d("MANAGE_DEBUG", uiState.toString())
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
DisposableEffect(lifecycleOwner, viewModel) {
|
||||
val observer = LifecycleEventObserver { _, event ->
|
||||
@@ -413,6 +411,7 @@ private fun ManageScreenAuthorizedPreview() {
|
||||
ManageScreenContent(
|
||||
uiState = State(
|
||||
isAuthorized = true,
|
||||
userId = "preview",
|
||||
userName = "User",
|
||||
userEmail = "user@example.com",
|
||||
devices = listOf(
|
||||
|
||||
@@ -11,6 +11,7 @@ object ManageScreenContract {
|
||||
|
||||
data class State(
|
||||
val isAuthorized: Boolean = false,
|
||||
val userId: String = "",
|
||||
val userName: String = "",
|
||||
val userEmail: String = "",
|
||||
val devicesLabel: String = "",
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.db3.airmq.features.manage.ManageScreenContract.DeviceItem
|
||||
import org.db3.airmq.features.manage.ManageScreenContract.Event
|
||||
import org.db3.airmq.features.manage.ManageScreenContract.State
|
||||
import org.db3.airmq.sdk.auth.AuthService
|
||||
import org.db3.airmq.sdk.auth.model.User
|
||||
import org.db3.airmq.sdk.device.data.remote.DeviceSubscriptionManager
|
||||
import org.db3.airmq.sdk.device.domain.DeviceRepository
|
||||
import org.db3.airmq.sdk.device.domain.OnlineStatus
|
||||
|
||||
@HiltViewModel
|
||||
@@ -30,6 +30,7 @@ class ManageViewModel @Inject constructor(
|
||||
@ApplicationContext private val appContext: Context,
|
||||
private val authService: AuthService,
|
||||
private val getMyDevicesUseCase: GetMyDevicesUseCase,
|
||||
private val deviceRepository: DeviceRepository,
|
||||
private val subscriptionManager: DeviceSubscriptionManager
|
||||
) : ViewModel() {
|
||||
|
||||
@@ -47,7 +48,7 @@ class ManageViewModel @Inject constructor(
|
||||
if (session?.isAuthenticated == true) {
|
||||
val user = session
|
||||
_uiState.update { state ->
|
||||
if (state.isAuthorized) {
|
||||
if (state.isAuthorized && state.userId == session.userId) {
|
||||
state.copy(
|
||||
devices = devices.map { device -> device.toDeviceItem(appContext) }
|
||||
)
|
||||
@@ -75,8 +76,20 @@ class ManageViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
val session = authService.getUser()
|
||||
if (session?.isAuthenticated == true) {
|
||||
subscriptionManager.start()
|
||||
_uiState.value = authorizedState(session)
|
||||
deviceRepository.ensureLocalDevicesMatchAccount(session.userId)
|
||||
subscriptionManager.start(session.userId)
|
||||
_uiState.update { prev ->
|
||||
val sameUser = prev.isAuthorized && prev.userId == session.userId
|
||||
State(
|
||||
isAuthorized = true,
|
||||
userId = session.userId,
|
||||
userName = session.displayName
|
||||
?: appContext.getString(R.string.text_anonymous_user),
|
||||
userEmail = session.email ?: "",
|
||||
devicesLabel = "",
|
||||
devices = if (sameUser) prev.devices else emptyList()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
subscriptionManager.stop()
|
||||
_uiState.value = anonymousState()
|
||||
@@ -86,19 +99,12 @@ class ManageViewModel @Inject constructor(
|
||||
|
||||
private fun anonymousState(): State = State(
|
||||
isAuthorized = false,
|
||||
userId = "",
|
||||
userName = appContext.getString(R.string.text_anonymous_user),
|
||||
userEmail = appContext.getString(R.string.text_please_sign_in),
|
||||
devicesLabel = appContext.getString(R.string.text_sign_in_small)
|
||||
)
|
||||
|
||||
private fun authorizedState(user: User): State = State(
|
||||
isAuthorized = true,
|
||||
userName = user.displayName ?: appContext.getString(R.string.text_anonymous_user),
|
||||
userEmail = user.email ?: "",
|
||||
devicesLabel = "",
|
||||
devices = emptyList()
|
||||
)
|
||||
|
||||
private fun org.db3.airmq.sdk.device.domain.Device.toDeviceItem(context: Context): DeviceItem {
|
||||
val statusText = when (toOnlineStatus()) {
|
||||
OnlineStatus.Online -> context.getString(R.string.map_status_online)
|
||||
|
||||
Reference in New Issue
Block a user