1
0
Fork 0

feat(negotiation): comprehensive media conversion filter negotiation across graph, UI, and shell

- Prevent cross-category graph leakage (png -> txt -> docx) in ConversionGraph.FindBestPath and ReachableOutputs
- Distinguish Video and Audio in MediaConversionNegotiator (block mp3->gif, allow mp4->png frame extraction)
- Handle empty common output intersection in MainWindow without forcing .jpg fallback
- Expand PopularOutputs in ContextMenuRegistrar to support mp4, mp3, and xlsx
- Add comprehensive TDD unit tests (213 passing tests)
This commit is contained in:
Yun Chan 2026-09-03 18:47:45 +09:00
parent 07d7dfeb40
commit 28624c386e
7 changed files with 410 additions and 29 deletions

View file

@ -4,7 +4,7 @@ using Microsoft.Win32;
namespace Everything2Everything.App.Shell;
internal static class ContextMenuRegistrar
public static class ContextMenuRegistrar
{
private const string MainVerb = "Everything2Everything";
private const string MainLabel = "Everything2Everything으로 변환";
@ -25,8 +25,22 @@ internal static class ContextMenuRegistrar
(".gif", "GIF (.gif)", "10"),
(".tif", "TIFF (.tif)", "11"),
(".bmp", "BMP (.bmp)", "12"),
(".mp4", "MP4 (.mp4)", "13"),
(".mp3", "MP3 (.mp3)", "14"),
(".xlsx", "Excel (.xlsx)", "15"),
};
public static IReadOnlyList<(string Ext, string Label, string SortPrefix)> GetAvailableOutputs(ConversionEngine engine, string ext)
{
var outputs = engine.Providers.OutputsForInput(ext)
.Select(o => o.ToLowerInvariant())
.ToHashSet();
return PopularOutputs
.Where(p => outputs.Contains(p.Ext) && !string.Equals(p.Ext, ext, StringComparison.OrdinalIgnoreCase))
.ToList();
}
public static void Register(ConversionEngine engine)
{
var exe = GetAppExecutablePath();
@ -34,14 +48,7 @@ internal static class ContextMenuRegistrar
foreach (var ext in CollectInputExtensions(engine))
{
var outputs = engine.Providers.OutputsForInput(ext)
.Select(o => o.ToLowerInvariant())
.ToHashSet();
var availableOutputs = PopularOutputs
.Where(p => outputs.Contains(p.Ext) && !string.Equals(p.Ext, ext, StringComparison.OrdinalIgnoreCase))
.ToList();
var availableOutputs = GetAvailableOutputs(engine, ext);
if (availableOutputs.Count == 0) continue;
WriteCascade(ext, exe, icon, availableOutputs);