Skip to content

Commit b5561d9

Browse files
authored
Merge pull request #82 from KhubaibKhan4/controls
-Controls Hide and Sow Added
2 parents ab3ad92 + f8597f1 commit b5561d9

File tree

9 files changed

+222
-169
lines changed

9 files changed

+222
-169
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ media3Exoplayer = "1.5.0"
1010
core = "12.1.0"
1111
compose = "1.7.1"
1212
androidx-appcompat = "1.7.0"
13-
androidx-activityCompose = "1.9.3"
13+
androidx-activityCompose = "1.10.0"
1414
compose-uitooling = "1.7.6"
1515
kotlinx-coroutines = "1.9.0"
1616

mediaplayer-kmp/src/androidMain/kotlin/YouTubePlayer.android.kt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ import org.jetbrains.kotlinx.multiplatform.library.template.R
8282
actual fun VideoPlayer(
8383
modifier: Modifier,
8484
url: String,
85-
autoPlay: Boolean
85+
autoPlay: Boolean,
86+
showControls: Boolean,
8687
) {
8788
when {
8889
url?.contains("youtube.com") == true || url?.contains("youtu.be") == true -> {
@@ -95,13 +96,14 @@ actual fun VideoPlayer(
9596
}
9697

9798
isVideoFile(url) -> {
98-
ExoPlayerVideoPlayer(videoURL = url!!, autoPlay = autoPlay)
99+
ExoPlayerVideoPlayer(videoURL = url!!, autoPlay = autoPlay, showControls = showControls)
99100
}
100101
}
101102
}
102103

104+
@OptIn(UnstableApi::class)
103105
@Composable
104-
fun ExoPlayerVideoPlayer(videoURL: String,autoPlay: Boolean) {
106+
fun ExoPlayerVideoPlayer(videoURL: String,autoPlay: Boolean, showControls: Boolean) {
105107
val context = LocalContext.current
106108
val activity = context as ComponentActivity
107109
val exoPlayer = remember { ExoPlayer.Builder(context).build() }
@@ -134,6 +136,11 @@ fun ExoPlayerVideoPlayer(videoURL: String,autoPlay: Boolean) {
134136
PlayerView(context).apply {
135137
player = exoPlayer
136138
useController = true
139+
if (showControls) {
140+
showController()
141+
}else{
142+
hideController()
143+
}
137144
setControllerVisibilityListener(object : PlayerView.ControllerVisibilityListener {
138145
@SuppressLint("ResourceType")
139146
override fun onVisibilityChanged(visibility: Int) {
@@ -203,7 +210,6 @@ fun isVideoFile(url: String?): Boolean {
203210
Regex(".*(stream|video|live|media).*", RegexOption.IGNORE_CASE)
204211
) == true
205212
}
206-
207213
@Composable
208214
fun YoutubeVideoPlayer(
209215
modifier: Modifier = Modifier,
@@ -214,8 +220,8 @@ fun YoutubeVideoPlayer(
214220
autoPlay: Boolean
215221
) {
216222
val mContext = LocalContext.current
217-
val mLifeCycleOwner = LocalLifecycleOwner.current
218-
val activity = mContext as ComponentActivity
223+
val mLifeCycleOwner = androidx.lifecycle.compose.LocalLifecycleOwner.current
224+
val activity = (mContext as Activity)
219225
val videoId = extractVideoId(youtubeURL)
220226
val startTimeInSeconds = extractStartTime(youtubeURL)
221227
var player: com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer? = null
@@ -536,7 +542,8 @@ actual fun MediaPlayer(
536542
volumeIconColor: Color,
537543
playIconColor: Color,
538544
sliderTrackColor: Color,
539-
sliderIndicatorColor: Color
545+
sliderIndicatorColor: Color,
546+
showControls: Boolean,
540547
) {
541548
if (isAudioFile(url)) {
542549
ExoPlayerAudioPlayer(
@@ -551,7 +558,7 @@ actual fun MediaPlayer(
551558
sliderIndicatorColor = sliderIndicatorColor
552559
)
553560
} else {
554-
ExoPlayerVideoPlayer(videoURL = url, autoPlay = autoPlay)
561+
ExoPlayerVideoPlayer(videoURL = url, autoPlay = autoPlay, showControls = showControls)
555562
}
556563
}
557564

mediaplayer-kmp/src/commonMain/kotlin/YouTubePlayer.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,21 @@ import androidx.compose.ui.graphics.Color
99
import androidx.compose.ui.unit.dp
1010

1111
@Composable
12-
expect fun VideoPlayer(modifier: Modifier, url: String, autoPlay: Boolean)
12+
expect fun VideoPlayer(modifier: Modifier, url: String, autoPlay: Boolean, showControls: Boolean)
1313

1414
@Composable
1515
expect fun MediaPlayer(
1616
modifier: Modifier,
1717
url: String,
18-
headers: Map<String, String> = emptyMap(),
18+
headers: Map<String, String>,
1919
startTime: Color,
2020
endTime: Color,
2121
autoPlay: Boolean,
2222
volumeIconColor: Color,
2323
playIconColor: Color,
2424
sliderTrackColor: Color,
25-
sliderIndicatorColor: Color
25+
sliderIndicatorColor: Color,
26+
showControls: Boolean= true,
2627
)
2728
enum class PagerType {
2829
Horizontal,
@@ -34,6 +35,7 @@ fun ReelsView(
3435
pagerType: PagerType,
3536
modifier: Modifier = Modifier,
3637
autoPlay: Boolean = true,
38+
showControls: Boolean = true,
3739
onInteraction: (Int, String) -> Unit = { _, _ -> }
3840
) {
3941
val pagerState = rememberPagerState(pageCount = {videoUrls.size})
@@ -47,7 +49,8 @@ fun ReelsView(
4749
VideoPlayerScreen(
4850
url = videoUrls[page],
4951
autoPlay = autoPlay,
50-
onInteraction = { onInteraction(page, videoUrls[page]) }
52+
onInteraction = { onInteraction(page, videoUrls[page]) },
53+
showControls = showControls
5154
)
5255
}
5356
}
@@ -59,7 +62,8 @@ fun ReelsView(
5962
VideoPlayerScreen(
6063
url = videoUrls[page],
6164
autoPlay = autoPlay,
62-
onInteraction = { onInteraction(page, videoUrls[page]) }
65+
onInteraction = { onInteraction(page, videoUrls[page]) },
66+
showControls = showControls
6367
)
6468
}
6569
}
@@ -70,13 +74,15 @@ fun ReelsView(
7074
fun VideoPlayerScreen(
7175
url: String,
7276
autoPlay: Boolean,
73-
onInteraction: () -> Unit
77+
onInteraction: () -> Unit,
78+
showControls: Boolean
7479
) {
7580
VideoPlayer(
7681
modifier = Modifier
7782
.fillMaxSize()
7883
.padding(8.dp),
7984
url = url,
80-
autoPlay = autoPlay
85+
autoPlay = autoPlay,
86+
showControls = showControls
8187
)
8288
}

mediaplayer-kmp/src/iosMain/kotlin/YouTubePlayer.ios.kt

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import platform.CoreGraphics.CGPoint
4040
import platform.CoreGraphics.CGRectGetMidX
4141
import platform.CoreGraphics.CGRectGetMidY
4242
import platform.Foundation.NSCoder
43+
import platform.UIKit.NSLayoutConstraint
4344
import platform.UIKit.UICollectionViewDelegateProtocol
4445
import platform.UIKit.UIColor.Companion.blackColor
4546
import platform.UIKit.UINib
@@ -53,46 +54,64 @@ import platform.darwin.NSObject
5354

5455
@Composable
5556
actual fun VideoPlayer(
56-
modifier: Modifier,
57-
url: String,
58-
autoPlay: Boolean
57+
modifier: Modifier, url: String, autoPlay: Boolean, showControls: Boolean
5958
) {
6059
if (url.contains("youtube.com") || url.contains("youtu.be")) {
61-
YouTubeIFramePlayer(url = url, modifier = modifier,autoPlay = autoPlay)
60+
YouTubeIFramePlayer(url = url, modifier = modifier,autoPlay = autoPlay, showControls = showControls)
6261
} else if (isVideoFile(url) || isAudioFile(url)) {
63-
AvPlayerView(modifier,url,autoPlay)
62+
AvPlayerView(modifier,url,autoPlay, showControls = showControls)
6463
} else {
6564
Text("Unsupported media format", modifier = modifier)
6665
}
6766
}
6867

6968
@Composable
70-
fun AvPlayerView(modifier: Modifier = Modifier, url: String, autoPlay: Boolean) {
69+
fun AvPlayerView(
70+
modifier: Modifier = Modifier,
71+
url: String,
72+
autoPlay: Boolean,
73+
showControls: Boolean
74+
) {
75+
val validUrl = remember(url) { NSURL.URLWithString(url) }
76+
7177
val player = remember {
72-
NSURL.URLWithString(url.toString())?.let { AVPlayer(uRL = it) }
78+
validUrl?.let { AVPlayer(uRL = it) }
7379
}
74-
val playerLayer = remember { AVPlayerLayer() }
80+
7581
val avPlayerViewController = remember { AVPlayerViewController() }
82+
7683
avPlayerViewController.player = player
77-
avPlayerViewController.showsPlaybackControls = true
78-
avPlayerViewController.allowsPictureInPicturePlayback = true
84+
avPlayerViewController.showsPlaybackControls = showControls
85+
avPlayerViewController.allowsPictureInPicturePlayback = showControls
7986

80-
playerLayer.player = player
8187
UIKitView(
8288
factory = {
8389
val playerContainer = UIView()
90+
91+
avPlayerViewController.view.translatesAutoresizingMaskIntoConstraints = false
8492
playerContainer.addSubview(avPlayerViewController.view)
93+
94+
NSLayoutConstraint.activateConstraints(
95+
listOf(
96+
avPlayerViewController.view.leadingAnchor.constraintEqualToAnchor(playerContainer.leadingAnchor),
97+
avPlayerViewController.view.trailingAnchor.constraintEqualToAnchor(playerContainer.trailingAnchor),
98+
avPlayerViewController.view.topAnchor.constraintEqualToAnchor(playerContainer.topAnchor),
99+
avPlayerViewController.view.bottomAnchor.constraintEqualToAnchor(playerContainer.bottomAnchor)
100+
)
101+
)
102+
85103
playerContainer
86104
},
87105
modifier = modifier,
88-
update = { view ->
89-
when(autoPlay){
90-
true -> player?.play()
91-
false -> {
92-
93-
}
106+
update = { _ ->
107+
if (autoPlay) {
108+
player?.play()
109+
} else {
110+
player?.pause()
94111
}
95-
avPlayerViewController.player?.play()
112+
},
113+
onRelease = {
114+
player?.pause()
96115
},
97116
properties = UIKitInteropProperties(
98117
isInteractive = true,
@@ -130,19 +149,18 @@ actual fun MediaPlayer(
130149
volumeIconColor: Color,
131150
playIconColor: Color,
132151
sliderTrackColor: Color,
133-
sliderIndicatorColor: Color
152+
sliderIndicatorColor: Color,
153+
showControls: Boolean,
134154
) {
135155
val player = remember {
136156
createAVPlayerWithHeaders(url, headers)
137157
}
138-
val playerLayer = remember { AVPlayerLayer() }
139158
val avPlayerViewController = remember { AVPlayerViewController() }
140159

160+
// Configure the player and controls based on `showControls`
141161
avPlayerViewController.player = player
142-
avPlayerViewController.showsPlaybackControls = true
143-
avPlayerViewController.allowsPictureInPicturePlayback = true
144-
145-
playerLayer.player = player
162+
avPlayerViewController.showsPlaybackControls = showControls
163+
avPlayerViewController.allowsPictureInPicturePlayback = showControls
146164

147165
UIKitView(
148166
factory = {
@@ -154,6 +172,8 @@ actual fun MediaPlayer(
154172
update = { _ ->
155173
if (autoPlay) {
156174
player?.play()
175+
} else {
176+
player?.pause()
157177
}
158178
},
159179
onRelease = {
@@ -178,14 +198,13 @@ private fun createAVPlayerWithHeaders(url: String, headers: Map<String, String>)
178198
}
179199

180200
@Composable
181-
fun YouTubeIFramePlayer(url: String, modifier: Modifier,autoPlay: Boolean) {
201+
fun YouTubeIFramePlayer(url: String, modifier: Modifier, autoPlay: Boolean, showControls: Boolean) {
182202
val videoId = remember(url) {
183-
url?.substringAfter("v=")?.substringBefore("&") ?: url?.substringAfterLast("/")
184-
}
185-
val isAutoPlay = when(autoPlay){
186-
true -> 1
187-
false -> 0
203+
url.substringAfter("v=").substringBefore("&").ifEmpty { url.substringAfterLast("/") }
188204
}
205+
val isAutoPlay = if (autoPlay) 1 else 0
206+
val controls = if (showControls) 1 else 0
207+
189208
val htmlContent = """
190209
<html>
191210
<head>
@@ -214,8 +233,9 @@ fun YouTubeIFramePlayer(url: String, modifier: Modifier,autoPlay: Boolean) {
214233
<body>
215234
<div class="video-container">
216235
<iframe
217-
src="https://www.youtube.com/embed/$videoId?autoplay=$isAutoPlay"
218-
allow="autoplay;">
236+
src="https://www.youtube.com/embed/$videoId?autoplay=$isAutoPlay&controls=$controls"
237+
allow="autoplay;"
238+
frameborder="0">
219239
</iframe>
220240
</div>
221241
</body>
@@ -231,9 +251,9 @@ fun YouTubeIFramePlayer(url: String, modifier: Modifier,autoPlay: Boolean) {
231251
},
232252
modifier = modifier
233253
.fillMaxWidth()
234-
.aspectRatio(16f / 13f),
254+
.aspectRatio(16f / 9f),
235255
update = { view ->
236-
// Update logic if needed
256+
237257
},
238258
properties = UIKitInteropProperties(
239259
isInteractive = true,

0 commit comments

Comments
 (0)