mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Use LazyColumn for all nav drawer items
This commit is contained in:
parent
ffc704bdce
commit
46073cbd74
2 changed files with 117 additions and 66 deletions
|
|
@ -5,6 +5,7 @@ import android.media.AudioManager
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import androidx.compose.foundation.MarqueeAnimationMode
|
import androidx.compose.foundation.MarqueeAnimationMode
|
||||||
import androidx.compose.foundation.basicMarquee
|
import androidx.compose.foundation.basicMarquee
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -17,6 +18,8 @@ import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.Density
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
@ -26,6 +29,7 @@ import timber.log.Timber
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
@ -199,3 +203,29 @@ inline fun <T : Collection<*>, R> T.letNotEmpty(block: (T) -> R): R? {
|
||||||
}
|
}
|
||||||
return if (this.isNotEmpty()) block(this) else null
|
return if (this.isNotEmpty()) block(this) else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adapted from https://stackoverflow.com/a/69196765
|
||||||
|
fun Arrangement.spacedByWithFooter(space: Dp) =
|
||||||
|
object : Arrangement.Vertical {
|
||||||
|
override val spacing = space
|
||||||
|
|
||||||
|
override fun Density.arrange(
|
||||||
|
totalSize: Int,
|
||||||
|
sizes: IntArray,
|
||||||
|
outPositions: IntArray,
|
||||||
|
) {
|
||||||
|
if (sizes.isEmpty()) return
|
||||||
|
val spacePx = space.roundToPx()
|
||||||
|
|
||||||
|
var occupied = 0
|
||||||
|
sizes.forEachIndexed { index, size ->
|
||||||
|
if (index == sizes.lastIndex) {
|
||||||
|
outPositions[index] = totalSize - size
|
||||||
|
} else {
|
||||||
|
outPositions[index] = min(occupied, totalSize - size)
|
||||||
|
}
|
||||||
|
val lastSpace = min(spacePx, totalSize - outPositions[index] - size)
|
||||||
|
occupied = outPositions[index] + size + lastSpace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
|
@ -27,8 +26,8 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusProperties
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.focus.focusRestorer
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
@ -60,6 +59,9 @@ import com.github.damontecres.dolphin.data.ServerRepository
|
||||||
import com.github.damontecres.dolphin.data.model.BaseItem
|
import com.github.damontecres.dolphin.data.model.BaseItem
|
||||||
import com.github.damontecres.dolphin.preferences.UserPreferences
|
import com.github.damontecres.dolphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.dolphin.ui.FontAwesome
|
import com.github.damontecres.dolphin.ui.FontAwesome
|
||||||
|
import com.github.damontecres.dolphin.ui.ifElse
|
||||||
|
import com.github.damontecres.dolphin.ui.spacedByWithFooter
|
||||||
|
import com.github.damontecres.dolphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.dolphin.util.ExceptionHandler
|
import com.github.damontecres.dolphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.dolphin.util.supportedCollectionTypes
|
import com.github.damontecres.dolphin.util.supportedCollectionTypes
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
|
@ -124,6 +126,7 @@ fun NavDrawer(
|
||||||
}
|
}
|
||||||
val libraries by viewModel.libraries.observeAsState(listOf())
|
val libraries by viewModel.libraries.observeAsState(listOf())
|
||||||
val selectedIndex by viewModel.selectedIndex.observeAsState(-1)
|
val selectedIndex by viewModel.selectedIndex.observeAsState(-1)
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
NavigationDrawer(
|
NavigationDrawer(
|
||||||
modifier =
|
modifier =
|
||||||
|
|
@ -132,76 +135,94 @@ fun NavDrawer(
|
||||||
drawerState = drawerState,
|
drawerState = drawerState,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
ProvideTextStyle(MaterialTheme.typography.labelMedium) {
|
ProvideTextStyle(MaterialTheme.typography.labelMedium) {
|
||||||
Column(
|
LazyColumn(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
state = listState,
|
||||||
|
contentPadding = PaddingValues(0.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.spacedByWithFooter(8.dp),
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.focusGroup()
|
.focusGroup()
|
||||||
// TODO fix focus restorer
|
.focusProperties {
|
||||||
.focusRestorer()
|
onEnter = {
|
||||||
.fillMaxHeight()
|
focusRequester.tryRequestFocus()
|
||||||
|
}
|
||||||
|
}.fillMaxHeight()
|
||||||
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)),
|
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)),
|
||||||
) {
|
) {
|
||||||
IconNavItem(
|
item {
|
||||||
text = user?.name ?: "",
|
IconNavItem(
|
||||||
subtext = server?.name ?: server?.url,
|
text = user?.name ?: "",
|
||||||
icon = Icons.Default.AccountCircle,
|
subtext = server?.name ?: server?.url,
|
||||||
selected = false,
|
icon = Icons.Default.AccountCircle,
|
||||||
onClick = {
|
selected = false,
|
||||||
navigationManager.navigateTo(Destination.UserList)
|
onClick = {
|
||||||
},
|
navigationManager.navigateTo(Destination.UserList)
|
||||||
)
|
},
|
||||||
IconNavItem(
|
)
|
||||||
text = "Search",
|
}
|
||||||
icon = Icons.Default.Search,
|
item {
|
||||||
selected = selectedIndex == -2,
|
IconNavItem(
|
||||||
onClick = {
|
text = "Search",
|
||||||
viewModel.setIndex(-2)
|
icon = Icons.Default.Search,
|
||||||
navigationManager.navigateToFromDrawer(Destination.Search)
|
selected = selectedIndex == -2,
|
||||||
},
|
onClick = {
|
||||||
)
|
viewModel.setIndex(-2)
|
||||||
IconNavItem(
|
navigationManager.navigateToFromDrawer(Destination.Search)
|
||||||
text = "Home",
|
},
|
||||||
icon = Icons.Default.Home,
|
modifier =
|
||||||
selected = selectedIndex == -1,
|
Modifier.ifElse(
|
||||||
onClick = {
|
selectedIndex == -2,
|
||||||
viewModel.setIndex(-1)
|
Modifier.focusRequester(focusRequester),
|
||||||
if (destination is Destination.Main) {
|
),
|
||||||
navigationManager.reloadHome()
|
)
|
||||||
} else {
|
}
|
||||||
navigationManager.goToHome()
|
item {
|
||||||
}
|
IconNavItem(
|
||||||
},
|
text = "Home",
|
||||||
)
|
icon = Icons.Default.Home,
|
||||||
LazyColumn(
|
selected = selectedIndex == -1,
|
||||||
state = listState,
|
onClick = {
|
||||||
contentPadding = PaddingValues(0.dp),
|
viewModel.setIndex(-1)
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
if (destination is Destination.Main) {
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
navigationManager.reloadHome()
|
||||||
modifier =
|
} else {
|
||||||
Modifier
|
navigationManager.goToHome()
|
||||||
.weight(1f),
|
}
|
||||||
) {
|
},
|
||||||
itemsIndexed(libraries) { index, it ->
|
modifier =
|
||||||
LibraryNavItem(
|
Modifier.ifElse(
|
||||||
library = it,
|
selectedIndex == -1,
|
||||||
selected = selectedIndex == index,
|
Modifier.focusRequester(focusRequester),
|
||||||
onClick = {
|
),
|
||||||
viewModel.setIndex(index)
|
)
|
||||||
navigationManager.navigateToFromDrawer(it.destination())
|
}
|
||||||
},
|
itemsIndexed(libraries) { index, it ->
|
||||||
)
|
LibraryNavItem(
|
||||||
}
|
library = it,
|
||||||
|
selected = selectedIndex == index,
|
||||||
|
onClick = {
|
||||||
|
viewModel.setIndex(index)
|
||||||
|
navigationManager.navigateToFromDrawer(it.destination())
|
||||||
|
},
|
||||||
|
modifier =
|
||||||
|
Modifier.ifElse(
|
||||||
|
selectedIndex == index,
|
||||||
|
Modifier.focusRequester(focusRequester),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
IconNavItem(
|
||||||
|
text = "Settings",
|
||||||
|
icon = Icons.Default.Settings,
|
||||||
|
selected = false,
|
||||||
|
onClick = {
|
||||||
|
navigationManager.navigateTo(Destination.Settings)
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
IconNavItem(
|
|
||||||
text = "Settings",
|
|
||||||
icon = Icons.Default.Settings,
|
|
||||||
selected = false,
|
|
||||||
onClick = {
|
|
||||||
navigationManager.navigateTo(Destination.Settings)
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue