Compare commits

...

4 Commits

Author SHA1 Message Date
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
12 changed files with 442 additions and 28 deletions

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

View File

@@ -26,6 +26,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading;
namespace QuickLook.Plugin.FontViewer; namespace QuickLook.Plugin.FontViewer;
@@ -34,6 +35,7 @@ public class WebfontPanel : WebpagePanel
protected const string _resourcePrefix = "QuickLook.Plugin.FontViewer.Resources."; protected const string _resourcePrefix = "QuickLook.Plugin.FontViewer.Resources.";
protected internal static readonly Dictionary<string, byte[]> _resources = []; protected internal static readonly Dictionary<string, byte[]> _resources = [];
protected byte[] _homePage; protected byte[] _homePage;
protected ObservableFileStream _fontStream = null;
static WebfontPanel() static WebfontPanel()
{ {
@@ -153,10 +155,11 @@ public class WebfontPanel : WebpagePanel
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = new ObservableFileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentType()); fileStream, 200, "OK", MimeTypes.GetContentType());
args.Response = response; 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) public static bool ContainsKey(string key)
{ {
return _resources.ContainsKey(key); return _resources.ContainsKey(key);

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

@@ -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

@@ -182,6 +182,7 @@
<MW_Run>{0} ausführen</MW_Run> <MW_Run>{0} ausführen</MW_Run>
<MW_Share>Freigeben</MW_Share> <MW_Share>Freigeben</MW_Share>
<MW_Reload>Neu laden</MW_Reload> <MW_Reload>Neu laden</MW_Reload>
<MW_More>Mehr</MW_More>
<Icon_RunAtStartup>Beim Systemstart &amp;ausführen</Icon_RunAtStartup> <Icon_RunAtStartup>Beim Systemstart &amp;ausführen</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Nach &amp;Updates suchen</Icon_CheckUpdate> <Icon_CheckUpdate>Nach &amp;Updates suchen</Icon_CheckUpdate>
@@ -216,6 +217,7 @@
<MW_Run>Run {0}</MW_Run> <MW_Run>Run {0}</MW_Run>
<MW_Share>Share</MW_Share> <MW_Share>Share</MW_Share>
<MW_Reload>Reload</MW_Reload> <MW_Reload>Reload</MW_Reload>
<MW_More>More</MW_More>
<Icon_RunAtStartup>Run at &amp;Startup</Icon_RunAtStartup> <Icon_RunAtStartup>Run at &amp;Startup</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Check for &amp;Updates...</Icon_CheckUpdate> <Icon_CheckUpdate>Check for &amp;Updates...</Icon_CheckUpdate>
@@ -250,6 +252,7 @@
<MW_Run>Iniciar {0}</MW_Run> <MW_Run>Iniciar {0}</MW_Run>
<MW_Share>Compartir</MW_Share> <MW_Share>Compartir</MW_Share>
<MW_Reload>Recargar</MW_Reload> <MW_Reload>Recargar</MW_Reload>
<MW_More>Más</MW_More>
<Icon_RunAtStartup>Iniciar con el &amp;sistema</Icon_RunAtStartup> <Icon_RunAtStartup>Iniciar con el &amp;sistema</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Buscar &amp;Actualizaciones...</Icon_CheckUpdate> <Icon_CheckUpdate>Buscar &amp;Actualizaciones...</Icon_CheckUpdate>
@@ -279,6 +282,7 @@
<MW_OpenWith>Ouvrir avec {0}</MW_OpenWith> <MW_OpenWith>Ouvrir avec {0}</MW_OpenWith>
<MW_Run>Exécuter {0}</MW_Run> <MW_Run>Exécuter {0}</MW_Run>
<MW_Reload>Recharger</MW_Reload> <MW_Reload>Recharger</MW_Reload>
<MW_More>Plus</MW_More>
<Icon_RunAtStartup>Exécuter au &amp;démarrage</Icon_RunAtStartup> <Icon_RunAtStartup>Exécuter au &amp;démarrage</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Vérifier s'il existe des &amp;mises à jour...</Icon_CheckUpdate> <Icon_CheckUpdate>Vérifier s'il existe des &amp;mises à jour...</Icon_CheckUpdate>
@@ -308,6 +312,7 @@
<MW_OpenWith>Apri con {0}</MW_OpenWith> <MW_OpenWith>Apri con {0}</MW_OpenWith>
<MW_Run>Esegui {0}</MW_Run> <MW_Run>Esegui {0}</MW_Run>
<MW_Reload>Ricarica</MW_Reload> <MW_Reload>Ricarica</MW_Reload>
<MW_More>Altro</MW_More>
<Icon_RunAtStartup>Esegui all'&amp;Avvio</Icon_RunAtStartup> <Icon_RunAtStartup>Esegui all'&amp;Avvio</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Verifica &amp;Aggiornamenti...</Icon_CheckUpdate> <Icon_CheckUpdate>Verifica &amp;Aggiornamenti...</Icon_CheckUpdate>
@@ -340,6 +345,7 @@
<MW_Run>{0} を起動</MW_Run> <MW_Run>{0} を起動</MW_Run>
<MW_Share>シェア</MW_Share> <MW_Share>シェア</MW_Share>
<MW_Reload>再読み込み</MW_Reload> <MW_Reload>再読み込み</MW_Reload>
<MW_More>その他</MW_More>
<Icon_RunAtStartup>スタートアップ時に起動</Icon_RunAtStartup> <Icon_RunAtStartup>スタートアップ時に起動</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>更新を確認する... (&amp;U)</Icon_CheckUpdate> <Icon_CheckUpdate>更新を確認する... (&amp;U)</Icon_CheckUpdate>
@@ -424,6 +430,7 @@
<MW_Run>Uruchom {0}</MW_Run> <MW_Run>Uruchom {0}</MW_Run>
<MW_Share>Udostępnij</MW_Share> <MW_Share>Udostępnij</MW_Share>
<MW_Reload>Przeładuj</MW_Reload> <MW_Reload>Przeładuj</MW_Reload>
<MW_More>Więcej</MW_More>
<Icon_RunAtStartup>Uruchamiaj automatycznie z systemem</Icon_RunAtStartup> <Icon_RunAtStartup>Uruchamiaj automatycznie z systemem</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Sprawdź &amp;aktualizacje...</Icon_CheckUpdate> <Icon_CheckUpdate>Sprawdź &amp;aktualizacje...</Icon_CheckUpdate>
@@ -458,6 +465,7 @@
<MW_Run>Executar {0}</MW_Run> <MW_Run>Executar {0}</MW_Run>
<MW_Share>Compartilhar</MW_Share> <MW_Share>Compartilhar</MW_Share>
<MW_Reload>Recarregar</MW_Reload> <MW_Reload>Recarregar</MW_Reload>
<MW_More>Mais</MW_More>
<Icon_RunAtStartup>Executar na &amp;Inicialização</Icon_RunAtStartup> <Icon_RunAtStartup>Executar na &amp;Inicialização</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Procurar por &amp;Atualizações...</Icon_CheckUpdate> <Icon_CheckUpdate>Procurar por &amp;Atualizações...</Icon_CheckUpdate>
@@ -515,6 +523,7 @@
<MW_PreventClosing>Закрепить</MW_PreventClosing> <MW_PreventClosing>Закрепить</MW_PreventClosing>
<MW_Share>Поделиться</MW_Share> <MW_Share>Поделиться</MW_Share>
<MW_Reload>Перезагрузить</MW_Reload> <MW_Reload>Перезагрузить</MW_Reload>
<MW_More>Еще</MW_More>
<Icon_RunAtStartup>Автозапуск</Icon_RunAtStartup> <Icon_RunAtStartup>Автозапуск</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Проверить &amp;обновления…</Icon_CheckUpdate> <Icon_CheckUpdate>Проверить &amp;обновления…</Icon_CheckUpdate>
@@ -575,6 +584,7 @@
<MW_Run>Запустити {0}</MW_Run> <MW_Run>Запустити {0}</MW_Run>
<MW_Share>Поширити</MW_Share> <MW_Share>Поширити</MW_Share>
<MW_Reload>Перезавантажити</MW_Reload> <MW_Reload>Перезавантажити</MW_Reload>
<MW_More>Більше</MW_More>
<Icon_RunAtStartup>Запускати під час &amp;старту</Icon_RunAtStartup> <Icon_RunAtStartup>Запускати під час &amp;старту</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>Перевірити наявність &amp;оновлення…</Icon_CheckUpdate> <Icon_CheckUpdate>Перевірити наявність &amp;оновлення…</Icon_CheckUpdate>
@@ -634,6 +644,7 @@
<MW_Run>运行 {0}</MW_Run> <MW_Run>运行 {0}</MW_Run>
<MW_Share>分享</MW_Share> <MW_Share>分享</MW_Share>
<MW_Reload>重新加载</MW_Reload> <MW_Reload>重新加载</MW_Reload>
<MW_More>更多</MW_More>
<Icon_RunAtStartup>启动时自动运行 (&amp;S)</Icon_RunAtStartup> <Icon_RunAtStartup>启动时自动运行 (&amp;S)</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>检查更新... (&amp;U)</Icon_CheckUpdate> <Icon_CheckUpdate>检查更新... (&amp;U)</Icon_CheckUpdate>
@@ -668,6 +679,7 @@
<MW_Run>執行 {0}</MW_Run> <MW_Run>執行 {0}</MW_Run>
<MW_Share>分享</MW_Share> <MW_Share>分享</MW_Share>
<MW_Reload>重新載入</MW_Reload> <MW_Reload>重新載入</MW_Reload>
<MW_More>更多</MW_More>
<Icon_RunAtStartup>系統啟動時自動執行 (&amp;S)</Icon_RunAtStartup> <Icon_RunAtStartup>系統啟動時自動執行 (&amp;S)</Icon_RunAtStartup>
<Icon_ToolTip>QuickLook v{0}</Icon_ToolTip> <Icon_ToolTip>QuickLook v{0}</Icon_ToolTip>
<Icon_CheckUpdate>檢查更新... (&amp;U)</Icon_CheckUpdate> <Icon_CheckUpdate>檢查更新... (&amp;U)</Icon_CheckUpdate>

View File

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

View File

@@ -22,12 +22,13 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
using System.Windows.Input;
namespace QuickLook; namespace QuickLook;
public partial class ViewerWindow : INotifyPropertyChanged 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") 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 ContextObject ContextObject { get; private set; }
public Themes CurrentTheme { get; private set; } public Themes CurrentTheme { get; private set; }
public ICommand CloseCommand { get; private set; }
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator] [NotifyPropertyChangedInvocator]

View File

@@ -6,7 +6,10 @@
xmlns:converters="clr-namespace:QuickLook.Converters" xmlns:converters="clr-namespace:QuickLook.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:glassLayer="clr-namespace:QuickLook.Controls.GlassLayer" 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: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" x:Name="mainWindow"
Title="QuickLook" Title="QuickLook"
MinWidth="400" MinWidth="400"
@@ -122,15 +125,24 @@
DockPanel.Dock="Right" DockPanel.Dock="Right"
Style="{StaticResource CaptionButtonStyle}" Style="{StaticResource CaptionButtonStyle}"
ToolTip="Reload" /> ToolTip="Reload" />
<!--<Button x:Name="buttonOpen" DockPanel.Dock="Right" <Button x:Name="buttonMore"
Style="{StaticResource CaptionTextButtonStyle}" Content="&#xE712;"
Visibility="{Binding ActualWidth, ElementName=windowCaptionContainer, Converter={StaticResource WidthToVisibilityCollapsedConverter}}"> DockPanel.Dock="Right"
<Button.Content> Style="{StaticResource CaptionButtonStyle}"
<TextBlock x:Name="buttonOpenText" VerticalAlignment="Center"> ToolTip="More">
Open with <Bold>AppName</Bold> <Button.ContextMenu>
</TextBlock> <ContextMenu FontSize="12">
</Button.Content> <MenuItem Command="{Binding OpenSettingsFileFolderCommand}" Header="SettingsFile">
</Button>--> <MenuItem.Icon>
<ui:FontIcon FontFamily="{DynamicResource SymbolThemeFontFamily}" Glyph="{x:Static ui:FontSymbols.OpenLocal}" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
<i:Interaction.Behaviors>
<controls:LeftContextMenuBehavior />
</i:Interaction.Behaviors>
</Button>
<Button x:Name="buttonTop" <Button x:Name="buttonTop"
DockPanel.Dock="Left" DockPanel.Dock="Left"
Tag="Auto" Tag="Auto"

View File

@@ -116,6 +116,7 @@ public partial class ViewerWindow : Window
buttonOpenWith.ToolTip = TranslationHelper.Get("MW_OpenWithMenu"); buttonOpenWith.ToolTip = TranslationHelper.Get("MW_OpenWithMenu");
buttonShare.ToolTip = TranslationHelper.Get("MW_Share"); buttonShare.ToolTip = TranslationHelper.Get("MW_Share");
buttonReload.ToolTip = TranslationHelper.Get("MW_Reload", failsafe: "Reload"); buttonReload.ToolTip = TranslationHelper.Get("MW_Reload", failsafe: "Reload");
buttonMore.ToolTip = TranslationHelper.Get("MW_More", failsafe: "More");
} }
public new void Close() public new void Close()