From 446273de80498b665e0d1fb58bb19c20b5a9fd12 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sun, 28 May 2023 17:35:57 -0400 Subject: [PATCH] Adds mute control per track on the screen. --- .../vitorpamplona/amethyst/ui/MainActivity.kt | 4 +- .../amethyst/ui/components/VideoView.kt | 58 ++++++++++--------- .../amethyst/ui/note/NoteCompose.kt | 3 +- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index f758617e8..d70a7adbf 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -28,7 +28,7 @@ import com.vitorpamplona.amethyst.service.model.PrivateDmEvent import com.vitorpamplona.amethyst.service.nip19.Nip19 import com.vitorpamplona.amethyst.service.notifications.PushNotificationUtils import com.vitorpamplona.amethyst.service.relays.Client -import com.vitorpamplona.amethyst.ui.components.muted +import com.vitorpamplona.amethyst.ui.components.DefaultMutedSetting import com.vitorpamplona.amethyst.ui.navigation.Route import com.vitorpamplona.amethyst.ui.note.Nip47 import com.vitorpamplona.amethyst.ui.screen.AccountScreen @@ -88,7 +88,7 @@ class MainActivity : FragmentActivity() { override fun onResume() { super.onResume() // starts muted every time - muted.value = true + DefaultMutedSetting.value = true // Only starts after login GlobalScope.launch(Dispatchers.IO) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index 909b366a7..78a2dc6ba 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -64,22 +64,26 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.io.File -public var muted = mutableStateOf(true) +public var DefaultMutedSetting = mutableStateOf(true) @Composable fun VideoView(localFile: File?, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) { if (localFile != null) { - VideoView(localFile.toUri(), description, null, onDialog) + val video = remember(localFile) { localFile.toUri() } + + VideoView(video, description, null, onDialog) } } @Composable fun VideoView(videoUri: String, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) { - VideoView(Uri.parse(videoUri), description, null, onDialog) + val video = remember(videoUri) { Uri.parse(videoUri) } + + VideoView(video, description, null, onDialog) } @Composable -fun VideoView(videoUri: String, description: String? = null, thumbUri: String, onDialog: ((Boolean) -> Unit)? = null) { +fun LoadThumbAndThenVideoView(videoUri: String, description: String? = null, thumbUri: String, onDialog: ((Boolean) -> Unit)? = null) { var loadingFinished by remember { mutableStateOf>(Pair(false, null)) } val context = LocalContext.current @@ -104,7 +108,9 @@ fun VideoView(videoUri: String, description: String? = null, thumbUri: String, o if (loadingFinished.first) { if (loadingFinished.second != null) { - VideoView(Uri.parse(videoUri), description, loadingFinished.second, onDialog) + val video = remember(videoUri) { Uri.parse(videoUri) } + + VideoView(video, description, loadingFinished.second, onDialog) } else { VideoView(videoUri, description, onDialog) } @@ -116,7 +122,7 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul val context = LocalContext.current val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current) - println("loading audio with artwork $thumb") + val mutedInstance = remember { mutableStateOf(DefaultMutedSetting.value) } val exoPlayer = remember(videoUri) { val mediaBuilder = MediaItem.Builder().setUri(videoUri) @@ -146,10 +152,6 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul } } - LaunchedEffect(key1 = muted.value) { - exoPlayer.volume = if (muted.value) 0f else 1f - } - DisposableEffect( BoxWithConstraints() { AndroidView( @@ -185,8 +187,11 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul } ) - MuteButton(muted, Modifier) { - muted.value = !muted.value + MuteButton(mutedInstance) { + mutedInstance.value = !mutedInstance.value + DefaultMutedSetting.value = mutedInstance.value + + exoPlayer.volume = if (mutedInstance.value) 0f else 1f } } ) { @@ -241,12 +246,14 @@ fun LayoutCoordinates.isCompletelyVisible(view: View): Boolean { } @Composable -private fun MuteButton(muted: MutableState, modifier: Modifier, toggle: () -> Unit) { +private fun MuteButton(muted: MutableState, toggle: () -> Unit) { Box( - modifier - .width(70.dp) - .height(70.dp) - .padding(10.dp) + remember { + Modifier + .width(70.dp) + .height(70.dp) + .padding(10.dp) + } ) { Box( Modifier @@ -256,23 +263,18 @@ private fun MuteButton(muted: MutableState, modifier: Modifier, toggle: .background(MaterialTheme.colors.background) ) - if (muted.value) { - IconButton( - onClick = toggle, - modifier = Modifier.size(50.dp) - ) { + IconButton( + onClick = toggle, + modifier = Modifier.size(50.dp) + ) { + if (muted.value) { Icon( imageVector = Icons.Default.VolumeOff, "Hash Verified", tint = MaterialTheme.colors.onBackground, modifier = Modifier.size(30.dp) ) - } - } else { - IconButton( - onClick = toggle, - modifier = Modifier.size(50.dp) - ) { + } else { Icon( imageVector = Icons.Default.VolumeUp, "Hash Verified", diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 852261619..f3df5d28a 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -107,6 +107,7 @@ import com.vitorpamplona.amethyst.service.model.RepostEvent import com.vitorpamplona.amethyst.service.model.TextNoteEvent import com.vitorpamplona.amethyst.ui.components.ClickableUrl import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji +import com.vitorpamplona.amethyst.ui.components.LoadThumbAndThenVideoView import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status import com.vitorpamplona.amethyst.ui.components.ResizeImage import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage @@ -1788,7 +1789,7 @@ fun AudioTrackHeader(noteEvent: AudioTrackEvent, note: Note, loggedIn: User, nav modifier = Modifier.padding(10.dp) ) { cover?.let { cover -> - VideoView( + LoadThumbAndThenVideoView( videoUri = media, description = noteEvent.subject(), thumbUri = cover