Adds mute control per track on the screen.
This commit is contained in:
@@ -28,7 +28,7 @@ import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
|||||||
import com.vitorpamplona.amethyst.service.nip19.Nip19
|
import com.vitorpamplona.amethyst.service.nip19.Nip19
|
||||||
import com.vitorpamplona.amethyst.service.notifications.PushNotificationUtils
|
import com.vitorpamplona.amethyst.service.notifications.PushNotificationUtils
|
||||||
import com.vitorpamplona.amethyst.service.relays.Client
|
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.navigation.Route
|
||||||
import com.vitorpamplona.amethyst.ui.note.Nip47
|
import com.vitorpamplona.amethyst.ui.note.Nip47
|
||||||
import com.vitorpamplona.amethyst.ui.screen.AccountScreen
|
import com.vitorpamplona.amethyst.ui.screen.AccountScreen
|
||||||
@@ -88,7 +88,7 @@ class MainActivity : FragmentActivity() {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
// starts muted every time
|
// starts muted every time
|
||||||
muted.value = true
|
DefaultMutedSetting.value = true
|
||||||
|
|
||||||
// Only starts after login
|
// Only starts after login
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
|||||||
@@ -64,22 +64,26 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
public var muted = mutableStateOf(true)
|
public var DefaultMutedSetting = mutableStateOf(true)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoView(localFile: File?, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) {
|
fun VideoView(localFile: File?, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) {
|
||||||
if (localFile != null) {
|
if (localFile != null) {
|
||||||
VideoView(localFile.toUri(), description, null, onDialog)
|
val video = remember(localFile) { localFile.toUri() }
|
||||||
|
|
||||||
|
VideoView(video, description, null, onDialog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoView(videoUri: String, description: String? = null, onDialog: ((Boolean) -> Unit)? = null) {
|
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
|
@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<Boolean, Drawable?>>(Pair(false, null)) }
|
var loadingFinished by remember { mutableStateOf<Pair<Boolean, Drawable?>>(Pair(false, null)) }
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
@@ -104,7 +108,9 @@ fun VideoView(videoUri: String, description: String? = null, thumbUri: String, o
|
|||||||
|
|
||||||
if (loadingFinished.first) {
|
if (loadingFinished.first) {
|
||||||
if (loadingFinished.second != null) {
|
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 {
|
} else {
|
||||||
VideoView(videoUri, description, onDialog)
|
VideoView(videoUri, description, onDialog)
|
||||||
}
|
}
|
||||||
@@ -116,7 +122,7 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
|
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
|
||||||
|
|
||||||
println("loading audio with artwork $thumb")
|
val mutedInstance = remember { mutableStateOf(DefaultMutedSetting.value) }
|
||||||
|
|
||||||
val exoPlayer = remember(videoUri) {
|
val exoPlayer = remember(videoUri) {
|
||||||
val mediaBuilder = MediaItem.Builder().setUri(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(
|
DisposableEffect(
|
||||||
BoxWithConstraints() {
|
BoxWithConstraints() {
|
||||||
AndroidView(
|
AndroidView(
|
||||||
@@ -185,8 +187,11 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
MuteButton(muted, Modifier) {
|
MuteButton(mutedInstance) {
|
||||||
muted.value = !muted.value
|
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
|
@Composable
|
||||||
private fun MuteButton(muted: MutableState<Boolean>, modifier: Modifier, toggle: () -> Unit) {
|
private fun MuteButton(muted: MutableState<Boolean>, toggle: () -> Unit) {
|
||||||
Box(
|
Box(
|
||||||
modifier
|
remember {
|
||||||
|
Modifier
|
||||||
.width(70.dp)
|
.width(70.dp)
|
||||||
.height(70.dp)
|
.height(70.dp)
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
@@ -256,23 +263,18 @@ private fun MuteButton(muted: MutableState<Boolean>, modifier: Modifier, toggle:
|
|||||||
.background(MaterialTheme.colors.background)
|
.background(MaterialTheme.colors.background)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (muted.value) {
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = toggle,
|
onClick = toggle,
|
||||||
modifier = Modifier.size(50.dp)
|
modifier = Modifier.size(50.dp)
|
||||||
) {
|
) {
|
||||||
|
if (muted.value) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.VolumeOff,
|
imageVector = Icons.Default.VolumeOff,
|
||||||
"Hash Verified",
|
"Hash Verified",
|
||||||
tint = MaterialTheme.colors.onBackground,
|
tint = MaterialTheme.colors.onBackground,
|
||||||
modifier = Modifier.size(30.dp)
|
modifier = Modifier.size(30.dp)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
IconButton(
|
|
||||||
onClick = toggle,
|
|
||||||
modifier = Modifier.size(50.dp)
|
|
||||||
) {
|
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.VolumeUp,
|
imageVector = Icons.Default.VolumeUp,
|
||||||
"Hash Verified",
|
"Hash Verified",
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ import com.vitorpamplona.amethyst.service.model.RepostEvent
|
|||||||
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
|
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
|
||||||
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
||||||
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
|
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.ObserveDisplayNip05Status
|
||||||
import com.vitorpamplona.amethyst.ui.components.ResizeImage
|
import com.vitorpamplona.amethyst.ui.components.ResizeImage
|
||||||
import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
|
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)
|
modifier = Modifier.padding(10.dp)
|
||||||
) {
|
) {
|
||||||
cover?.let { cover ->
|
cover?.let { cover ->
|
||||||
VideoView(
|
LoadThumbAndThenVideoView(
|
||||||
videoUri = media,
|
videoUri = media,
|
||||||
description = noteEvent.subject(),
|
description = noteEvent.subject(),
|
||||||
thumbUri = cover
|
thumbUri = cover
|
||||||
|
|||||||
Reference in New Issue
Block a user