From 6c92bae305e187ad6e341b33b4555c10aba0ee64 Mon Sep 17 00:00:00 2001 From: James Ding Date: Tue, 30 Jun 2026 22:00:17 -0700 Subject: [PATCH] fix(frontend): show media details for Remote Dev / Gateway files maybeSendMediaInfo short-circuited on source.isRemote, so no MediaInfo payload ever reached the player for a remote file. Without a payload hasMediaInfo stays false and the details disclosure chevron is never rendered. The probe runs host-side and resolves the file by id, exactly like the spectrogram, which already omits the guard, so remote files can be probed too. Gate on a new EditorMediaSource.canProbeMediaInfo that excludes only raw headerless codecs. --- .../kotlin/dev/twango/jetplay/editor/MediaLoader.kt | 3 +-- .../dev/twango/jetplay/media/EditorMediaSource.kt | 3 +++ .../twango/jetplay/media/EditorMediaSourceTest.kt | 13 +++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaLoader.kt b/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaLoader.kt index 37d4d070..5bfff62c 100644 --- a/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaLoader.kt +++ b/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaLoader.kt @@ -134,8 +134,7 @@ class MediaLoader( } private fun maybeSendMediaInfo() { - if (source.isRemote) return - if (source.extension.lowercase() in MediaClassification.rawAudioExtensions) return + if (!source.canProbeMediaInfo) return scope.launch { val info = MediaAccessor.getInstance().extractMediaInfo(fileId, projectId) if (info != null && !bridge.disposed) bridge.sendMediaInfo(info) diff --git a/frontend/src/main/kotlin/dev/twango/jetplay/media/EditorMediaSource.kt b/frontend/src/main/kotlin/dev/twango/jetplay/media/EditorMediaSource.kt index 4cea74f9..d3add6ad 100644 --- a/frontend/src/main/kotlin/dev/twango/jetplay/media/EditorMediaSource.kt +++ b/frontend/src/main/kotlin/dev/twango/jetplay/media/EditorMediaSource.kt @@ -12,6 +12,9 @@ class EditorMediaSource(val file: VirtualFile) { val needsTranscoding: Boolean = MediaClassification.needsTranscoding(extension) val isRemote: Boolean = file.fileSystem !is LocalFileSystem + // Header probing runs host-side, so remote files stay eligible; raw headerless codecs can't be probed. + val canProbeMediaInfo: Boolean = extension !in MediaClassification.rawAudioExtensions + /** Non-null only when the bytes are readable in this process. */ fun localFileOrNull(): File? = if (!isRemote) runCatching { file.toNioPath().toFile() }.getOrNull()?.takeIf { it.isFile } else null diff --git a/frontend/src/test/kotlin/dev/twango/jetplay/media/EditorMediaSourceTest.kt b/frontend/src/test/kotlin/dev/twango/jetplay/media/EditorMediaSourceTest.kt index 3f45f5e6..c78a50a8 100644 --- a/frontend/src/test/kotlin/dev/twango/jetplay/media/EditorMediaSourceTest.kt +++ b/frontend/src/test/kotlin/dev/twango/jetplay/media/EditorMediaSourceTest.kt @@ -1,6 +1,7 @@ package dev.twango.jetplay.media import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.testFramework.LightVirtualFile import com.intellij.testFramework.fixtures.BasePlatformTestCase import java.nio.file.Files @@ -38,4 +39,16 @@ class EditorMediaSourceTest : BasePlatformTestCase() { assertFalse(source.needsTranscoding) assertEquals("mp3", source.extension) } + + // A LightVirtualFile isn't backed by LocalFileSystem, standing in for a Remote Dev / Gateway file. + fun testRemoteFileStaysEligibleForMediaInfo() { + val remote = EditorMediaSource(LightVirtualFile("song.mp3")) + assertTrue("a non-LocalFileSystem file must read as remote", remote.isRemote) + assertTrue("media-info probing runs host-side, so a remote file must stay eligible", remote.canProbeMediaInfo) + } + + fun testRawAudioIsNotEligibleForMediaInfo() { + val raw = EditorMediaSource(LightVirtualFile("call.pcmu")) + assertFalse("headerless raw codecs can't be probed", raw.canProbeMediaInfo) + } }