mirror of
https://github.com/jellyfin/jellyfin-android.git
synced 2026-10-26 16:45:26 +00:00
Decouple NativePlayer from WebViewFragment
This commit is contained in:
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()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user