mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-07-31 16:49:28 +00:00
Cleanup added logs
This commit is contained in:
parent
a0af6ab07e
commit
cf2b7459f9
3 changed files with 7 additions and 372 deletions
|
|
@ -256,45 +256,6 @@ internal fun PlayerScreenRuntime.RenderPlayerRuntimeUi() {
|
|||
openingMessage = p2pInitialLoadingMessage,
|
||||
openingProgress = p2pInitialLoadingProgress,
|
||||
)
|
||||
val desktopControlsReadinessSignature = listOf(
|
||||
playerSurfaceSourceUrl != null,
|
||||
title.isNotBlank(),
|
||||
episodeText.isNotBlank(),
|
||||
activeStreamTitle.isNotBlank(),
|
||||
activeProviderName.isNotBlank(),
|
||||
openingOverlayWanted,
|
||||
playbackSnapshot.isLoading,
|
||||
initialLoadCompleted,
|
||||
errorMessage != null,
|
||||
background != null || poster != null,
|
||||
logo != null,
|
||||
p2pInitialLoadingMessage != null,
|
||||
p2pInitialLoadingProgress != null,
|
||||
).joinToString("|")
|
||||
LaunchedEffect(isDesktop, desktopControlsReadinessSignature) {
|
||||
if (!isDesktop) return@LaunchedEffect
|
||||
println(
|
||||
"[NuvioDesktopPlayerHandoff] compose controls " +
|
||||
"sourceReady=${playerSurfaceSourceUrl != null} " +
|
||||
"titleReady=${title.isNotBlank()} titleLen=${title.length} " +
|
||||
"episodeReady=${episodeText.isNotBlank()} " +
|
||||
"streamReady=${activeStreamTitle.isNotBlank()} streamLen=${activeStreamTitle.length} " +
|
||||
"providerReady=${activeProviderName.isNotBlank()} providerLen=${activeProviderName.length} " +
|
||||
"openingWanted=$openingOverlayWanted nativeLoading=${playbackSnapshot.isLoading} " +
|
||||
"initialLoadCompleted=$initialLoadCompleted error=${errorMessage != null} " +
|
||||
"artwork=${background != null || poster != null} logo=${logo != null} " +
|
||||
"p2pMessage=${p2pInitialLoadingMessage != null} p2pProgress=${p2pInitialLoadingProgress != null}",
|
||||
)
|
||||
}
|
||||
LaunchedEffect(isDesktop, playerSurfaceSourceUrl) {
|
||||
if (isDesktop) {
|
||||
println(
|
||||
"[NuvioDesktopPlayerHandoff] surface source " +
|
||||
"ready=${playerSurfaceSourceUrl != null} " +
|
||||
"mode=${if (isP2pPlaybackActive) "p2p" else "direct"}",
|
||||
)
|
||||
}
|
||||
}
|
||||
val gestureCallbacks = rememberSurfaceGestureCallbacks()
|
||||
|
||||
Box(
|
||||
|
|
@ -349,34 +310,10 @@ internal fun PlayerScreenRuntime.RenderPlayerRuntimeUi() {
|
|||
true
|
||||
},
|
||||
onControllerReady = { controller ->
|
||||
if (isDesktop) {
|
||||
println(
|
||||
"[NuvioDesktopPlayerHandoff] controller ready " +
|
||||
"titleReady=${title.isNotBlank()} streamReady=${activeStreamTitle.isNotBlank()}",
|
||||
)
|
||||
}
|
||||
playerController = controller
|
||||
playerControllerSourceUrl = activeSourceUrl
|
||||
},
|
||||
onSnapshot = { snapshot ->
|
||||
val previousSnapshot = playbackSnapshot
|
||||
if (
|
||||
isDesktop &&
|
||||
(
|
||||
previousSnapshot.isLoading != snapshot.isLoading ||
|
||||
previousSnapshot.isPlaying != snapshot.isPlaying ||
|
||||
(previousSnapshot.durationMs <= 0L && snapshot.durationMs > 0L) ||
|
||||
previousSnapshot.isEnded != snapshot.isEnded
|
||||
)
|
||||
) {
|
||||
println(
|
||||
"[NuvioDesktopPlayerHandoff] snapshot " +
|
||||
"loading=${snapshot.isLoading} wasLoading=${previousSnapshot.isLoading} " +
|
||||
"playing=${snapshot.isPlaying} durationMs=${snapshot.durationMs} " +
|
||||
"positionMs=${snapshot.positionMs} ended=${snapshot.isEnded} " +
|
||||
"initialLoadCompletedBefore=$initialLoadCompleted",
|
||||
)
|
||||
}
|
||||
playbackSnapshot = snapshot
|
||||
if (!snapshot.isLoading) initialLoadCompleted = true
|
||||
if (snapshot.isEnded) {
|
||||
|
|
@ -549,17 +486,14 @@ private fun PlayerScreenRuntime.handlePlayerControlsAction(action: PlayerControl
|
|||
args.onBack()
|
||||
}
|
||||
PlayerControlsAction.TogglePlayback -> {
|
||||
println("[NuvioPlayerControls] action toggle route=native-fallback")
|
||||
prepareTogglePlaybackForNativeFallback()
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.SeekBack -> {
|
||||
println("[NuvioPlayerControls] action seekBack route=native-fallback")
|
||||
prepareSeekByForNativeFallback(-10_000L)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.SeekForward -> {
|
||||
println("[NuvioPlayerControls] action seekForward route=native-fallback")
|
||||
prepareSeekByForNativeFallback(10_000L)
|
||||
return false
|
||||
}
|
||||
|
|
@ -574,7 +508,6 @@ private fun PlayerScreenRuntime.handlePlayerControlsAction(action: PlayerControl
|
|||
showAudioModal = true
|
||||
}
|
||||
PlayerControlsAction.Sources -> {
|
||||
println("[NuvioPlayerControls] action sources")
|
||||
prepareSourcesForPlayerControls()
|
||||
}
|
||||
PlayerControlsAction.Episodes -> {
|
||||
|
|
@ -594,12 +527,10 @@ private fun PlayerScreenRuntime.handlePlayerControlsAction(action: PlayerControl
|
|||
}
|
||||
}
|
||||
PlayerControlsAction.DoubleTapSeekBack -> {
|
||||
println("[NuvioPlayerControls] action doubleTapSeekBack route=native-fallback")
|
||||
prepareDoubleTapSeekForNativeFallback(PlayerSeekDirection.Backward)
|
||||
return false
|
||||
}
|
||||
PlayerControlsAction.DoubleTapSeekForward -> {
|
||||
println("[NuvioPlayerControls] action doubleTapSeekForward route=native-fallback")
|
||||
prepareDoubleTapSeekForNativeFallback(PlayerSeekDirection.Forward)
|
||||
return false
|
||||
}
|
||||
|
|
@ -610,15 +541,10 @@ private fun PlayerScreenRuntime.handlePlayerControlsAction(action: PlayerControl
|
|||
private fun PlayerScreenRuntime.handlePlayerControlsEvent(type: String, value: Double): Boolean {
|
||||
when (type) {
|
||||
"reloadSources" -> {
|
||||
println("[NuvioPlayerControls] event reloadSources")
|
||||
prepareSourcesForPlayerControls(forceRefresh = true)
|
||||
}
|
||||
"selectSource" -> {
|
||||
val streams = sourceStreamsState.groups.flatMap { it.streams }
|
||||
println(
|
||||
"[NuvioPlayerControls] event selectSource index=${value.toInt()} " +
|
||||
"available=${streams.size} ${sourceStreamsState.playerControlsStreamsSummary()}",
|
||||
)
|
||||
val stream = streams.getOrNull(value.toInt()) ?: return true
|
||||
if (requestP2pConsentForPlayerControls(stream = stream, episode = null)) return true
|
||||
switchToSource(stream)
|
||||
|
|
@ -780,18 +706,9 @@ private fun PlayerScreenRuntime.enableP2pForPlayerControls() {
|
|||
private fun PlayerScreenRuntime.prepareSourcesForPlayerControls(forceRefresh: Boolean = false) {
|
||||
val vid = activeVideoId
|
||||
if (vid == null) {
|
||||
println(
|
||||
"[NuvioPlayerControls] loadSources ignored reason=no-active-video " +
|
||||
"type=${contentType ?: parentMetaType} parent=$parentMetaId force=$forceRefresh",
|
||||
)
|
||||
return
|
||||
}
|
||||
val requestType = contentType ?: parentMetaType
|
||||
println(
|
||||
"[NuvioPlayerControls] loadSources request type=$requestType id=$vid " +
|
||||
"season=$activeSeasonNumber episode=$activeEpisodeNumber force=$forceRefresh " +
|
||||
"before=${sourceStreamsState.playerControlsStreamsSummary()}",
|
||||
)
|
||||
PlayerStreamsRepository.loadSources(
|
||||
type = requestType,
|
||||
videoId = vid,
|
||||
|
|
@ -824,14 +741,6 @@ private fun PlayerScreenRuntime.requestEpisodeStreamsForPlayerControls(
|
|||
episodeStreamsPanelState = EpisodeStreamsPanelState(showStreams = true, selectedEpisode = episode)
|
||||
}
|
||||
|
||||
private fun com.nuvio.app.features.streams.StreamsUiState.playerControlsStreamsSummary(): String {
|
||||
val streams = groups.sumOf { it.streams.size }
|
||||
val loadingGroups = groups.count { it.isLoading }
|
||||
val errorGroups = groups.count { !it.error.isNullOrBlank() }
|
||||
return "groups=${groups.size} streams=$streams isAnyLoading=$isAnyLoading " +
|
||||
"loadingGroups=$loadingGroups errorGroups=$errorGroups empty=${emptyStateReason ?: "none"}"
|
||||
}
|
||||
|
||||
private fun PlayerScreenRuntime.submitIntroFromPlayerControls() {
|
||||
if (isSubmitIntroSubmitting) return
|
||||
val imdbId = activeSubmitIntroImdbId()
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ internal class NativePlayerController(
|
|||
private var pendingSource: PendingSource? = null
|
||||
private var controlsState = PlayerControlsState()
|
||||
private var lastSentControlsStructureKey: PlayerControlsState? = null
|
||||
private var lastSourceControlsDiagnostics: String? = null
|
||||
private var lastPlayerControlsDiagnostics: String? = null
|
||||
private var onAction: (PlayerControlsAction) -> Boolean = { false }
|
||||
private var onEvent: (String, Double) -> Boolean = { _, _ -> false }
|
||||
private var onScrubChange: (Long) -> Boolean = { false }
|
||||
|
|
@ -57,11 +55,6 @@ internal class NativePlayerController(
|
|||
initialPositionMs: Long,
|
||||
onError: (String?) -> Unit,
|
||||
) {
|
||||
println(
|
||||
"[NuvioDesktopControls] attach requested " +
|
||||
"source=${sourceUrl.redactedPlaybackSourceForLog()} " +
|
||||
"headers=${sourceHeaders.size} playWhenReady=$playWhenReady initialPositionMs=$initialPositionMs",
|
||||
)
|
||||
val pending = PendingSource(
|
||||
sourceUrl = sourceUrl,
|
||||
headerLines = sourceHeaders.toHeaderLines(),
|
||||
|
|
@ -80,19 +73,10 @@ internal class NativePlayerController(
|
|||
val pending = pendingSource ?: return
|
||||
SwingUtilities.invokeLater {
|
||||
if (!host.isDisplayable) {
|
||||
println(
|
||||
"[NuvioDesktopControls] attach pending " +
|
||||
"hostDisplayable=false source=${pending.sourceUrl.redactedPlaybackSourceForLog()}",
|
||||
)
|
||||
return@invokeLater
|
||||
}
|
||||
dispose()
|
||||
runCatching {
|
||||
println(
|
||||
"[NuvioDesktopControls] create native player " +
|
||||
"source=${pending.sourceUrl.redactedPlaybackSourceForLog()} " +
|
||||
"headers=${pending.headerLines.size} initialPositionMs=${pending.initialPositionMs}",
|
||||
)
|
||||
val hostViewPtr = AwtNativeViewResolver.resolveNativeViewPointer(host)
|
||||
handle = NativePlayerBridge.create(
|
||||
hostViewPtr = hostViewPtr,
|
||||
|
|
@ -104,16 +88,8 @@ internal class NativePlayerController(
|
|||
eventSink = eventSink,
|
||||
)
|
||||
if (handle == 0L) error("Native player did not return a handle.")
|
||||
println(
|
||||
"[NuvioDesktopControls] create native player success " +
|
||||
"handleReady=true source=${pending.sourceUrl.redactedPlaybackSourceForLog()}",
|
||||
)
|
||||
updateControls(controlsState)
|
||||
}.onFailure { error ->
|
||||
println(
|
||||
"[NuvioDesktopControls] create native player failed " +
|
||||
"source=${pending.sourceUrl.redactedPlaybackSourceForLog()} error=${error.message}",
|
||||
)
|
||||
pending.onError(error.message)
|
||||
}
|
||||
}
|
||||
|
|
@ -135,29 +111,10 @@ internal class NativePlayerController(
|
|||
controlsState = state
|
||||
val currentHandle = handle
|
||||
val structureKey = state.nativeControlsStructureKey()
|
||||
val willSend = currentHandle != 0L && structureKey != lastSentControlsStructureKey
|
||||
val sourceDiagnostics = state.sourceControlsDiagnostics()
|
||||
if (sourceDiagnostics != lastSourceControlsDiagnostics) {
|
||||
println("[NuvioDesktopControls] state handleReady=${currentHandle != 0L} willSend=$willSend $sourceDiagnostics")
|
||||
lastSourceControlsDiagnostics = sourceDiagnostics
|
||||
}
|
||||
val playerDiagnostics = state.playerControlsDiagnostics()
|
||||
if (playerDiagnostics != lastPlayerControlsDiagnostics) {
|
||||
println(
|
||||
"[NuvioDesktopControls] controls handleReady=${currentHandle != 0L} " +
|
||||
"willSend=$willSend changed=${structureKey != lastSentControlsStructureKey} $playerDiagnostics",
|
||||
)
|
||||
lastPlayerControlsDiagnostics = playerDiagnostics
|
||||
}
|
||||
val current = currentHandle.takeIf { it != 0L } ?: return
|
||||
if (structureKey == lastSentControlsStructureKey) return
|
||||
lastSentControlsStructureKey = structureKey
|
||||
val controlsJson = state.toControlsJson()
|
||||
println(
|
||||
"[NuvioDesktopControls] controls send " +
|
||||
"jsonBytes=${controlsJson.length} $playerDiagnostics",
|
||||
)
|
||||
NativePlayerBridge.updateControls(current, controlsJson)
|
||||
NativePlayerBridge.updateControls(current, state.toControlsJson())
|
||||
}
|
||||
|
||||
fun setResizeMode(mode: PlayerResizeMode) {
|
||||
|
|
@ -174,10 +131,6 @@ internal class NativePlayerController(
|
|||
}
|
||||
|
||||
private fun handlePlayerEvent(type: String, value: Double) {
|
||||
val shouldLog = type.isControlsDiagnosticEvent()
|
||||
if (shouldLog) {
|
||||
println("[NuvioDesktopControls] event received type=$type value=$value")
|
||||
}
|
||||
when (type) {
|
||||
"scrubChange" -> {
|
||||
if (!onScrubChange(value.toLong())) {
|
||||
|
|
@ -186,31 +139,16 @@ internal class NativePlayerController(
|
|||
}
|
||||
"scrubFinish" -> {
|
||||
val scrubHandled = onScrubFinished(value.toLong())
|
||||
if (shouldLog) {
|
||||
println(
|
||||
"[NuvioDesktopControls] event route type=$type " +
|
||||
"onScrubFinished=$scrubHandled fallback=${!scrubHandled}",
|
||||
)
|
||||
}
|
||||
if (!scrubHandled) {
|
||||
seekTo(value.toLong())
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val eventHandled = onEvent(type, value)
|
||||
if (shouldLog) {
|
||||
println("[NuvioDesktopControls] event route type=$type onEvent=$eventHandled")
|
||||
}
|
||||
if (eventHandled) return
|
||||
val action = type.toPlayerControlsAction()
|
||||
if (shouldLog) {
|
||||
println("[NuvioDesktopControls] event map type=$type action=${action ?: "none"}")
|
||||
}
|
||||
if (action == null) return
|
||||
val actionHandled = onAction(action)
|
||||
if (shouldLog) {
|
||||
println("[NuvioDesktopControls] event action=$action onAction=$actionHandled fallback=${!actionHandled}")
|
||||
}
|
||||
if (!actionHandled) {
|
||||
handleFallbackAction(action)
|
||||
}
|
||||
|
|
@ -227,16 +165,9 @@ internal class NativePlayerController(
|
|||
when (action) {
|
||||
PlayerControlsAction.TogglePlayback -> {
|
||||
val current = handle
|
||||
if (current == 0L) {
|
||||
println("[NuvioDesktopControls] fallback direct action=$action handleReady=false")
|
||||
return
|
||||
}
|
||||
if (current == 0L) return
|
||||
val isEnded = NativePlayerBridge.isEnded(current)
|
||||
val isPaused = NativePlayerBridge.isPaused(current)
|
||||
println(
|
||||
"[NuvioDesktopControls] fallback direct action=$action " +
|
||||
"handleReady=true ended=$isEnded paused=$isPaused",
|
||||
)
|
||||
if (isEnded) {
|
||||
NativePlayerBridge.seekTo(current, 0L)
|
||||
NativePlayerBridge.setPaused(current, false)
|
||||
|
|
@ -244,21 +175,17 @@ internal class NativePlayerController(
|
|||
NativePlayerBridge.setPaused(current, !isPaused)
|
||||
}
|
||||
}
|
||||
PlayerControlsAction.SeekBack -> fallbackSeekBy(action, -10_000L)
|
||||
PlayerControlsAction.SeekForward -> fallbackSeekBy(action, 10_000L)
|
||||
PlayerControlsAction.DoubleTapSeekBack -> fallbackSeekBy(action, -10_000L)
|
||||
PlayerControlsAction.DoubleTapSeekForward -> fallbackSeekBy(action, 10_000L)
|
||||
PlayerControlsAction.SeekBack -> fallbackSeekBy(-10_000L)
|
||||
PlayerControlsAction.SeekForward -> fallbackSeekBy(10_000L)
|
||||
PlayerControlsAction.DoubleTapSeekBack -> fallbackSeekBy(-10_000L)
|
||||
PlayerControlsAction.DoubleTapSeekForward -> fallbackSeekBy(10_000L)
|
||||
PlayerControlsAction.Speed -> cycleFallbackSpeed()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun fallbackSeekBy(action: PlayerControlsAction, offsetMs: Long) {
|
||||
private fun fallbackSeekBy(offsetMs: Long) {
|
||||
val current = handle
|
||||
println(
|
||||
"[NuvioDesktopControls] fallback direct action=$action " +
|
||||
"handleReady=${current != 0L} offsetMs=$offsetMs",
|
||||
)
|
||||
if (current != 0L) {
|
||||
NativePlayerBridge.seekBy(current, offsetMs)
|
||||
}
|
||||
|
|
@ -521,25 +448,6 @@ private fun String.toPlayerControlsAction(): PlayerControlsAction? =
|
|||
else -> null
|
||||
}
|
||||
|
||||
private fun String.isControlsDiagnosticEvent(): Boolean =
|
||||
when (this) {
|
||||
"toggle",
|
||||
"seekBack",
|
||||
"seekForward",
|
||||
"doubleTapSeekBack",
|
||||
"doubleTapSeekForward",
|
||||
"scrubFinish",
|
||||
"sources",
|
||||
"reloadSources",
|
||||
"selectSource",
|
||||
"episodes",
|
||||
"reloadEpisodeStreams",
|
||||
"selectEpisode",
|
||||
"selectEpisodeStream",
|
||||
"backToEpisodes" -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun PlayerControlsState.toControlsJson(): String =
|
||||
buildString {
|
||||
append('{')
|
||||
|
|
@ -781,46 +689,6 @@ private fun PlayerControlsState.nativeControlsStructureKey(): PlayerControlsStat
|
|||
positionMs = 0L,
|
||||
)
|
||||
|
||||
private fun PlayerControlsState.sourceControlsDiagnostics(): String {
|
||||
val loadingFilters = sourceFilters.count { it.isLoading }
|
||||
val errorFilters = sourceFilters.count { it.hasError }
|
||||
val currentItems = sourceItems.count { it.isCurrent }
|
||||
val disabledItems = sourceItems.count { !it.isEnabled }
|
||||
val firstItem = sourceItems.firstOrNull()?.let { item ->
|
||||
"${item.addonName}:${item.label}".replace('\n', ' ').take(96)
|
||||
} ?: "none"
|
||||
return "sources(show=$showSources loading=$sourceIsLoading filters=${sourceFilters.size} " +
|
||||
"filterLoading=$loadingFilters filterErrors=$errorFilters items=${sourceItems.size} " +
|
||||
"current=$currentItems disabled=$disabledItems first=$firstItem)"
|
||||
}
|
||||
|
||||
private fun PlayerControlsState.playerControlsDiagnostics(): String {
|
||||
val openingProgressLabel = openingProgress?.let { value ->
|
||||
(value.coerceIn(0f, 1f) * 100).toInt().toString() + "%"
|
||||
} ?: "none"
|
||||
return "metadata(title=${title.isNotBlank()}:${title.length} " +
|
||||
"episode=${episodeText.isNotBlank()}:${episodeText.length} " +
|
||||
"stream=${streamTitle.isNotBlank()}:${streamTitle.length} " +
|
||||
"provider=${providerName.isNotBlank()}:${providerName.length}) " +
|
||||
"opening(wanted=$showOpeningOverlay artwork=${!openingArtwork.isNullOrBlank()} " +
|
||||
"logo=${!openingLogo.isNullOrBlank()} title=${openingTitle.isNotBlank()}:${openingTitle.length} " +
|
||||
"message=${!openingMessage.isNullOrBlank()} progress=$openingProgressLabel) " +
|
||||
"playback(loading=$isLoading playing=$isPlaying controlsVisible=$controlsVisible locked=$isLocked)"
|
||||
}
|
||||
|
||||
private fun String.redactedPlaybackSourceForLog(): String {
|
||||
val schemeEnd = indexOf("://")
|
||||
if (schemeEnd < 0) return "opaque"
|
||||
val scheme = substring(0, schemeEnd)
|
||||
if (scheme == "file") return "file://<local>"
|
||||
val host = substring(schemeEnd + 3)
|
||||
.substringBefore('/')
|
||||
.substringBefore('?')
|
||||
.takeIf { it.isNotBlank() }
|
||||
?: "<host>"
|
||||
return "$scheme://$host/<redacted>"
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendJsonField(name: String, value: String) {
|
||||
append('"').append(name).append("\":")
|
||||
append(value.toJsonString())
|
||||
|
|
|
|||
|
|
@ -2032,50 +2032,13 @@
|
|||
endTime: "00:00",
|
||||
status: "",
|
||||
};
|
||||
let lastSourceControlsDiagnostic = "";
|
||||
let lastMetadataDiagnostic = "";
|
||||
let lastOpeningDiagnostic = "";
|
||||
let lastNativeUpdateDiagnostic = "";
|
||||
let lastControlsUpdateDiagnostic = "";
|
||||
let playerNativeUpdateCount = 0;
|
||||
let playerControlsUpdateCount = 0;
|
||||
let hasReceivedPlayerControls = false;
|
||||
const prefersReducedMotion = window.matchMedia &&
|
||||
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
const modalTransitionMs = prefersReducedMotion ? 1 : 240;
|
||||
|
||||
const diagnosticCommands = new Set([
|
||||
"toggle",
|
||||
"seekBack",
|
||||
"seekForward",
|
||||
"doubleTapSeekBack",
|
||||
"doubleTapSeekForward",
|
||||
"scrubFinish",
|
||||
"sources",
|
||||
"reloadSources",
|
||||
"selectSource",
|
||||
"episodes",
|
||||
"reloadEpisodeStreams",
|
||||
"selectEpisode",
|
||||
"selectEpisodeStream",
|
||||
"backToEpisodes",
|
||||
]);
|
||||
|
||||
const postDiagnostic = message => {
|
||||
const bridge = window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.player;
|
||||
if (!bridge) return;
|
||||
try {
|
||||
bridge.postMessage({ type: "diagnostic", value: 0, message });
|
||||
} catch (_) {
|
||||
// Diagnostics must never break controls.
|
||||
}
|
||||
};
|
||||
|
||||
const send = (type, value = 0) => {
|
||||
const bridge = window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.player;
|
||||
if (diagnosticCommands.has(type)) {
|
||||
postDiagnostic(`event type=${type} value=${value} activeModal=${activeModal || "none"}`);
|
||||
}
|
||||
if (bridge) bridge.postMessage({ type, value });
|
||||
};
|
||||
|
||||
|
|
@ -2124,33 +2087,6 @@
|
|||
return Number.isFinite(progress) ? Math.max(0, Math.min(1, progress)) : null;
|
||||
};
|
||||
|
||||
const booleanFlag = value => Boolean(value) ? "1" : "0";
|
||||
|
||||
const textReadiness = text => {
|
||||
const value = String(text || "");
|
||||
return `${booleanFlag(value.trim())}:${value.length}`;
|
||||
};
|
||||
|
||||
const progressReadiness = progress =>
|
||||
progress === null ? "none" : `${Math.round(progress * 100)}%`;
|
||||
|
||||
const controlsReadinessDiagnostic = () => {
|
||||
const progress = normalizedOpeningProgress();
|
||||
return [
|
||||
`title=${textReadiness(state.title)}`,
|
||||
`episode=${textReadiness(state.episodeText)}`,
|
||||
`stream=${textReadiness(state.streamTitle)}`,
|
||||
`provider=${textReadiness(state.providerName)}`,
|
||||
`openingWanted=${booleanFlag(state.showOpeningOverlay)}`,
|
||||
`nativeLoading=${booleanFlag(state.isLoading)}`,
|
||||
`artwork=${booleanFlag(state.openingArtwork)}`,
|
||||
`logo=${booleanFlag(state.openingLogo)}`,
|
||||
`openingTitle=${textReadiness(state.openingTitle)}`,
|
||||
`message=${textReadiness(state.openingMessage)}`,
|
||||
`progress=${progressReadiness(progress)}`,
|
||||
].join(" ");
|
||||
};
|
||||
|
||||
const rangePositionMs = () => {
|
||||
const durationMs = Math.max(0, Number(state.durationMs) || 0);
|
||||
return durationMs > 0 ? Math.round(durationMs * Number(seek.value) / 1000) : 0;
|
||||
|
|
@ -2559,27 +2495,6 @@
|
|||
container.appendChild(row);
|
||||
};
|
||||
|
||||
const sourceControlsDiagnostic = controlsState => {
|
||||
const filters = normalizeItems(controlsState.sourceFilters);
|
||||
const items = normalizeItems(controlsState.sourceItems);
|
||||
const loadingFilters = filters.filter(filter => Boolean(filter.isLoading)).length;
|
||||
const errorFilters = filters.filter(filter => Boolean(filter.hasError)).length;
|
||||
const currentItems = items.filter(item => Boolean(item.isCurrent)).length;
|
||||
const disabledItems = items.filter(item => item.isEnabled === false).length;
|
||||
return [
|
||||
`activeModal=${activeModal || "none"}`,
|
||||
`showSources=${Boolean(controlsState.showSources)}`,
|
||||
`sourceLoading=${Boolean(controlsState.sourceIsLoading)}`,
|
||||
`filters=${filters.length}`,
|
||||
`filterLoading=${loadingFilters}`,
|
||||
`filterErrors=${errorFilters}`,
|
||||
`items=${items.length}`,
|
||||
`current=${currentItems}`,
|
||||
`disabled=${disabledItems}`,
|
||||
`sourceFilter=${sourceFilterId || "all"}`,
|
||||
].join(" ");
|
||||
};
|
||||
|
||||
const renderSourceModal = () => {
|
||||
sourcePanelTitle.textContent = state.sourcesPanelTitle || "Sources";
|
||||
sourceReloadButton.textContent = state.reloadLabel || "Reload";
|
||||
|
|
@ -2600,11 +2515,6 @@
|
|||
items = items.filter(item => String(item.filterId || "") === sourceFilterId);
|
||||
}
|
||||
if (items.length === 0) {
|
||||
postDiagnostic(
|
||||
`render sources empty loading=${Boolean(state.sourceIsLoading)} ` +
|
||||
`rawItems=${normalizeItems(state.sourceItems).length} filters=${filters.length} ` +
|
||||
`sourceFilter=${sourceFilterId || "all"}`,
|
||||
);
|
||||
appendEmptyTrackState(
|
||||
sourceList,
|
||||
state.sourceIsLoading ? "Loading streams..." : (state.noStreamsLabel || "No streams found"),
|
||||
|
|
@ -2824,21 +2734,6 @@
|
|||
const titleText = String(state.openingTitle || state.title || "").trim();
|
||||
const messageText = String(state.openingMessage || "").trim();
|
||||
const showHorizontalProgress = hasProgress && !logoUrl;
|
||||
const openingDiagnostic = [
|
||||
`visible=${booleanFlag(showOpening)}`,
|
||||
`wanted=${booleanFlag(wantsOpening)}`,
|
||||
`bootstrap=${booleanFlag(openingBootstrap)}`,
|
||||
`nativeLoading=${booleanFlag(state.isLoading)}`,
|
||||
`artwork=${booleanFlag(artworkUrl)}`,
|
||||
`logo=${booleanFlag(logoUrl)}`,
|
||||
`title=${textReadiness(titleText)}`,
|
||||
`message=${textReadiness(messageText)}`,
|
||||
`progress=${progressReadiness(progress)}`,
|
||||
].join(" ");
|
||||
if (openingDiagnostic !== lastOpeningDiagnostic) {
|
||||
lastOpeningDiagnostic = openingDiagnostic;
|
||||
postDiagnostic(`opening ${openingDiagnostic}`);
|
||||
}
|
||||
|
||||
root.classList.toggle("opening-active", showOpening);
|
||||
openingOverlay.classList.toggle("visible", showOpening);
|
||||
|
|
@ -2869,18 +2764,6 @@
|
|||
root.classList.toggle("locked-visible", Boolean(state.isLocked && state.lockedOverlayVisible));
|
||||
root.classList.toggle("chrome-hidden", Boolean(!state.controlsVisible && !(state.isLocked && state.lockedOverlayVisible)));
|
||||
const showOpening = renderOpeningOverlay();
|
||||
const metadataDiagnostic = [
|
||||
`title=${textReadiness(state.title)}`,
|
||||
`episode=${textReadiness(state.episodeText)}`,
|
||||
`stream=${textReadiness(state.streamTitle)}`,
|
||||
`provider=${textReadiness(state.providerName)}`,
|
||||
`controlsVisible=${booleanFlag(state.controlsVisible)}`,
|
||||
`locked=${booleanFlag(state.isLocked)}`,
|
||||
].join(" ");
|
||||
if (metadataDiagnostic !== lastMetadataDiagnostic) {
|
||||
lastMetadataDiagnostic = metadataDiagnostic;
|
||||
postDiagnostic(`metadata ${metadataDiagnostic}`);
|
||||
}
|
||||
|
||||
title.textContent = state.title || "";
|
||||
setText(episode, state.episodeText);
|
||||
|
|
@ -3232,25 +3115,12 @@
|
|||
});
|
||||
|
||||
window.playerUpdate = update => {
|
||||
playerNativeUpdateCount += 1;
|
||||
const durationMs = Math.round((Number(update.duration) || 0) * 1000);
|
||||
const positionMs = Math.round((Number(update.position) || 0) * 1000);
|
||||
const audioTracks = normalizeTracks(update.audioTracks);
|
||||
const subtitleTracks = normalizeTracks(update.subtitleTracks);
|
||||
const audioTracksChanged = trackListSignature(audioTracks) !== trackListSignature(state.audioTracks);
|
||||
const subtitleTracksChanged = trackListSignature(subtitleTracks) !== trackListSignature(state.subtitleTracks);
|
||||
const nativeUpdateDiagnostic = [
|
||||
`loading=${booleanFlag(update.loading || update.isLoading)}`,
|
||||
`paused=${booleanFlag(update.paused)}`,
|
||||
`durationReady=${booleanFlag(durationMs > 0)}`,
|
||||
`audioTracks=${audioTracks.length}`,
|
||||
`subtitleTracks=${subtitleTracks.length}`,
|
||||
`openingWanted=${booleanFlag(state.showOpeningOverlay)}`,
|
||||
].join(" ");
|
||||
if (nativeUpdateDiagnostic !== lastNativeUpdateDiagnostic) {
|
||||
lastNativeUpdateDiagnostic = nativeUpdateDiagnostic;
|
||||
postDiagnostic(`nativeUpdate #${playerNativeUpdateCount} ${nativeUpdateDiagnostic}`);
|
||||
}
|
||||
state = {
|
||||
...state,
|
||||
durationMs,
|
||||
|
|
@ -3268,20 +3138,9 @@
|
|||
};
|
||||
|
||||
window.playerControls = nextState => {
|
||||
playerControlsUpdateCount += 1;
|
||||
const previousCloseToken = Number(state.closeModalsToken) || 0;
|
||||
state = { ...state, ...nextState };
|
||||
hasReceivedPlayerControls = true;
|
||||
const controlsUpdateDiagnostic = controlsReadinessDiagnostic();
|
||||
if (controlsUpdateDiagnostic !== lastControlsUpdateDiagnostic) {
|
||||
lastControlsUpdateDiagnostic = controlsUpdateDiagnostic;
|
||||
postDiagnostic(`controlsUpdate #${playerControlsUpdateCount} ${controlsUpdateDiagnostic}`);
|
||||
}
|
||||
const sourceDiagnostic = sourceControlsDiagnostic(state);
|
||||
if (sourceDiagnostic !== lastSourceControlsDiagnostic) {
|
||||
lastSourceControlsDiagnostic = sourceDiagnostic;
|
||||
postDiagnostic(`state ${sourceDiagnostic}`);
|
||||
}
|
||||
const closeToken = Number(state.closeModalsToken) || 0;
|
||||
if (closeToken !== previousCloseToken) {
|
||||
closePlayerModal();
|
||||
|
|
@ -3332,7 +3191,6 @@
|
|||
setProgress(0, 0);
|
||||
focusShortcutRoot();
|
||||
render();
|
||||
postDiagnostic("controlsReady window.playerControls=1");
|
||||
send("controlsReady", 0);
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Reference in a new issue