mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
ui: float the offline indicator opposite the library FAB
Drop the strip above the tab bar, which kept the bottom of the library busy, and go back to a floating tonal cloud-off button at the bottom start, level with the FAB on the other side. Tapping it still leaves offline mode, and the tab bar goes back to just tabs and the gear.
This commit is contained in:
@@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -46,6 +45,7 @@ import androidx.compose.material.icons.rounded.Search
|
||||
import androidx.compose.material.icons.rounded.Settings
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FilledTonalIconButton
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
@@ -90,7 +90,6 @@ import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.drawscope.clipPath
|
||||
import androidx.compose.ui.graphics.drawscope.clipRect
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.graphics.lerp
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.boundsInParent
|
||||
import androidx.compose.ui.layout.layout
|
||||
@@ -100,7 +99,6 @@ import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
@@ -593,9 +591,6 @@ fun LibraryScreen(
|
||||
.onSizeChanged { tabBarHeightPx = it.height.toFloat() }
|
||||
.padding(bottom = bottomInset),
|
||||
) {
|
||||
if (offline) {
|
||||
OfflineStrip(onGoOnline = onExitOffline, headerColor = headerColor)
|
||||
}
|
||||
LibraryTabs(
|
||||
pagerState = pagerState,
|
||||
onTabSelected = { tab ->
|
||||
@@ -623,6 +618,20 @@ fun LibraryScreen(
|
||||
}
|
||||
|
||||
if (!searchActive) {
|
||||
if (offline) {
|
||||
FilledTonalIconButton(
|
||||
onClick = onExitOffline,
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.padding(start = 16.dp, bottom = tabBarHeight + 16.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.CloudOff,
|
||||
contentDescription = stringResource(R.string.offline_mode_status),
|
||||
)
|
||||
}
|
||||
}
|
||||
val searchFab = selectedTab == LibraryTab.Home
|
||||
FloatingActionButton(
|
||||
onClick = { if (searchFab) onOpenSearch() else showOptions = true },
|
||||
@@ -837,7 +846,6 @@ private val TAB_ICON_SIZE = 24.dp
|
||||
private val TAB_VERTICAL_PADDING = 6.dp
|
||||
private val TOUCH_TARGET = 48.dp
|
||||
private const val LIST_OPTIONS_WEIGHT = 0.11f
|
||||
private const val OFFLINE_STRIP_TINT = 0.10f
|
||||
private val LIST_OPTIONS_BAR_WIDTHS = listOf(1f, 0.62f, 0.34f)
|
||||
|
||||
@Composable
|
||||
@@ -1015,44 +1023,6 @@ internal fun LibraryTabs(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OfflineStrip(
|
||||
onGoOnline: () -> Unit,
|
||||
headerColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier =
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.background(lerp(headerColor, MaterialTheme.colorScheme.primary, OFFLINE_STRIP_TINT))
|
||||
.heightIn(min = 48.dp)
|
||||
.clickable(role = Role.Button, onClick = onGoOnline)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.CloudOff,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.offline_mode_banner),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
maxLines = 2,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.offline_go_online),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TabButton(
|
||||
|
||||
@@ -175,8 +175,7 @@
|
||||
<string name="filters">Filters</string>
|
||||
<string name="filter_downloaded">Downloaded</string>
|
||||
<string name="close_search">Close search</string>
|
||||
<string name="offline_mode_banner">Offline mode</string>
|
||||
<string name="offline_go_online">Go online</string>
|
||||
<string name="offline_mode_status">Offline mode; tap to go online</string>
|
||||
<string name="shuffle_artist">Shuffle artist</string>
|
||||
|
||||
<string name="status_playing">Playing</string>
|
||||
|
||||
@@ -510,7 +510,7 @@ class LibraryScreenTest {
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "de-rDE-w320dp-h640dp-xhdpi")
|
||||
fun theOfflineStripExplainsTheModeAndGoesOnline() {
|
||||
fun theOfflineIndicatorGoesOnline() {
|
||||
var exited = false
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
@@ -533,11 +533,10 @@ class LibraryScreenTest {
|
||||
}
|
||||
composeRule.waitForIdle()
|
||||
|
||||
composeRule.onNodeWithText(composeRule.activity.getString(R.string.offline_mode_banner)).performClick()
|
||||
assertTrue("the offline strip should leave offline mode", exited)
|
||||
composeRule
|
||||
.onNodeWithContentDescription(composeRule.activity.getString(R.string.navigation_tabs_settings))
|
||||
.assertWidthIsEqualTo(40.dp)
|
||||
.onNodeWithContentDescription(composeRule.activity.getString(R.string.offline_mode_status))
|
||||
.performClick()
|
||||
assertTrue("the offline indicator should leave offline mode", exited)
|
||||
}
|
||||
|
||||
private fun tabBounds(tab: LibraryTab) =
|
||||
|
||||
Reference in New Issue
Block a user