add loading indicator to audio controller
This commit is contained in:
parent
72d6874880
commit
afceb43308
|
@ -16,6 +16,9 @@
|
||||||
<SelectionState runConfigName="VideoPlayerControllerDropDownPreview">
|
<SelectionState runConfigName="VideoPlayerControllerDropDownPreview">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
|
<SelectionState runConfigName="AudioPlayerControllerPreview">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -20,25 +20,27 @@
|
||||||
|
|
||||||
package net.newpipe.newplayer.ui.audioplayer;
|
package net.newpipe.newplayer.ui.audioplayer;
|
||||||
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.animation.fadeIn
|
|
||||||
import androidx.compose.animation.fadeOut
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.FastForward
|
||||||
|
import androidx.compose.material.icons.filled.FastRewind
|
||||||
import androidx.compose.material.icons.filled.Pause
|
import androidx.compose.material.icons.filled.Pause
|
||||||
import androidx.compose.material.icons.filled.PlayArrow
|
import androidx.compose.material.icons.filled.PlayArrow
|
||||||
import androidx.compose.material.icons.filled.SkipNext
|
import androidx.compose.material.icons.filled.SkipNext
|
||||||
import androidx.compose.material.icons.filled.SkipPrevious
|
import androidx.compose.material.icons.filled.SkipPrevious
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
@ -51,8 +53,7 @@ import net.newpipe.newplayer.R
|
||||||
import net.newpipe.newplayer.model.NewPlayerUIState
|
import net.newpipe.newplayer.model.NewPlayerUIState
|
||||||
import net.newpipe.newplayer.model.NewPlayerViewModel
|
import net.newpipe.newplayer.model.NewPlayerViewModel
|
||||||
import net.newpipe.newplayer.model.NewPlayerViewModelDummy
|
import net.newpipe.newplayer.model.NewPlayerViewModelDummy
|
||||||
import net.newpipe.newplayer.ui.common.RepeatModeButton
|
import net.newpipe.newplayer.ui.LoadingPlaceholder
|
||||||
import net.newpipe.newplayer.ui.common.ShuffleModeButton
|
|
||||||
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
|
||||||
|
|
||||||
@androidx.annotation.OptIn(UnstableApi::class)
|
@androidx.annotation.OptIn(UnstableApi::class)
|
||||||
|
@ -63,12 +64,15 @@ fun AudioPlaybackController(viewModel: NewPlayerViewModel, uiState: NewPlayerUIS
|
||||||
modifier = Modifier.background(MaterialTheme.colorScheme.background),
|
modifier = Modifier.background(MaterialTheme.colorScheme.background),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
ShuffleModeButton(viewModel = viewModel, uiState = uiState)
|
//ShuffleModeButton(viewModel = viewModel, uiState = uiState)
|
||||||
|
|
||||||
Box(modifier = Modifier.size(80.dp), contentAlignment = Alignment.Center) {
|
Box(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1F)
|
||||||
|
.weight(1F), contentAlignment = Alignment.Center) {
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxWidth()
|
||||||
.aspectRatio(1f),
|
.aspectRatio(1f),
|
||||||
onClick = viewModel::prevStream,
|
onClick = viewModel::prevStream,
|
||||||
colors = lightAudioControlButtonColorScheme(),
|
colors = lightAudioControlButtonColorScheme(),
|
||||||
|
@ -83,11 +87,41 @@ fun AudioPlaybackController(viewModel: NewPlayerViewModel, uiState: NewPlayerUIS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1F)
|
||||||
|
.weight(1F), contentAlignment = Alignment.Center) {
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1f),
|
||||||
|
onClick = {
|
||||||
|
viewModel.fastSeek(1)
|
||||||
|
viewModel.finishFastSeek()
|
||||||
|
},
|
||||||
|
colors = lightAudioControlButtonColorScheme(),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
imageVector = Icons.Filled.FastRewind,
|
||||||
|
contentDescription = stringResource(R.string.widget_description_fast_rewind)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.size(80.dp),
|
modifier = Modifier.size(80.dp),
|
||||||
onClick = if (uiState.playing) viewModel::pause else viewModel::play,
|
onClick = if (uiState.playing) viewModel::pause else viewModel::play,
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
) {
|
) {
|
||||||
|
if(uiState.isLoading) {
|
||||||
|
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxSize().aspectRatio(1F),
|
||||||
|
color = MaterialTheme.colorScheme.onSurface)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
imageVector = if (uiState.playing) Icons.Filled.Pause else Icons.Filled.PlayArrow,
|
imageVector = if (uiState.playing) Icons.Filled.Pause else Icons.Filled.PlayArrow,
|
||||||
|
@ -97,11 +131,37 @@ fun AudioPlaybackController(viewModel: NewPlayerViewModel, uiState: NewPlayerUIS
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(modifier = Modifier.size(80.dp), contentAlignment = Alignment.Center) {
|
Box(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1F)
|
||||||
|
.weight(1F), contentAlignment = Alignment.Center) {
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1f),
|
||||||
|
onClick = {
|
||||||
|
viewModel.fastSeek(1)
|
||||||
|
viewModel.finishFastSeek()
|
||||||
|
},
|
||||||
|
colors = lightAudioControlButtonColorScheme(),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
imageVector = Icons.Filled.FastForward,
|
||||||
|
contentDescription = stringResource(R.string.widget_description_fast_forward)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1F)
|
||||||
|
.weight(1F), contentAlignment = Alignment.Center) {
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
.aspectRatio(1f),
|
.aspectRatio(1f),
|
||||||
onClick = viewModel::nextStream,
|
onClick = viewModel::nextStream,
|
||||||
colors = lightAudioControlButtonColorScheme(),
|
colors = lightAudioControlButtonColorScheme(),
|
||||||
|
@ -115,7 +175,7 @@ fun AudioPlaybackController(viewModel: NewPlayerViewModel, uiState: NewPlayerUIS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RepeatModeButton(viewModel = viewModel, uiState = uiState)
|
//RepeatModeButton(viewModel = viewModel, uiState = uiState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +187,7 @@ fun AudioPlayerControllerPreview() {
|
||||||
VideoPlayerTheme {
|
VideoPlayerTheme {
|
||||||
AudioPlaybackController(
|
AudioPlaybackController(
|
||||||
viewModel = NewPlayerViewModelDummy(),
|
viewModel = NewPlayerViewModelDummy(),
|
||||||
uiState = NewPlayerUIState.DUMMY.copy(playList = emptyList())
|
uiState = NewPlayerUIState.DUMMY.copy(playList = emptyList(), isLoading = true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@ package net.newpipe.newplayer.ui.audioplayer
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
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.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
@ -73,7 +74,7 @@ import net.newpipe.newplayer.utils.getEmbeddedUiConfig
|
||||||
@Composable
|
@Composable
|
||||||
fun AudioBottomUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
fun AudioBottomUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
||||||
|
|
||||||
val embeddedUiConfig = if(LocalContext.current is Activity)
|
val embeddedUiConfig = if (LocalContext.current is Activity)
|
||||||
getEmbeddedUiConfig(activity = LocalContext.current as Activity)
|
getEmbeddedUiConfig(activity = LocalContext.current as Activity)
|
||||||
else
|
else
|
||||||
EmbeddedUiConfig.DUMMY
|
EmbeddedUiConfig.DUMMY
|
||||||
|
@ -107,6 +108,7 @@ fun AudioBottomUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
androidx.compose.animation.AnimatedVisibility(visible = uiState.chapters.isNotEmpty()) {
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
viewModel.changeUiMode(UIModeState.AUDIO_CHAPTER_SELECT, embeddedUiConfig)
|
viewModel.changeUiMode(UIModeState.AUDIO_CHAPTER_SELECT, embeddedUiConfig)
|
||||||
}, colors = lightAudioControlButtonColorScheme()) {
|
}, colors = lightAudioControlButtonColorScheme()) {
|
||||||
|
@ -117,6 +119,9 @@ fun AudioBottomUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
androidx.compose.animation.AnimatedVisibility(visible = 1 < uiState.playList.size) {
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
viewModel.changeUiMode(UIModeState.AUDIO_STREAM_SELECT, embeddedUiConfig)
|
viewModel.changeUiMode(UIModeState.AUDIO_STREAM_SELECT, embeddedUiConfig)
|
||||||
}, colors = lightAudioControlButtonColorScheme()) {
|
}, colors = lightAudioControlButtonColorScheme()) {
|
||||||
|
@ -128,6 +133,7 @@ fun AudioBottomUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Menu()
|
Menu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +142,7 @@ fun AudioBottomUI(viewModel: NewPlayerViewModel, uiState: NewPlayerUIState) {
|
||||||
private fun Menu() {
|
private fun Menu() {
|
||||||
var showMenu: Boolean by remember { mutableStateOf(false) }
|
var showMenu: Boolean by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val embeddedUiConfig = if(LocalContext.current is Activity)
|
val embeddedUiConfig = if (LocalContext.current is Activity)
|
||||||
getEmbeddedUiConfig(activity = LocalContext.current as Activity)
|
getEmbeddedUiConfig(activity = LocalContext.current as Activity)
|
||||||
else
|
else
|
||||||
EmbeddedUiConfig.DUMMY
|
EmbeddedUiConfig.DUMMY
|
||||||
|
@ -183,7 +189,10 @@ private fun Menu() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = { /*TODO*/ showMenu = false })
|
onClick = { /*TODO*/ showMenu = false })
|
||||||
DropdownMenuItem(text = { Text(stringResource(R.string.pip_button_description)) }, onClick = { /*TODO*/ }, leadingIcon = {
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringResource(R.string.pip_button_description)) },
|
||||||
|
onClick = { /*TODO*/ },
|
||||||
|
leadingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.PictureInPicture,
|
imageVector = Icons.Filled.PictureInPicture,
|
||||||
contentDescription = stringResource(
|
contentDescription = stringResource(
|
||||||
|
|
|
@ -29,7 +29,9 @@
|
||||||
<string name="menu_item_language">Language</string>
|
<string name="menu_item_language">Language</string>
|
||||||
<string name="menu_item_playback_speed">Playback speed</string>
|
<string name="menu_item_playback_speed">Playback speed</string>
|
||||||
<string name="widget_description_previous_stream">Previous stream</string>
|
<string name="widget_description_previous_stream">Previous stream</string>
|
||||||
|
<string name="widget_description_fast_rewind">Fast rewind</string>
|
||||||
<string name="widget_description_next_stream">Next stream</string>
|
<string name="widget_description_next_stream">Next stream</string>
|
||||||
|
<string name="widget_description_fast_forward">Fast forward</string>
|
||||||
<string name="widget_description_play">Play</string>
|
<string name="widget_description_play">Play</string>
|
||||||
<string name="widget_description_pause">Pause</string>
|
<string name="widget_description_pause">Pause</string>
|
||||||
<string name="widget_description_toggle_fullscreen">Toggle fullscreen</string>
|
<string name="widget_description_toggle_fullscreen">Toggle fullscreen</string>
|
||||||
|
|
Loading…
Reference in New Issue