diff --git a/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminLandingScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminLandingScreen.kt index b81a6e67..f920297d 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminLandingScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminLandingScreen.kt @@ -2,7 +2,6 @@ package com.fabledsword.minstrel.admin.ui import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -11,7 +10,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -44,6 +42,7 @@ import com.fabledsword.minstrel.nav.AdminQuarantine import com.fabledsword.minstrel.nav.AdminRequests import com.fabledsword.minstrel.nav.AdminUsers import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import dagger.hilt.android.lifecycle.HiltViewModel @@ -230,10 +229,3 @@ private fun SectionCard( } } } - -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} diff --git a/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminQuarantineScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminQuarantineScreen.kt index b56dfafd..6f650613 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminQuarantineScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminQuarantineScreen.kt @@ -1,7 +1,6 @@ package com.fabledsword.minstrel.admin.ui import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -11,7 +10,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.AssistChip import androidx.compose.material3.Button -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -36,6 +34,7 @@ import com.composables.icons.lucide.Lucide import com.fabledsword.minstrel.models.AdminQuarantineItemRef import com.fabledsword.minstrel.nav.AdminQuarantine import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold @@ -185,10 +184,3 @@ private fun ActionButtons( Button(onClick = onDeleteViaLidarr) { Text("Delete + Lidarr") } } } - -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} diff --git a/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminRequestsScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminRequestsScreen.kt index 4156564a..f99dd0fc 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminRequestsScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/admin/ui/AdminRequestsScreen.kt @@ -1,7 +1,6 @@ package com.fabledsword.minstrel.admin.ui import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -11,7 +10,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.AssistChip import androidx.compose.material3.Button -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -35,6 +33,7 @@ import com.composables.icons.lucide.Lucide import com.fabledsword.minstrel.models.RequestRef import com.fabledsword.minstrel.nav.AdminRequests import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold @@ -170,13 +169,6 @@ private fun AdminRequestRow( } } -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} - // UUID prefix length used as a friendlier-than-raw-UUID fallback when // the admin users list fetch fails and we can't resolve userId → name. private const val USER_ID_PREFIX_LEN = 8 diff --git a/android/app/src/main/java/com/fabledsword/minstrel/discover/ui/DiscoverScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/discover/ui/DiscoverScreen.kt index b73df0b4..1084ca31 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/discover/ui/DiscoverScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/discover/ui/DiscoverScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FilterChip import androidx.compose.material3.HorizontalDivider @@ -44,6 +43,7 @@ import com.fabledsword.minstrel.models.ArtistSuggestionRef import com.fabledsword.minstrel.models.LidarrRequestKind import com.fabledsword.minstrel.models.LidarrSearchResultRef import com.fabledsword.minstrel.nav.Discover +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import kotlinx.coroutines.launch @@ -257,13 +257,6 @@ private fun ResultsList( } } -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} - @Composable private fun CenteredMessage(text: String) { Box(modifier = Modifier.fillMaxSize().padding(24.dp), contentAlignment = Alignment.Center) { diff --git a/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt b/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt index 3019d419..078e132a 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/history/ui/HistoryTab.kt @@ -2,7 +2,6 @@ package com.fabledsword.minstrel.history.ui import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -10,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -29,6 +27,7 @@ import com.fabledsword.minstrel.history.data.HistoryRepository import com.fabledsword.minstrel.models.TrackRef import com.fabledsword.minstrel.player.PlayerController import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton @@ -200,13 +199,6 @@ private fun HistoryRow( } } -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} - // ─── Time helpers ──────────────────────────────────────────────────── private const val MINUTES_PER_HOUR = 60L diff --git a/android/app/src/main/java/com/fabledsword/minstrel/library/ui/LibraryScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/library/ui/LibraryScreen.kt index 18f12538..fbdea37e 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/library/ui/LibraryScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/library/ui/LibraryScreen.kt @@ -157,7 +157,10 @@ private fun ArtistsTab( body = "Scan a folder in your server settings to " + "populate the library.", ) - is LibraryUiState.Error -> ErrorRetry(message = s.message, onRetry = {}) + is LibraryUiState.Error -> ErrorRetry( + message = s.message, + onRetry = { viewModel.refresh() }, + ) is LibraryUiState.Success -> ArtistsGrid( artists = s.artists, onArtistClick = { id -> navController.navigate(ArtistDetail(id)) }, @@ -182,7 +185,10 @@ private fun AlbumsTab( body = "Scan a folder in your server settings to " + "populate the library.", ) - is LibraryUiState.Error -> ErrorRetry(message = s.message, onRetry = {}) + is LibraryUiState.Error -> ErrorRetry( + message = s.message, + onRetry = { viewModel.refresh() }, + ) is LibraryUiState.Success -> AlbumsGrid( albums = s.albums, onAlbumClick = { id -> navController.navigate(AlbumDetail(id)) }, diff --git a/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt b/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt index 18db9030..3a0e6eb2 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/likes/ui/LikedTab.kt @@ -2,7 +2,6 @@ package com.fabledsword.minstrel.likes.ui import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -14,7 +13,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -40,6 +38,7 @@ import com.fabledsword.minstrel.nav.ArtistDetail import com.fabledsword.minstrel.player.PlayerController import com.fabledsword.minstrel.shared.widgets.EmptyState import com.fabledsword.minstrel.shared.widgets.HorizontalScrollRow +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton @@ -280,10 +279,3 @@ private fun LikedTrackRow( ) } } - -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} diff --git a/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistsListScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistsListScreen.kt index 4223e53b..007d3b65 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistsListScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/playlists/ui/PlaylistsListScreen.kt @@ -1,7 +1,6 @@ package com.fabledsword.minstrel.playlists.ui import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -10,7 +9,6 @@ import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -18,7 +16,6 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -33,6 +30,7 @@ import com.fabledsword.minstrel.nav.Playlists import com.fabledsword.minstrel.playlists.data.PlaylistsRepository import com.fabledsword.minstrel.playlists.widgets.PlaylistCard import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import dagger.hilt.android.lifecycle.HiltViewModel @@ -191,10 +189,3 @@ private fun SectionHeader(text: String) { .padding(horizontal = 8.dp, vertical = 12.dp), ) } - -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} diff --git a/android/app/src/main/java/com/fabledsword/minstrel/quarantine/ui/HiddenTab.kt b/android/app/src/main/java/com/fabledsword/minstrel/quarantine/ui/HiddenTab.kt index ccae3eca..8841a387 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/quarantine/ui/HiddenTab.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/quarantine/ui/HiddenTab.kt @@ -1,7 +1,6 @@ package com.fabledsword.minstrel.quarantine.ui import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -10,7 +9,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.AssistChip -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -28,6 +26,7 @@ import com.composables.icons.lucide.ArchiveRestore import com.composables.icons.lucide.Lucide import com.fabledsword.minstrel.models.QuarantineRef import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb @@ -119,13 +118,6 @@ private fun HiddenRow(row: QuarantineRef, onUnflag: () -> Unit) { } } -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} - // ─── Time helper (duplicated from HistoryTab to keep the widget local) ── private const val MINUTES_PER_HOUR = 60L diff --git a/android/app/src/main/java/com/fabledsword/minstrel/requests/ui/RequestsScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/requests/ui/RequestsScreen.kt index 874abe9a..7e57b759 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/requests/ui/RequestsScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/requests/ui/RequestsScreen.kt @@ -3,7 +3,6 @@ package com.fabledsword.minstrel.requests.ui import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -15,7 +14,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.material3.AlertDialog import androidx.compose.material3.AssistChip import androidx.compose.material3.Button -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -51,6 +49,7 @@ import com.fabledsword.minstrel.nav.AlbumDetail import com.fabledsword.minstrel.nav.ArtistDetail import com.fabledsword.minstrel.nav.Requests import com.fabledsword.minstrel.shared.widgets.EmptyState +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.MainAppBarActions import com.fabledsword.minstrel.shared.widgets.PullToRefreshScaffold @@ -321,10 +320,3 @@ private fun KindPill(label: String) { }, ) } - -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} diff --git a/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt b/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt index 3f475258..dac52da2 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/search/ui/SearchScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -59,6 +58,7 @@ import com.fabledsword.minstrel.models.SearchResponseRef import com.fabledsword.minstrel.models.TrackRef import com.fabledsword.minstrel.nav.AlbumDetail import com.fabledsword.minstrel.nav.ArtistDetail +import com.fabledsword.minstrel.shared.widgets.LoadingCentered import com.fabledsword.minstrel.shared.widgets.TrackCoverThumb import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsButton import com.fabledsword.minstrel.shared.widgets.trackactions.TrackActionsViewModel @@ -346,9 +346,3 @@ private fun CenteredHint(text: String) { } } -@Composable -private fun LoadingCentered() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) - } -} diff --git a/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/LoadingCentered.kt b/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/LoadingCentered.kt new file mode 100644 index 00000000..fce7ec60 --- /dev/null +++ b/android/app/src/main/java/com/fabledsword/minstrel/shared/widgets/LoadingCentered.kt @@ -0,0 +1,36 @@ +package com.fabledsword.minstrel.shared.widgets + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +/** + * Shared loading-spinner widget for screens that wrap their content in + * [PullToRefreshScaffold]. Rendered inside a single-item LazyColumn + * (mirroring [EmptyState]) so the widget participates in nested-scroll + * dispatch — pull-to-refresh fires on the Loading branch, letting users + * recover from a stuck cold-load via pull-down instead of having to + * kill the process. + * + * Replaces the per-screen `private fun LoadingCentered()` duplicates + * that used a bare `Box(fillMaxSize)` and silently swallowed the + * pull-to-refresh gesture. + */ +@Composable +fun LoadingCentered(modifier: Modifier = Modifier) { + LazyColumn(modifier = modifier.fillMaxSize()) { + item { + Box( + modifier = Modifier.fillParentMaxSize(), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator(color = MaterialTheme.colorScheme.primary) + } + } + } +}