From 9528f88f91c69688c9a72a7e9766c5e5ddc932e0 Mon Sep 17 00:00:00 2001 From: James Ding Date: Mon, 22 Jun 2026 08:46:55 -0700 Subject: [PATCH 1/5] fix: classify .m2t transport streams as video The frontend descriptor registers .m2t but MediaClassification.VIDEO_EXTENSIONS omitted it, so .m2t files classified as audio. This affects both the file icon and playback (PlayerConfig.isVideo drives the player UI via EditorMediaSource). Sync the set to the descriptor's video extensions: add m2t, drop the unused ts (.ts stays unregistered to avoid clobbering TypeScript files). --- .../kotlin/dev/twango/jetplay/media/MediaClassification.kt | 5 +++-- .../dev/twango/jetplay/media/MediaClassificationTest.kt | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/shared/src/main/kotlin/dev/twango/jetplay/media/MediaClassification.kt b/shared/src/main/kotlin/dev/twango/jetplay/media/MediaClassification.kt index dd8fecc4..0c140d97 100644 --- a/shared/src/main/kotlin/dev/twango/jetplay/media/MediaClassification.kt +++ b/shared/src/main/kotlin/dev/twango/jetplay/media/MediaClassification.kt @@ -2,7 +2,8 @@ package dev.twango.jetplay.media object MediaClassification { - // Keep in sync with the video extensions in plugin.xml. + // Video extensions registered by the media file type in the frontend descriptor. + // .ts is excluded to avoid clobbering TypeScript files. private val VIDEO_EXTENSIONS = setOf( "mp4", "m4v", @@ -13,9 +14,9 @@ object MediaClassification { "flv", "webm", "ogv", - "ts", "mts", "m2ts", + "m2t", "3gp", "ivf", ) diff --git a/shared/src/test/kotlin/dev/twango/jetplay/media/MediaClassificationTest.kt b/shared/src/test/kotlin/dev/twango/jetplay/media/MediaClassificationTest.kt index fae46249..c444757f 100644 --- a/shared/src/test/kotlin/dev/twango/jetplay/media/MediaClassificationTest.kt +++ b/shared/src/test/kotlin/dev/twango/jetplay/media/MediaClassificationTest.kt @@ -62,6 +62,13 @@ class MediaClassificationTest { assertFalse(MediaClassification.isVideo("opus")) } + @Test + fun transportStreamContainersClassifyAsVideo() { + assertTrue(MediaClassification.isVideo("mts")) + assertTrue(MediaClassification.isVideo("m2ts")) + assertTrue(MediaClassification.isVideo("m2t")) + } + @Test fun rawAudioExtensionsNeedTranscoding() { MediaClassification.rawAudioExtensions.forEach { From 3e1cd0ba7e36a965d3cb1b41612c6495e2427ef7 Mon Sep 17 00:00:00 2001 From: James Ding Date: Mon, 22 Jun 2026 08:46:55 -0700 Subject: [PATCH 2/5] feat: add audio/video file-type icon assets 16x16 monochrome SVGs (light #6C707E, dark #CED0D6) adapted from Lucide file-music and file-video-camera. Live in the frontend module so they ship client-side for Remote Dev split mode. --- frontend/src/main/resources/icons/audio.svg | 6 ++++++ frontend/src/main/resources/icons/audio_dark.svg | 6 ++++++ frontend/src/main/resources/icons/video.svg | 6 ++++++ frontend/src/main/resources/icons/video_dark.svg | 6 ++++++ 4 files changed, 24 insertions(+) create mode 100644 frontend/src/main/resources/icons/audio.svg create mode 100644 frontend/src/main/resources/icons/audio_dark.svg create mode 100644 frontend/src/main/resources/icons/video.svg create mode 100644 frontend/src/main/resources/icons/video_dark.svg diff --git a/frontend/src/main/resources/icons/audio.svg b/frontend/src/main/resources/icons/audio.svg new file mode 100644 index 00000000..dcd00fbc --- /dev/null +++ b/frontend/src/main/resources/icons/audio.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/src/main/resources/icons/audio_dark.svg b/frontend/src/main/resources/icons/audio_dark.svg new file mode 100644 index 00000000..6b9b5add --- /dev/null +++ b/frontend/src/main/resources/icons/audio_dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/src/main/resources/icons/video.svg b/frontend/src/main/resources/icons/video.svg new file mode 100644 index 00000000..bd8eca9c --- /dev/null +++ b/frontend/src/main/resources/icons/video.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/src/main/resources/icons/video_dark.svg b/frontend/src/main/resources/icons/video_dark.svg new file mode 100644 index 00000000..3e7ee9a5 --- /dev/null +++ b/frontend/src/main/resources/icons/video_dark.svg @@ -0,0 +1,6 @@ + + + + + + From 7df17c699f8606a2cb1ade471a6d513562b37d76 Mon Sep 17 00:00:00 2001 From: James Ding Date: Mon, 22 Jun 2026 08:46:55 -0700 Subject: [PATCH 3/5] feat: distinct audio/video icons via FileIconProvider Add a FileIconProvider that returns the audio or video icon per file based on MediaClassification.isVideo, keeping the single Media file type intact. Providers are consulted before FileType.getIcon, so this overrides the generic icon in the project tree, tabs, and navigation without touching the editor-selection paths. --- .../dev/twango/jetplay/editor/JetplayIcons.kt | 13 +++++++++++++ .../jetplay/editor/MediaFileIconProvider.kt | 19 +++++++++++++++++++ .../resources/dev.twango.jetplay.frontend.xml | 1 + .../editor/MediaFileIconResourcesTest.kt | 19 +++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 frontend/src/main/kotlin/dev/twango/jetplay/editor/JetplayIcons.kt create mode 100644 frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaFileIconProvider.kt create mode 100644 frontend/src/test/kotlin/dev/twango/jetplay/editor/MediaFileIconResourcesTest.kt diff --git a/frontend/src/main/kotlin/dev/twango/jetplay/editor/JetplayIcons.kt b/frontend/src/main/kotlin/dev/twango/jetplay/editor/JetplayIcons.kt new file mode 100644 index 00000000..66196123 --- /dev/null +++ b/frontend/src/main/kotlin/dev/twango/jetplay/editor/JetplayIcons.kt @@ -0,0 +1,13 @@ +package dev.twango.jetplay.editor + +import com.intellij.openapi.util.IconLoader +import javax.swing.Icon + +object JetplayIcons { + + @JvmField + val Audio: Icon = IconLoader.getIcon("/icons/audio.svg", JetplayIcons::class.java) + + @JvmField + val Video: Icon = IconLoader.getIcon("/icons/video.svg", JetplayIcons::class.java) +} diff --git a/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaFileIconProvider.kt b/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaFileIconProvider.kt new file mode 100644 index 00000000..d42cb3f7 --- /dev/null +++ b/frontend/src/main/kotlin/dev/twango/jetplay/editor/MediaFileIconProvider.kt @@ -0,0 +1,19 @@ +package dev.twango.jetplay.editor + +import com.intellij.ide.FileIconProvider +import com.intellij.openapi.project.DumbAware +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import dev.twango.jetplay.media.MediaClassification +import javax.swing.Icon + +class MediaFileIconProvider : + FileIconProvider, + DumbAware { + + override fun getIcon(file: VirtualFile, flags: Int, project: Project?): Icon? { + if (file.fileType != MediaFileType.INSTANCE) return null + val extension = file.extension ?: return null + return if (MediaClassification.isVideo(extension)) JetplayIcons.Video else JetplayIcons.Audio + } +} diff --git a/frontend/src/main/resources/dev.twango.jetplay.frontend.xml b/frontend/src/main/resources/dev.twango.jetplay.frontend.xml index ff48d7ae..2c9c10f9 100644 --- a/frontend/src/main/resources/dev.twango.jetplay.frontend.xml +++ b/frontend/src/main/resources/dev.twango.jetplay.frontend.xml @@ -8,6 +8,7 @@ implementationClass="dev.twango.jetplay.editor.MediaFileType" fieldName="INSTANCE" extensions="mp4;m4v;mkv;avi;mov;wmv;flv;webm;ogv;mts;m2ts;m2t;3gp;ivf;mp3;wav;ogg;oga;opus;m4a;aac;wma;aiff;aif;flac;ac3;eac3;caf;adts;amr;au;pcmu;ulaw;pcma;alaw;g722;gsm;sln"/> + diff --git a/frontend/src/test/kotlin/dev/twango/jetplay/editor/MediaFileIconResourcesTest.kt b/frontend/src/test/kotlin/dev/twango/jetplay/editor/MediaFileIconResourcesTest.kt new file mode 100644 index 00000000..c1a7120e --- /dev/null +++ b/frontend/src/test/kotlin/dev/twango/jetplay/editor/MediaFileIconResourcesTest.kt @@ -0,0 +1,19 @@ +package dev.twango.jetplay.editor + +import org.junit.Assert.assertNotNull +import org.junit.Test + +class MediaFileIconResourcesTest { + + @Test + fun audioAndVideoIconsArePresentInBothThemes() { + listOf( + "/icons/audio.svg", + "/icons/audio_dark.svg", + "/icons/video.svg", + "/icons/video_dark.svg", + ).forEach { path -> + assertNotNull("missing icon resource $path", javaClass.getResource(path)) + } + } +} From f12fbd74efc949f0b8aeb0fd7a74a613aa4516df Mon Sep 17 00:00:00 2001 From: James Ding Date: Mon, 22 Jun 2026 09:03:30 -0700 Subject: [PATCH 4/5] feat: use music and film glyphs for the audio/video icons Swap the file-shaped file-music/file-video-camera pair for the bolder music note and film strip so the type reads at a glance, and thin the stroke from 2.5 to Lucide's native 2.0. --- frontend/src/main/resources/icons/audio.svg | 9 ++++----- frontend/src/main/resources/icons/audio_dark.svg | 9 ++++----- frontend/src/main/resources/icons/video.svg | 14 +++++++++----- frontend/src/main/resources/icons/video_dark.svg | 14 +++++++++----- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/frontend/src/main/resources/icons/audio.svg b/frontend/src/main/resources/icons/audio.svg index dcd00fbc..fc937895 100644 --- a/frontend/src/main/resources/icons/audio.svg +++ b/frontend/src/main/resources/icons/audio.svg @@ -1,6 +1,5 @@ - - - - - + + + + diff --git a/frontend/src/main/resources/icons/audio_dark.svg b/frontend/src/main/resources/icons/audio_dark.svg index 6b9b5add..c8b7f8e7 100644 --- a/frontend/src/main/resources/icons/audio_dark.svg +++ b/frontend/src/main/resources/icons/audio_dark.svg @@ -1,6 +1,5 @@ - - - - - + + + + diff --git a/frontend/src/main/resources/icons/video.svg b/frontend/src/main/resources/icons/video.svg index bd8eca9c..5b290983 100644 --- a/frontend/src/main/resources/icons/video.svg +++ b/frontend/src/main/resources/icons/video.svg @@ -1,6 +1,10 @@ - - - - - + + + + + + + + + diff --git a/frontend/src/main/resources/icons/video_dark.svg b/frontend/src/main/resources/icons/video_dark.svg index 3e7ee9a5..7ffca897 100644 --- a/frontend/src/main/resources/icons/video_dark.svg +++ b/frontend/src/main/resources/icons/video_dark.svg @@ -1,6 +1,10 @@ - - - - - + + + + + + + + + From d7c6602f182277b68abc6e05156cac7d63e90fe1 Mon Sep 17 00:00:00 2001 From: James Ding Date: Mon, 22 Jun 2026 09:28:43 -0700 Subject: [PATCH 5/5] docs: attribute bundled Lucide icons (ISC/MIT) --- THIRD-PARTY-NOTICES.md | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 THIRD-PARTY-NOTICES.md diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md new file mode 100644 index 00000000..72bfa529 --- /dev/null +++ b/THIRD-PARTY-NOTICES.md @@ -0,0 +1,55 @@ +# Third-Party Notices + +This project bundles third-party assets, listed below with their licenses. + +## Lucide icons + +The audio and video file-type icons in `frontend/src/main/resources/icons/` +(`audio.svg`, `audio_dark.svg`, `video.svg`, `video_dark.svg`) are adapted from +[Lucide](https://lucide.dev) — the `music` and `film` icons, recolored and +resized for use in the IDE. + +`film` is covered by Lucide's ISC license. `music` is one of Lucide's +Feather-derived icons and is covered by the MIT license. Both notices follow. + +### ISC License + +``` +Copyright (c) 2026 Lucide Icons and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +``` + +### MIT License (for Feather-derived icons, including `music`) + +``` +Copyright (c) 2013-present Cole Bemis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +```