diff --git a/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailScreen.kt b/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailScreen.kt index c3c7314..f0ab82c 100644 --- a/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailScreen.kt +++ b/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailScreen.kt @@ -121,6 +121,7 @@ fun ListDetailScreen( val list by viewModel.list.collectAsState() val fields by viewModel.fields.collectAsState() val items by viewModel.items.collectAsState() + val isLoading by viewModel.isLoading.collectAsState() // Use derivedStateOf to create stable references val stableFields by remember { derivedStateOf { fields } } @@ -239,15 +240,18 @@ fun ListDetailScreen( val processedItems = transformed.processed val groupedItems = transformed.grouped - if (stableFields.isEmpty()) { - Box( - modifier = - Modifier - .fillMaxSize() - .padding(padding), - contentAlignment = Alignment.Center, - ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { + // Root container to allow loading overlay + Box( + modifier = + Modifier + .fillMaxSize() + .padding(padding), + ) { + if (stableFields.isEmpty()) { + Column( + modifier = Modifier.align(Alignment.Center), + horizontalAlignment = Alignment.CenterHorizontally, + ) { Text( text = "No fields yet. Add fields to get started!", style = MaterialTheme.typography.bodyLarge, @@ -260,14 +264,12 @@ fun ListDetailScreen( Text(stringResource(R.string.add_field)) } } - } - } else { - Column( - modifier = - Modifier - .fillMaxSize() - .padding(padding), - ) { + } else { + Column( + modifier = + Modifier + .fillMaxSize(), + ) { // Filter/Sort/Group Controls - Always visible above table Row( modifier = @@ -560,6 +562,17 @@ fun ListDetailScreen( ) } } + + // Loading overlay during initial content load + if (isLoading) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + androidx.compose.material3.CircularProgressIndicator() + } + } + } } // Items list below the fixed header diff --git a/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailViewModel.kt b/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailViewModel.kt index 6fe420c..4a077bc 100644 --- a/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailViewModel.kt +++ b/CollabTableAndroid/app/src/main/java/com/collabtable/app/ui/screens/ListDetailViewModel.kt @@ -34,6 +34,9 @@ class ListDetailViewModel( private val _items = MutableStateFlow>(emptyList()) val items: StateFlow> = _items.asStateFlow() + private val _isLoading = MutableStateFlow(true) + val isLoading: StateFlow = _isLoading.asStateFlow() + private val syncRepository = SyncRepository(context) init { @@ -42,6 +45,15 @@ class ListDetailViewModel( } private fun loadListData() { + // Track first emissions to flip loading off after initial data is ready + var hasList = false + var hasFields = false + var hasItems = false + fun maybeLoaded() { + if (hasList && hasFields && hasItems) { + _isLoading.value = false + } + } viewModelScope.launch { database .listDao() @@ -49,6 +61,10 @@ class ListDetailViewModel( .debounce(75) .collect { listWithFields -> _list.value = listWithFields?.list + if (!hasList) { + hasList = true + maybeLoaded() + } } } @@ -59,6 +75,10 @@ class ListDetailViewModel( .debounce(75) .collect { itemsData -> _items.value = itemsData + if (!hasItems) { + hasItems = true + maybeLoaded() + } } } @@ -69,6 +89,10 @@ class ListDetailViewModel( .debounce(75) .collect { fieldsData -> _fields.value = fieldsData + if (!hasFields) { + hasFields = true + maybeLoaded() + } } } }