Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import com.bumptech.glide.request.target.CustomTarget
import tech.salroid.filmy.ui.full.YoutubePlayerActivity.Companion.IS_SHORT
import tech.salroid.filmy.ui.full.YoutubePlayerActivity.Companion.VIDEO_ID
import tech.salroid.filmy.ui.full.YoutubePlayerActivity.Companion.VIDEO_TITLE
import tech.salroid.filmy.utility.isYoutubeShortVideo

@AndroidEntryPoint
class MovieDetailsActivity : AppCompatActivity() {
Expand Down Expand Up @@ -267,13 +269,17 @@ class MovieDetailsActivity : AppCompatActivity() {

binding.trailerView.setOnClickListener {
trailerFinal?.let {
Intent(
this@MovieDetailsActivity,
YoutubePlayerActivity::class.java
).run {
putExtra(VIDEO_ID, trailerFinal)
putExtra(VIDEO_TITLE, trailerTitle)
startActivity(this)
lifecycleScope.launch {
val isShort = isYoutubeShortVideo(it)
Intent(
this@MovieDetailsActivity,
YoutubePlayerActivity::class.java
).run {
putExtra(VIDEO_ID, trailerFinal)
putExtra(VIDEO_TITLE, trailerTitle)
putExtra(IS_SHORT, isShort)
startActivity(this)
}
}
}
}
Expand Down Expand Up @@ -701,4 +707,4 @@ class MovieDetailsActivity : AppCompatActivity() {
startActivity(Intent.createChooser(myIntent, "Share with"))
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ import android.view.*
import android.view.animation.DecelerateInterpolator
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import kotlinx.coroutines.launch
import tech.salroid.filmy.R
import tech.salroid.filmy.data.local.model.TrailerData
import tech.salroid.filmy.databinding.AllTrailerLayoutBinding
import tech.salroid.filmy.ui.adapters.MovieTrailersAdapter
import tech.salroid.filmy.ui.full.YoutubePlayerActivity.Companion.IS_SHORT
import tech.salroid.filmy.utility.isYoutubeShortVideo
import tech.salroid.filmy.utility.themeSystemBars
import kotlin.math.hypot
import androidx.core.graphics.toColorInt
Expand Down Expand Up @@ -130,10 +134,14 @@ class AllTrailersFragment : Fragment() {
}

private fun playTrailerOnYoutube(trailerId: String, trailerTitle: String?) {
Intent(activity, YoutubePlayerActivity::class.java).run {
putExtra(YoutubePlayerActivity.VIDEO_ID, trailerId)
putExtra(YoutubePlayerActivity.VIDEO_TITLE, trailerTitle)
startActivity(this)
lifecycleScope.launch {
val isShort = isYoutubeShortVideo(trailerId)
Intent(activity, YoutubePlayerActivity::class.java).run {
putExtra(YoutubePlayerActivity.VIDEO_ID, trailerId)
putExtra(YoutubePlayerActivity.VIDEO_TITLE, trailerTitle)
putExtra(IS_SHORT, isShort)
startActivity(this)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ package tech.salroid.filmy.ui.full

import android.annotation.SuppressLint
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
import android.graphics.Color
import android.os.Bundle
import android.view.Gravity
import android.view.HapticFeedbackConstants.VIRTUAL_KEY
import android.view.View
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
Expand All @@ -25,22 +28,28 @@ class YoutubePlayerActivity : AppCompatActivity() {

private var videoId: String? = null
private var videoTitle: String? = null
private var isShort: Boolean = false
private var html5VideoView: View? = null
private var customViewCallback: WebChromeClient.CustomViewCallback? = null

companion object {
const val VIDEO_ID = "video_id"
const val VIDEO_TITLE = "video_title"
private const val YT_BASE_URL = "https://www.youtube.com"
const val IS_SHORT = "is_short"
private const val APP_BASE_URL = "https://app.filmy.tech"
private const val MIME_TYPE = "text/html"
private const val ENCODING = "utf-8"
private const val DESKTOP_USER_AGENT =
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

videoId = intent.getStringExtra(VIDEO_ID)
videoTitle = intent.getStringExtra(VIDEO_TITLE)
isShort = intent.getBooleanExtra(IS_SHORT, false)

binding = ActivityFullScreenYoutubeBinding.inflate(layoutInflater)
setContentView(binding.root)
setupUI()
Expand All @@ -63,18 +72,20 @@ class YoutubePlayerActivity : AppCompatActivity() {
setBackgroundColor(Color.TRANSPARENT)
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
mediaPlaybackRequiresUserGesture = false
setSupportZoom(false)
builtInZoomControls = false
displayZoomControls = false
userAgentString = DESKTOP_USER_AGENT
}

webViewClient = YTWebViewClient()
webChromeClient = YTWebChromeClient()

// Load the YouTube video iframe HTML
loadDataWithBaseURL(
YT_BASE_URL,
APP_BASE_URL,
getYouTubeIframeHTML(id),
MIME_TYPE,
ENCODING,
Expand All @@ -89,17 +100,22 @@ class YoutubePlayerActivity : AppCompatActivity() {
view: WebView?,
request: WebResourceRequest?
): Boolean {
try {
view?.context?.startActivity(
android.content.Intent(
android.content.Intent.ACTION_VIEW,
request?.url
val url = request?.url.toString()
return if (url.startsWith("https://www.youtube.com")) {
false
} else {
try {
view?.context?.startActivity(
android.content.Intent(
android.content.Intent.ACTION_VIEW,
request?.url
)
)
)
} catch (e: Exception) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
true
}
return true
}
}

Expand All @@ -112,7 +128,26 @@ class YoutubePlayerActivity : AppCompatActivity() {
html5VideoView = view
customViewCallback = callback

requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE
if (isShort) {
requestedOrientation = SCREEN_ORIENTATION_PORTRAIT
val displayMetrics = resources.displayMetrics
val screenWidth = displayMetrics.widthPixels
val videoHeight = screenWidth * 16 / 9

val layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
videoHeight,
Gravity.CENTER
)
view?.layoutParams = layoutParams
} else {
requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE
val layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
)
view?.layoutParams = layoutParams
}

binding.headerContainer.visibility = View.GONE
binding.webviewContainer.visibility = View.GONE
Expand Down Expand Up @@ -161,4 +196,4 @@ class YoutubePlayerActivity : AppCompatActivity() {
binding.youtubeWebView.destroy()
super.onDestroy()
}
}
}
31 changes: 27 additions & 4 deletions app/src/main/java/tech/salroid/filmy/utility/YoutubeUtils.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package tech.salroid.filmy.utility

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request

/**
* Generates the HTML string required to embed a YouTube video using an iframe.
Expand All @@ -25,10 +29,10 @@ fun getYouTubeIframeHTML(youtubeVideoId: String): String {
'controls': 1,
'fs': 1,
'rel': 0,
'modestbranding': 1,
'iv_load_policy': 3,
'showinfo': 0,
'playsinline': 1
'playsinline': 1,
'origin': 'https://app.filmy.tech',
'enablejsapi': 1
},
events: {
'onReady': function(event) { event.target.playVideo(); }
Expand All @@ -43,4 +47,23 @@ fun getYouTubeIframeHTML(youtubeVideoId: String): String {
</body>
</html>
""".trimIndent()
}
}

private val client = OkHttpClient()

suspend fun isYoutubeShortVideo(videoId: String): Boolean =
withContext(Dispatchers.IO) {
val url = "https://www.youtube.com/watch?v=$videoId"

val request = Request.Builder().url(url).build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) return@withContext false

val body = response.body?.string() ?: return@withContext false

val shortsPattern = Regex("""href=["'](https://www\.youtube\.com/shorts/[^"']+)["']""")
val match = shortsPattern.find(body)

return@withContext match != null
}
}