Decouple NativePlayer from WebViewFragment

This commit is contained in:
Maxr1998 authored and Niels van Velzen committed 2022-09-24 16:34:30 +02:00
1 parent cbd2bfd27e
commit d9d41db7b1
6 files changed
+31 -32

No files matched your search

@@ -19,6 +19,7 @@ import okhttp3.OkHttpClient
import org.chromium.net.CronetEngine
import org.chromium.net.CronetProvider
import org.jellyfin.mobile.MainViewModel
import org.jellyfin.mobile.bridge.NativePlayer
import org.jellyfin.mobile.events.ActivityEventHandler
import org.jellyfin.mobile.player.audio.car.LibraryBrowser
import org.jellyfin.mobile.player.deviceprofile.DeviceProfileBuilder
@@ -58,6 +59,9 @@ val applicationModule = module {
single { ActivityEventHandler(get()) }
single { WebappFunctionChannel() }
// Bridge interfaces
single { NativePlayer(get(), get(), get(named(PLAYER_EVENT_CHANNEL))) }
// ViewModels
viewModel { MainViewModel(get(), get()) }
@@ -3,20 +3,20 @@ package org.jellyfin.mobile.bridge
import android.webkit.JavascriptInterface
import kotlinx.coroutines.channels.Channel
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.app.PLAYER_EVENT_CHANNEL
import org.jellyfin.mobile.events.ActivityEvent
import org.jellyfin.mobile.events.ActivityEventHandler
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.player.interaction.PlayerEvent
import org.jellyfin.mobile.settings.VideoPlayerType
import org.jellyfin.mobile.utils.Constants
import org.json.JSONObject
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.qualifier.named
class NativePlayer(private val host: NativePlayerHost) : KoinComponent {
private val appPreferences: AppPreferences by inject()
private val playerEventChannel: Channel<PlayerEvent> by inject(named(PLAYER_EVENT_CHANNEL))
@Suppress("unused")
class NativePlayer(
private val appPreferences: AppPreferences,
private val activityEventHandler: ActivityEventHandler,
private val playerEventChannel: Channel<PlayerEvent>,
) {
@JavascriptInterface
fun isEnabled() = appPreferences.videoPlayerType == VideoPlayerType.EXO_PLAYER
@@ -24,7 +24,7 @@ class NativePlayer(private val host: NativePlayerHost) : KoinComponent {
@JavascriptInterface
fun loadPlayer(args: String) {
PlayOptions.fromJson(JSONObject(args))?.let { options ->
host.loadNativePlayer(options)
activityEventHandler.emit(ActivityEvent.LaunchNativePlayer(options))
}
}
@@ -1,7 +0,0 @@
package org.jellyfin.mobile.bridge
import org.jellyfin.mobile.player.interaction.PlayOptions
interface NativePlayerHost {
fun loadNativePlayer(playOptions: PlayOptions)
}
@@ -1,10 +1,12 @@
package org.jellyfin.mobile.events
import android.net.Uri
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.json.JSONArray
sealed class ActivityEvent {
class ChangeFullscreen(val isFullscreen: Boolean) : ActivityEvent()
class LaunchNativePlayer(val playOptions: PlayOptions) : ActivityEvent()
class OpenUrl(val uri: String) : ActivityEvent()
class DownloadFile(val uri: Uri, val title: String, val filename: String) : ActivityEvent()
class CastMessage(val action: String, val args: JSONArray) : ActivityEvent()
@@ -4,6 +4,8 @@ import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.pm.ActivityInfo
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.add
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
@@ -13,7 +15,9 @@ import kotlinx.coroutines.launch
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
import org.jellyfin.mobile.bridge.JavascriptCallback
import org.jellyfin.mobile.player.ui.PlayerFragment
import org.jellyfin.mobile.settings.SettingsFragment
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.extensions.addFragment
import org.jellyfin.mobile.utils.extensions.disableFullscreen
import org.jellyfin.mobile.utils.extensions.enableFullscreen
@@ -54,6 +58,15 @@ class ActivityEventHandler(
window.setBackgroundDrawableResource(R.color.theme_background)
}
}
is ActivityEvent.LaunchNativePlayer -> {
supportFragmentManager.beginTransaction().apply {
val args = Bundle().apply {
putParcelable(Constants.EXTRA_MEDIA_PLAY_OPTIONS, event.playOptions)
}
add<PlayerFragment>(R.id.fragment_container, args = args)
addToBackStack(null)
}.commit()
}
is ActivityEvent.OpenUrl -> {
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(event.uri))
@@ -17,7 +17,6 @@ import androidx.core.view.ViewCompat
import androidx.core.view.doOnNextLayout
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.add
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.webkit.WebViewAssetLoader.AssetsPathHandler
@@ -29,11 +28,8 @@ import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.bridge.ExternalPlayer
import org.jellyfin.mobile.bridge.NativeInterface
import org.jellyfin.mobile.bridge.NativePlayer
import org.jellyfin.mobile.bridge.NativePlayerHost
import org.jellyfin.mobile.data.entity.ServerEntity
import org.jellyfin.mobile.databinding.FragmentWebviewBinding
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.player.ui.PlayerFragment
import org.jellyfin.mobile.setup.ConnectFragment
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.FRAGMENT_WEB_VIEW_EXTRA_SERVER
@@ -50,12 +46,13 @@ import org.jellyfin.mobile.utils.requestNoBatteryOptimizations
import org.jellyfin.mobile.utils.runOnUiThread
import org.koin.android.ext.android.inject
class WebViewFragment : Fragment(), NativePlayerHost {
class WebViewFragment : Fragment() {
val appPreferences: AppPreferences by inject()
private val apiClientController: ApiClientController by inject()
private val webappFunctionChannel: WebappFunctionChannel by inject()
private lateinit var assetsPathHandler: AssetsPathHandler
private lateinit var jellyfinWebViewClient: JellyfinWebViewClient
private val nativePlayer: NativePlayer by inject()
private lateinit var externalPlayer: ExternalPlayer
lateinit var server: ServerEntity
@@ -178,7 +175,7 @@ class WebViewFragment : Fragment(), NativePlayerHost {
webChromeClient = LoggingWebChromeClient()
settings.applyDefault()
addJavascriptInterface(NativeInterface(requireContext()), "NativeInterface")
addJavascriptInterface(NativePlayer(this@WebViewFragment), "NativePlayer")
addJavascriptInterface(nativePlayer, "NativePlayer")
addJavascriptInterface(externalPlayer, "ExternalPlayer")
loadUrl(server.hostname)
@@ -250,14 +247,4 @@ class WebViewFragment : Fragment(), NativePlayerHost {
connected = false
onSelectServer(error = true)
}
override fun loadNativePlayer(playOptions: PlayOptions) = runOnUiThread {
parentFragmentManager.beginTransaction().apply {
val args = Bundle().apply {
putParcelable(Constants.EXTRA_MEDIA_PLAY_OPTIONS, playOptions)
}
add<PlayerFragment>(R.id.fragment_container, args = args)
addToBackStack(null)
}.commit()
}
}