Merge the deduplication and dead-code removal pass

Consolidates duplicated logic behind shared implementations — paginated
grid tabs, focus chrome, cached remote stores, sheet selection columns,
the server artifact store and a test fixture layer — and removes code
that had become unreachable. Net reduction of about 5,500 lines with no
behaviour change.

Where a fix had landed separately in code that moved into a shared
helper, the fix was re-applied inside the helper rather than left behind
in the copy that went away.
This commit is contained in:
edde746
2026-07-26 19:41:23 +02:00
425 changed files with 12045 additions and 17543 deletions
@@ -77,6 +77,7 @@ import com.edde746.plezy.shared.FlutterOverlayHelper
import com.edde746.plezy.shared.FrameRateManager
import com.edde746.plezy.shared.MediaCodecQuery
import com.edde746.plezy.shared.PlayerSurfaceHost
import com.edde746.plezy.shared.SurfacePlayerCore
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicLong
import org.chromium.net.CronetEngine
@@ -102,7 +103,7 @@ interface ExoPlayerDelegate : com.edde746.plezy.shared.PlayerDelegate {
internal fun playbackMimeType(isLive: Boolean): String? = if (isLive) MimeTypes.APPLICATION_M3U8 else null
@OptIn(UnstableApi::class)
class ExoPlayerCore(private val activity: Activity) : Player.Listener {
class ExoPlayerCore(private val activity: Activity) : Player.Listener, SurfacePlayerCore {
companion object {
private const val TAG = "ExoPlayerCore"
@@ -3501,7 +3502,7 @@ class ExoPlayerCore(private val activity: Activity) : Player.Listener {
else -> null
}
fun setVisible(visible: Boolean) {
override fun setVisible(visible: Boolean) {
if (disposing) return
currentVisible = visible
activity.runOnUiThread {
@@ -3594,7 +3595,7 @@ class ExoPlayerCore(private val activity: Activity) : Player.Listener {
}
}
fun onPipModeChanged(isInPipMode: Boolean) {
override fun onPipModeChanged(isInPipMode: Boolean) {
if (disposing) return
activity.runOnUiThread {
if (disposing) return@runOnUiThread
@@ -3610,7 +3611,7 @@ class ExoPlayerCore(private val activity: Activity) : Player.Listener {
}
}
fun updateFrame() {
override fun updateFrame() {
if (disposing) return
activity.runOnUiThread {
if (disposing) return@runOnUiThread
@@ -3625,15 +3626,15 @@ class ExoPlayerCore(private val activity: Activity) : Player.Listener {
// Audio Focus
fun requestAudioFocus(): Boolean = audioFocusManager?.requestAudioFocus() ?: false
override fun requestAudioFocus(): Boolean = audioFocusManager?.requestAudioFocus() ?: false
fun abandonAudioFocus() {
override fun abandonAudioFocus() {
audioFocusManager?.abandonAudioFocus()
}
// Frame Rate Matching
fun setVideoFrameRate(
override fun setVideoFrameRate(
fps: Float,
videoDurationMs: Long,
extraDelayMs: Long,
@@ -3649,7 +3650,7 @@ class ExoPlayerCore(private val activity: Activity) : Player.Listener {
mgr.setVideoFrameRate(fps, videoDurationMs, extraDelayMs, videoWidth, videoHeight, onComplete)
}
fun clearVideoFrameRate() {
override fun clearVideoFrameRate() {
frameRateManager?.clearVideoFrameRate()
}
@@ -12,6 +12,7 @@ import com.edde746.plezy.shared.MpvContentUriResolver
import com.edde746.plezy.shared.PlayerChannelBinding
import com.edde746.plezy.shared.PlayerDelegate
import com.edde746.plezy.shared.ResolvedMpvUri
import com.edde746.plezy.shared.SurfacePlayerCore
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
@@ -46,6 +47,10 @@ class ExoPlayerPlugin :
private var activity: Activity? = null
private var activityBinding: ActivityPluginBinding? = null
/** Whichever core currently owns the surface; both expose [SurfacePlayerCore] identically. */
private val activeSurfaceCore: SurfacePlayerCore?
get() = if (usingMpvFallback) mpvCore else playerCore
// Every Dart observeProperty registration, kept so an ExoPlayer→MPV
// fallback can re-observe exactly what Dart asked for instead of
// maintaining a parallel hard-coded list.
@@ -951,20 +956,12 @@ class ExoPlayerPlugin :
return
}
if (usingMpvFallback) {
mpvCore?.setVisible(visible)
} else {
playerCore?.setVisible(visible)
}
activeSurfaceCore?.setVisible(visible)
result.success(null)
}
private fun handleUpdateFrame(result: MethodChannel.Result) {
if (usingMpvFallback) {
mpvCore?.updateFrame()
} else {
playerCore?.updateFrame()
}
activeSurfaceCore?.updateFrame()
result.success(null)
}
@@ -976,51 +973,31 @@ class ExoPlayerPlugin :
val videoHeight = call.argument<Number>("videoHeight")?.toInt() ?: 0
Log.d(TAG, "setVideoFrameRate: fps=$fps, duration=$duration, extraDelayMs=$extraDelayMs, video=${videoWidth}x$videoHeight")
val onComplete: (Boolean) -> Unit = { switched -> result.success(switched) }
if (usingMpvFallback) {
val core = mpvCore
if (core == null) {
result.success(false)
} else {
core.setVideoFrameRate(fps, duration, extraDelayMs, videoWidth, videoHeight, onComplete)
}
} else {
val core = playerCore
if (core == null) {
result.success(false)
} else {
core.setVideoFrameRate(fps, duration, extraDelayMs, videoWidth, videoHeight, onComplete)
}
val core = activeSurfaceCore
if (core == null) {
result.success(false)
return
}
core.setVideoFrameRate(fps, duration, extraDelayMs, videoWidth, videoHeight) { switched ->
result.success(switched)
}
}
private fun handleClearVideoFrameRate(result: MethodChannel.Result) {
Log.d(TAG, "clearVideoFrameRate")
if (usingMpvFallback) {
mpvCore?.clearVideoFrameRate()
} else {
playerCore?.clearVideoFrameRate()
}
activeSurfaceCore?.clearVideoFrameRate()
result.success(null)
}
private fun handleRequestAudioFocus(result: MethodChannel.Result) {
Log.d(TAG, "requestAudioFocus")
val granted = if (usingMpvFallback) {
mpvCore?.requestAudioFocus() ?: false
} else {
playerCore?.requestAudioFocus() ?: false
}
val granted = activeSurfaceCore?.requestAudioFocus() ?: false
result.success(granted)
}
private fun handleAbandonAudioFocus(result: MethodChannel.Result) {
Log.d(TAG, "abandonAudioFocus")
if (usingMpvFallback) {
mpvCore?.abandonAudioFocus()
} else {
playerCore?.abandonAudioFocus()
}
activeSurfaceCore?.abandonAudioFocus()
result.success(null)
}
@@ -1230,11 +1207,7 @@ class ExoPlayerPlugin :
fun onPipModeChanged(isInPipMode: Boolean) {
activity?.runOnUiThread {
if (usingMpvFallback) {
mpvCore?.onPipModeChanged(isInPipMode)
} else {
playerCore?.onPipModeChanged(isInPipMode)
}
activeSurfaceCore?.onPipModeChanged(isInPipMode)
}
}
@@ -19,6 +19,7 @@ import com.edde746.plezy.shared.AudioFocusManager
import com.edde746.plezy.shared.FrameRateManager
import com.edde746.plezy.shared.PlayerDelegate
import com.edde746.plezy.shared.PlayerSurfaceHost
import com.edde746.plezy.shared.SurfacePlayerCore
import dev.jdtech.mpv.*
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
@@ -40,7 +41,7 @@ class MpvPlayerCore private constructor(
private val audioOnly: Boolean,
private val propertyWriterOverride: (suspend (String, String) -> Unit)?,
initializedForTesting: Boolean
) : SurfaceHolder.Callback {
) : SurfaceHolder.Callback, SurfacePlayerCore {
constructor(context: Context, audioOnly: Boolean = false) : this(context, audioOnly, null, false)
internal constructor(
@@ -405,7 +406,7 @@ class MpvPlayerCore private constructor(
// Audio Focus
fun requestAudioFocus(): Boolean {
override fun requestAudioFocus(): Boolean {
val granted = audioFocusManager?.requestAudioFocus() ?: false
if (granted && pausedForAudioFocusLoss) {
resumeAfterAudioFocusGain("audio focus request granted")
@@ -413,7 +414,7 @@ class MpvPlayerCore private constructor(
return granted
}
fun abandonAudioFocus() {
override fun abandonAudioFocus() {
audioFocusManager?.abandonAudioFocus()
}
@@ -1096,7 +1097,7 @@ class MpvPlayerCore private constructor(
}
}
fun setVisible(visible: Boolean) {
override fun setVisible(visible: Boolean) {
// Audio-only: no render layer to show or hide — tolerated no-op.
if (audioOnly || disposing) return
runOnMain {
@@ -1121,11 +1122,11 @@ class MpvPlayerCore private constructor(
}
}
fun onPipModeChanged(isInPipMode: Boolean) {
override fun onPipModeChanged(isInPipMode: Boolean) {
// MPV handles aspect ratio internally via its own surface management
}
fun updateFrame() {
override fun updateFrame() {
// Audio-only: no surface to refresh — tolerated no-op.
if (audioOnly || disposing) return
runOnMain {
@@ -1160,7 +1161,7 @@ class MpvPlayerCore private constructor(
// Frame Rate Matching
fun setVideoFrameRate(
override fun setVideoFrameRate(
fps: Float,
videoDurationMs: Long,
extraDelayMs: Long,
@@ -1182,7 +1183,7 @@ class MpvPlayerCore private constructor(
}
}
fun clearVideoFrameRate() {
override fun clearVideoFrameRate() {
frameRateManager?.clearVideoFrameRate()
}
@@ -0,0 +1,27 @@
package com.edde746.plezy.shared
/**
* Surface and display concerns that the ExoPlayer and mpv cores implement
* identically, so a plugin holding either one dispatches without branching
* on which backend is active.
*
* Only backend-independent members belong here: playback control
* (play/seek/track selection) stays off this interface because mpv drives it
* through properties and commands where ExoPlayer uses direct method calls.
*/
interface SurfacePlayerCore {
fun setVisible(visible: Boolean)
fun updateFrame()
fun onPipModeChanged(isInPipMode: Boolean)
fun requestAudioFocus(): Boolean
fun abandonAudioFocus()
fun clearVideoFrameRate()
fun setVideoFrameRate(
fps: Float,
videoDurationMs: Long,
extraDelayMs: Long,
videoWidth: Int,
videoHeight: Int,
onComplete: (switched: Boolean) -> Unit
)
}