mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Few UI tweaks (#325)
- Move loading indicator to center of grid when changing filters so it's more obvious - Move 'remove' filter to top for the first filter dropdown for consistency - Use theme color for download progress indicator - Show playback controls at the end of playing a video if there's nothing up next
This commit is contained in:
parent
0bfe3d2653
commit
c0237a6123
7 changed files with 58 additions and 44 deletions
|
|
@ -21,7 +21,10 @@ fun CircularProgress(modifier: Modifier = Modifier) {
|
||||||
Box(modifier = modifier) {
|
Box(modifier = modifier) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
color = MaterialTheme.colorScheme.border,
|
color = MaterialTheme.colorScheme.border,
|
||||||
modifier = Modifier.align(Alignment.Center),
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.align(Alignment.Center),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -571,7 +571,7 @@ fun CollectionFolderGrid(
|
||||||
backgroundLoading == LoadingState.Loading,
|
backgroundLoading == LoadingState.Loading,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.align(Alignment.BottomEnd)
|
.align(Alignment.Center)
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
) {
|
) {
|
||||||
CircularProgress(
|
CircularProgress(
|
||||||
|
|
|
||||||
|
|
@ -78,31 +78,7 @@ fun FilterByButton(
|
||||||
nestedDropDown = null
|
nestedDropDown = null
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
filterOptions
|
|
||||||
.forEach { filterOption ->
|
|
||||||
val currentValue = remember(current) { filterOption.get(current) }
|
|
||||||
TvDropdownMenuItem(
|
|
||||||
leadingIcon = {
|
|
||||||
if (currentValue != null) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Check,
|
|
||||||
contentDescription = "Filter active",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Text(
|
|
||||||
text = stringResource(filterOption.stringRes),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onClick = {
|
|
||||||
nestedDropDown = filterOption
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (filterCount > 0) {
|
if (filterCount > 0) {
|
||||||
HorizontalDivider()
|
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
val focused by interactionSource.collectIsFocusedAsState()
|
val focused by interactionSource.collectIsFocusedAsState()
|
||||||
TvDropdownMenuItem(
|
TvDropdownMenuItem(
|
||||||
|
|
@ -126,7 +102,35 @@ fun FilterByButton(
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
)
|
)
|
||||||
|
HorizontalDivider()
|
||||||
}
|
}
|
||||||
|
filterOptions
|
||||||
|
.forEachIndexed { index, filterOption ->
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
if (index == 0) {
|
||||||
|
LaunchedEffect(Unit) { focusRequester.tryRequestFocus() }
|
||||||
|
}
|
||||||
|
val currentValue = remember(current) { filterOption.get(current) }
|
||||||
|
TvDropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
if (currentValue != null) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Check,
|
||||||
|
contentDescription = "Filter active",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(filterOption.stringRes),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
nestedDropDown = filterOption
|
||||||
|
},
|
||||||
|
modifier = Modifier.focusRequester(focusRequester),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import kotlinx.coroutines.flow.debounce
|
||||||
*/
|
*/
|
||||||
class ControllerViewState internal constructor(
|
class ControllerViewState internal constructor(
|
||||||
@param:IntRange(from = 0)
|
@param:IntRange(from = 0)
|
||||||
private val hideMilliseconds: Long,
|
var hideMilliseconds: Long,
|
||||||
val controlsEnabled: Boolean,
|
val controlsEnabled: Boolean,
|
||||||
) {
|
) {
|
||||||
private val channel = Channel<Long>(CONFLATED)
|
private val channel = Channel<Long>(CONFLATED)
|
||||||
|
|
|
||||||
|
|
@ -167,17 +167,8 @@ fun PlaybackPage(
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
focusRequester.tryRequestFocus()
|
focusRequester.tryRequestFocus()
|
||||||
}
|
}
|
||||||
val controllerViewState =
|
val controllerViewState = remember { viewModel.controllerViewState }
|
||||||
remember {
|
|
||||||
ControllerViewState(
|
|
||||||
preferences.appPreferences.playbackPreferences.controllerTimeoutMs,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
}.also {
|
|
||||||
LaunchedEffect(it) {
|
|
||||||
it.observe()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var skipIndicatorDuration by remember { mutableLongStateOf(0L) }
|
var skipIndicatorDuration by remember { mutableLongStateOf(0L) }
|
||||||
LaunchedEffect(controllerViewState.controlsVisible) {
|
LaunchedEffect(controllerViewState.controlsVisible) {
|
||||||
// If controller shows/hides, immediately cancel the skip indicator
|
// If controller shows/hides, immediately cancel the skip indicator
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,12 @@ class PlaybackViewModel
|
||||||
}
|
}
|
||||||
internal val mutex = Mutex()
|
internal val mutex = Mutex()
|
||||||
|
|
||||||
|
val controllerViewState =
|
||||||
|
ControllerViewState(
|
||||||
|
AppPreference.ControllerTimeout.defaultValue,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
|
||||||
val loading = MutableLiveData<LoadingState>(LoadingState.Loading)
|
val loading = MutableLiveData<LoadingState>(LoadingState.Loading)
|
||||||
|
|
||||||
val currentMediaInfo = MutableLiveData<CurrentMediaInfo>(CurrentMediaInfo.EMPTY)
|
val currentMediaInfo = MutableLiveData<CurrentMediaInfo>(CurrentMediaInfo.EMPTY)
|
||||||
|
|
@ -153,6 +159,7 @@ class PlaybackViewModel
|
||||||
val subtitleSearchLanguage = MutableLiveData<String>(Locale.current.language)
|
val subtitleSearchLanguage = MutableLiveData<String>(Locale.current.language)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
viewModelScope.launch(ExceptionHandler()) { controllerViewState.observe() }
|
||||||
player.addListener(this)
|
player.addListener(this)
|
||||||
(player as? ExoPlayer)?.addAnalyticsListener(this)
|
(player as? ExoPlayer)?.addAnalyticsListener(this)
|
||||||
addCloseable { player.removeListener(this@PlaybackViewModel) }
|
addCloseable { player.removeListener(this@PlaybackViewModel) }
|
||||||
|
|
@ -178,6 +185,8 @@ class PlaybackViewModel
|
||||||
) {
|
) {
|
||||||
nextUp.value = null
|
nextUp.value = null
|
||||||
this.preferences = preferences
|
this.preferences = preferences
|
||||||
|
controllerViewState.hideMilliseconds =
|
||||||
|
preferences.appPreferences.playbackPreferences.controllerTimeoutMs
|
||||||
this.deviceProfile = deviceProfile
|
this.deviceProfile = deviceProfile
|
||||||
this.forceTranscoding =
|
this.forceTranscoding =
|
||||||
(destination as? Destination.Playback)?.forceTranscoding ?: false
|
(destination as? Destination.Playback)?.forceTranscoding ?: false
|
||||||
|
|
@ -696,6 +705,9 @@ class PlaybackViewModel
|
||||||
Timber.v("Setting next up to ${nextItem?.id}")
|
Timber.v("Setting next up to ${nextItem?.id}")
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
nextUp.value = nextItem
|
nextUp.value = nextItem
|
||||||
|
if (nextItem == null) {
|
||||||
|
controllerViewState.showControls()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -360,15 +360,19 @@ fun DownloadDialog(
|
||||||
if (progress != null) {
|
if (progress != null) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
progress = { progress },
|
progress = { progress },
|
||||||
Modifier
|
color = MaterialTheme.colorScheme.border,
|
||||||
.size(48.dp)
|
modifier =
|
||||||
.padding(8.dp),
|
Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
.padding(8.dp),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
Modifier
|
color = MaterialTheme.colorScheme.border,
|
||||||
.size(48.dp)
|
modifier =
|
||||||
.padding(8.dp),
|
Modifier
|
||||||
|
.size(48.dp)
|
||||||
|
.padding(8.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue