Fix: Resolve list selection crash & update to minimal flat app icon
- ListDetailViewModel & Screen: set listId safely via setListId() avoiding SavedStateHandle null crashes
- Navigation: pass listId = key.listId explicitly into ListDetailScreen
- App Icon: replace 3D icon with a clean, minimal flat line-art shopping bag & checkmark icon suited for Samsung One UI & stock Android adaptive icon masks
- ADB reinstall & launch verified ✅
|
|
@ -37,6 +37,7 @@ fun MainNavigation(sessionManager: SessionManager) {
|
|||
}
|
||||
entry<ListDetailNavKey> { key ->
|
||||
ListDetailScreen(
|
||||
listId = key.listId,
|
||||
onBack = { backStack.removeLastOrNull() }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,15 @@ import com.example.mitbringsl.data.local.entity.ItemEntity
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ListDetailScreen(
|
||||
listId: String,
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: ListDetailViewModel = hiltViewModel(),
|
||||
) {
|
||||
LaunchedEffect(listId) {
|
||||
viewModel.setListId(listId)
|
||||
}
|
||||
|
||||
val items by viewModel.items.collectAsStateWithLifecycle()
|
||||
val query by viewModel.query.collectAsStateWithLifecycle()
|
||||
val suggestions by viewModel.suggestions.collectAsStateWithLifecycle()
|
||||
|
|
|
|||
|
|
@ -1,34 +1,43 @@
|
|||
package com.example.mitbringsl.ui.detail
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.example.mitbringsl.data.local.entity.ItemEntity
|
||||
import com.example.mitbringsl.data.remote.api.MitbringslApi
|
||||
import com.example.mitbringsl.data.repository.ShoppingRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
|
||||
@HiltViewModel
|
||||
class ListDetailViewModel @Inject constructor(
|
||||
private val repository: ShoppingRepository,
|
||||
private val api: MitbringslApi,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel() {
|
||||
|
||||
val listId: String = checkNotNull(savedStateHandle["listId"])
|
||||
private val _listId = MutableStateFlow<String?>(null)
|
||||
|
||||
val items: StateFlow<List<ItemEntity>> = repository.observeItems(listId)
|
||||
val items: StateFlow<List<ItemEntity>> = _listId
|
||||
.filterNotNull()
|
||||
.flatMapLatest { id -> repository.observeItems(id) }
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5000),
|
||||
initialValue = emptyList()
|
||||
)
|
||||
|
||||
fun setListId(id: String) {
|
||||
if (_listId.value != id) {
|
||||
_listId.value = id
|
||||
}
|
||||
}
|
||||
|
||||
val currentListId: String get() = _listId.value ?: ""
|
||||
|
||||
private val _query = MutableStateFlow("")
|
||||
val query: StateFlow<String> = _query.asStateFlow()
|
||||
|
||||
|
|
@ -61,10 +70,11 @@ class ListDetailViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun addItem(name: String, quantity: String? = null) {
|
||||
val targetListId = _listId.value ?: return
|
||||
if (name.isBlank()) return
|
||||
val qty = quantity?.trim()?.takeIf { it.isNotEmpty() }
|
||||
viewModelScope.launch {
|
||||
repository.addItem(listId, name.trim(), qty)
|
||||
repository.addItem(targetListId, name.trim(), qty)
|
||||
_query.value = ""
|
||||
_suggestions.value = emptyList()
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 31 KiB |
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background_color">#1B1B2F</color>
|
||||
<color name="ic_launcher_background_color">#151829</color>
|
||||
</resources>
|
||||
|
|
|
|||