From 3f9dce517aa232bcf3e8b518aba20d30cfab8ddd Mon Sep 17 00:00:00 2001 From: ema Date: Sat, 25 Apr 2026 11:35:32 +0800 Subject: [PATCH] Add cross-plugin 'Open in' more-menu items --- .../Plugin.MoreMenu.cs | 65 +++++++++++++++++++ .../QuickLook.Plugin.AppViewer/Plugin.cs | 6 +- .../Translations.config | 2 + .../Plugin.MoreMenu.cs | 34 +++++++++- .../Translations.config | 2 + 5 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.MoreMenu.cs diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.MoreMenu.cs b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.MoreMenu.cs new file mode 100644 index 0000000..fc1d1d9 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.MoreMenu.cs @@ -0,0 +1,65 @@ +// Copyright © 2017-2026 QL-Win Contributors +// +// This file is part of QuickLook program. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using QuickLook.Common.Commands; +using QuickLook.Common.Controls; +using QuickLook.Common.Helpers; +using QuickLook.Common.Plugin.MoreMenu; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +namespace QuickLook.Plugin.AppViewer; + +public sealed partial class Plugin +{ + public IEnumerable GetMenuItems() + { + if (string.IsNullOrEmpty(_path)) + yield break; + + string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config"); + + if (_path.EndsWith(".apk", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".apk.1", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".aab", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".ipa", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".hap", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".hap.1", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".appx", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".appxbundle", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".msix", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".msixbundle", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".nupkg", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".snupkg", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".wgt", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".wgtu", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".aar", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".har", StringComparison.OrdinalIgnoreCase)) + { + // If the file is ZIP-based (PK..), allow reopening with ArchiveViewer + yield return new MoreMenuItem() + { + Icon = FontSymbols.Tablet, + Header = TranslationHelper.Get("MW_OpenInArchiveViewer", translationFile), + MenuItems = null, + Command = new RelayCommand(() => PluginHelper.InvokePluginPreview("QuickLook.Plugin.ArchiveViewer", _path)), + }; + } + } +} diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs index 35f295f..601a160 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Plugin.cs @@ -16,6 +16,8 @@ // along with this program. If not, see . using QuickLook.Common.Plugin; +using QuickLook.Common.Plugin.MoreMenu; +using System.Collections.Generic; using QuickLook.Plugin.AppViewer.InfoPanels; using System; using System.IO; @@ -24,7 +26,7 @@ using System.Windows; namespace QuickLook.Plugin.AppViewer; -public sealed class Plugin : IViewer +public sealed partial class Plugin : IViewer, IMoreMenu { private static readonly string[] _extensions = [ @@ -68,6 +70,8 @@ public sealed class Plugin : IViewer public int Priority => 0; + public IEnumerable MenuItems => GetMenuItems(); + public void Init() { } diff --git a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config index f3eb31c..a507fa0 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config +++ b/QuickLook.Plugin/QuickLook.Plugin.AppViewer/Translations.config @@ -200,6 +200,7 @@ License Target Frameworks Dependencies + Open with Archive Viewer 제품 버전 @@ -320,6 +321,7 @@ 许可证 目标框架 依赖项 + 在归档查看器中打开 產品版本 diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Plugin.MoreMenu.cs b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Plugin.MoreMenu.cs index 7229178..58203d4 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Plugin.MoreMenu.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Plugin.MoreMenu.cs @@ -53,14 +53,17 @@ public sealed partial class Plugin /// public IEnumerable GetMenuItems() { + if (string.IsNullOrEmpty(_path)) + yield break; + + // Use external Translations.config shipped next to the executing assembly + string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config"); + // Currently only supports for CFB and EIF files if (_path.EndsWith(".cfb", StringComparison.OrdinalIgnoreCase) || _path.EndsWith(".eif", StringComparison.OrdinalIgnoreCase) || _path.EndsWith(".pak", StringComparison.OrdinalIgnoreCase)) { - // Use external Translations.config shipped next to the executing assembly - string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config"); - yield return new MoreMenuItem() { Icon = FontSymbols.MoveToFolder, @@ -69,6 +72,31 @@ public sealed partial class Plugin Command = ExtractToDirectoryCommand, }; } + else if (_path.EndsWith(".apk", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".apk.1", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".aab", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".ipa", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".hap", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".hap.1", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".appx", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".appxbundle", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".msix", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".msixbundle", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".nupkg", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".snupkg", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".wgt", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".wgtu", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".aar", StringComparison.OrdinalIgnoreCase) + || _path.EndsWith(".har", StringComparison.OrdinalIgnoreCase)) + { + yield return new MoreMenuItem() + { + Icon = FontSymbols.Package, + Header = TranslationHelper.Get("MW_OpenInAppViewer", translationFile), + MenuItems = null, + Command = new RelayCommand(() => PluginHelper.InvokePluginPreview("QuickLook.Plugin.AppViewer", _path)), + }; + } } /// diff --git a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Translations.config b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Translations.config index 4a893ea..6789bc5 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Translations.config +++ b/QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/Translations.config @@ -44,6 +44,7 @@ Extract to directory Do you want to keep the order of stored sticker files? + Open with App Viewer 폴더로 추출 @@ -96,6 +97,7 @@ 提取到目录 是否需要保持已保存表情包文件的顺序? + 在应用查看器中打开 提取到資料夾