Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ buildscript {
}

plugins {
id 'com.android.application' version '8.5.2' apply false
id 'com.android.library' version '8.5.2' apply false
id 'com.android.application' version '8.11.2' apply false
id 'com.android.library' version '8.11.2' apply false
id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false
id 'com.google.gms.google-services' version '4.4.2' apply false
id "com.google.firebase.crashlytics" version "3.0.2" apply false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.os.Bundle
import android.view.View
import android.webkit.WebView
import android.widget.FrameLayout
import androidx.core.os.bundleOf
import androidx.core.view.WindowInsetsCompat
Expand All @@ -12,7 +13,6 @@
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.options.IFramePlayerOptions
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.utils.YouTubePlayerTracker
import com.pierfrancescosoffritti.androidyoutubeplayer.core.ui.DefaultPlayerUiController
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
Expand All @@ -39,8 +39,8 @@

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.videoUrl = requireArguments().getString(ARG_BLOCK_VIDEO_URL, "")
blockId = requireArguments().getString(ARG_BLOCK_ID, "")
// Enable WebView debugging for YouTube player
WebView.setWebContentsDebuggingEnabled(true)
if (viewModel.currentVideoTime == 0L) {
viewModel.currentVideoTime = requireArguments().getLong(ARG_VIDEO_TIME, 0)
}
Expand All @@ -67,8 +67,10 @@

lifecycle.addObserver(binding.youtubePlayerView)
val options = IFramePlayerOptions.Builder()
.controls(0)
.rel(0)
.controls(0) // Hide default controls (using custom UI)

Check warning

Code scanning / detekt

Reports multiple space usages Warning

Unnecessary long whitespace
.rel(0) // Don't show related videos

Check warning

Code scanning / detekt

Reports multiple space usages Warning

Unnecessary long whitespace
.ivLoadPolicy(3) // Critical: Disable video annotations

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

Check warning

Code scanning / detekt

Reports multiple space usages Warning

Unnecessary long whitespace
.ccLoadPolicy(1) // Show closed captions

Check warning

Code scanning / detekt

Reports multiple space usages Warning

Unnecessary long whitespace
.build()

binding.youtubePlayerView.initialize(
Expand All @@ -80,12 +82,20 @@
state: PlayerConstants.PlayerState,
) {
super.onStateChange(youTubePlayer, state)
android.util.Log.d("YoutubePlayerFS", "Player state: $state")

if (state == PlayerConstants.PlayerState.ENDED) {
viewModel.markBlockCompleted(blockId, CourseAnalyticsKey.YOUTUBE.key)
}
viewModel.isPlaying = when (state) {
PlayerConstants.PlayerState.PLAYING -> true
PlayerConstants.PlayerState.PAUSED -> false
PlayerConstants.PlayerState.PLAYING -> {
android.util.Log.d("YoutubePlayerFS", "✅ Fullscreen video PLAYING")
true
}
PlayerConstants.PlayerState.PAUSED -> {
android.util.Log.d("YoutubePlayerFS", "⏸️ Fullscreen video PAUSED")
false
}
else -> return
}
}
Expand All @@ -108,21 +118,23 @@
override fun onReady(youTubePlayer: YouTubePlayer) {
super.onReady(youTubePlayer)
binding.youtubePlayerView.isVisible = true
val defPlayerUiController =
DefaultPlayerUiController(binding.youtubePlayerView, youTubePlayer)
defPlayerUiController.setFullScreenButtonClickListener {
parentFragmentManager.popBackStack()
}

binding.youtubePlayerView.setCustomPlayerUi(defPlayerUiController.rootView)
android.util.Log.d("YoutubePlayerFS", "=== Fullscreen onReady ===")
android.util.Log.d("YoutubePlayerFS", "Video URL: ${viewModel.videoUrl}")

val videoId = viewModel.videoUrl.split("watch?v=")[1]
if (viewModel.isPlaying == true) {
youTubePlayer.loadVideo(videoId, viewModel.currentVideoTime.toFloat() / 1000)
val videoId = extractYouTubeVideoId(viewModel.videoUrl)
android.util.Log.d("YoutubePlayerFS", "Extracted video ID: '$videoId'")

if (videoId != null) {
val startTime = viewModel.currentVideoTime.toFloat() / 1000
// Always use cueVideo - avoids autoplay policy issues
android.util.Log.d("YoutubePlayerFS", "Action: cueVideo, Start time: $startTime sec")

youTubePlayer.cueVideo(videoId, startTime)
youTubePlayer.addListener(youtubeTrackerListener)
} else {
youTubePlayer.cueVideo(videoId, viewModel.currentVideoTime.toFloat() / 1000)
android.util.Log.e("YoutubePlayerFS", "❌ FAILED to extract video ID from: ${viewModel.videoUrl}")

Check warning

Code scanning / detekt

Reports lines with exceeded length Warning

Exceeded max line length (120)

Check warning

Code scanning / detekt

Line detected, which is longer than the defined maximum line length in the code style. Warning

Line detected, which is longer than the defined maximum line length in the code style.

Check warning

Code scanning / detekt

Reports incorrect argument list wrapping Warning

Argument should be on a separate line (unless all arguments can fit a single line)

Check warning

Code scanning / detekt

Reports incorrect argument list wrapping Warning

Argument should be on a separate line (unless all arguments can fit a single line)

Check warning

Code scanning / detekt

Reports incorrect argument list wrapping Warning

Missing newline before ")"
}
youTubePlayer.addListener(youtubeTrackerListener)
}
},
options
Expand All @@ -134,6 +146,48 @@
super.onDestroyView()
}

private fun extractYouTubeVideoId(url: String): String? {
return try {
when {
// Standard watch URL: https://www.youtube.com/watch?v=VIDEO_ID
url.contains("watch?v=") -> {
val parts = url.split("watch?v=")
if (parts.size > 1) {
parts[1].split("&").firstOrNull()
} else null

Check warning

Code scanning / detekt

Detects multiline if-else statements without braces Warning

Missing { ... }
}
// Short URL: https://youtu.be/VIDEO_ID
url.contains("youtu.be/") -> {
val parts = url.split("youtu.be/")
if (parts.size > 1) {
parts[1].split("?").firstOrNull()?.split("&")?.firstOrNull()
} else null

Check warning

Code scanning / detekt

Detects multiline if-else statements without braces Warning

Missing { ... }
}
// Embed URL: https://www.youtube.com/embed/VIDEO_ID
url.contains("/embed/") -> {
val parts = url.split("/embed/")
if (parts.size > 1) {
parts[1].split("?").firstOrNull()?.split("&")?.firstOrNull()
} else null

Check warning

Code scanning / detekt

Detects multiline if-else statements without braces Warning

Missing { ... }
}
// v parameter: https://youtube.com/v/VIDEO_ID
url.contains("/v/") -> {
val parts = url.split("/v/")
if (parts.size > 1) {
parts[1].split("?").firstOrNull()?.split("&")?.firstOrNull()
} else null

Check warning

Code scanning / detekt

Detects multiline if-else statements without braces Warning

Missing { ... }
}
else -> {
android.util.Log.w("YoutubePlayer", "Unknown YouTube URL format: $url")
null
}
}
} catch (e: Exception) {
android.util.Log.e("YoutubePlayer", "Error extracting video ID from: $url", e)
null
}
}

companion object {
private const val ARG_BLOCK_VIDEO_URL = "blockVideoUrl"
private const val ARG_VIDEO_TIME = "videoTime"
Expand Down
Loading
Loading