Untitled

Text Detected boxlabs 8 Views Size: 2.93 KB Posted on: Jun 3, 26 @ 5:41 PM
  1. // Embedded Twitter/X video player
  2. @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
  3. @Composable
  4. private fun TwitterVideoPlayer(videoUrl: String, onClose: () -> Unit) {
  5.     val context = LocalContext.current
  6.     val lifecycleOwner = androidx.lifecycle.compose.LocalLifecycleOwner.current
  7.  
  8.     // One player instance per URL. fxtwitter hands back either a progressive MP4 or an HLS
  9.     // (.m3u8) URL; the default media-source factory picks the right one from the URL because
  10.     // the HLS module is on the classpath, so no explicit MediaSource wiring is needed.
  11.     val exoPlayer = remember(videoUrl) {
  12.         androidx.media3.exoplayer.ExoPlayer.Builder(context).build().apply {
  13.             setMediaItem(androidx.media3.common.MediaItem.fromUri(videoUrl))
  14.             playWhenReady = true
  15.             prepare()
  16.         }
  17.     }
  18.  
  19.     // Pause when the app goes to the background so audio doesn't keep playing, and always
  20.     // release the player when this preview leaves composition (scrolled away / dismissed).
  21.     androidx.compose.runtime.DisposableEffect(lifecycleOwner, videoUrl) {
  22.         val observer = androidx.lifecycle.LifecycleEventObserver { _, event ->
  23.             if (event == androidx.lifecycle.Lifecycle.Event.ON_PAUSE) exoPlayer.pause()
  24.         }
  25.         lifecycleOwner.lifecycle.addObserver(observer)
  26.         onDispose {
  27.             lifecycleOwner.lifecycle.removeObserver(observer)
  28.             exoPlayer.release()
  29.         }
  30.     }
  31.  
  32.     Box(
  33.         modifier = Modifier
  34.             .fillMaxWidth()
  35.             .heightIn(max = 240.dp)
  36.             .clip(RoundedCornerShape(8.dp))
  37.             .background(Color.Black),
  38.         contentAlignment = Alignment.Center,
  39.     ) {
  40.         AndroidView(
  41.             factory = { ctx ->
  42.                 androidx.media3.ui.PlayerView(ctx).apply {
  43.                     player = exoPlayer
  44.                     useController = true
  45.                     setShowNextButton(false)
  46.                     setShowPreviousButton(false)
  47.                     layoutParams = android.view.ViewGroup.LayoutParams(
  48.                         android.view.ViewGroup.LayoutParams.MATCH_PARENT,
  49.                         android.view.ViewGroup.LayoutParams.MATCH_PARENT,
  50.                     )
  51.                 }
  52.             },
  53.             modifier = Modifier.fillMaxSize(),
  54.             onRelease = { it.player = null },
  55.         )
  56.         IconButton(
  57.             onClick = onClose,
  58.             modifier = Modifier
  59.                 .align(Alignment.TopEnd)
  60.                 .padding(4.dp)
  61.                 .size(36.dp)
  62.                 .background(Color.Black.copy(alpha = 0.55f), RoundedCornerShape(18.dp)),
  63.         ) {
  64.             Icon(
  65.                 imageVector        = Icons.Default.Close,
  66.                 contentDescription = "Close player",
  67.                 tint               = Color.White,
  68.                 modifier           = Modifier.size(18.dp),
  69.             )
  70.         }
  71.     }
  72. }

Raw Paste

Comments 0
Login to post a comment.
  • No comments yet. Be the first.
Login to post a comment. Login or Register
We use cookies. To comply with GDPR in the EU and the UK we have to show you these.

We use cookies and similar technologies to keep this website functional (including spam protection via Google reCAPTCHA or Cloudflare Turnstile), and — with your consent — to measure usage and show ads. See Privacy.