mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #3671 from Flow-Launcher/release_notes
Release Notes Window
This commit is contained in:
commit
60770da446
17 changed files with 1271 additions and 58 deletions
|
|
@ -220,5 +220,18 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetStringAsync(string url, CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Debug(ClassName, $"Url <{url}>");
|
||||
return await client.GetStringAsync(url, token);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
|||
_storage.Save();
|
||||
}
|
||||
|
||||
private string _theme = Constant.DefaultTheme;
|
||||
public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
|
||||
public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
|
||||
public string ColorScheme { get; set; } = "System";
|
||||
|
|
@ -64,6 +63,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
|||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
private string _theme = Constant.DefaultTheme;
|
||||
public string Theme
|
||||
{
|
||||
get => _theme;
|
||||
|
|
@ -79,6 +79,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
|||
}
|
||||
public bool UseDropShadowEffect { get; set; } = true;
|
||||
public BackdropTypes BackdropType{ get; set; } = BackdropTypes.None;
|
||||
public string ReleaseNotesVersion { get; set; } = string.Empty;
|
||||
|
||||
/* Appearance Settings. It should be separated from the setting later.*/
|
||||
public double WindowHeightSize { get; set; } = 42;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,15 @@ namespace Flow.Launcher.Plugin
|
|||
/// <param name="subTitle">Optional message subtitle</param>
|
||||
void ShowMsgError(string title, string subTitle = "");
|
||||
|
||||
/// <summary>
|
||||
/// Show the error message using Flow's standard error icon.
|
||||
/// </summary>
|
||||
/// <param name="title">Message title</param>
|
||||
/// <param name="buttonText">Message button content</param>
|
||||
/// <param name="buttonAction">Message button action</param>
|
||||
/// <param name="subTitle">Optional message subtitle</param>
|
||||
void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "");
|
||||
|
||||
/// <summary>
|
||||
/// Show the MainWindow when hiding
|
||||
/// </summary>
|
||||
|
|
@ -127,6 +136,27 @@ namespace Flow.Launcher.Plugin
|
|||
/// <param name="useMainWindowAsOwner">when true will use main windows as the owner</param>
|
||||
void ShowMsg(string title, string subTitle, string iconPath, bool useMainWindowAsOwner = true);
|
||||
|
||||
/// <summary>
|
||||
/// Show message box with button
|
||||
/// </summary>
|
||||
/// <param name="title">Message title</param>
|
||||
/// <param name="buttonText">Message button content</param>
|
||||
/// <param name="buttonAction">Message button action</param>
|
||||
/// <param name="subTitle">Message subtitle</param>
|
||||
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
|
||||
void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "");
|
||||
|
||||
/// <summary>
|
||||
/// Show message box with button
|
||||
/// </summary>
|
||||
/// <param name="title">Message title</param>
|
||||
/// <param name="buttonText">Message button content</param>
|
||||
/// <param name="buttonAction">Message button action</param>
|
||||
/// <param name="subTitle">Message subtitle</param>
|
||||
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
|
||||
/// <param name="useMainWindowAsOwner">when true will use main windows as the owner</param>
|
||||
void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true);
|
||||
|
||||
/// <summary>
|
||||
/// Open setting dialog
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@ namespace Flow.Launcher
|
|||
Current.Resources["SettingWindowFont"] = new FontFamily(_settings.SettingWindowFont);
|
||||
Current.Resources["ContentControlThemeFontFamily"] = new FontFamily(_settings.SettingWindowFont);
|
||||
|
||||
Notification.Install();
|
||||
|
||||
Ioc.Default.GetRequiredService<Portable>().PreStartCleanUpAfterPortabilityUpdate();
|
||||
|
||||
API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------");
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="InputSimulator" Version="1.0.4" />
|
||||
<PackageReference Include="MdXaml" Version="1.27.0" />
|
||||
<PackageReference Include="MdXaml.AnimatedGif" Version="1.27.0" />
|
||||
<PackageReference Include="MdXaml.Html" Version="1.27.0" />
|
||||
<PackageReference Include="MdXaml.Plugins" Version="1.27.0" />
|
||||
<PackageReference Include="MdXaml.Svg" Version="1.27.0" />
|
||||
<!-- Do not upgrade Microsoft.Extensions.DependencyInjection and Microsoft.Extensions.Hosting since we are .Net7.0 -->
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
|
|
|
|||
|
|
@ -365,6 +365,13 @@
|
|||
<system:String x:Key="LogLevelINFO">Info</system:String>
|
||||
<system:String x:Key="settingWindowFontTitle">Setting Window Font</system:String>
|
||||
|
||||
<!-- Release Notes Window -->
|
||||
<system:String x:Key="seeMoreReleaseNotes">See more release notes on GitHub</system:String>
|
||||
<system:String x:Key="checkNetworkConnectionTitle">Failed to fetch release notes</system:String>
|
||||
<system:String x:Key="checkNetworkConnectionSubTitle">Please check your network connection or ensure GitHub is accessible</system:String>
|
||||
<system:String x:Key="appUpdateTitle">Flow Launcher has been updated to {0}</system:String>
|
||||
<system:String x:Key="appUpdateButtonContent">Click here to view the release notes</system:String>
|
||||
|
||||
<!-- FileManager Setting Dialog -->
|
||||
<system:String x:Key="fileManagerWindow">Select File Manager</system:String>
|
||||
<system:String x:Key="fileManager_learnMore">Learn more</system:String>
|
||||
|
|
|
|||
|
|
@ -121,6 +121,9 @@ namespace Flow.Launcher
|
|||
// Set First Launch to false
|
||||
_settings.FirstLaunch = false;
|
||||
|
||||
// Update release notes version
|
||||
_settings.ReleaseNotesVersion = Constant.Version;
|
||||
|
||||
// Set Backdrop Type to Acrylic for Windows 11 when First Launch. Default is None
|
||||
if (Win32Helper.IsBackdropSupported()) _settings.BackdropType = BackdropTypes.Acrylic;
|
||||
|
||||
|
|
@ -132,6 +135,25 @@ namespace Flow.Launcher
|
|||
welcomeWindow.Show();
|
||||
}
|
||||
|
||||
if (_settings.ReleaseNotesVersion != Constant.Version)
|
||||
{
|
||||
// Update release notes version
|
||||
_settings.ReleaseNotesVersion = Constant.Version;
|
||||
|
||||
// Display message box with button
|
||||
App.API.ShowMsgWithButton(
|
||||
string.Format(App.API.GetTranslation("appUpdateTitle"), Constant.Version),
|
||||
App.API.GetTranslation("appUpdateButtonContent"),
|
||||
() =>
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var releaseNotesWindow = new ReleaseNotesWindow();
|
||||
releaseNotesWindow.Show();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize place holder
|
||||
SetupPlaceholderText();
|
||||
_viewModel.PlaceholderText = _settings.PlaceholderText;
|
||||
|
|
|
|||
|
|
@ -1,41 +1,76 @@
|
|||
<Window x:Class="Flow.Launcher.Msg"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Background="#ebebeb"
|
||||
Topmost="True"
|
||||
SizeToContent="Height"
|
||||
ResizeMode="NoResize"
|
||||
WindowStyle="None"
|
||||
ShowInTaskbar="False"
|
||||
Title="Msg" Height="60" Width="420">
|
||||
<Window
|
||||
x:Class="Flow.Launcher.Msg"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Msg"
|
||||
Width="420"
|
||||
Height="60"
|
||||
Background="#ebebeb"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
SizeToContent="Height"
|
||||
Topmost="True"
|
||||
WindowStyle="None">
|
||||
<Window.Triggers>
|
||||
<EventTrigger RoutedEvent="Window.Loaded">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation x:Name="showAnimation" Duration="0:0:0.3" Storyboard.TargetProperty="Top"
|
||||
AccelerationRatio="0.2" />
|
||||
<DoubleAnimation
|
||||
x:Name="showAnimation"
|
||||
AccelerationRatio="0.2"
|
||||
Storyboard.TargetProperty="Top"
|
||||
Duration="0:0:0.3" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
|
||||
</Window.Triggers>
|
||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5">
|
||||
|
||||
<Grid
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="2.852" />
|
||||
<ColumnDefinition Width="13.148"/>
|
||||
<ColumnDefinition Width="13.148" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" Margin="0,9" />
|
||||
<Grid HorizontalAlignment="Stretch" Margin="5 0 0 0" Grid.Column="1" VerticalAlignment="Stretch">
|
||||
<Image
|
||||
x:Name="imgIco"
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="0 9"
|
||||
HorizontalAlignment="Left" />
|
||||
<Grid
|
||||
Grid.Column="1"
|
||||
Margin="5 0 0 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="tbTitle" FontSize="16" Foreground="#37392c" FontWeight="Medium">Title</TextBlock>
|
||||
<TextBlock Grid.Row="1" Foreground="#8e94a4" x:Name="tbSubTitle">sdfdsf</TextBlock>
|
||||
<TextBlock
|
||||
x:Name="tbTitle"
|
||||
FontSize="16"
|
||||
FontWeight="Medium"
|
||||
Foreground="#37392c">
|
||||
Title
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
x:Name="tbSubTitle"
|
||||
Grid.Row="1"
|
||||
Foreground="#8e94a4">
|
||||
sdfdsf
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
<Image x:Name="imgClose" Grid.Column="2" Cursor="Hand" Width="16" VerticalAlignment="Top"
|
||||
HorizontalAlignment="Right" Grid.ColumnSpan="2" />
|
||||
<Image
|
||||
x:Name="imgClose"
|
||||
Grid.Column="2"
|
||||
Grid.ColumnSpan="2"
|
||||
Width="16"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Cursor="Hand" />
|
||||
</Grid>
|
||||
</Window>
|
||||
84
Flow.Launcher/MsgWithButton.xaml
Normal file
84
Flow.Launcher/MsgWithButton.xaml
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<Window
|
||||
x:Class="Flow.Launcher.MsgWithButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Msg"
|
||||
Width="420"
|
||||
Height="60"
|
||||
Background="#ebebeb"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
SizeToContent="Height"
|
||||
Topmost="True"
|
||||
WindowStyle="None">
|
||||
<Window.Triggers>
|
||||
<EventTrigger RoutedEvent="Window.Loaded">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
x:Name="showAnimation"
|
||||
AccelerationRatio="0.2"
|
||||
Storyboard.TargetProperty="Top"
|
||||
Duration="0:0:0.3" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</Window.Triggers>
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="2.852" />
|
||||
<ColumnDefinition Width="13.148" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
x:Name="imgIco"
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="0 9"
|
||||
HorizontalAlignment="Left" />
|
||||
<Grid
|
||||
Grid.Column="1"
|
||||
Margin="5 0 0 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
x:Name="tbTitle"
|
||||
FontSize="16"
|
||||
FontWeight="Medium"
|
||||
Foreground="#37392c">
|
||||
Title
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
x:Name="tbSubTitle"
|
||||
Grid.Row="1"
|
||||
Foreground="#8e94a4">
|
||||
sdfdsf
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
<Image
|
||||
x:Name="imgClose"
|
||||
Grid.Column="2"
|
||||
Grid.ColumnSpan="2"
|
||||
Width="16"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Cursor="Hand" />
|
||||
</Grid>
|
||||
<Button
|
||||
x:Name="btn"
|
||||
Margin="5 0 5 5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="fwafaw"
|
||||
Foreground="#dcdcdc" />
|
||||
</StackPanel>
|
||||
</Window>
|
||||
95
Flow.Launcher/MsgWithButton.xaml.cs
Normal file
95
Flow.Launcher/MsgWithButton.xaml.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
public partial class MsgWithButton : Window
|
||||
{
|
||||
private readonly Storyboard fadeOutStoryboard = new();
|
||||
private bool closing;
|
||||
|
||||
public MsgWithButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
|
||||
var dipWorkingArea = Win32Helper.TransformPixelsToDIP(this,
|
||||
screen.WorkingArea.Width,
|
||||
screen.WorkingArea.Height);
|
||||
Left = dipWorkingArea.X - Width;
|
||||
Top = dipWorkingArea.Y;
|
||||
showAnimation.From = dipWorkingArea.Y;
|
||||
showAnimation.To = dipWorkingArea.Y - Height;
|
||||
|
||||
// Create the fade out storyboard
|
||||
fadeOutStoryboard.Completed += fadeOutStoryboard_Completed;
|
||||
DoubleAnimation fadeOutAnimation = new DoubleAnimation(dipWorkingArea.Y - Height, dipWorkingArea.Y, new Duration(TimeSpan.FromSeconds(5)))
|
||||
{
|
||||
AccelerationRatio = 0.2
|
||||
};
|
||||
Storyboard.SetTarget(fadeOutAnimation, this);
|
||||
Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(TopProperty));
|
||||
fadeOutStoryboard.Children.Add(fadeOutAnimation);
|
||||
|
||||
_ = LoadImageAsync();
|
||||
|
||||
imgClose.MouseUp += imgClose_MouseUp;
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task LoadImageAsync()
|
||||
{
|
||||
imgClose.Source = await App.API.LoadImageAsync(Path.Combine(Constant.ProgramDirectory, "Images\\close.png"));
|
||||
}
|
||||
|
||||
void imgClose_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (!closing)
|
||||
{
|
||||
closing = true;
|
||||
fadeOutStoryboard.Begin();
|
||||
}
|
||||
}
|
||||
|
||||
private void fadeOutStoryboard_Completed(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
public async void Show(string title, string buttonText, Action buttonAction, string subTitle, string iconPath)
|
||||
{
|
||||
tbTitle.Text = title;
|
||||
tbSubTitle.Text = subTitle;
|
||||
btn.Content = buttonText;
|
||||
btn.Click += (s, e) => buttonAction();
|
||||
if (string.IsNullOrEmpty(subTitle))
|
||||
{
|
||||
tbSubTitle.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
if (!File.Exists(iconPath))
|
||||
{
|
||||
imgIco.Source = await App.API.LoadImageAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png"));
|
||||
}
|
||||
else
|
||||
{
|
||||
imgIco.Source = await App.API.LoadImageAsync(iconPath);
|
||||
}
|
||||
|
||||
Show();
|
||||
|
||||
await Dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
if (!closing)
|
||||
{
|
||||
closing = true;
|
||||
await Dispatcher.InvokeAsync(fadeOutStoryboard.Begin);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
using Flow.Launcher.Infrastructure;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
|
|
@ -12,10 +13,30 @@ namespace Flow.Launcher
|
|||
|
||||
internal static bool legacy = !Win32Helper.IsNotificationSupported();
|
||||
|
||||
private static readonly ConcurrentDictionary<string, Action> _notificationActions = new();
|
||||
|
||||
internal static void Install()
|
||||
{
|
||||
if (!legacy)
|
||||
{
|
||||
ToastNotificationManagerCompat.OnActivated += toastArgs =>
|
||||
{
|
||||
var actionId = toastArgs.Argument; // Or use toastArgs.UserInput if using input
|
||||
if (_notificationActions.TryGetValue(actionId, out var action))
|
||||
{
|
||||
action?.Invoke();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Uninstall()
|
||||
{
|
||||
if (!legacy)
|
||||
{
|
||||
_notificationActions.Clear();
|
||||
ToastNotificationManagerCompat.Uninstall();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Show(string title, string subTitle, string iconPath = null)
|
||||
|
|
@ -67,5 +88,58 @@ namespace Flow.Launcher
|
|||
var msg = new Msg();
|
||||
msg.Show(title, subTitle, iconPath);
|
||||
}
|
||||
|
||||
public static void ShowWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath = null)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
ShowInternalWithButton(title, buttonText, buttonAction, subTitle, iconPath);
|
||||
});
|
||||
}
|
||||
|
||||
private static void ShowInternalWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath = null)
|
||||
{
|
||||
// Handle notification for win7/8/early win10
|
||||
if (legacy)
|
||||
{
|
||||
LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// Using Windows Notification System
|
||||
var Icon = !File.Exists(iconPath)
|
||||
? Path.Combine(Constant.ProgramDirectory, "Images\\app.png")
|
||||
: iconPath;
|
||||
|
||||
try
|
||||
{
|
||||
var guid = Guid.NewGuid().ToString();
|
||||
new ToastContentBuilder()
|
||||
.AddText(title, hintMaxLines: 1)
|
||||
.AddText(subTitle)
|
||||
.AddButton(buttonText, ToastActivationType.Background, guid)
|
||||
.AddAppLogoOverride(new Uri(Icon))
|
||||
.Show();
|
||||
_notificationActions.AddOrUpdate(guid, buttonAction, (key, oldValue) => buttonAction);
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
// Temporary fix for the Windows 11 notification issue
|
||||
// Possibly from 22621.1413 or 22621.1485, judging by post time of #2024
|
||||
App.API.LogException(ClassName, "Notification InvalidOperationException Error", e);
|
||||
LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
App.API.LogException(ClassName, "Notification Error", e);
|
||||
LegacyShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void LegacyShowWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath)
|
||||
{
|
||||
var msg = new MsgWithButton();
|
||||
msg.Show(title, buttonText, buttonAction, subTitle, iconPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,6 +123,9 @@ namespace Flow.Launcher
|
|||
public void ShowMsgError(string title, string subTitle = "") =>
|
||||
ShowMsg(title, subTitle, Constant.ErrorIcon, true);
|
||||
|
||||
public void ShowMsgErrorWithButton(string title, string buttonText, Action buttonAction, string subTitle = "") =>
|
||||
ShowMsgWithButton(title, buttonText, buttonAction, subTitle, Constant.ErrorIcon, true);
|
||||
|
||||
public void ShowMsg(string title, string subTitle = "", string iconPath = "") =>
|
||||
ShowMsg(title, subTitle, iconPath, true);
|
||||
|
||||
|
|
@ -131,6 +134,14 @@ namespace Flow.Launcher
|
|||
Notification.Show(title, subTitle, iconPath);
|
||||
}
|
||||
|
||||
public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle = "", string iconPath = "") =>
|
||||
ShowMsgWithButton(title, buttonText, buttonAction, subTitle, iconPath, true);
|
||||
|
||||
public void ShowMsgWithButton(string title, string buttonText, Action buttonAction, string subTitle, string iconPath, bool useMainWindowAsOwner = true)
|
||||
{
|
||||
Notification.ShowWithButton(title, buttonText, buttonAction, subTitle, iconPath);
|
||||
}
|
||||
|
||||
public void OpenSettingDialog()
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
|
|
|
|||
227
Flow.Launcher/ReleaseNotesWindow.xaml
Normal file
227
Flow.Launcher/ReleaseNotesWindow.xaml
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
<Window
|
||||
x:Class="Flow.Launcher.ReleaseNotesWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Flow.Launcher"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mdxam="clr-namespace:MdXaml;assembly=MdXaml"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
|
||||
Title="{DynamicResource releaseNotes}"
|
||||
Width="940"
|
||||
Height="600"
|
||||
MinWidth="940"
|
||||
MinHeight="600"
|
||||
Background="{DynamicResource PopuBGColor}"
|
||||
Closed="Window_Closed"
|
||||
Foreground="{DynamicResource PopupTextColor}"
|
||||
Loaded="Window_Loaded"
|
||||
ResizeMode="CanResize"
|
||||
StateChanged="Window_StateChanged"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
|
||||
</WindowChrome.WindowChrome>
|
||||
<Window.InputBindings>
|
||||
<KeyBinding Key="Escape" Command="Close" />
|
||||
</Window.InputBindings>
|
||||
<Window.CommandBindings>
|
||||
<CommandBinding Command="Close" Executed="OnCloseExecuted" />
|
||||
</Window.CommandBindings>
|
||||
|
||||
<Grid>
|
||||
<Border Style="{StaticResource WindowMainPanelStyle}">
|
||||
<Grid Background="{DynamicResource Color01B}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32" />
|
||||
<RowDefinition Height="24" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<!-- TitleBar and Control -->
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="10 4 4 4"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Source="/Images/app.png" />
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="4 0 0 0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Color05B}"
|
||||
Text="{DynamicResource releaseNotes}" />
|
||||
|
||||
<Button
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Click="OnMinimizeButtonClick"
|
||||
RenderOptions.EdgeMode="Aliased"
|
||||
Style="{DynamicResource TitleBarButtonStyle}">
|
||||
<Path
|
||||
Width="46"
|
||||
Height="32"
|
||||
Data="M 18,15 H 28"
|
||||
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
|
||||
StrokeThickness="1">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
</Button>
|
||||
<Button
|
||||
Name="MaximizeButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="3"
|
||||
Click="OnMaximizeRestoreButtonClick"
|
||||
Style="{StaticResource TitleBarButtonStyle}">
|
||||
<Path
|
||||
Width="46"
|
||||
Height="32"
|
||||
Data="M 18.5,10.5 H 27.5 V 19.5 H 18.5 Z"
|
||||
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
|
||||
StrokeThickness="1">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
</Button>
|
||||
<Button
|
||||
Name="RestoreButton"
|
||||
Grid.Row="0"
|
||||
Grid.Column="3"
|
||||
Click="OnMaximizeRestoreButtonClick"
|
||||
Style="{StaticResource TitleBarButtonStyle}">
|
||||
<Path
|
||||
Width="46"
|
||||
Height="32"
|
||||
Data="M 18.5,12.5 H 25.5 V 19.5 H 18.5 Z M 20.5,12.5 V 10.5 H 27.5 V 17.5 H 25.5"
|
||||
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
|
||||
StrokeThickness="1">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
</Button>
|
||||
<Button
|
||||
Grid.Row="0"
|
||||
Grid.Column="4"
|
||||
Click="OnCloseButtonClick"
|
||||
Style="{StaticResource TitleBarCloseButtonStyle}">
|
||||
<Path
|
||||
Width="46"
|
||||
Height="32"
|
||||
Data="M 18,11 27,20 M 18,20 27,11"
|
||||
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
|
||||
StrokeThickness="1">
|
||||
<Path.Style>
|
||||
<Style TargetType="Path">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
</Path>
|
||||
</Button>
|
||||
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="5"
|
||||
Margin="18 0 18 0">
|
||||
<cc:HyperLink x:Name="SeeMore" Text="{DynamicResource seeMoreReleaseNotes}" />
|
||||
</Grid>
|
||||
|
||||
<!-- Do not use scroll function of MarkdownViewer because it does not support smooth scroll -->
|
||||
<ScrollViewer
|
||||
x:Name="MarkdownScrollViewer"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="5"
|
||||
Width="500"
|
||||
Height="500">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<!-- This row is for bottom margin -->
|
||||
<RowDefinition Height="20" />
|
||||
</Grid.RowDefinitions>
|
||||
<mdxam:MarkdownScrollViewer
|
||||
x:Name="MarkdownViewer"
|
||||
Grid.Row="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ClickAction="SafetyDisplayWithRelativePath"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
Loaded="MarkdownViewer_Loaded"
|
||||
MouseWheel="MarkdownViewer_MouseWheel"
|
||||
Plugins="{StaticResource MdXamlPlugins}"
|
||||
PreviewMouseWheel="MarkdownViewer_PreviewMouseWheel"
|
||||
VerticalScrollBarVisibility="Disabled"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- This Grid is for display progress ring and refresh button. -->
|
||||
<!-- And it is also for changing the size of the MarkdownViewer. -->
|
||||
<!-- Because VerticalAlignment="Stretch" can cause size issue with MarkdownScrollViewer. -->
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="5"
|
||||
Margin="15 0 20 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
SizeChanged="Grid_SizeChanged">
|
||||
<ui:ProgressRing
|
||||
x:Name="RefreshProgressRing"
|
||||
Width="32"
|
||||
Height="32"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsActive="True" />
|
||||
<Button
|
||||
x:Name="RefreshButton"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Click="RefreshButton_Click"
|
||||
Content="{DynamicResource refresh}"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
255
Flow.Launcher/ReleaseNotesWindow.xaml.cs
Normal file
255
Flow.Launcher/ReleaseNotesWindow.xaml.cs
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using Flow.Launcher.Infrastructure.Http;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
public partial class ReleaseNotesWindow : Window
|
||||
{
|
||||
private static readonly string ReleaseNotes = Properties.Settings.Default.GithubRepo + "/releases";
|
||||
|
||||
public ReleaseNotesWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
SeeMore.Uri = ReleaseNotes;
|
||||
ModernWpf.ThemeManager.Current.ActualApplicationThemeChanged += ThemeManager_ActualApplicationThemeChanged;
|
||||
}
|
||||
|
||||
#region Window Events
|
||||
|
||||
private void ThemeManager_ActualApplicationThemeChanged(ModernWpf.ThemeManager sender, object args)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (ModernWpf.ThemeManager.Current.ActualApplicationTheme == ModernWpf.ApplicationTheme.Light)
|
||||
{
|
||||
MarkdownViewer.MarkdownStyle = (Style)Application.Current.Resources["DocumentStyleGithubLikeLight"];
|
||||
MarkdownViewer.Foreground = Brushes.Black;
|
||||
MarkdownViewer.Background = Brushes.White;
|
||||
}
|
||||
else
|
||||
{
|
||||
MarkdownViewer.MarkdownStyle = (Style)Application.Current.Resources["DocumentStyleGithubLikeDark"];
|
||||
MarkdownViewer.Foreground = Brushes.White;
|
||||
MarkdownViewer.Background = Brushes.Black;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshMaximizeRestoreButton();
|
||||
ThemeManager_ActualApplicationThemeChanged(null, null);
|
||||
}
|
||||
|
||||
private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Window_Closed(object sender, EventArgs e)
|
||||
{
|
||||
ModernWpf.ThemeManager.Current.ActualApplicationThemeChanged -= ThemeManager_ActualApplicationThemeChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Window Custom TitleBar
|
||||
|
||||
private void OnMinimizeButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
private void OnMaximizeRestoreButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowState = WindowState switch
|
||||
{
|
||||
WindowState.Maximized => WindowState.Normal,
|
||||
_ => WindowState.Maximized
|
||||
};
|
||||
}
|
||||
|
||||
private void OnCloseButtonClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void RefreshMaximizeRestoreButton()
|
||||
{
|
||||
if (WindowState == WindowState.Maximized)
|
||||
{
|
||||
MaximizeButton.Visibility = Visibility.Hidden;
|
||||
RestoreButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaximizeButton.Visibility = Visibility.Visible;
|
||||
RestoreButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_StateChanged(object sender, EventArgs e)
|
||||
{
|
||||
RefreshMaximizeRestoreButton();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Control Events
|
||||
|
||||
private void MarkdownViewer_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshMarkdownViewer();
|
||||
}
|
||||
|
||||
private void RefreshButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshButton.Visibility = Visibility.Collapsed;
|
||||
RefreshProgressRing.Visibility = Visibility.Visible;
|
||||
RefreshMarkdownViewer();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void RefreshMarkdownViewer()
|
||||
{
|
||||
var output = await GetReleaseNotesMarkdownAsync().ConfigureAwait(false);
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
RefreshProgressRing.Visibility = Visibility.Collapsed;
|
||||
if (string.IsNullOrEmpty(output))
|
||||
{
|
||||
RefreshButton.Visibility = Visibility.Visible;
|
||||
MarkdownViewer.Visibility = Visibility.Collapsed;
|
||||
App.API.ShowMsgError(
|
||||
App.API.GetTranslation("checkNetworkConnectionTitle"),
|
||||
App.API.GetTranslation("checkNetworkConnectionSubTitle"));
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshButton.Visibility = Visibility.Collapsed;
|
||||
MarkdownViewer.Markdown = output;
|
||||
MarkdownViewer.Visibility = Visibility.Visible;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
MarkdownScrollViewer.Height = e.NewSize.Height;
|
||||
MarkdownScrollViewer.Width = e.NewSize.Width;
|
||||
}
|
||||
|
||||
private void MarkdownViewer_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
RaiseMouseWheelEvent(sender, e);
|
||||
}
|
||||
|
||||
private void MarkdownViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
RaiseMouseWheelEvent(sender, e);
|
||||
}
|
||||
|
||||
private void RaiseMouseWheelEvent(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
e.Handled = true; // Prevent the inner control from handling the event
|
||||
|
||||
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
|
||||
{
|
||||
RoutedEvent = UIElement.MouseWheelEvent,
|
||||
Source = sender
|
||||
};
|
||||
|
||||
// Raise the event on the parent ScrollViewer
|
||||
MarkdownScrollViewer.RaiseEvent(eventArg);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Release Notes
|
||||
|
||||
private static async Task<string> GetReleaseNotesMarkdownAsync()
|
||||
{
|
||||
var releaseNotesJSON = await Http.GetStringAsync("https://api.github.com/repos/Flow-Launcher/Flow.Launcher/releases");
|
||||
|
||||
if (string.IsNullOrEmpty(releaseNotesJSON))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
var releases = JsonSerializer.Deserialize<List<GitHubReleaseInfo>>(releaseNotesJSON);
|
||||
|
||||
// Get the latest releases
|
||||
var latestReleases = releases.OrderByDescending(release => release.PublishedDate).Take(3);
|
||||
|
||||
// Build the release notes in Markdown format
|
||||
var releaseNotesHtmlBuilder = new StringBuilder(string.Empty);
|
||||
foreach (var release in latestReleases)
|
||||
{
|
||||
releaseNotesHtmlBuilder.AppendLine("# " + release.Name);
|
||||
|
||||
// Because MdXaml.Html package cannot correctly render images without units,
|
||||
// We need to manually add unit for images
|
||||
// E.g. Replace <img src="..." width="500"> with <img src="..." width="500px">
|
||||
var notes = ImageUnitRegex().Replace(release.ReleaseNotes, m =>
|
||||
{
|
||||
var prefix = m.Groups[1].Value;
|
||||
var widthValue = m.Groups[2].Value;
|
||||
var quote = m.Groups[3].Value;
|
||||
var suffix = m.Groups[4].Value;
|
||||
// Only replace if width is number like 500 without units like 500px
|
||||
if (IsNumber(widthValue))
|
||||
return $"{prefix}{widthValue}px{quote}{suffix}";
|
||||
return m.Value;
|
||||
});
|
||||
|
||||
releaseNotesHtmlBuilder.AppendLine(notes);
|
||||
releaseNotesHtmlBuilder.AppendLine();
|
||||
}
|
||||
|
||||
return releaseNotesHtmlBuilder.ToString();
|
||||
}
|
||||
|
||||
private static bool IsNumber(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return false;
|
||||
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (!char.IsDigit(c))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private sealed class GitHubReleaseInfo
|
||||
{
|
||||
[JsonPropertyName("published_at")]
|
||||
public DateTimeOffset PublishedDate { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("tag_name")]
|
||||
public string TagName { get; set; }
|
||||
|
||||
[JsonPropertyName("body")]
|
||||
public string ReleaseNotes { get; set; }
|
||||
}
|
||||
|
||||
[GeneratedRegex("(<img\\s+[^>]*width\\s*=\\s*[\"']?)(\\d+)([\"']?)([^>]*>)", RegexOptions.IgnoreCase, "en-GB")]
|
||||
private static partial Regex ImageUnitRegex();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,10 @@
|
|||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mdagif="clr-namespace:MdXaml.AnimatedGif;assembly=MdXaml.AnimatedGif"
|
||||
xmlns:mdhtml="clr-namespace:MdXaml.Html;assembly=MdXaml.Html"
|
||||
xmlns:mdplugins="clr-namespace:MdXaml.Plugins;assembly=MdXaml.Plugins"
|
||||
xmlns:mdsvg="clr-namespace:MdXaml.Svg;assembly=MdXaml.Svg"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019">
|
||||
|
||||
|
|
@ -2408,12 +2412,15 @@
|
|||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Explorer Plugin Expander -->
|
||||
<!-- Explorer Plugin Expander -->
|
||||
<Style x:Key="ExpanderHeaderRightArrowStyle" TargetType="ToggleButton">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ToggleButton">
|
||||
<Border x:Name="RootBorder" Background="Transparent" Padding="16,15,16,15">
|
||||
<Border
|
||||
x:Name="RootBorder"
|
||||
Padding="16 15 16 15"
|
||||
Background="Transparent">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
|
|
@ -2421,41 +2428,43 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentPresenter
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="True"
|
||||
Content="{TemplateBinding Content}"
|
||||
Margin="8 0 0 0"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
Grid.Column="0"
|
||||
Margin="8 0 0 0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="True" />
|
||||
|
||||
<Grid Grid.Column="1"
|
||||
Width="20" Height="20"
|
||||
Margin="8 0 4 0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Background="Transparent"
|
||||
RenderTransformOrigin="0.5,0.5"
|
||||
x:Name="ChevronGrid">
|
||||
<Grid
|
||||
x:Name="ChevronGrid"
|
||||
Grid.Column="1"
|
||||
Width="20"
|
||||
Height="20"
|
||||
Margin="8 0 4 0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
RenderTransformOrigin="0.5,0.5">
|
||||
<Grid.RenderTransform>
|
||||
<RotateTransform Angle="0"/>
|
||||
<RotateTransform Angle="0" />
|
||||
</Grid.RenderTransform>
|
||||
<Ellipse
|
||||
x:Name="circle"
|
||||
Width="19"
|
||||
Height="19"
|
||||
Stroke="Transparent"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
x:Name="circle"
|
||||
Width="19"
|
||||
Height="19"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stroke="Transparent" />
|
||||
<Path
|
||||
x:Name="arrow"
|
||||
Data="M 1,1.5 L 4.5,5 L 8,1.5"
|
||||
Stroke="#666"
|
||||
StrokeThickness="1"
|
||||
SnapsToDevicePixels="False"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
x:Name="arrow"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Data="M 1,1.5 L 4.5,5 L 8,1.5"
|
||||
SnapsToDevicePixels="False"
|
||||
Stroke="#666"
|
||||
StrokeThickness="1" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
|
@ -5754,4 +5763,340 @@
|
|||
<Setter Property="Margin" Value="0 2 0 0" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource Color04B}" />
|
||||
</Style>
|
||||
|
||||
<!-- Release Notes -->
|
||||
<mdplugins:MdXamlPlugins x:Key="MdXamlPlugins">
|
||||
<mdhtml:HtmlPluginSetup />
|
||||
<mdsvg:SvgPluginSetup />
|
||||
<mdagif:AnimatedGifPluginSetup />
|
||||
</mdplugins:MdXamlPlugins>
|
||||
|
||||
<Style x:Key="DocumentStyleGithubLikeLight" TargetType="FlowDocument">
|
||||
<Setter Property="FontFamily" Value="Calibri" />
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
<Setter Property="PagePadding" Value="0" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
|
||||
<Style.Resources>
|
||||
<Style TargetType="Section">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="Blockquote">
|
||||
<Setter Property="Padding" Value="10 5" />
|
||||
<Setter Property="BorderBrush" Value="#DEDEDE" />
|
||||
<Setter Property="BorderThickness" Value="5 0 0 0" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" TargetType="avalonEdit:TextEditor">
|
||||
<Setter Property="Background" Value="#EEEEEE" />
|
||||
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="Margin" Value="2 0 2 0" />
|
||||
<Setter Property="Padding" Value="3" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Paragraph">
|
||||
<Setter Property="Margin" Value="0 7 0 0" />
|
||||
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="Heading1">
|
||||
<Setter Property="Margin" Value="0 0 15 0" />
|
||||
|
||||
<Setter Property="Foreground" Value="#ff000000" />
|
||||
<Setter Property="FontSize" Value="28" />
|
||||
<Setter Property="FontWeight" Value="UltraBold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Heading2">
|
||||
<Setter Property="Margin" Value="0 0 15 0" />
|
||||
|
||||
<Setter Property="Foreground" Value="#ff000000" />
|
||||
<Setter Property="FontSize" Value="21" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Heading3">
|
||||
<Setter Property="Margin" Value="0 0 10 0" />
|
||||
|
||||
<Setter Property="Foreground" Value="#ff000000" />
|
||||
<Setter Property="FontSize" Value="17.5" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Heading4">
|
||||
<Setter Property="Margin" Value="0 0 5 0" />
|
||||
|
||||
<Setter Property="Foreground" Value="#ff000000" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="CodeBlock">
|
||||
<Setter Property="FontFamily" Value="Courier New" />
|
||||
<Setter Property="FontSize" Value="11.9" />
|
||||
<Setter Property="Background" Value="#12181F25" />
|
||||
<Setter Property="Padding" Value="20 10" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Note">
|
||||
<Setter Property="Margin" Value="5 0 5 0" />
|
||||
<Setter Property="Padding" Value="10 5" />
|
||||
<Setter Property="BorderBrush" Value="#DEDEDE" />
|
||||
<Setter Property="BorderThickness" Value="3 3 3 3" />
|
||||
<Setter Property="Background" Value="#FAFAFA" />
|
||||
</Trigger>
|
||||
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Run">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="CodeSpan">
|
||||
<Setter Property="FontFamily" Value="Courier New" />
|
||||
<Setter Property="FontSize" Value="11.9" />
|
||||
<Setter Property="Background" Value="#12181F25" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style TargetType="Span">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="CodeSpan">
|
||||
<Setter Property="FontFamily" Value="Courier New" />
|
||||
<Setter Property="FontSize" Value="11.9" />
|
||||
<Setter Property="Background" Value="#12181F25" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Hyperlink">
|
||||
<Setter Property="TextDecorations" Value="None" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Image">
|
||||
<Setter Property="RenderOptions.BitmapScalingMode" Value="NearestNeighbor" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="imageright">
|
||||
<Setter Property="Margin" Value="20 0 0 0" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
The Table's style don't seem to support border-collapse.
|
||||
By making the ruled line width 0.5 and applying it to cell and table,
|
||||
it looks like the ruled lines are not doubled.
|
||||
-->
|
||||
<Style TargetType="Table">
|
||||
<Setter Property="CellSpacing" Value="0" />
|
||||
<Setter Property="BorderThickness" Value="0.5" />
|
||||
<Setter Property="BorderBrush" Value="#DFE2E5" />
|
||||
<Style.Resources>
|
||||
<Style TargetType="TableCell">
|
||||
<Setter Property="BorderThickness" Value="0.5" />
|
||||
<Setter Property="BorderBrush" Value="#DFE2E5" />
|
||||
<Setter Property="Padding" Value="13 6" />
|
||||
</Style>
|
||||
</Style.Resources>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TableRowGroup">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="TableHeader">
|
||||
<Setter Property="FontWeight" Value="DemiBold" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="Background" Value="#FFFFFF" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TableRow">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="EvenTableRow">
|
||||
<Setter Property="Background" Value="#F6F8FA" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="BlockUIContainer">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="RuleSingle">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="RuleDouble">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="RuleBold">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="RuleBoldWithSingle">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Style.Resources>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="DocumentStyleGithubLikeDark" TargetType="FlowDocument">
|
||||
<Setter Property="FontFamily" Value="Calibri" />
|
||||
<Setter Property="TextAlignment" Value="Left" />
|
||||
<Setter Property="PagePadding" Value="0" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
|
||||
<Style.Resources>
|
||||
<Style TargetType="Section">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="Blockquote">
|
||||
<Setter Property="Padding" Value="10 5" />
|
||||
<Setter Property="BorderBrush" Value="#212121" />
|
||||
<Setter Property="BorderThickness" Value="5 0 0 0" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" TargetType="avalonEdit:TextEditor">
|
||||
<Setter Property="Background" Value="#111111" />
|
||||
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="Margin" Value="2 0 2 0" />
|
||||
<Setter Property="Padding" Value="3" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Paragraph">
|
||||
<Setter Property="Margin" Value="0 7 0 0" />
|
||||
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="Heading1">
|
||||
<Setter Property="Margin" Value="0 0 15 0" />
|
||||
<Setter Property="Foreground" Value="#FFFFFFFF" />
|
||||
<Setter Property="FontSize" Value="28" />
|
||||
<Setter Property="FontWeight" Value="UltraBold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Heading2">
|
||||
<Setter Property="Margin" Value="0 0 15 0" />
|
||||
<Setter Property="Foreground" Value="#FFFFFFFF" />
|
||||
<Setter Property="FontSize" Value="21" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Heading3">
|
||||
<Setter Property="Margin" Value="0 0 10 0" />
|
||||
<Setter Property="Foreground" Value="#FFFFFFFF" />
|
||||
<Setter Property="FontSize" Value="17.5" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Heading4">
|
||||
<Setter Property="Margin" Value="0 0 5 0" />
|
||||
<Setter Property="Foreground" Value="#FFFFFFFF" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="CodeBlock">
|
||||
<Setter Property="FontFamily" Value="Courier New" />
|
||||
<Setter Property="FontSize" Value="11.9" />
|
||||
<Setter Property="Background" Value="#E0E7DFDA" />
|
||||
<Setter Property="Padding" Value="20 10" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="Note">
|
||||
<Setter Property="Margin" Value="5 0 5 0" />
|
||||
<Setter Property="Padding" Value="10 5" />
|
||||
<Setter Property="BorderBrush" Value="#212121" />
|
||||
<Setter Property="BorderThickness" Value="3 3 3 3" />
|
||||
<Setter Property="Background" Value="#050505" />
|
||||
</Trigger>
|
||||
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Run">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="CodeSpan">
|
||||
<Setter Property="FontFamily" Value="Courier New" />
|
||||
<Setter Property="FontSize" Value="11.9" />
|
||||
<Setter Property="Background" Value="#E0E7DFDA" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Span">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="CodeSpan">
|
||||
<Setter Property="FontFamily" Value="Courier New" />
|
||||
<Setter Property="FontSize" Value="11.9" />
|
||||
<Setter Property="Background" Value="#E0E7DFDA" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Hyperlink">
|
||||
<Setter Property="TextDecorations" Value="None" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Image">
|
||||
<Setter Property="RenderOptions.BitmapScalingMode" Value="NearestNeighbor" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="imageright">
|
||||
<Setter Property="Margin" Value="20 0 0 0" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Table">
|
||||
<Setter Property="CellSpacing" Value="0" />
|
||||
<Setter Property="BorderThickness" Value="0.5" />
|
||||
<Setter Property="BorderBrush" Value="#202020" />
|
||||
<Style.Resources>
|
||||
<Style TargetType="TableCell">
|
||||
<Setter Property="BorderThickness" Value="0.5" />
|
||||
<Setter Property="BorderBrush" Value="#202020" />
|
||||
<Setter Property="Padding" Value="13 6" />
|
||||
</Style>
|
||||
</Style.Resources>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TableRowGroup">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="TableHeader">
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="Background" Value="#000000" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TableRow">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="EvenTableRow">
|
||||
<Setter Property="Background" Value="#090708" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="BlockUIContainer">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Tag" Value="RuleSingle">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="RuleDouble">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="RuleBold">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Tag" Value="RuleBoldWithSingle">
|
||||
<Setter Property="Margin" Value="0 3" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Style.Resources>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -314,4 +314,11 @@ public partial class SettingsPaneAboutViewModel : BaseModel
|
|||
{
|
||||
SettingWindowFont = Win32Helper.GetSystemDefaultFont(false);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenReleaseNotes()
|
||||
{
|
||||
var releaseNotesWindow = new ReleaseNotesWindow();
|
||||
releaseNotesWindow.Show();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
</cc:Card>
|
||||
|
||||
<cc:Card Title="{DynamicResource releaseNotes}" Icon="">
|
||||
<cc:HyperLink Text="{DynamicResource releaseNotes}" Uri="{Binding ReleaseNotes}" />
|
||||
<Button Command="{Binding OpenReleaseNotesCommand}" Content="{DynamicResource releaseNotes}" />
|
||||
</cc:Card>
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue