Compare commits

..

22 Commits

Author SHA1 Message Date
ema
e4e014d9d7 Refactor Lottie and TGS file validation methods
Renamed and split validation methods for Lottie and TGS files to improve clarity and code reuse. Added IsVaildContent for both detectors and updated WebHandler to use the new method names.
2025-09-22 04:56:16 +08:00
copilot-swe-agent[bot]
cafd2413be Remove TgsExtractor.cs from Lottie folder
Co-authored-by: emako <24737061+emako@users.noreply.github.com>
2025-09-20 20:47:00 +00:00
copilot-swe-agent[bot]
0b0e9e9a7a Refactor TGS support into separate Tgs folder structure
Co-authored-by: emako <24737061+emako@users.noreply.github.com>
2025-09-20 20:27:55 +00:00
copilot-swe-agent[bot]
2ca513f2ab Update documentation to include TGS and Lottie formats
Co-authored-by: emako <24737061+emako@users.noreply.github.com>
2025-09-20 17:12:18 +00:00
copilot-swe-agent[bot]
e7a65387b5 Implement TGS support for Telegram stickers
Co-authored-by: emako <24737061+emako@users.noreply.github.com>
2025-09-20 17:09:05 +00:00
copilot-swe-agent[bot]
dd04a18c2c Initial plan 2025-09-20 17:04:27 +00:00
ema
297e7ef092 Refactor cover art extraction logic to fix #1759 2025-09-21 00:52:07 +08:00
ema
e1c53b8691 Extract cover art will not cause the title to be lost #1759
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
2025-09-21 00:13:39 +08:00
ema
c3b828e70f Add SUPPORTED_FORMATS.md documentation
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
Introduces a new SUPPORTED_FORMATS.md file listing all file formats supported by QuickLook, organized by category. This documentation helps users and developers quickly reference supported file types.
2025-09-19 18:05:02 +08:00
ema
c9d120bd36 Add pull request template
Introduces a standardized pull request template to ensure PRs include checklists, descriptions, related issues, and additional notes for better review and project consistency.
2025-09-19 17:47:35 +08:00
ema
0bca38e2bf Add .slnx extension to XML syntax highlighting
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
2025-09-15 12:50:07 +08:00
ema
3cdf847f3d Fix NuGet package path issue for FreeTypeSharp
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
2025-09-11 11:05:39 +08:00
samueljoh
ae05deea46 Add Swedish translation (#1755) 2025-09-11 11:01:23 +08:00
ema
a491ed9970 Add 'Copy as path' option to More menu
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
2025-09-08 03:53:16 +08:00
ema
c748f6d7e4 Update NuGet package versions in project files
This commit updates various NuGet package references to newer versions across multiple QuickLook plugin and main project .csproj files. These updates include dependencies such as WixToolset.Dtf.WindowsInstaller, UTF.Unknown, FreeTypeSharp, Microsoft.Web.WebView2, Magick.NET-Q8-AnyCPU, Google.Protobuf, MsgReader, HelixToolkit, bblanchon.PDFiumV8.Win32, Melanchall.DryWetMidi, WPF-UI.Violeta, and Lib.Harmony, ensuring the projects use the latest compatible releases.
2025-09-08 02:42:09 +08:00
ema
e0a2204e56 Add diff file syntax highlighting 2025-09-08 02:16:55 +08:00
ema
d6274ac331 Prepare new feature for MoreMenu 2025-09-08 01:49:36 +08:00
ema
07debda5e4 feat: improve UI/UX of font loading 2025-09-08 01:14:01 +08:00
ema
cddf767c6c refactor: simplify tray menu ctor calling 2025-09-07 23:55:24 +08:00
ema
21a3dd3d4b Fix the same previous issue in other plugins
Some checks failed
MSBuild / build (push) Has been cancelled
MSBuild / publish (push) Has been cancelled
2025-08-15 02:17:50 +08:00
ema
ebb48366a0 Fix font file unicode name is not supported 2025-08-15 02:09:38 +08:00
ema
e12bb2201b Fix issue where font file stays locked #77 2025-08-15 02:01:59 +08:00
57 changed files with 1185 additions and 103 deletions

14
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,14 @@
## PR Checklist
- [ ] Functionality has been tested, no obvious bugs
- [ ] Code style follows project conventions
- [ ] Documentation/comments updated (if applicable)
## Brief Description of Changes
Please briefly describe the main changes in this PR:
## Related Issue (if any)
Please provide related issue numbers:
## Additional Notes
Add any extra notes here:

View File

@@ -61,8 +61,8 @@ public class AppImageReader
public AppImageReader(string path)
{
using FileStream fs = File.OpenRead(path);
Open(fs);
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
Open(fileStream);
}
private void Open(Stream stream)

View File

@@ -29,7 +29,7 @@ internal static class WgtParser
{
public static WgtInfo Parse(string path)
{
using var fileStream = File.OpenRead(path);
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
var manifestEntry = zipArchive.GetEntry("manifest.json");

View File

@@ -72,7 +72,7 @@
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="6.0.1" />
<PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="6.0.2" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PureSharpCompress" Version="0.40.0" />

View File

@@ -232,4 +232,37 @@
<TERMINAL>Terminal</TERMINAL>
<VENDOR>Anbieter</VENDOR>
</de>
<sv>
<PRODUCT_VERSION>Produktversion</PRODUCT_VERSION>
<PRODUCT_NAME>Produktnamn</PRODUCT_NAME>
<MANUFACTURER>Tillverkare</MANUFACTURER>
<TOTAL_SIZE>Total storlek</TOTAL_SIZE>
<LAST_MODIFIED>Senast ändrad</LAST_MODIFIED>
<PUBLISHER>Utgivare</PUBLISHER>
<CAPABILITIES>Funktioner</CAPABILITIES>
<ABI>ABI</ABI>
<APP_NAME>Program</APP_NAME>
<APP_VERSION>Version</APP_VERSION>
<APP_VERSION_NAME>Versionsnamn</APP_VERSION_NAME>
<APP_VERSION_CODE>Versionskod</APP_VERSION_CODE>
<PERMISSIONS>Behörigheter</PERMISSIONS>
<PACKAGE_NAME>Paketnamn</PACKAGE_NAME>
<APP_MIN_SDK_VERSION>Minsta SDK-version</APP_MIN_SDK_VERSION>
<APP_TARGET_SDK_VERSION>Mål SDK-version</APP_TARGET_SDK_VERSION>
<APP_MIN_OS_VERSION>Minsta OS-version</APP_MIN_OS_VERSION>
<APP_TARGET_OS_VERSION>Mål OS-version</APP_TARGET_OS_VERSION>
<DEVICE_FAMILY>Enhetsfamilj</DEVICE_FAMILY>
<BUNDLE_NAME>Paketnamn</BUNDLE_NAME>
<DEVICE_TYPES>Enhetstyp</DEVICE_TYPES>
<APP_MIN_API_VERSION>Minsta API-version</APP_MIN_API_VERSION>
<APP_TARGET_API_VERSION>Mål API-version</APP_TARGET_API_VERSION>
<COMPILE_SDK_VERSION>Kompilerad SDK-version</COMPILE_SDK_VERSION>
<ARCHITECTURE>Arkitektur</ARCHITECTURE>
<MAINTAINER>Paketansvarig</MAINTAINER>
<DESCRIPTION>Beskrivning</DESCRIPTION>
<ENVIRONMENT>Miljö</ENVIRONMENT>
<TYPE>Typ</TYPE>
<TERMINAL>Terminal</TERMINAL>
<VENDOR>Leverantör</VENDOR>
</sv>
</Translations>

View File

@@ -134,14 +134,14 @@ public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropert
private void LoadItemsFromArchive(string path)
{
using var stream = File.OpenRead(path);
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
// ReaderFactory is slow... so limit its usage
string[] useReader = [".tar.gz", ".tgz", ".tar.bz2", ".tar.lz", ".tar.xz"];
if (useReader.Any(path.ToLower().EndsWith))
{
var reader = ReaderFactory.Open(stream, new ChardetReaderOptions());
var reader = ReaderFactory.Open(fileStream, new ChardetReaderOptions());
_type = reader.ArchiveType.ToString();
@@ -149,13 +149,13 @@ public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropert
{
if (_disposed)
return;
LoadPercent = 100d * stream.Position / stream.Length;
LoadPercent = 100d * fileStream.Position / fileStream.Length;
ProcessByLevel(reader.Entry);
}
}
else
{
var archive = ArchiveFactory.Open(stream, new ChardetReaderOptions());
var archive = ArchiveFactory.Open(fileStream, new ChardetReaderOptions());
_type = archive.Type.ToString();
@@ -163,7 +163,7 @@ public partial class ArchiveInfoPanel : UserControl, IDisposable, INotifyPropert
{
if (_disposed)
return;
LoadPercent = 100d * stream.Position / stream.Length;
LoadPercent = 100d * fileStream.Position / fileStream.Length;
ProcessByLevel(entry);
}
}

View File

@@ -53,7 +53,7 @@
<ItemGroup>
<PackageReference Include="PureSharpCompress" Version="0.40.0" />
<PackageReference Include="UTF.Unknown" Version="2.5.1" />
<PackageReference Include="UTF.Unknown" Version="2.6.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -49,4 +49,10 @@
<ConfirmDeleteText>¿Está seguro de que desea eliminar permanentemente estos {0} elemento(s)?</ConfirmDeleteText>
<RecycleBinSizeText>Tamaño total {0}, {1} elementos</RecycleBinSizeText>
</es>
<sv>
<RecycleBinEmptyText>Papperskorgen är tom</RecycleBinEmptyText>
<RecycleBinButton>Töm papperskorgen</RecycleBinButton>
<ConfirmDeleteText>Vill du ta bort de här {0} objekten permanent?</ConfirmDeleteText>
<RecycleBinSizeText>Total storlek: {0} ({1} objekt)</RecycleBinSizeText>
</sv>
</Translations>

View File

@@ -53,7 +53,7 @@
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.1.0" />
<PackageReference Include="UTF.Unknown" Version="2.5.1" />
<PackageReference Include="UTF.Unknown" Version="2.6.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -43,4 +43,10 @@
<FORMAT_PROFILE>Formatprofil</FORMAT_PROFILE>
<NAME>Name</NAME>
</de>
<sv>
<TOTAL_SIZE>Total storlek</TOTAL_SIZE>
<FORMAT>Format</FORMAT>
<FORMAT_PROFILE>Formatprofil</FORMAT_PROFILE>
<NAME>Namn</NAME>
</sv>
</Translations>

View File

@@ -40,12 +40,19 @@ internal unsafe static class FreeTypeApi
error = FT_New_Face(lib, (byte*)Marshal.StringToHGlobalAnsi(path), IntPtr.Zero, &face);
if (error == FT_Error.FT_Err_Ok)
try
{
var familyName = Marshal.PtrToStringAnsi((nint)face->family_name);
return familyName;
if (error == FT_Error.FT_Err_Ok)
{
var familyName = Marshal.PtrToStringAnsi((nint)face->family_name);
return familyName;
}
}
finally
{
FT_Done_Face(face);
FT_Done_FreeType(lib);
}
return null;
}
}

View File

@@ -0,0 +1,26 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace QuickLook.Plugin.FontViewer;
public class ObservableFileStream(string path, FileMode mode, FileAccess access, FileShare share) : FileStream(path, mode, access, share)
{
public bool IsEndOfStream { get; protected set; } = false;
public override int Read(byte[] array, int offset, int count)
{
int result = base.Read(array, offset, count);
if (result == 0)
IsEndOfStream = true;
return result;
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
int result = await base.ReadAsync(buffer, offset, count, cancellationToken);
if (result == 0)
IsEndOfStream = true;
return result;
}
}

View File

@@ -19,6 +19,7 @@ using QuickLook.Common.Plugin;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace QuickLook.Plugin.FontViewer;
@@ -52,7 +53,12 @@ public class Plugin : IViewer
context.ViewerContent = _panel;
context.Title = Path.GetFileName(path);
context.IsBusy = false;
_ = Task.Run(() =>
{
_ = _panel.WaitForFontSent();
context.IsBusy = false;
});
}
public void Cleanup()

View File

@@ -53,17 +53,17 @@
</PropertyGroup>
<ItemGroup>
<Content Include="$(NuGetPackageRoot)\FreeTypeSharp\3.0.0\runtimes\win-x64\native\freetype.dll">
<Content Include="$(NuGetPackageRoot)\FreeTypeSharp\3.0.1\runtimes\win-x64\native\freetype.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<DestinationFolder>$(OutDir)win-x64\</DestinationFolder>
<Link>runtimes\win-x64\freetype.dll</Link>
</Content>
<Content Include="$(NuGetPackageRoot)\FreeTypeSharp\3.0.0\runtimes\win-x86\native\freetype.dll">
<Content Include="$(NuGetPackageRoot)\FreeTypeSharp\3.0.1\runtimes\win-x86\native\freetype.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<DestinationFolder>$(OutDir)win-x86\</DestinationFolder>
<Link>runtimes\win-x86\freetype.dll</Link>
</Content>
<!--<Content Include="$(NuGetPackageRoot)\FreeTypeSharp\3.0.0\runtimes\win-arm64\native\freetype.dll">
<!--<Content Include="$(NuGetPackageRoot)\FreeTypeSharp\3.0.1\runtimes\win-arm64\native\freetype.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<DestinationFolder>$(OutDir)win-arm64\</DestinationFolder>
<Link>runtimes\win-arm64\freetype.dll</Link>
@@ -71,9 +71,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="FreeTypeSharp" Version="3.0.0" />
<PackageReference Include="FreeTypeSharp" Version="3.0.1" />
<PackageReference Include="QuickLook.Typography.OpenFont" Version="1.0.1" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3351.48">
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3405.78">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -16,4 +16,7 @@
<de>
<SAMPLE_TEXT>Der schnelle braune Fuchs sprang über den faulen Hund. 1234567890</SAMPLE_TEXT>
</de>
<sv>
<SAMPLE_TEXT>Flygande bäckasiner söka hwila på mjuka tuvor. 1234567890</SAMPLE_TEXT>
</sv>
</Translations>

View File

@@ -26,6 +26,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
namespace QuickLook.Plugin.FontViewer;
@@ -34,6 +35,7 @@ public class WebfontPanel : WebpagePanel
protected const string _resourcePrefix = "QuickLook.Plugin.FontViewer.Resources.";
protected internal static readonly Dictionary<string, byte[]> _resources = [];
protected byte[] _homePage;
protected ObservableFileStream _fontStream = null;
static WebfontPanel()
{
@@ -149,14 +151,15 @@ public class WebfontPanel : WebpagePanel
}
else
{
var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
var localPath = _fallbackPath + Uri.UnescapeDataString(requestedUri.AbsolutePath).Replace('/', '\\');
if (File.Exists(localPath))
{
var fileStream = File.OpenRead(localPath);
var fileStream = new ObservableFileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentType());
args.Response = response;
_fontStream = fileStream; // Only the font request will set this
}
}
}
@@ -168,6 +171,19 @@ public class WebfontPanel : WebpagePanel
}
}
public bool WaitForFontSent()
{
bool timeout = SpinWait.SpinUntil(
() => _fontStream is not null && _fontStream.IsEndOfStream,
TimeSpan.FromSeconds(1.5d) // The prediction is MAX 100MB
);
// Only when the `IsEndOfStream` is true
// Delay 15ms per MB for webview2 to render the font
if (timeout) Thread.Sleep(15 * (int)(_fontStream.Position / 1_048_576));
return timeout;
}
public static bool ContainsKey(string key)
{
return _resources.ContainsKey(key);

View File

@@ -52,8 +52,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HelixToolkit" Version="2.27.0" />
<PackageReference Include="HelixToolkit.Wpf" Version="2.27.0" />
<PackageReference Include="HelixToolkit" Version="2.27.3" />
<PackageReference Include="HelixToolkit.Wpf" Version="2.27.3" />
<PackageReference Include="AssimpNet" Version="5.0.0-beta1" />
<PackageReference Include="PcdSharp" Version="1.0.1" />
</ItemGroup>

View File

@@ -61,7 +61,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3351.48">
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3405.78">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -40,4 +40,7 @@
<uk-UA>
<WEBVIEW2_NOT_AVAILABLE>Для перегляду цього файлу потрібно встановити Microsoft Edge WebView2.&#10;Натисніть тут, щоб завантажити його.</WEBVIEW2_NOT_AVAILABLE>
</uk-UA>
<sv>
<WEBVIEW2_NOT_AVAILABLE>För att visa denna fil krävs att Microsoft Edge WebView2 är installerat.&#10;Klicka här för att ladda ner det.</WEBVIEW2_NOT_AVAILABLE>
</sv>
</Translations>

View File

@@ -210,7 +210,7 @@ public class WebpagePanel : UserControl
if (File.Exists(fallbackFilePath))
{
// Serve the file from the fallback directory
var fileStream = File.OpenRead(fallbackFilePath);
var fileStream = new FileStream(fallbackFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", "Content-Type: application/octet-stream");
args.Response = response;

View File

@@ -59,13 +59,13 @@
<PackageReference Include="QuickLook.ImageGlass.WebP" Version="1.4.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.7.0">
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.8.2">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3351.48">
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3405.78">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Google.Protobuf" Version="3.31.1">
<PackageReference Include="Google.Protobuf" Version="3.32.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Memory" Version="4.6.3">

View File

@@ -22,12 +22,25 @@ namespace QuickLook.Plugin.ImageViewer.Webview.Lottie;
internal static class LottieDetector
{
public static bool IsVaild(string path)
public static bool IsVaildFile(string path)
{
try
{
var jsonString = File.ReadAllText(path);
return IsVaildContent(jsonString);
}
catch
{
// If any exception occurs, assume it's not a valid Lottie file
}
return false;
}
public static bool IsVaildContent(string jsonString)
{
try
{
// No exception will be thrown here
var jsonLottie = LottieParser.Parse<Dictionary<string, object>>(jsonString);

View File

@@ -27,7 +27,7 @@ internal static class LottieExtractor
{
public static string GetJsonContent(string path)
{
using var fileStream = File.OpenRead(path);
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
var manifestEntry = zipArchive.GetEntry("manifest.json");

View File

@@ -130,11 +130,11 @@ public class SvgImagePanel : WebpagePanel, IWebImagePanel
}
else
{
var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
var localPath = _fallbackPath + Uri.UnescapeDataString(requestedUri.AbsolutePath).Replace('/', '\\');
if (File.Exists(localPath))
{
var fileStream = File.OpenRead(localPath);
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentTypeHeader());
args.Response = response;
@@ -149,7 +149,7 @@ public class SvgImagePanel : WebpagePanel, IWebImagePanel
{
if (File.Exists(localPath))
{
var fileStream = File.OpenRead(localPath);
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK",
$"""

View File

@@ -0,0 +1,42 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using QuickLook.Plugin.ImageViewer.Webview.Lottie;
namespace QuickLook.Plugin.ImageViewer.Webview.Tgs;
internal static class TgsDetector
{
public static bool IsValidFile(string path)
{
try
{
// Extract JSON content from gzipped TGS file
var jsonString = TgsExtractor.GetJsonContent(path);
return IsVaildContent(jsonString);
}
catch
{
// If any exception occurs, assume it's not a valid TGS file
}
return false;
}
public static bool IsVaildContent(string jsonString)
=> LottieDetector.IsVaildContent(jsonString);
}

View File

@@ -0,0 +1,33 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using System.IO;
using System.IO.Compression;
using System.Text;
namespace QuickLook.Plugin.ImageViewer.Webview.Tgs;
internal static class TgsExtractor
{
public static string GetJsonContent(string path)
{
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
using var gzipStream = new GZipStream(fileStream, CompressionMode.Decompress);
using var reader = new StreamReader(gzipStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}

View File

@@ -0,0 +1,92 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using Microsoft.Web.WebView2.Core;
using QuickLook.Plugin.ImageViewer.Webview.Svg;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace QuickLook.Plugin.ImageViewer.Webview.Tgs;
public class TgsImagePanel : SvgImagePanel
{
public override void Preview(string path)
{
FallbackPath = Path.GetDirectoryName(path);
ObjectForScripting ??= new TgsScriptHandler(path);
_homePage = _resources["/lottie2html.html"];
NavigateToUri(new Uri("file://quicklook/"));
}
protected override void WebView_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs args)
{
try
{
var requestedUri = new Uri(args.Request.Uri);
if ((requestedUri.Scheme == "https" || requestedUri.Scheme == "http")
&& requestedUri.AbsolutePath.EndsWith(".tgs", StringComparison.OrdinalIgnoreCase))
{
var localPath = Uri.UnescapeDataString($"{requestedUri.Authority}:{requestedUri.AbsolutePath}".Replace('/', '\\'));
if (localPath.StartsWith(_fallbackPath, StringComparison.OrdinalIgnoreCase))
{
if (File.Exists(localPath))
{
var content = TgsExtractor.GetJsonContent(localPath);
byte[] byteArray = Encoding.UTF8.GetBytes(content);
var stream = new MemoryStream(byteArray);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
stream, 200, "OK",
$"""
Access-Control-Allow-Origin: *
Content-Type: {MimeTypes.GetMimeType()}
"""
);
args.Response = response;
return;
}
}
}
}
catch (Exception e)
{
// We don't need to feel burdened by any exceptions
Debug.WriteLine(e);
}
base.WebView_WebResourceRequested(sender, args);
}
}
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public sealed class TgsScriptHandler(string path)
{
public string Path { get; } = path;
public async Task<string> GetPath()
{
return await Task.FromResult(new Uri(Path).AbsolutePath);
}
}

View File

@@ -0,0 +1,62 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using QuickLook.Plugin.ImageViewer.Webview.Lottie;
using System.Collections.Generic;
using System.IO;
using System.Windows;
namespace QuickLook.Plugin.ImageViewer.Webview.Tgs;
public class TgsMetaProvider(string path) : IWebMetaProvider
{
private readonly string _path = path;
private Size _size = Size.Empty;
public Size GetSize()
{
if (_size != Size.Empty)
{
return _size;
}
if (!File.Exists(_path))
{
return _size;
}
try
{
var jsonString = TgsExtractor.GetJsonContent(_path);
var jsonLottie = LottieParser.Parse<Dictionary<string, object>>(jsonString);
if (jsonLottie.ContainsKey("w")
&& jsonLottie.ContainsKey("h")
&& double.TryParse(jsonLottie["w"].ToString(), out double width)
&& double.TryParse(jsonLottie["h"].ToString(), out double height))
{
return _size = new Size(width, height);
}
}
catch
{
// That's fine, just return the default size.
}
return new Size(800, 600);
}
}

View File

@@ -20,6 +20,7 @@ using QuickLook.Common.Plugin;
using QuickLook.Plugin.ImageViewer.Webview.Lottie;
using QuickLook.Plugin.ImageViewer.Webview.Svg;
using QuickLook.Plugin.ImageViewer.Webview.Svga;
using QuickLook.Plugin.ImageViewer.Webview.Tgs;
using System;
using System.IO;
using System.Windows;
@@ -37,7 +38,8 @@ internal static class WebHandler
{
".svg" => SettingHelper.Get("RenderSvgWeb", true, "QuickLook.Plugin.ImageViewer"),
".svga" or ".lottie" => true,
".json" => LottieDetector.IsVaild(path), // Check for Lottie files
".tgs" => TgsDetector.IsValidFile(path), // Check for TGS files
".json" => LottieDetector.IsVaildFile(path), // Check for Lottie files
_ => false,
};
}
@@ -47,7 +49,7 @@ internal static class WebHandler
string ext = Path.GetExtension(path).ToLower();
if (ext == ".svg" || ext == ".svga"
|| ext == ".lottie" || ext == ".json")
|| ext == ".lottie" || ext == ".tgs" || ext == ".json")
{
if (ext == ".svg")
{
@@ -63,6 +65,7 @@ internal static class WebHandler
".svg" => new SvgMetaProvider(path),
".svga" => new SvgaMetaProvider(path),
".lottie" or ".json" => new LottieMetaProvider(path),
".tgs" => new TgsMetaProvider(path),
_ => throw new NotSupportedException($"Unsupported file type: {ext}")
};
var sizeSvg = metaWeb.GetSize();
@@ -85,7 +88,8 @@ internal static class WebHandler
string ext = Path.GetExtension(path).ToLower();
if (ext == ".svg" || ext == ".svga"
|| ext == ".lottie" || ext == ".json")
|| ext == ".lottie" || ext == ".json"
|| ext == ".tgs")
{
if (ext == ".svg")
{
@@ -101,6 +105,7 @@ internal static class WebHandler
".svg" => new SvgImagePanel(),
".svga" => new SvgaImagePanel(metaWeb),
".lottie" or ".json" => new LottieImagePanel(),
".tgs" => new TgsImagePanel(),
_ => throw new NotSupportedException($"Unsupported file type: {ext}")
};

View File

@@ -55,7 +55,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MsgReader" Version="6.0.1" />
<PackageReference Include="MsgReader" Version="6.0.4" />
</ItemGroup>
<ItemGroup>

View File

@@ -124,11 +124,11 @@ public class MarkdownPanel : WebpagePanel
}
else
{
var localPath = _fallbackPath + requestedUri.AbsolutePath.Replace('/', '\\');
var localPath = _fallbackPath + Uri.UnescapeDataString(requestedUri.AbsolutePath).Replace('/', '\\');
if (File.Exists(localPath))
{
var fileStream = File.OpenRead(localPath);
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentType());
args.Response = response;

View File

@@ -59,9 +59,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="UTF.Unknown" Version="2.5.1" />
<PackageReference Include="UTF.Unknown" Version="2.6.0" />
<Reference Include="WindowsBase" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3351.48">
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3405.78">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -55,4 +55,10 @@
<ConfirmDeleteText>¿Está seguro de que desea eliminar permanentemente estos {0} elemento(s)?</ConfirmDeleteText>
<RecycleBinSizeText>Tamaño total {0}, {1} elementos</RecycleBinSizeText>
</es>
<sv>
<RecycleBinEmptyText>Papperskorgen är tom</RecycleBinEmptyText>
<RecycleBinButton>Töm papperskorgen</RecycleBinButton>
<ConfirmDeleteText>Vill du ta bort de här {0} objekten permanent?</ConfirmDeleteText>
<RecycleBinSizeText>Total storlek: {0} ({1} objekt)</RecycleBinSizeText>
</sv>
</Translations>

View File

@@ -64,7 +64,7 @@
<ItemGroup>
<PackageReference Include="PdfiumViewer.Updated" Version="2.14.5" />
<PackageReference Include="bblanchon.PDFiumV8.Win32" Version="140.0.7269" />
<PackageReference Include="bblanchon.PDFiumV8.Win32" Version="141.0.7388" />
<Reference Include="WindowsBase" />
</ItemGroup>

View File

@@ -50,4 +50,11 @@
<BTN_OpenFile>Datei öffnen</BTN_OpenFile>
<BTN_Cancel>Abbrechen</BTN_Cancel>
</de>
<sv>
<PW_Title>Ange lösenord</PW_Title>
<Pw_Hint>Filen är lösenordskyddad. Ange lösenordet för att öppna filen.</Pw_Hint>
<PW_Error>Kontrollera lösenordet</PW_Error>
<BTN_OpenFile>Öppna filen</BTN_OpenFile>
<BTN_Cancel>Avbryt</BTN_Cancel>
</sv>
</Translations>

View File

@@ -36,4 +36,9 @@
<FILE_VERSION>Dateiversion</FILE_VERSION>
<PRODUCT_VERSION>Produktversion</PRODUCT_VERSION>
</de>
<sv>
<TOTAL_SIZE>Total storlek</TOTAL_SIZE>
<FILE_VERSION>Filversion</FILE_VERSION>
<PRODUCT_VERSION>Produktversion</PRODUCT_VERSION>
</sv>
</Translations>

View File

@@ -69,9 +69,9 @@ public class Plugin : IViewer
if (path.EndsWith(".rtf", StringComparison.OrdinalIgnoreCase))
{
var rtfBox = new RichTextBox();
using FileStream fs = File.OpenRead(path);
using var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
rtfBox.Background = new SolidColorBrush(Colors.Transparent);
rtfBox.Selection.Load(fs, DataFormats.Rtf);
rtfBox.Selection.Load(fileStream, DataFormats.Rtf);
rtfBox.IsReadOnly = true;
rtfBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
rtfBox.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;

View File

@@ -60,7 +60,7 @@
<ItemGroup>
<PackageReference Include="AvalonEdit" Version="6.3.1.120" />
<PackageReference Include="UTF.Unknown" Version="2.5.1" />
<PackageReference Include="UTF.Unknown" Version="2.6.0" />
<Reference Include="WindowsBase" />
<Reference Include="System.ComponentModel.Composition" />
<PackageReference Include="System.Memory" Version="4.6.3" />

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.syn;.lang;.manifest;.config;.addin;.xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.resx;.user;.ilproj;.booproj;.build;.xfrm;.targets;.axaml;.xaml;.xpt;.xft;.map;.wsdl;.disco;.ascx;.atom;.bpmn;.cpt;.csl;.props;.dotsettings">
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.syn;.lang;.manifest;.config;.addin;.xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.resx;.user;.ilproj;.booproj;.build;.xfrm;.targets;.axaml;.xaml;.xpt;.xft;.map;.wsdl;.disco;.ascx;.atom;.bpmn;.cpt;.csl;.props;.dotsettings;.slnx">
<Environment>
<Default color="#D4D4D4" bgcolor="#1E1E1E"/>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.syn;.lang;.manifest;.config;.addin;.xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.resx;.user;.ilproj;.booproj;.build;.xfrm;.targets;.axaml;.xaml;.xpt;.xft;.map;.wsdl;.disco;.ascx;.atom;.bpmn;.cpt;.csl;.props;.dotsettings">
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.syn;.lang;.manifest;.config;.addin;.xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.resx;.user;.ilproj;.booproj;.build;.xfrm;.targets;.axaml;.xaml;.xpt;.xft;.map;.wsdl;.disco;.ascx;.atom;.bpmn;.cpt;.csl;.props;.dotsettings;.slnx">
<Environment>
<Default color="Black" bgcolor="#FFFFFF"/>

View File

@@ -0,0 +1,124 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Rendering;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace QuickLook.Plugin.TextViewer.Themes.HighlightingDefinitions.Dark;
public class DiffHighlightingDefinition : DarkHighlightingDefinition
{
public override string Name => "Diff";
public override string Extension => ".diff";
public override HighlightingRuleSet MainRuleSet => new()
{
Rules =
{
// Diff header (diff --git, index, etc.)
new HighlightingRule
{
Regex = new Regex(@"^(diff --git|index|---|\+\+\+)", RegexOptions.Compiled),
Color = GetNamedColor("Header")
},
// File mode and other metadata
new HighlightingRule
{
Regex = new Regex(@"^(new file mode|deleted file mode|old mode|new mode|similarity index|dissimilarity index|rename from|rename to|copy from|copy to)", RegexOptions.Compiled),
Color = GetNamedColor("Metadata")
},
// Hunk headers (@@ ... @@)
new HighlightingRule
{
Regex = new Regex(@"^@@.*@@$", RegexOptions.Compiled),
Color = GetNamedColor("HunkHeader")
},
// Added lines (+)
new HighlightingRule
{
Regex = new Regex(@"^\+.*$", RegexOptions.Compiled),
Color = GetNamedColor("Added")
},
// Removed lines (-)
new HighlightingRule
{
Regex = new Regex(@"^-.*$", RegexOptions.Compiled),
Color = GetNamedColor("Removed")
},
// Context lines (unchanged)
new HighlightingRule
{
Regex = new Regex(@"^ .*", RegexOptions.Compiled),
Color = GetNamedColor("Context")
}
}
};
public override HighlightingColor GetNamedColor(string name)
{
return name switch
{
"Header" => new HighlightingColor
{
Name = "Header",
Foreground = new SimpleHighlightingBrush("#569CD6".ToColor()), // Blue for headers
},
"Metadata" => new HighlightingColor
{
Name = "Metadata",
Foreground = new SimpleHighlightingBrush("#808080".ToColor()), // Gray for metadata
},
"HunkHeader" => new HighlightingColor
{
Name = "HunkHeader",
Foreground = new SimpleHighlightingBrush("#C586C0".ToColor()), // Purple for hunk headers
},
"Added" => new HighlightingColor
{
Name = "Added",
Foreground = new SimpleHighlightingBrush("#6A9949".ToColor()), // Green for added lines
},
"Removed" => new HighlightingColor
{
Name = "Removed",
Foreground = new SimpleHighlightingBrush("#F44747".ToColor()), // Red for removed lines
},
"Context" => new HighlightingColor
{
Name = "Context",
Foreground = new SimpleHighlightingBrush("#D4D4D4".ToColor()), // Light gray for context
},
_ => null,
};
}
public override IEnumerable<HighlightingColor> NamedHighlightingColors =>
[
GetNamedColor("Header"),
GetNamedColor("Metadata"),
GetNamedColor("HunkHeader"),
GetNamedColor("Added"),
GetNamedColor("Removed"),
GetNamedColor("Context"),
];
public override DocumentColorizingTransformer[] LineTransformers { get; } = [];
}

View File

@@ -0,0 +1,124 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Rendering;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace QuickLook.Plugin.TextViewer.Themes.HighlightingDefinitions.Light;
public class DiffHighlightingDefinition : LightHighlightingDefinition
{
public override string Name => "Diff";
public override string Extension => ".diff";
public override HighlightingRuleSet MainRuleSet => new()
{
Rules =
{
// Diff header (diff --git, index, etc.)
new HighlightingRule
{
Regex = new Regex(@"^(diff --git|index|---|\+\+\+)", RegexOptions.Compiled),
Color = GetNamedColor("Header")
},
// File mode and other metadata
new HighlightingRule
{
Regex = new Regex(@"^(new file mode|deleted file mode|old mode|new mode|similarity index|dissimilarity index|rename from|rename to|copy from|copy to)", RegexOptions.Compiled),
Color = GetNamedColor("Metadata")
},
// Hunk headers (@@ ... @@)
new HighlightingRule
{
Regex = new Regex(@"^@@.*@@$", RegexOptions.Compiled),
Color = GetNamedColor("HunkHeader")
},
// Added lines (+)
new HighlightingRule
{
Regex = new Regex(@"^\+.*$", RegexOptions.Compiled),
Color = GetNamedColor("Added")
},
// Removed lines (-)
new HighlightingRule
{
Regex = new Regex(@"^-.*$", RegexOptions.Compiled),
Color = GetNamedColor("Removed")
},
// Context lines (unchanged)
new HighlightingRule
{
Regex = new Regex(@"^ .*", RegexOptions.Compiled),
Color = GetNamedColor("Context")
}
}
};
public override HighlightingColor GetNamedColor(string name)
{
return name switch
{
"Header" => new HighlightingColor
{
Name = "Header",
Foreground = new SimpleHighlightingBrush("#2563EB".ToColor()), // Blue for headers
},
"Metadata" => new HighlightingColor
{
Name = "Metadata",
Foreground = new SimpleHighlightingBrush("#6B7280".ToColor()), // Gray for metadata
},
"HunkHeader" => new HighlightingColor
{
Name = "HunkHeader",
Foreground = new SimpleHighlightingBrush("#7C3AED".ToColor()), // Purple for hunk headers
},
"Added" => new HighlightingColor
{
Name = "Added",
Foreground = new SimpleHighlightingBrush("#15803D".ToColor()), // Green for added lines
},
"Removed" => new HighlightingColor
{
Name = "Removed",
Foreground = new SimpleHighlightingBrush("#DC2626".ToColor()), // Red for removed lines
},
"Context" => new HighlightingColor
{
Name = "Context",
Foreground = new SimpleHighlightingBrush("#374151".ToColor()), // Gray for context
},
_ => null,
};
}
public override IEnumerable<HighlightingColor> NamedHighlightingColors =>
[
GetNamedColor("Header"),
GetNamedColor("Metadata"),
GetNamedColor("HunkHeader"),
GetNamedColor("Added"),
GetNamedColor("Removed"),
GetNamedColor("Context"),
];
public override DocumentColorizingTransformer[] LineTransformers { get; } = [];
}

View File

@@ -187,8 +187,8 @@ public class HighlightingThemeManager
{
Debug.WriteLine(file);
var ext = Path.GetFileNameWithoutExtension(file);
using Stream s = File.OpenRead(Path.GetFullPath(file));
using var reader = new XmlTextReader(s);
using var fileStream = new FileStream(Path.GetFullPath(file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
using var reader = new XmlTextReader(fileStream);
var xshd = HighlightingLoader.LoadXshd(reader);
var highlightingDefinition = HighlightingLoader.Load(xshd, hlm);
if (xshd.Extensions.Count > 0)

View File

@@ -96,4 +96,9 @@
<Editor_Copy>Aντιγραφή</Editor_Copy>
<Editor_SelectAll>Επιλογή όλων</Editor_SelectAll>
</el>
<sv>
<Editor_FontFamily>Consolas</Editor_FontFamily>
<Editor_Copy>Kopiera</Editor_Copy>
<Editor_SelectAll>Markera allt</Editor_SelectAll>
</sv>
</Translations>

View File

@@ -0,0 +1,82 @@
using QuickLook.Common.ExtensionMethods;
using QuickLook.Plugin.VideoViewer.Extensions;
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Media.Imaging;
namespace QuickLook.Plugin.VideoViewer.AudioTrack;
internal static class CoverDataExtractor
{
/// <summary>
/// Extracts cover image data from a Base64 string.
/// </summary>
/// <param name="base64strings">A Base64-encoded string (may contain multiple covers separated by " / ").</param>
/// <returns>Byte array of the cover image, or null if extraction fails.</returns>
public static byte[] Extract(string base64strings)
{
try
{
var coverData = base64strings.Trim();
if (!string.IsNullOrEmpty(coverData))
{
// MediaInfo may return multiple covers in one string.
// In that case, only take the first one.
var coverBytes = Convert.FromBase64String
(
coverData.Contains(' ')
? coverData.Split(" / ")[0]
: coverData
);
return coverBytes;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
}
return null;
}
/// <summary>
/// Extracts a <see cref="BitmapSource"/> from cover image bytes.
/// </summary>
/// <param name="coverBytes">Cover image as a byte array.</param>
/// <returns><see cref="BitmapSource"/> if successful; otherwise, null.</returns>
public static BitmapSource Extract(byte[] coverBytes)
{
using var ms = new MemoryStream(coverBytes);
try
{
// First try decoding with WPF's built-in decoder.
var coverArt = BitmapFrame.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
return coverArt;
}
catch
{
// Fallback:
// https://github.com/QL-Win/QuickLook/issues/1759
// Use System.Drawing's Bitmap decoder, which is more forgiving with common JPEG files
// and tends not to throw WINCODEC_ERR_STREAMREAD like WPF often does.
try
{
using var bmp = new Bitmap(ms);
var coverArt = bmp.ToBitmapSource();
return coverArt;
}
catch (Exception e)
{
Debug.WriteLine(e);
}
}
return null;
}
}

View File

@@ -48,8 +48,8 @@
<Reference Include="DirectShowLib-2005, Version=2.1.0.26626, Culture=neutral, PublicKeyToken=67e7b740cdfc2d3f, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
<PackageReference Include="UTF.Unknown" Version="2.5.1" />
<PackageReference Include="Melanchall.DryWetMidi" Version="8.0.1" />
<PackageReference Include="UTF.Unknown" Version="2.6.0" />
<PackageReference Include="Melanchall.DryWetMidi" Version="8.0.2" />
</ItemGroup>
<ItemGroup>

View File

@@ -22,7 +22,6 @@ using QuickLook.Common.Annotations;
using QuickLook.Common.Helpers;
using QuickLook.Common.Plugin;
using QuickLook.Plugin.VideoViewer.AudioTrack;
using QuickLook.Plugin.VideoViewer.Extensions;
using QuickLook.Plugin.VideoViewer.LyricTrack;
using System;
using System.ComponentModel;
@@ -69,7 +68,7 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
_context = context;
mediaElement.MediaUriPlayer.LAVFilterDirectory =
IntPtr.Size == 8 ? "LAVFilters-x64\\" : "LAVFilters-x86\\";
IntPtr.Size == 8 ? @"LAVFilters-x64\" : @"LAVFilters-x86\";
//ShowViedoControlContainer(null, null);
viewerPanel.PreviewMouseMove += ShowViedoControlContainer;
@@ -83,21 +82,21 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
buttonPlayPause.Click += TogglePlayPause;
buttonLoop.Click += ToggleShouldLoop;
buttonTime.Click += (sender, e) => buttonTime.Tag = (string)buttonTime.Tag == "Time" ? "Length" : "Time";
buttonMute.Click += (sender, e) => volumeSliderLayer.Visibility = Visibility.Visible;
volumeSliderLayer.MouseDown += (sender, e) => volumeSliderLayer.Visibility = Visibility.Collapsed;
buttonTime.Click += (_, _) => buttonTime.Tag = (string)buttonTime.Tag == "Time" ? "Length" : "Time";
buttonMute.Click += (_, _) => volumeSliderLayer.Visibility = Visibility.Visible;
volumeSliderLayer.MouseDown += (_, _) => volumeSliderLayer.Visibility = Visibility.Collapsed;
sliderProgress.PreviewMouseDown += (sender, e) =>
sliderProgress.PreviewMouseDown += (_, e) =>
{
_wasPlaying = mediaElement.IsPlaying;
mediaElement.Pause();
};
sliderProgress.PreviewMouseUp += (sender, e) =>
sliderProgress.PreviewMouseUp += (_, _) =>
{
if (_wasPlaying) mediaElement.Play();
};
PreviewMouseWheel += (sender, e) => ChangeVolume((double)e.Delta / 120 * 0.04);
PreviewMouseWheel += (_, e) => ChangeVolume(e.Delta / 120d * 0.04d);
}
private partial void LoadAndInsertGlassLayer();
@@ -285,22 +284,14 @@ public partial class ViewerPanel : UserControl, IDisposable, INotifyPropertyChan
metaArtists.Text = artist;
metaAlbum.Text = album;
// Extract cover art
var coverData = info.Get(StreamKind.General, 0, "Cover_Data");
if (!string.IsNullOrEmpty(coverData))
{
var coverBytes = Convert.FromBase64String
(
coverData.Contains(' ') // MediaInfo may will return multiple covers
? coverData.Split(" / ")[0] // Get the first cover only
: coverData
);
using var ms = new MemoryStream(coverBytes);
CoverArt = BitmapFrame.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
var coverBytes = CoverDataExtractor.Extract(coverData);
CoverArt = CoverDataExtractor.Extract(coverBytes);
}
catch (Exception)
catch (Exception e)
{
Debug.WriteLine(e);
metaTitle.Text = Path.GetFileName(path);
metaArtists.Text = metaAlbum.Text = string.Empty;
}

View File

@@ -0,0 +1,88 @@
// Copyright © 2017-2025 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 <http://www.gnu.org/licenses/>.
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace QuickLook.Controls;
public sealed class LeftContextMenuBehavior : Behavior<FrameworkElement>
{
public Point? PlacementOffset { get; set; } = null;
public PlacementMode Placement { get; set; } = PlacementMode.Bottom;
public double? PlacementOffsetX
{
get => PlacementOffset?.X;
set => PlacementOffset = value != null ? new(value ?? 0d, PlacementOffset?.Y ?? 0d) : null;
}
public double? PlacementOffsetY
{
get => PlacementOffset?.Y;
set => PlacementOffset = value != null ? new(PlacementOffset?.X ?? 0d, value ?? 0d) : null;
}
public LeftContextMenuBehavior()
{
}
protected override void OnAttached()
{
base.OnAttached();
Register(AssociatedObject, PlacementOffset, Placement);
}
protected override void OnDetaching()
{
base.OnDetaching();
Unregister(AssociatedObject);
}
public static void Register(FrameworkElement frameworkElement, Point? placementOffset = null, PlacementMode placement = PlacementMode.Bottom)
{
if (frameworkElement?.ContextMenu == null)
{
return;
}
frameworkElement.PreviewMouseRightButtonUp += (_, e) => e.Handled = true;
frameworkElement.MouseRightButtonUp += (_, e) => e.Handled = true;
frameworkElement.PreviewMouseLeftButtonDown += (_, _) =>
{
ContextMenu contextMenu = frameworkElement.ContextMenu;
if (contextMenu != null)
{
if (contextMenu.PlacementTarget != frameworkElement)
{
contextMenu.PlacementTarget = frameworkElement;
contextMenu.PlacementRectangle = new Rect(placementOffset ?? new Point(), new Size(frameworkElement.ActualWidth, frameworkElement.ActualHeight));
contextMenu.Placement = placement;
contextMenu.StaysOpen = false;
}
contextMenu.IsOpen = !contextMenu.IsOpen;
}
};
}
public static void Unregister(FrameworkElement frameworkElement)
{
_ = frameworkElement;
}
}

View File

@@ -36,7 +36,7 @@ internal class PluginManager
private PluginManager()
{
LoadPlugins(App.UserPluginPath);
LoadPlugins(Path.Combine(App.AppPath, "QuickLook.Plugin\\"));
LoadPlugins(Path.Combine(App.AppPath, @"QuickLook.Plugin\"));
InitLoadedPlugins();
}

View File

@@ -102,10 +102,10 @@
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="WPF-UI.Violeta" Version="4.0.3.2">
<PackageReference Include="WPF-UI.Violeta" Version="4.0.3.6">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Lib.Harmony" Version="2.3.6">
<PackageReference Include="Lib.Harmony" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="UnblockZoneIdentifier" Version="1.0.0">

View File

@@ -182,6 +182,7 @@
<MW_Run>{0} ausführen</MW_Run>
<MW_Share>Freigeben</MW_Share>
<MW_Reload>Neu laden</MW_Reload>
<MW_More>Mehr</MW_More>
<Icon_RunAtStartup>Beim Systemstart &amp;ausführen</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Nach &amp;Updates suchen</Icon_CheckUpdate>
@@ -216,6 +217,7 @@
<MW_Run>Run {0}</MW_Run>
<MW_Share>Share</MW_Share>
<MW_Reload>Reload</MW_Reload>
<MW_More>More</MW_More>
<Icon_RunAtStartup>Run at &amp;Startup</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Check for &amp;Updates...</Icon_CheckUpdate>
@@ -234,6 +236,8 @@
<InfoPanel_Files>{0} files</InfoPanel_Files>
<InfoPanel_FolderAndFile>({0} and {1})</InfoPanel_FolderAndFile>
<InfoPanel_CantPreventClosing>Cancellation of "Prevent Closing" is not supported</InfoPanel_CantPreventClosing>
<InfoPanelMoreItem_CopyAsPath>Copy as path</InfoPanelMoreItem_CopyAsPath>
<InfoPanelMoreItem_CopySucc>Copy successfully</InfoPanelMoreItem_CopySucc>
</en>
<es>
<UI_FontFamily>Segoe UI</UI_FontFamily>
@@ -250,6 +254,7 @@
<MW_Run>Iniciar {0}</MW_Run>
<MW_Share>Compartir</MW_Share>
<MW_Reload>Recargar</MW_Reload>
<MW_More>Más</MW_More>
<Icon_RunAtStartup>Iniciar con el &amp;sistema</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Buscar &amp;Actualizaciones...</Icon_CheckUpdate>
@@ -279,6 +284,7 @@
<MW_OpenWith>Ouvrir avec {0}</MW_OpenWith>
<MW_Run>Exécuter {0}</MW_Run>
<MW_Reload>Recharger</MW_Reload>
<MW_More>Plus</MW_More>
<Icon_RunAtStartup>Exécuter au &amp;démarrage</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Vérifier s'il existe des &amp;mises à jour...</Icon_CheckUpdate>
@@ -308,6 +314,7 @@
<MW_OpenWith>Apri con {0}</MW_OpenWith>
<MW_Run>Esegui {0}</MW_Run>
<MW_Reload>Ricarica</MW_Reload>
<MW_More>Altro</MW_More>
<Icon_RunAtStartup>Esegui all'&amp;Avvio</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Verifica &amp;Aggiornamenti...</Icon_CheckUpdate>
@@ -340,6 +347,7 @@
<MW_Run>{0} を起動</MW_Run>
<MW_Share>シェア</MW_Share>
<MW_Reload>再読み込み</MW_Reload>
<MW_More>その他</MW_More>
<Icon_RunAtStartup>スタートアップ時に起動</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>更新を確認する... (&amp;U)</Icon_CheckUpdate>
@@ -424,6 +432,7 @@
<MW_Run>Uruchom {0}</MW_Run>
<MW_Share>Udostępnij</MW_Share>
<MW_Reload>Przeładuj</MW_Reload>
<MW_More>Więcej</MW_More>
<Icon_RunAtStartup>Uruchamiaj automatycznie z systemem</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Sprawdź &amp;aktualizacje...</Icon_CheckUpdate>
@@ -458,6 +467,7 @@
<MW_Run>Executar {0}</MW_Run>
<MW_Share>Compartilhar</MW_Share>
<MW_Reload>Recarregar</MW_Reload>
<MW_More>Mais</MW_More>
<Icon_RunAtStartup>Executar na &amp;Inicialização</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Procurar por &amp;Atualizações...</Icon_CheckUpdate>
@@ -515,6 +525,7 @@
<MW_PreventClosing>Закрепить</MW_PreventClosing>
<MW_Share>Поделиться</MW_Share>
<MW_Reload>Перезагрузить</MW_Reload>
<MW_More>Еще</MW_More>
<Icon_RunAtStartup>Автозапуск</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Проверить &amp;обновления…</Icon_CheckUpdate>
@@ -575,6 +586,7 @@
<MW_Run>Запустити {0}</MW_Run>
<MW_Share>Поширити</MW_Share>
<MW_Reload>Перезавантажити</MW_Reload>
<MW_More>Більше</MW_More>
<Icon_RunAtStartup>Запускати під час &amp;старту</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Перевірити наявність &amp;оновлення…</Icon_CheckUpdate>
@@ -634,6 +646,7 @@
<MW_Run>运行 {0}</MW_Run>
<MW_Share>分享</MW_Share>
<MW_Reload>重新加载</MW_Reload>
<MW_More>更多</MW_More>
<Icon_RunAtStartup>启动时自动运行 (&amp;S)</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>检查更新... (&amp;U)</Icon_CheckUpdate>
@@ -668,6 +681,7 @@
<MW_Run>執行 {0}</MW_Run>
<MW_Share>分享</MW_Share>
<MW_Reload>重新載入</MW_Reload>
<MW_More>更多</MW_More>
<Icon_RunAtStartup>系統啟動時自動執行 (&amp;S)</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>檢查更新... (&amp;U)</Icon_CheckUpdate>
@@ -797,4 +811,38 @@
<InfoPanel_Files>{0} αρχεία</InfoPanel_Files>
<InfoPanel_FolderAndFile>({0} και {1})</InfoPanel_FolderAndFile>
</el>
<sv>
<UI_FontFamily>Segoe UI</UI_FontFamily>
<APP_START>QuickLook körs i bakgrunden.</APP_START>
<APP_SECOND>QuickLook körs redan</APP_SECOND>
<APP_SECOND_TEXT>QuickLook möjliggör snabb förhandsgranskning av vissa filtyper genom att trycka ned mellanslag när filen är markerad.</APP_SECOND_TEXT>
<APP_PATH_NOT_WRITABLE>Sökvägen "{0}" är inte skrivbar. Kontrollera att du har rätt behörigheter.</APP_PATH_NOT_WRITABLE>
<MW_StayTop>Behåll överst</MW_StayTop>
<MW_PreventClosing>Behåll öppet</MW_PreventClosing>
<MW_BrowseFolder>Bläddra i {0}</MW_BrowseFolder>
<MW_Open>Öppna {0}</MW_Open>
<MW_OpenWith>Öppna med {0}</MW_OpenWith>
<MW_OpenWithMenu>Öppna med…</MW_OpenWithMenu>
<MW_Run>Kör {0}</MW_Run>
<MW_Share>Dela</MW_Share>
<MW_Reload>Ladda om</MW_Reload>
<Icon_RunAtStartup>Kör vid &amp;start</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Leta efter &amp;uppdateringar...</Icon_CheckUpdate>
<Icon_GetPlugin>Hitta nya &amp;tillägg...</Icon_GetPlugin>
<Icon_OpenDataFolder>Öppna datamappen</Icon_OpenDataFolder>
<Icon_Restart>&amp;Starta om</Icon_Restart>
<Icon_Quit>&amp;Avsluta</Icon_Quit>
<Update_NoUpdate>Du har den senaste versionen.</Update_NoUpdate>
<Update_Found>QuickLook {0} har lanserats. Klicka här för att öppna nedladdningssidan.</Update_Found>
<Update_Error>Det gick inte att leta efter uppdateringar: {0}</Update_Error>
<InfoPanel_LastModified>Senast ändrad: {0}</InfoPanel_LastModified>
<InfoPanel_DriveSize>Kapacitet: {0} ({1} ledigt)</InfoPanel_DriveSize>
<InfoPanel_Folder>{0} mapp</InfoPanel_Folder>
<InfoPanel_Folders>{0} mappar</InfoPanel_Folders>
<InfoPanel_File>{0} fil</InfoPanel_File>
<InfoPanel_Files>{0} filer</InfoPanel_Files>
<InfoPanel_FolderAndFile>({0} och {1})</InfoPanel_FolderAndFile>
<InfoPanel_CantPreventClosing>Det är inte möjligt att avbryta "Behåll öppet", stäng fönstret istället.</InfoPanel_CantPreventClosing>
</sv>
</Translations>

View File

@@ -35,19 +35,7 @@ internal partial class TrayIconManager : IDisposable
private readonly TrayIconHost _icon;
private readonly TrayMenuItem _itemAutorun =
new()
{
Header = TranslationHelper.Get("Icon_RunAtStartup"),
Command = new RelayCommand(() =>
{
if (AutoStartupHelper.IsAutorun())
AutoStartupHelper.RemoveAutorunShortcut();
else
AutoStartupHelper.CreateAutorunShortcut();
}),
IsEnabled = !App.IsUWP,
};
private readonly TrayMenuItem _itemAutorun = null!;
private TrayIconManager()
{
@@ -79,7 +67,18 @@ internal partial class TrayIconManager : IDisposable
Header = TranslationHelper.Get("Icon_OpenDataFolder"),
Command = new RelayCommand(() => Process.Start("explorer.exe", SettingHelper.LocalDataPath)),
},
_itemAutorun,
_itemAutorun = new TrayMenuItem()
{
Header = TranslationHelper.Get("Icon_RunAtStartup"),
Command = new RelayCommand(() =>
{
if (AutoStartupHelper.IsAutorun())
AutoStartupHelper.RemoveAutorunShortcut();
else
AutoStartupHelper.CreateAutorunShortcut();
}),
IsEnabled = !App.IsUWP,
},
new TrayMenuItem()
{
Header = TranslationHelper.Get("Icon_Restart"),
@@ -94,7 +93,10 @@ internal partial class TrayIconManager : IDisposable
IsVisible = SettingHelper.Get("ShowTrayIcon", true)
};
_icon.RightDown += (sender, e) => { _itemAutorun.IsChecked = AutoStartupHelper.IsAutorun(); };
_icon.RightDown += (_, _) =>
{
_itemAutorun.IsChecked = AutoStartupHelper.IsAutorun();
};
}
public void Dispose()

View File

@@ -22,12 +22,13 @@ using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace QuickLook;
public partial class ViewerWindow : INotifyPropertyChanged
{
private readonly ResourceDictionary _darkDict = new ResourceDictionary
private readonly ResourceDictionary _darkDict = new()
{
Source = new Uri("pack://application:,,,/QuickLook.Common;component/Styles/MainWindowStyles.Dark.xaml")
};
@@ -50,6 +51,8 @@ public partial class ViewerWindow : INotifyPropertyChanged
public ContextObject ContextObject { get; private set; }
public Themes CurrentTheme { get; private set; }
public ICommand CloseCommand { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]

View File

@@ -6,7 +6,10 @@
xmlns:converters="clr-namespace:QuickLook.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:glassLayer="clr-namespace:QuickLook.Controls.GlassLayer"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:vio="http://schemas.lepo.co/wpfui/2022/xaml/violeta"
x:Name="mainWindow"
Title="QuickLook"
MinWidth="400"
@@ -122,15 +125,32 @@
DockPanel.Dock="Right"
Style="{StaticResource CaptionButtonStyle}"
ToolTip="Reload" />
<!--<Button x:Name="buttonOpen" DockPanel.Dock="Right"
Style="{StaticResource CaptionTextButtonStyle}"
Visibility="{Binding ActualWidth, ElementName=windowCaptionContainer, Converter={StaticResource WidthToVisibilityCollapsedConverter}}">
<Button.Content>
<TextBlock x:Name="buttonOpenText" VerticalAlignment="Center">
Open with <Bold>AppName</Bold>
</TextBlock>
</Button.Content>
</Button>-->
<Button x:Name="buttonMore"
Content="&#xE712;"
DockPanel.Dock="Right"
Style="{StaticResource CaptionButtonStyle}"
ToolTip="More">
<Button.ContextMenu>
<ContextMenu FontSize="12">
<MenuItem x:Name="moreItemCopyAsPath">
<MenuItem.Icon>
<ui:FontIcon FontFamily="{DynamicResource SymbolThemeFontFamily}" Glyph="{x:Static ui:FontSymbols.Copy}" />
</MenuItem.Icon>
</MenuItem>
<Separator Visibility="Collapsed" />
<MenuItem x:Name="moreItemOpenSettings"
Header="Settings"
Visibility="Collapsed">
<MenuItem.Icon>
<ui:FontIcon FontFamily="{DynamicResource SymbolThemeFontFamily}" Glyph="{x:Static ui:FontSymbols.Settings}" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
<i:Interaction.Behaviors>
<controls:LeftContextMenuBehavior />
</i:Interaction.Behaviors>
</Button>
<Button x:Name="buttonTop"
DockPanel.Dock="Left"
Tag="Auto"

View File

@@ -20,6 +20,7 @@ using QuickLook.Common.Helpers;
using QuickLook.Common.Plugin;
using QuickLook.Helpers;
using System;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Input;
@@ -110,12 +111,32 @@ public partial class ViewerWindow : Window
buttonReload.Visibility = SettingHelper.Get("ShowReload", false) ? Visibility.Visible : Visibility.Collapsed;
moreItemCopyAsPath.Click += (_, _) =>
{
try
{
Clipboard.SetText(_path);
Toast.Success(TranslationHelper.Get("InfoPanelMoreItem_CopySucc"));
}
catch (Exception e)
{
Debug.WriteLine(e);
}
};
moreItemOpenSettings.Click += (_, _) =>
{
Toast.Warning("Coming soon...");
};
// Set UI translations
buttonTop.ToolTip = TranslationHelper.Get("MW_StayTop");
buttonPin.ToolTip = TranslationHelper.Get("MW_PreventClosing");
buttonOpenWith.ToolTip = TranslationHelper.Get("MW_OpenWithMenu");
buttonShare.ToolTip = TranslationHelper.Get("MW_Share");
buttonReload.ToolTip = TranslationHelper.Get("MW_Reload", failsafe: "Reload");
buttonMore.ToolTip = TranslationHelper.Get("MW_More", failsafe: "More");
moreItemCopyAsPath.Header = TranslationHelper.Get("InfoPanelMoreItem_CopyAsPath");
}
public new void Close()

189
SUPPORTED_FORMATS.md Normal file
View File

@@ -0,0 +1,189 @@
## Supported Formats in QuickLook
### Text files
- `.txt` (Plain text file)
- `.rtf` (Rich Text Format)
- Most other plain text files
### Image files
- `.apng` (Animated PNG)
- `.ari`, `.arw` (Sony RAW image)
- `.avif` (AV1 Image File Format)
- `.ani` (Animated cursor)
- `.bay` (Casio RAW image)
- `.bmp` (Bitmap image)
- `.cap` (Phase One RAW image)
- `.cr2`, `.cr3`, `.crw` (Canon RAW image)
- `.cur` (Windows cursor)
- `.dcr`, `.dcs`, `.drf` (Kodak RAW image)
- `.dds` (DirectDraw Surface)
- `.dng` (Digital Negative RAW)
- `.eip` (Capture One Enhanced Image Package)
- `.emf` (Enhanced Metafile)
- `.erf` (Epson RAW image)
- `.exr` (OpenEXR image)
- `.fff` (Imacon/Hasselblad RAW)
- `.gif` (Graphics Interchange Format)
- `.hdr` (High Dynamic Range image)
- `.heic`, `.heif` (High Efficiency Image Format)
- `.ico`, `.icon` (Windows icon)
- `.icns` (macOS icon)
- `.iiq` (Phase One RAW image)
- `.jfif` (JPEG File Interchange Format)
- `.jp2`, `.j2k`, `.jpf`, `.jpx`, `.jpm` (JPEG 2000)
- `.jpeg`, `.jpg` (JPEG image)
- `.jxl` (JPEG XL)
- `.jxr` (JPEG XR)
- `.k25`, `.kdc` (Kodak RAW image)
- `.lottie` (Lottie animation)
- `.mdc` (MagicDraw UML)
- `.mef` (Mamiya RAW image)
- `.mos` (Leaf RAW image)
- `.mrw` (Minolta RAW image)
- `.mj2` (Motion JPEG 2000)
- `.miff` (Magick Image File Format)
- `.nef`, `.nrw` (Nikon RAW image)
- `.obm` (Open BIM)
- `.orf` (Olympus RAW image)
- `.pbm`, `.pgm`, `.pnm`, `.ppm` (Portable bitmap/graymap/pixmap)
- `.pcx` (Paintbrush image)
- `.pef` (Pentax RAW image)
- `.png` (Portable Network Graphics)
- `.psb`, `.psd` (Adobe Photoshop)
- `.ptx` (Pentax RAW image)
- `.pxn` (PixelNet image)
- `.qoi` (Quite OK Image)
- `.r3d` (REDCODE RAW)
- `.raf` (Fujifilm RAW image)
- `.raw` (Generic RAW image)
- `.rw2`, `.rwl`, `.rwz` (Panasonic/Leica RAW image)
- `.sr2`, `.srf`, `.srw` (Sony RAW image)
- `.svg`, `.svgz` (Scalable Vector Graphics)
- `.svga` (SVGA animation)
- `.tga` (Truevision TGA)
- `.tgs` (Telegram sticker, Lottie animation)
- `.tif`, `.tiff` (Tagged Image File Format)
- `.wdp` (Windows Media Photo)
- `.webp` (WebP image)
- `.wmf` (Windows Metafile)
- `.x3f` (Sigma RAW image)
- `.xcf` (GIMP image)
- `.xbm`, `.xpm` (X11 bitmap/pixmap)
### PDF files
- `.pdf` (Portable Document Format)
### Archive files
- `.7z` (7-Zip archive)
- `.bz2` (Bzip2 archive)
- `.cb7`, `.cbr`, `.cbt`, `.cbz` (Comic book archive)
- `.crx` (Chrome extension)
- `.gz` (Gzip archive)
- `.jar` (Java archive)
- `.lz` (Lzip archive)
- `.nupkg` (NuGet package)
- `.rar` (RAR archive)
- `.tar`, `.tgz` (TAR archive)
- `.vsix` (Visual Studio extension)
- `.xz` (XZ archive)
- `.zip` (ZIP archive)
### Markdown files
- `.md`, `.markdown` (Markdown)
- `.mdx` (MDX: Markdown + JSX)
- `.mmd` (MultiMarkdown)
- `.mkd`, `.mdwn`, `.mdown` (Markdown variants)
- `.mdc` (Cursor AI Markdown)
- `.qmd` (Quarto Markdown)
- `.rmd`, `.rmarkdown` (R Markdown)
- `.apib` (API Blueprint)
- `.mdtxt`, `.mdtext` (Other Markdown variants)
### CSV/TSV files
- `.csv` (Comma-separated values)
- `.tsv` (Tab-separated values)
### Font files
- `.ttf` (TrueType Font)
- `.otf` (OpenType Font)
- `.woff`, `.woff2` (Web Open Font Format)
- `.ttc` (TrueType Collection)
### Office files
- `.doc`, `.docx`, `.docm` (Microsoft Word)
- `.odt` (OpenDocument Text)
- `.xls`, `.xlsx`, `.xlsm`, `.xlsb` (Microsoft Excel)
- `.ods` (OpenDocument Spreadsheet)
- `.ppt`, `.pptx`, `.odp` (Microsoft PowerPoint / OpenDocument Presentation)
- `.vsd`, `.vsdx` (Microsoft Visio)
### Video/Audio files
- Most common video formats (e.g., `.mp4`, `.mkv`, `.avi`, `.mov`, `.wmv`, `.flv`, `.webm`, etc.)
- Most common audio formats (e.g., `.mp3`, `.flac`, `.wav`, `.aac`, `.ogg`, `.m4a`, etc.)
### HTML/Web files
- `.mht`, `.mhtml` (MHTML web archive)
- `.htm`, `.html` (HTML file)
- `.url` (Internet shortcut, http/https)
### Mail files
- `.eml` (Email message)
- `.msg` (Outlook message)
### Thumbnail/Design files
- `.cdr` (CorelDRAW project file)
- `.fig` (Figma project file)
- `.kra` (Krita project file)
- `.pdn` (Paint.NET project file)
- `.pip`, `.pix` (Pixso project file)
- `.sketch` (Sketch project file)
- `.xd` (Adobe XD project file)
- `.xmind` (XMind mind map file)
### ELF/Mach-O/UImage files
- `.axf` (ARM Executable)
- `.bin` (Binary file)
- `.elf` (Executable and Linkable Format)
- `.o`, `.out` (Object file)
- `.prx` (PSP executable)
- `.puff` (Puff executable)
- `.ko`, `.mod` (Linux kernel module)
- `.so` (Shared object)
- `.uimage` (U-Boot image)
- `.dylib` (macOS dynamic library)
### PE (Portable Executable) files
- `.exe` (Windows executable)
- `.sys` (Windows system file)
- `.scr` (Windows screensaver)
- `.ocx` (ActiveX control)
- `.cpl` (Control panel item)
- `.bpl` (Borland package library)
- `.dll` (Dynamic-link library)
- `.ax` (DirectShow filter)
- `.drv` (Driver file)
- `.vxd` (Virtual device driver)
- `.mui` (Multilingual User Interface)
- `.mun` (Windows resource file)
- `.tlb` (Type library)
- `.efi` (Extensible Firmware Interface)
- `.mz` (DOS executable)
### App Installer files
- `.apk` (Android Package)
- `.aab` (Android App Bundle)
- `.appx`, `.appxbundle` (Windows AppX installer)
- `.msi` (Windows Installer)
- `.msix`, `.msixbundle` (Windows MSIX installer)
- `.dmg` (macOS Disk Image)
- `.ipa` (iOS App Package)
- `.hap` (HarmonyOS App Package)
- `.deb` (Debian package)
- `.appimage` (Linux AppImage)
- `.rpm` (Red Hat Package Manager)
- `.wgt`, `.wgtu` (UniApp Widget)
### Plugin Installer files
- `.qlplugin` (QuickLook plugin package)