Merge branch 'dev' into dev1

This commit is contained in:
Jeremy 2024-12-08 16:24:31 +11:00
commit bce07ee7d2
60 changed files with 500 additions and 373 deletions

View file

@ -40,7 +40,7 @@ namespace Flow.Launcher.Core.Configuration
#endif #endif
IndicateDeletion(DataLocation.PortableDataPath); IndicateDeletion(DataLocation.PortableDataPath);
MessageBox.Show("Flow Launcher needs to restart to finish disabling portable mode, " + MessageBoxEx.Show("Flow Launcher needs to restart to finish disabling portable mode, " +
"after the restart your portable data profile will be deleted and roaming data profile kept"); "after the restart your portable data profile will be deleted and roaming data profile kept");
UpdateManager.RestartApp(Constant.ApplicationFileName); UpdateManager.RestartApp(Constant.ApplicationFileName);
@ -64,7 +64,7 @@ namespace Flow.Launcher.Core.Configuration
#endif #endif
IndicateDeletion(DataLocation.RoamingDataPath); IndicateDeletion(DataLocation.RoamingDataPath);
MessageBox.Show("Flow Launcher needs to restart to finish enabling portable mode, " + MessageBoxEx.Show("Flow Launcher needs to restart to finish enabling portable mode, " +
"after the restart your roaming data profile will be deleted and portable data profile kept"); "after the restart your roaming data profile will be deleted and portable data profile kept");
UpdateManager.RestartApp(Constant.ApplicationFileName); UpdateManager.RestartApp(Constant.ApplicationFileName);
@ -95,13 +95,13 @@ namespace Flow.Launcher.Core.Configuration
public void MoveUserDataFolder(string fromLocation, string toLocation) public void MoveUserDataFolder(string fromLocation, string toLocation)
{ {
FilesFolders.CopyAll(fromLocation, toLocation); FilesFolders.CopyAll(fromLocation, toLocation, MessageBoxEx.Show);
VerifyUserDataAfterMove(fromLocation, toLocation); VerifyUserDataAfterMove(fromLocation, toLocation);
} }
public void VerifyUserDataAfterMove(string fromLocation, string toLocation) public void VerifyUserDataAfterMove(string fromLocation, string toLocation)
{ {
FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation); FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, MessageBoxEx.Show);
} }
public void CreateShortcuts() public void CreateShortcuts()
@ -157,13 +157,13 @@ namespace Flow.Launcher.Core.Configuration
// delete it and prompt the user to pick the portable data location // delete it and prompt the user to pick the portable data location
if (File.Exists(roamingDataDeleteFilePath)) if (File.Exists(roamingDataDeleteFilePath))
{ {
FilesFolders.RemoveFolderIfExists(roamingDataDir); FilesFolders.RemoveFolderIfExists(roamingDataDir, MessageBoxEx.Show);
if (MessageBox.Show("Flow Launcher has detected you enabled portable mode, " + if (MessageBoxEx.Show("Flow Launcher has detected you enabled portable mode, " +
"would you like to move it to a different location?", string.Empty, "would you like to move it to a different location?", string.Empty,
MessageBoxButton.YesNo) == MessageBoxResult.Yes) MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
FilesFolders.OpenPath(Constant.RootDirectory); FilesFolders.OpenPath(Constant.RootDirectory, MessageBoxEx.Show);
Environment.Exit(0); Environment.Exit(0);
} }
@ -172,9 +172,9 @@ namespace Flow.Launcher.Core.Configuration
// delete it and notify the user about it. // delete it and notify the user about it.
else if (File.Exists(portableDataDeleteFilePath)) else if (File.Exists(portableDataDeleteFilePath))
{ {
FilesFolders.RemoveFolderIfExists(portableDataDir); FilesFolders.RemoveFolderIfExists(portableDataDir, MessageBoxEx.Show);
MessageBox.Show("Flow Launcher has detected you disabled portable mode, " + MessageBoxEx.Show("Flow Launcher has detected you disabled portable mode, " +
"the relevant shortcuts and uninstaller entry have been created"); "the relevant shortcuts and uninstaller entry have been created");
} }
} }
@ -186,7 +186,7 @@ namespace Flow.Launcher.Core.Configuration
if (roamingLocationExists && portableLocationExists) if (roamingLocationExists && portableLocationExists)
{ {
MessageBox.Show(string.Format("Flow Launcher detected your user data exists both in {0} and " + MessageBoxEx.Show(string.Format("Flow Launcher detected your user data exists both in {0} and " +
"{1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred.", "{1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred.",
DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine));

View file

@ -4,8 +4,8 @@ using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedCommands;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
@ -57,7 +57,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
EnvName, EnvName,
Environment.NewLine Environment.NewLine
); );
if (MessageBox.Show(noRuntimeMessage, string.Empty, MessageBoxButtons.YesNo) == DialogResult.No) if (MessageBoxEx.Show(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
{ {
var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName);
string selectedFile; string selectedFile;
@ -82,7 +82,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
} }
else else
{ {
MessageBox.Show(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language));
Log.Error("PluginsLoader", Log.Error("PluginsLoader",
$"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.",
$"{Language}Environment"); $"{Language}Environment");
@ -98,7 +98,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
if (expectedPath == currentPath) if (expectedPath == currentPath)
return; return;
FilesFolders.RemoveFolderIfExists(installedDirPath); FilesFolders.RemoveFolderIfExists(installedDirPath, MessageBoxEx.Show);
InstallEnvironment(); InstallEnvironment();

View file

@ -28,7 +28,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal override void InstallEnvironment() internal override void InstallEnvironment()
{ {
FilesFolders.RemoveFolderIfExists(InstallPath); FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show);
// Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and // Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and
// uses Python plugin they need to custom install and use v3.8.9 // uses Python plugin they need to custom install and use v3.8.9

View file

@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal override void InstallEnvironment() internal override void InstallEnvironment()
{ {
FilesFolders.RemoveFolderIfExists(InstallPath); FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show);
DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait();

View file

@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal override void InstallEnvironment() internal override void InstallEnvironment()
{ {
FilesFolders.RemoveFolderIfExists(InstallPath); FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show);
DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait();

View file

@ -1,9 +1,9 @@
<Window <Window
x:Class="Flow.Launcher.MessageBoxEx" x:Class="Flow.Launcher.Core.MessageBoxEx"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher" xmlns:local="clr-namespace:Flow.Launcher.Core"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="MessageBoxWindow" x:Name="MessageBoxWindow"
Width="420" Width="420"
@ -21,7 +21,7 @@
<KeyBinding Key="Escape" Command="Close" /> <KeyBinding Key="Escape" Command="Close" />
</Window.InputBindings> </Window.InputBindings>
<Window.CommandBindings> <Window.CommandBindings>
<CommandBinding Command="Close" Executed="cmdEsc_OnPress" /> <CommandBinding Command="Close" Executed="KeyEsc_OnPress" />
</Window.CommandBindings> </Window.CommandBindings>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
@ -33,14 +33,11 @@
<StackPanel> <StackPanel>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Button <Button
Grid.Column="4" Grid.Column="1"
Click="Button_Cancel" Click="Button_Cancel"
Style="{StaticResource TitleBarCloseButtonStyle}"> Style="{StaticResource TitleBarCloseButtonStyle}">
<Path <Path
@ -63,8 +60,12 @@
</Grid> </Grid>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="1" Margin="30 0 30 24"> <Grid Grid.Row="1" Margin="30 0 30 24">
<Grid Grid.Column="0" Margin="0 0 0 12"> <Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0 0 0 12">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
@ -74,7 +75,7 @@
Grid.Column="0" Grid.Column="0"
Width="18" Width="18"
Height="18" Height="18"
Margin="0 0 0 0" Margin="0 0 10 0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center" VerticalAlignment="Center"
RenderOptions.BitmapScalingMode="Fant" RenderOptions.BitmapScalingMode="Fant"
@ -84,7 +85,7 @@
x:Name="TitleTextBlock" x:Name="TitleTextBlock"
Grid.Column="1" Grid.Column="1"
MaxWidth="400" MaxWidth="400"
Margin="10 0 26 0" Margin="0 0 26 0"
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="Segoe UI" FontFamily="Segoe UI"
FontSize="20" FontSize="20"
@ -94,14 +95,26 @@
</Grid> </Grid>
<TextBlock <TextBlock
x:Name="DescTextBlock" x:Name="DescTextBlock"
Grid.Column="1" Grid.Row="1"
MaxWidth="400" MaxWidth="400"
Margin="0 0 26 0" Margin="0 0 26 0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
FontSize="14" FontSize="14"
TextAlignment="Left" TextAlignment="Left"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</StackPanel> <TextBlock
x:Name="DescOnlyTextBlock"
Grid.Row="0"
Grid.RowSpan="2"
MaxWidth="400"
Margin="0 0 26 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
FontSize="14"
TextAlignment="Left"
TextWrapping="Wrap"
Visibility="Collapsed" />
</Grid>
<Border <Border
Grid.Row="2" Grid.Row="2"
Margin="0 0 0 0" Margin="0 0 0 0"
@ -112,30 +125,30 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
Orientation="Horizontal"> Orientation="Horizontal">
<Button
x:Name="btnCancel"
MinWidth="140"
Margin="5 0 5 0"
Click="Button_Click"
Content="{DynamicResource commonCancel}" />
<Button
x:Name="btnNo"
MinWidth="140"
Margin="5 0 5 0"
Click="Button_Click"
Content="{DynamicResource commonNo}" />
<Button <Button
x:Name="btnOk" x:Name="btnOk"
MinWidth="140" MinWidth="120"
Margin="5 0 5 0" Margin="5 0 5 0"
Click="Button_Click" Click="Button_Click"
Content="{DynamicResource commonOK}" /> Content="{DynamicResource commonOK}" />
<Button <Button
x:Name="btnYes" x:Name="btnYes"
MinWidth="140" MinWidth="120"
Margin="5 0 5 0" Margin="5 0 5 0"
Click="Button_Click" Click="Button_Click"
Content="{DynamicResource commonYes}" /> Content="{DynamicResource commonYes}" />
<Button
x:Name="btnNo"
MinWidth="120"
Margin="5 0 5 0"
Click="Button_Click"
Content="{DynamicResource commonNo}" />
<Button
x:Name="btnCancel"
MinWidth="120"
Margin="5 0 5 0"
Click="Button_Click"
Content="{DynamicResource commonCancel}" />
</WrapPanel> </WrapPanel>
</Border> </Border>
</Grid> </Grid>

View file

@ -0,0 +1,203 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher.Core
{
public partial class MessageBoxEx : Window
{
private static MessageBoxEx msgBox;
private static MessageBoxResult _result = MessageBoxResult.None;
private readonly MessageBoxButton _button;
private MessageBoxEx(MessageBoxButton button)
{
_button = button;
InitializeComponent();
}
public static MessageBoxResult Show(string messageBoxText)
=> Show(messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.OK);
public static MessageBoxResult Show(
string messageBoxText,
string caption = "",
MessageBoxButton button = MessageBoxButton.OK,
MessageBoxImage icon = MessageBoxImage.None,
MessageBoxResult defaultResult = MessageBoxResult.OK)
{
if (!Application.Current.Dispatcher.CheckAccess())
{
return Application.Current.Dispatcher.Invoke(() => Show(messageBoxText, caption, button, icon, defaultResult));
}
try
{
msgBox = new MessageBoxEx(button);
if (caption == string.Empty && button == MessageBoxButton.OK && icon == MessageBoxImage.None)
{
msgBox.Title = messageBoxText;
msgBox.DescOnlyTextBlock.Visibility = Visibility.Visible;
msgBox.DescOnlyTextBlock.Text = messageBoxText;
}
else
{
msgBox.Title = caption;
msgBox.TitleTextBlock.Text = caption;
msgBox.DescTextBlock.Text = messageBoxText;
_ = SetImageOfMessageBoxAsync(icon);
}
SetButtonVisibilityFocusAndResult(button, defaultResult);
msgBox.ShowDialog();
return _result;
}
catch (Exception e)
{
Log.Error($"|MessageBoxEx.Show|An error occurred: {e.Message}");
msgBox = null;
return MessageBoxResult.None;
}
}
private static void SetButtonVisibilityFocusAndResult(MessageBoxButton button, MessageBoxResult defaultResult)
{
switch (button)
{
case MessageBoxButton.OK:
msgBox.btnCancel.Visibility = Visibility.Collapsed;
msgBox.btnNo.Visibility = Visibility.Collapsed;
msgBox.btnYes.Visibility = Visibility.Collapsed;
msgBox.btnOk.Focus();
_result = MessageBoxResult.OK;
break;
case MessageBoxButton.OKCancel:
msgBox.btnNo.Visibility = Visibility.Collapsed;
msgBox.btnYes.Visibility = Visibility.Collapsed;
if (defaultResult == MessageBoxResult.Cancel)
{
msgBox.btnCancel.Focus();
_result = MessageBoxResult.Cancel;
}
else
{
msgBox.btnOk.Focus();
_result = MessageBoxResult.OK;
}
break;
case MessageBoxButton.YesNo:
msgBox.btnOk.Visibility = Visibility.Collapsed;
msgBox.btnCancel.Visibility = Visibility.Collapsed;
if (defaultResult == MessageBoxResult.No)
{
msgBox.btnNo.Focus();
_result = MessageBoxResult.No;
}
else
{
msgBox.btnYes.Focus();
_result = MessageBoxResult.Yes;
}
break;
case MessageBoxButton.YesNoCancel:
msgBox.btnOk.Visibility = Visibility.Collapsed;
if (defaultResult == MessageBoxResult.No)
{
msgBox.btnNo.Focus();
_result = MessageBoxResult.No;
}
else if (defaultResult == MessageBoxResult.Cancel)
{
msgBox.btnCancel.Focus();
_result = MessageBoxResult.Cancel;
}
else
{
msgBox.btnYes.Focus();
_result = MessageBoxResult.Yes;
}
break;
default:
break;
}
}
private static async Task SetImageOfMessageBoxAsync(MessageBoxImage icon)
{
switch (icon)
{
case MessageBoxImage.Exclamation:
await msgBox.SetImageAsync("Exclamation.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
case MessageBoxImage.Question:
await msgBox.SetImageAsync("Question.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
case MessageBoxImage.Information:
await msgBox.SetImageAsync("Information.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
case MessageBoxImage.Error:
await msgBox.SetImageAsync("Error.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
default:
msgBox.Img.Visibility = Visibility.Collapsed;
break;
}
}
private async Task SetImageAsync(string imageName)
{
var imagePath = Path.Combine(Constant.ProgramDirectory, "Images", imageName);
var imageSource = await ImageLoader.LoadAsync(imagePath);
Img.Source = imageSource;
}
private void KeyEsc_OnPress(object sender, ExecutedRoutedEventArgs e)
{
if (_button == MessageBoxButton.YesNo)
return;
else if (_button == MessageBoxButton.OK)
_result = MessageBoxResult.OK;
else
_result = MessageBoxResult.Cancel;
DialogResult = false;
Close();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (sender == btnOk)
_result = MessageBoxResult.OK;
else if (sender == btnYes)
_result = MessageBoxResult.Yes;
else if (sender == btnNo)
_result = MessageBoxResult.No;
else if (sender == btnCancel)
_result = MessageBoxResult.Cancel;
else
_result = MessageBoxResult.None;
msgBox.Close();
msgBox = null;
}
private void Button_Cancel(object sender, RoutedEventArgs e)
{
if (_button == MessageBoxButton.YesNo)
return;
else if (_button == MessageBoxButton.OK)
_result = MessageBoxResult.OK;
else
_result = MessageBoxResult.Cancel;
msgBox.Close();
msgBox = null;
}
}
}

View file

@ -519,7 +519,7 @@ namespace Flow.Launcher.Core.Plugin
var newPluginPath = Path.Combine(installDirectory, folderName); var newPluginPath = Path.Combine(installDirectory, folderName);
FilesFolders.CopyAll(pluginFolderPath, newPluginPath); FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show);
Directory.Delete(tempFolderPluginPath, true); Directory.Delete(tempFolderPluginPath, true);

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows;
using Flow.Launcher.Core.ExternalPlugins.Environments; using Flow.Launcher.Core.ExternalPlugins.Environments;
#pragma warning disable IDE0005 #pragma warning disable IDE0005
using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Logger;
@ -119,10 +119,10 @@ namespace Flow.Launcher.Core.Plugin
_ = Task.Run(() => _ = Task.Run(() =>
{ {
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + MessageBoxEx.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
$"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" +
$"Please refer to the logs for more information", "", $"Please refer to the logs for more information", "",
MessageBoxButtons.OK, MessageBoxIcon.Warning); MessageBoxButton.OK, MessageBoxImage.Warning);
}); });
} }

View file

@ -124,7 +124,7 @@ namespace Flow.Launcher.Core.Resource
// "Do you want to search with pinyin?" // "Do you want to search with pinyin?"
string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ; string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ;
if (MessageBox.Show(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) if (MessageBoxEx.Show(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
return false; return false;
return true; return true;

View file

@ -110,7 +110,7 @@ namespace Flow.Launcher.Core.Resource
Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found"); Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found");
if (theme != defaultTheme) if (theme != defaultTheme)
{ {
MessageBox.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme));
ChangeTheme(defaultTheme); ChangeTheme(defaultTheme);
} }
return false; return false;
@ -120,7 +120,7 @@ namespace Flow.Launcher.Core.Resource
Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse"); Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse");
if (theme != defaultTheme) if (theme != defaultTheme)
{ {
MessageBox.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme));
ChangeTheme(defaultTheme); ChangeTheme(defaultTheme);
} }
return false; return false;

View file

@ -53,7 +53,7 @@ namespace Flow.Launcher.Core
if (newReleaseVersion <= currentVersion) if (newReleaseVersion <= currentVersion)
{ {
if (!silentUpdate) if (!silentUpdate)
MessageBox.Show(api.GetTranslation("update_flowlauncher_already_on_latest")); MessageBoxEx.Show(api.GetTranslation("update_flowlauncher_already_on_latest"));
return; return;
} }
@ -68,9 +68,9 @@ namespace Flow.Launcher.Core
if (DataLocation.PortableDataLocationInUse()) if (DataLocation.PortableDataLocationInUse())
{ {
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}";
FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination); FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, MessageBoxEx.Show);
if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination)) if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, MessageBoxEx.Show))
MessageBox.Show(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), MessageBoxEx.Show(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"),
DataLocation.PortableDataPath, DataLocation.PortableDataPath,
targetDestination)); targetDestination));
} }
@ -83,7 +83,7 @@ namespace Flow.Launcher.Core
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
if (MessageBox.Show(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) if (MessageBoxEx.Show(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
UpdateManager.RestartApp(Constant.ApplicationFileName); UpdateManager.RestartApp(Constant.ApplicationFileName);
} }

View file

@ -31,6 +31,7 @@ namespace Flow.Launcher.Infrastructure
public static readonly string ErrorIcon = Path.Combine(ImagesDirectory, "app_error.png"); public static readonly string ErrorIcon = Path.Combine(ImagesDirectory, "app_error.png");
public static readonly string MissingImgIcon = Path.Combine(ImagesDirectory, "app_missing_img.png"); public static readonly string MissingImgIcon = Path.Combine(ImagesDirectory, "app_missing_img.png");
public static readonly string LoadingImgIcon = Path.Combine(ImagesDirectory, "loading.png"); public static readonly string LoadingImgIcon = Path.Combine(ImagesDirectory, "loading.png");
public static readonly string ImageIcon = Path.Combine(ImagesDirectory, "image.png");
public static string PythonPath; public static string PythonPath;
public static string NodePath; public static string NodePath;

View file

@ -55,7 +55,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MemoryPack" Version="1.21.3" /> <PackageReference Include="MemoryPack" Version="1.21.3" />
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.10.48" /> <PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.12.19" />
<PackageReference Include="NLog" Version="4.7.10" /> <PackageReference Include="NLog" Version="4.7.10" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" /> <PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" /> <PackageReference Include="System.Drawing.Common" Version="7.0.0" />

View file

@ -22,6 +22,7 @@ namespace Flow.Launcher.Infrastructure.Image
private static readonly ConcurrentDictionary<string, string> GuidToKey = new(); private static readonly ConcurrentDictionary<string, string> GuidToKey = new();
private static IImageHashGenerator _hashGenerator; private static IImageHashGenerator _hashGenerator;
private static readonly bool EnableImageHash = true; private static readonly bool EnableImageHash = true;
public static ImageSource Image { get; } = new BitmapImage(new Uri(Constant.ImageIcon));
public static ImageSource MissingImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon)); public static ImageSource MissingImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon));
public static ImageSource LoadingImage { get; } = new BitmapImage(new Uri(Constant.LoadingImgIcon)); public static ImageSource LoadingImage { get; } = new BitmapImage(new Uri(Constant.LoadingImgIcon));
public const int SmallIconSize = 64; public const int SmallIconSize = 64;
@ -139,7 +140,7 @@ namespace Flow.Launcher.Infrastructure.Image
return new ImageResult(image, ImageType.ImageFile); return new ImageResult(image, ImageType.ImageFile);
} }
if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) if (path.StartsWith("data:image", StringComparison.OrdinalIgnoreCase))
{ {
var imageSource = new BitmapImage(new Uri(path)); var imageSource = new BitmapImage(new Uri(path));
imageSource.Freeze(); imageSource.Freeze();
@ -215,8 +216,16 @@ namespace Flow.Launcher.Infrastructure.Image
type = ImageType.ImageFile; type = ImageType.ImageFile;
if (loadFullImage) if (loadFullImage)
{ {
image = LoadFullImage(path); try
type = ImageType.FullImageFile; {
image = LoadFullImage(path);
type = ImageType.FullImageFile;
}
catch (NotSupportedException)
{
image = Image;
type = ImageType.Error;
}
} }
else else
{ {

View file

@ -1,4 +1,4 @@
using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.Plugin.SharedModels;
using JetBrains.Annotations; using JetBrains.Annotations;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -7,6 +7,7 @@ using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace Flow.Launcher.Plugin namespace Flow.Launcher.Plugin
{ {
@ -304,5 +305,16 @@ namespace Flow.Launcher.Plugin
/// This method should run when selected item is from context menu or history. /// This method should run when selected item is from context menu or history.
/// </summary> /// </summary>
public void BackToQueryResults(); public void BackToQueryResults();
/// <summary>
/// Displays a standardised Flow message box.
/// </summary>
/// <param name="messageBoxText">The message of the message box.</param>
/// <param name="caption">The caption of the message box.</param>
/// <param name="button">Specifies which button or buttons to display.</param>
/// <param name="icon">Specifies the icon to display.</param>
/// <param name="defaultResult">Specifies the default result of the message box.</param>
/// <returns>Specifies which message box button is clicked by the user.</returns>
public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.OK);
} }
} }

View file

@ -70,7 +70,8 @@ namespace Flow.Launcher.Plugin
&& !string.IsNullOrEmpty(PluginDirectory) && !string.IsNullOrEmpty(PluginDirectory)
&& !Path.IsPathRooted(value) && !Path.IsPathRooted(value)
&& !value.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !value.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
&& !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
&& !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase))
{ {
_icoPath = Path.Combine(PluginDirectory, value); _icoPath = Path.Combine(PluginDirectory, value);
} }

View file

@ -21,7 +21,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
/// </summary> /// </summary>
/// <param name="sourcePath"></param> /// <param name="sourcePath"></param>
/// <param name="targetPath"></param> /// <param name="targetPath"></param>
public static void CopyAll(this string sourcePath, string targetPath) /// <param name="messageBoxExShow"></param>
public static void CopyAll(this string sourcePath, string targetPath, Func<string, MessageBoxResult> messageBoxExShow = null)
{ {
// Get the subdirectories for the specified directory. // Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourcePath); DirectoryInfo dir = new DirectoryInfo(sourcePath);
@ -54,7 +55,7 @@ namespace Flow.Launcher.Plugin.SharedCommands
foreach (DirectoryInfo subdir in dirs) foreach (DirectoryInfo subdir in dirs)
{ {
string temppath = Path.Combine(targetPath, subdir.Name); string temppath = Path.Combine(targetPath, subdir.Name);
CopyAll(subdir.FullName, temppath); CopyAll(subdir.FullName, temppath, messageBoxExShow);
} }
} }
catch (Exception) catch (Exception)
@ -62,8 +63,9 @@ namespace Flow.Launcher.Plugin.SharedCommands
#if DEBUG #if DEBUG
throw; throw;
#else #else
MessageBox.Show(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath)); messageBoxExShow ??= MessageBox.Show;
RemoveFolderIfExists(targetPath); messageBoxExShow(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath));
RemoveFolderIfExists(targetPath, messageBoxExShow);
#endif #endif
} }
@ -75,8 +77,9 @@ namespace Flow.Launcher.Plugin.SharedCommands
/// </summary> /// </summary>
/// <param name="fromPath"></param> /// <param name="fromPath"></param>
/// <param name="toPath"></param> /// <param name="toPath"></param>
/// <param name="messageBoxExShow"></param>
/// <returns></returns> /// <returns></returns>
public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath) public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath, Func<string, MessageBoxResult> messageBoxExShow = null)
{ {
try try
{ {
@ -96,7 +99,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
#if DEBUG #if DEBUG
throw; throw;
#else #else
MessageBox.Show(string.Format("Unable to verify folders and files between {0} and {1}", fromPath, toPath)); messageBoxExShow ??= MessageBox.Show;
messageBoxExShow(string.Format("Unable to verify folders and files between {0} and {1}", fromPath, toPath));
return false; return false;
#endif #endif
} }
@ -107,7 +111,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
/// Deletes a folder if it exists /// Deletes a folder if it exists
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path"></param>
public static void RemoveFolderIfExists(this string path) /// <param name="messageBoxExShow"></param>
public static void RemoveFolderIfExists(this string path, Func<string, MessageBoxResult> messageBoxExShow = null)
{ {
try try
{ {
@ -119,7 +124,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
#if DEBUG #if DEBUG
throw; throw;
#else #else
MessageBox.Show(string.Format("Not able to delete folder {0}, please go to the location and manually delete it", path)); messageBoxExShow ??= MessageBox.Show;
messageBoxExShow(string.Format("Not able to delete folder {0}, please go to the location and manually delete it", path));
#endif #endif
} }
} }
@ -148,7 +154,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
/// Open a directory window (using the OS's default handler, usually explorer) /// Open a directory window (using the OS's default handler, usually explorer)
/// </summary> /// </summary>
/// <param name="fileOrFolderPath"></param> /// <param name="fileOrFolderPath"></param>
public static void OpenPath(string fileOrFolderPath) /// <param name="messageBoxExShow"></param>
public static void OpenPath(string fileOrFolderPath, Func<string, MessageBoxResult> messageBoxExShow = null)
{ {
var psi = new ProcessStartInfo var psi = new ProcessStartInfo
{ {
@ -166,7 +173,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
#if DEBUG #if DEBUG
throw; throw;
#else #else
MessageBox.Show(string.Format("Unable to open the path {0}, please check if it exists", fileOrFolderPath)); messageBoxExShow ??= MessageBox.Show;
messageBoxExShow(string.Format("Unable to open the path {0}, please check if it exists", fileOrFolderPath));
#endif #endif
} }
} }
@ -177,7 +185,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
/// <param name="filePath">File path</param> /// <param name="filePath">File path</param>
/// <param name="workingDir">Working directory</param> /// <param name="workingDir">Working directory</param>
/// <param name="asAdmin">Open as Administrator</param> /// <param name="asAdmin">Open as Administrator</param>
public static void OpenFile(string filePath, string workingDir = "", bool asAdmin = false) /// <param name="messageBoxExShow"></param>
public static void OpenFile(string filePath, string workingDir = "", bool asAdmin = false, Func<string, MessageBoxResult> messageBoxExShow = null)
{ {
var psi = new ProcessStartInfo var psi = new ProcessStartInfo
{ {
@ -196,7 +205,8 @@ namespace Flow.Launcher.Plugin.SharedCommands
#if DEBUG #if DEBUG
throw; throw;
#else #else
MessageBox.Show(string.Format("Unable to open the path {0}, please check if it exists", filePath)); messageBoxExShow ??= MessageBox.Show;
messageBoxExShow(string.Format("Unable to open the path {0}, please check if it exists", filePath));
#endif #endif
} }
} }

View file

@ -54,7 +54,7 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -2,6 +2,7 @@
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using Flow.Launcher.Core;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -43,7 +44,7 @@ namespace Flow.Launcher
else else
{ {
string msg = translater.GetTranslation("newActionKeywordsHasBeenAssigned"); string msg = translater.GetTranslation("newActionKeywordsHasBeenAssigned");
MessageBox.Show(msg); MessageBoxEx.Show(msg);
} }
} }
} }

View file

@ -6,7 +6,7 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Controls; using System.Windows.Controls;
using Flow.Launcher.ViewModel; using Flow.Launcher.Core;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -63,7 +63,7 @@ namespace Flow.Launcher
o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey);
if (updateCustomHotkey == null) if (updateCustomHotkey == null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey"));
Close(); Close();
return; return;
} }

View file

@ -3,6 +3,7 @@ using System;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Flow.Launcher.SettingPages.ViewModels; using Flow.Launcher.SettingPages.ViewModels;
using Flow.Launcher.Core;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -42,13 +43,13 @@ namespace Flow.Launcher
{ {
if (String.IsNullOrEmpty(Key) || String.IsNullOrEmpty(Value)) if (String.IsNullOrEmpty(Key) || String.IsNullOrEmpty(Value))
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("emptyShortcut"));
return; return;
} }
// Check if key is modified or adding a new one // Check if key is modified or adding a new one
if (((update && originalKey != Key) || !update) && _hotkeyVm.DoesShortcutExist(Key)) if (((update && originalKey != Key) || !update) && _hotkeyVm.DoesShortcutExist(Key))
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("duplicateShortcut"));
return; return;
} }
DialogResult = !update || originalKey != Key || originalValue != Value; DialogResult = !update || originalKey != Key || originalValue != Value;

View file

@ -4,8 +4,8 @@ using System;
using NHotkey; using NHotkey;
using NHotkey.Wpf; using NHotkey.Wpf;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
using System.Windows;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using Flow.Launcher.Core;
namespace Flow.Launcher.Helper; namespace Flow.Launcher.Helper;
@ -46,7 +46,7 @@ internal static class HotKeyMapper
{ {
string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr); string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr);
string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle"); string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle");
MessageBox.Show(errorMsg,errorMsgTitle); MessageBoxEx.Show(errorMsg, errorMsgTitle);
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 738 B

View file

@ -308,7 +308,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Panel.ZIndex="2" Panel.ZIndex="2"
RenderOptions.BitmapScalingMode="HighQuality" RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding PluginIconPath}" Source="{Binding PluginIconSource}"
Stretch="Uniform" Stretch="Uniform"
Style="{DynamicResource PluginActivationIcon}" /> Style="{DynamicResource PluginActivationIcon}" />
<Canvas Style="{DynamicResource SearchIconPosition}"> <Canvas Style="{DynamicResource SearchIconPosition}">

View file

@ -1,192 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Image;
using YamlDotNet.Core.Tokens;
namespace Flow.Launcher
{
public partial class MessageBoxEx : Window
{
public MessageBoxEx()
{
InitializeComponent();
}
public enum MessageBoxType
{
ConfirmationWithYesNo = 0,
ConfirmationWithYesNoCancel,
YesNo,
Information,
Error,
Warning
}
public enum MessageBoxImage
{
Warning = 0,
Question,
Information,
Error,
None
}
static MessageBoxEx msgBox;
static MessageBoxResult _result = MessageBoxResult.No;
/// 1 parameter
public static MessageBoxResult Show(string msg)
{
return Show(string.Empty, msg, MessageBoxButton.OK, MessageBoxImage.None);
}
// 2 parameter
public static MessageBoxResult Show(string caption, string text)
{
return Show(caption, text, MessageBoxButton.OK, MessageBoxImage.None);
}
/// 3 parameter
public static MessageBoxResult Show(string caption, string msg, MessageBoxType type)
{
switch (type)
{
case MessageBoxType.ConfirmationWithYesNo:
return Show(caption, msg, MessageBoxButton.YesNo,
MessageBoxImage.Question);
case MessageBoxType.YesNo:
return Show(caption, msg, MessageBoxButton.YesNo,
MessageBoxImage.Question);
case MessageBoxType.ConfirmationWithYesNoCancel:
return Show(caption, msg, MessageBoxButton.YesNoCancel,
MessageBoxImage.Question);
case MessageBoxType.Information:
return Show(caption, msg, MessageBoxButton.OK,
MessageBoxImage.Information);
case MessageBoxType.Error:
return Show(caption, msg, MessageBoxButton.OK,
MessageBoxImage.Error);
case MessageBoxType.Warning:
return Show(caption, msg, MessageBoxButton.OK,
MessageBoxImage.Warning);
default:
return MessageBoxResult.No;
}
}
// 4 parameter, Final Display Message.
public static MessageBoxResult Show(string caption, string text, MessageBoxButton button, MessageBoxImage image)
{
msgBox = new MessageBoxEx();
msgBox.TitleTextBlock.Text = text;
msgBox.DescTextBlock.Text = caption;
msgBox.Title = text;
SetVisibilityOfButtons(button);
SetImageOfMessageBox(image);
msgBox.ShowDialog();
return _result;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (sender == btnOk)
_result = MessageBoxResult.OK;
else if (sender == btnYes)
_result = MessageBoxResult.Yes;
else if (sender == btnNo)
_result = MessageBoxResult.No;
else if (sender == btnCancel)
_result = MessageBoxResult.Cancel;
else
_result = MessageBoxResult.None;
msgBox.Close();
msgBox = null;
}
private static void SetVisibilityOfButtons(MessageBoxButton button)
{
switch (button)
{
case MessageBoxButton.OK:
msgBox.btnCancel.Visibility = Visibility.Collapsed;
msgBox.btnNo.Visibility = Visibility.Collapsed;
msgBox.btnYes.Visibility = Visibility.Collapsed;
msgBox.btnOk.Focus();
break;
case MessageBoxButton.OKCancel:
msgBox.btnNo.Visibility = Visibility.Collapsed;
msgBox.btnYes.Visibility = Visibility.Collapsed;
msgBox.btnCancel.Focus();
break;
case MessageBoxButton.YesNo:
msgBox.btnOk.Visibility = Visibility.Collapsed;
msgBox.btnCancel.Visibility = Visibility.Collapsed;
msgBox.btnNo.Focus();
break;
case MessageBoxButton.YesNoCancel:
msgBox.btnOk.Visibility = Visibility.Collapsed;
msgBox.btnCancel.Focus();
break;
default:
break;
}
}
private static void SetImageOfMessageBox(MessageBoxImage image)
{
switch (image)
{
case MessageBoxImage.Warning:
msgBox.SetImage("Warning.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
case MessageBoxImage.Question:
msgBox.SetImage("Question.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
case MessageBoxImage.Information:
msgBox.SetImage("Information.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
case MessageBoxImage.Error:
msgBox.SetImage("Error.png");
msgBox.Img.Visibility = Visibility.Visible;
break;
default:
msgBox.Img.Visibility = Visibility.Collapsed;
break;
}
}
private void SetImage(string imageName)
{
string uri = Constant.ProgramDirectory + "/Images/" + imageName;
var uriSource = new Uri(uri, UriKind.RelativeOrAbsolute);
Img.Source = new BitmapImage(uriSource);
}
private void cmdEsc_OnPress(object sender, ExecutedRoutedEventArgs e)
{
DialogResult = false;
Close();
}
private void Button_Cancel(object sender, RoutedEventArgs e)
{
msgBox.Close();
msgBox = null;
}
}
}

View file

@ -5,6 +5,7 @@ using Flow.Launcher.ViewModel;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Flow.Launcher.Core;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -23,7 +24,7 @@ namespace Flow.Launcher
this.pluginViewModel = pluginViewModel; this.pluginViewModel = pluginViewModel;
if (plugin == null) if (plugin == null)
{ {
MessageBox.Show(translater.GetTranslation("cannotFindSpecifiedPlugin")); MessageBoxEx.Show(translater.GetTranslation("cannotFindSpecifiedPlugin"));
Close(); Close();
} }
} }
@ -43,7 +44,7 @@ namespace Flow.Launcher
else else
{ {
string msg = translater.GetTranslation("invalidPriority"); string msg = translater.GetTranslation("invalidPriority");
MessageBox.Show(msg); MessageBoxEx.Show(msg);
} }
} }

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -25,6 +25,7 @@ using Flow.Launcher.Infrastructure.Storage;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Collections.Specialized; using System.Collections.Specialized;
using Flow.Launcher.Core;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -320,6 +321,9 @@ namespace Flow.Launcher
public void BackToQueryResults() => _mainVM.BackToQueryResults(); public void BackToQueryResults() => _mainVM.BackToQueryResults();
public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.OK) =>
MessageBoxEx.Show(messageBoxText, caption, button, icon, defaultResult);
#endregion #endregion
#region Private Methods #region Private Methods

View file

@ -11,7 +11,6 @@ using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using static Flow.Launcher.MessageBoxEx;
namespace Flow.Launcher.SettingPages.ViewModels; namespace Flow.Launcher.SettingPages.ViewModels;
@ -66,7 +65,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel
var confirmResult = MessageBoxEx.Show( var confirmResult = MessageBoxEx.Show(
InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"),
InternationalizationManager.Instance.GetTranslation("clearlogfolder"), InternationalizationManager.Instance.GetTranslation("clearlogfolder"),
MessageBoxType.YesNo MessageBoxButton.YesNo
); );
if (confirmResult == MessageBoxResult.Yes) if (confirmResult == MessageBoxResult.Yes)

View file

@ -7,6 +7,7 @@ using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.Core;
namespace Flow.Launcher.SettingPages.ViewModels; namespace Flow.Launcher.SettingPages.ViewModels;
@ -41,11 +42,11 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
var item = SelectedCustomPluginHotkey; var item = SelectedCustomPluginHotkey;
if (item is null) if (item is null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
return; return;
} }
var result = MessageBox.Show( var result = MessageBoxEx.Show(
string.Format( string.Format(
InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey
), ),
@ -66,7 +67,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
var item = SelectedCustomPluginHotkey; var item = SelectedCustomPluginHotkey;
if (item is null) if (item is null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
return; return;
} }
@ -87,11 +88,11 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
var item = SelectedCustomShortcut; var item = SelectedCustomShortcut;
if (item is null) if (item is null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
return; return;
} }
var result = MessageBox.Show( var result = MessageBoxEx.Show(
string.Format( string.Format(
InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value
), ),
@ -111,7 +112,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
var item = SelectedCustomShortcut; var item = SelectedCustomShortcut;
if (item is null) if (item is null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
return; return;
} }

View file

@ -1,5 +1,4 @@
using System.Net; using System.Net;
using System.Windows;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core; using Flow.Launcher.Core;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
@ -23,7 +22,7 @@ public partial class SettingsPaneProxyViewModel : BaseModel
private void OnTestProxyClicked() private void OnTestProxyClicked()
{ {
var message = TestProxy(); var message = TestProxy();
MessageBox.Show(InternationalizationManager.Instance.GetTranslation(message)); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation(message));
} }
private string TestProxy() private string TestProxy()

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -15,6 +14,7 @@ using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using ModernWpf; using ModernWpf;
using Flow.Launcher.Core;
using ThemeManager = Flow.Launcher.Core.Resource.ThemeManager; using ThemeManager = Flow.Launcher.Core.Resource.ThemeManager;
using ThemeManagerForColorSchemeSwitch = ModernWpf.ThemeManager; using ThemeManagerForColorSchemeSwitch = ModernWpf.ThemeManager;
@ -49,7 +49,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel
{ {
if (ThemeManager.Instance.BlurEnabled && value) if (ThemeManager.Instance.BlurEnabled && value)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed"));
return; return;
} }

View file

@ -171,6 +171,7 @@
IsPaneToggleButtonVisible="False" IsPaneToggleButtonVisible="False"
IsSettingsVisible="False" IsSettingsVisible="False"
IsTabStop="False" IsTabStop="False"
Loaded="NavView_Loaded"
OpenPaneLength="240" OpenPaneLength="240"
PaneDisplayMode="Left" PaneDisplayMode="Left"
SelectionChanged="NavigationView_SelectionChanged"> SelectionChanged="NavigationView_SelectionChanged">

View file

@ -29,7 +29,6 @@ public partial class SettingWindow
_api = api; _api = api;
InitializePosition(); InitializePosition();
InitializeComponent(); InitializeComponent();
NavView.SelectedItem = NavView.MenuItems[0]; /* Set First Page */
} }
private void OnLoaded(object sender, RoutedEventArgs e) private void OnLoaded(object sender, RoutedEventArgs e)
@ -169,7 +168,11 @@ public partial class SettingWindow
else else
{ {
var selectedItem = (NavigationViewItem)args.SelectedItem; var selectedItem = (NavigationViewItem)args.SelectedItem;
if (selectedItem == null) return; if (selectedItem == null)
{
NavView_Loaded(sender, null); /* Reset First Page */
return;
}
var pageType = selectedItem.Name switch var pageType = selectedItem.Name switch
{ {
@ -186,5 +189,22 @@ public partial class SettingWindow
} }
} }
private void NavView_Loaded(object sender, RoutedEventArgs e)
{
if (ContentFrame.IsLoaded)
{
ContentFrame_Loaded(sender, e);
}
else
{
ContentFrame.Loaded += ContentFrame_Loaded;
}
}
private void ContentFrame_Loaded(object sender, RoutedEventArgs e)
{
NavView.SelectedItem ??= NavView.MenuItems[0]; /* Set First Page */
}
public record PaneData(Settings Settings, Updater Updater, IPortable Portable); public record PaneData(Settings Settings, Updater Updater, IPortable Portable);
} }

View file

@ -1,29 +1,30 @@
using System.Collections.Generic; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
namespace Flow.Launcher.Storage namespace Flow.Launcher.Storage
{ {
// todo this class is not thread safe.... but used from multiple threads.
public class TopMostRecord public class TopMostRecord
{ {
[JsonInclude] [JsonInclude]
public Dictionary<string, Record> records { get; private set; } = new Dictionary<string, Record>(); public ConcurrentDictionary<string, Record> records { get; private set; } = new ConcurrentDictionary<string, Record>();
internal bool IsTopMost(Result result) internal bool IsTopMost(Result result)
{ {
if (records.Count == 0 || !records.ContainsKey(result.OriginQuery.RawQuery)) if (records.IsEmpty || result.OriginQuery == null ||
!records.TryGetValue(result.OriginQuery.RawQuery, out var value))
{ {
return false; return false;
} }
// since this dictionary should be very small (or empty) going over it should be pretty fast. // since this dictionary should be very small (or empty) going over it should be pretty fast.
return records[result.OriginQuery.RawQuery].Equals(result); return value.Equals(result);
} }
internal void Remove(Result result) internal void Remove(Result result)
{ {
records.Remove(result.OriginQuery.RawQuery); records.Remove(result.OriginQuery.RawQuery, out _);
} }
internal void AddOrUpdate(Result result) internal void AddOrUpdate(Result result)
@ -34,17 +35,15 @@ namespace Flow.Launcher.Storage
Title = result.Title, Title = result.Title,
SubTitle = result.SubTitle SubTitle = result.SubTitle
}; };
records[result.OriginQuery.RawQuery] = record; records.AddOrUpdate(result.OriginQuery.RawQuery, record, (key, oldValue) => record);
} }
public void Load(Dictionary<string, Record> dictionary) public void Load(Dictionary<string, Record> dictionary)
{ {
records = dictionary; records = new ConcurrentDictionary<string, Record>(dictionary);
} }
} }
public class Record public class Record
{ {
public string Title { get; set; } public string Title { get; set; }

View file

@ -51,6 +51,11 @@ namespace Flow.Launcher.Storage
private static int GenerateQueryAndResultHashCode(Query query, Result result) private static int GenerateQueryAndResultHashCode(Query query, Result result)
{ {
if (query == null)
{
return GenerateResultHashCode(result);
}
int hashcode = GenerateStaticHashCode(query.ActionKeyword); int hashcode = GenerateStaticHashCode(query.ActionKeyword);
hashcode = GenerateStaticHashCode(query.Search, hashcode); hashcode = GenerateStaticHashCode(query.Search, hashcode);
hashcode = GenerateStaticHashCode(result.Title, hashcode); hashcode = GenerateStaticHashCode(result.Title, hashcode);

View file

@ -23,6 +23,8 @@ using CommunityToolkit.Mvvm.Input;
using System.Globalization; using System.Globalization;
using System.Windows.Input; using System.Windows.Input;
using System.ComponentModel; using System.ComponentModel;
using Flow.Launcher.Infrastructure.Image;
using System.Windows.Media;
namespace Flow.Launcher.ViewModel namespace Flow.Launcher.ViewModel
{ {
@ -730,6 +732,8 @@ namespace Flow.Launcher.ViewModel
set => Settings.ResultSubItemFontSize = value; set => Settings.ResultSubItemFontSize = value;
} }
public ImageSource PluginIconSource { get; private set; } = null;
public string PluginIconPath { get; set; } = null; public string PluginIconPath { get; set; } = null;
public string OpenResultCommandModifiers => Settings.OpenResultModifiers; public string OpenResultCommandModifiers => Settings.OpenResultModifiers;
@ -1074,6 +1078,7 @@ namespace Flow.Launcher.ViewModel
Results.Clear(); Results.Clear();
Results.Visibility = Visibility.Collapsed; Results.Visibility = Visibility.Collapsed;
PluginIconPath = null; PluginIconPath = null;
PluginIconSource = null;
SearchIconVisibility = Visibility.Visible; SearchIconVisibility = Visibility.Visible;
return; return;
} }
@ -1107,11 +1112,13 @@ namespace Flow.Launcher.ViewModel
if (plugins.Count == 1) if (plugins.Count == 1)
{ {
PluginIconPath = plugins.Single().Metadata.IcoPath; PluginIconPath = plugins.Single().Metadata.IcoPath;
PluginIconSource = await ImageLoader.LoadAsync(PluginIconPath);
SearchIconVisibility = Visibility.Hidden; SearchIconVisibility = Visibility.Hidden;
} }
else else
{ {
PluginIconPath = null; PluginIconPath = null;
PluginIconSource = null;
SearchIconVisibility = Visibility.Visible; SearchIconVisibility = Visibility.Visible;
} }

View file

@ -82,6 +82,7 @@
<ui:Frame <ui:Frame
x:Name="ContentFrame" x:Name="ContentFrame"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Loaded="ContentFrame_Loaded"
ScrollViewer.CanContentScroll="True" ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"> ScrollViewer.VerticalScrollBarVisibility="Visible">

View file

@ -17,7 +17,6 @@ namespace Flow.Launcher
InitializeComponent(); InitializeComponent();
BackButton.IsEnabled = false; BackButton.IsEnabled = false;
this.settings = settings; this.settings = settings;
ContentFrame.Navigate(PageTypeSelector(1), settings);
} }
private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo() private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo()
@ -102,9 +101,15 @@ namespace Flow.Launcher
var tRequest = new TraversalRequest(FocusNavigationDirection.Next); var tRequest = new TraversalRequest(FocusNavigationDirection.Next);
textBox.MoveFocus(tRequest); textBox.MoveFocus(tRequest);
} }
private void OnActivated(object sender, EventArgs e) private void OnActivated(object sender, EventArgs e)
{ {
Keyboard.ClearFocus(); Keyboard.ClearFocus();
} }
private void ContentFrame_Loaded(object sender, RoutedEventArgs e)
{
ContentFrame.Navigate(PageTypeSelector(1), settings); /* Set First Page */
}
} }
} }

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using Mages.Core; using Mages.Core;
using Flow.Launcher.Plugin.Calculator.ViewModels; using Flow.Launcher.Plugin.Calculator.ViewModels;
@ -101,7 +100,7 @@ namespace Flow.Launcher.Plugin.Calculator
} }
catch (ExternalException) catch (ExternalException)
{ {
MessageBox.Show("Copy failed, please try later"); Context.API.ShowMsgBox("Copy failed, please try later");
return false; return false;
} }
} }

View file

@ -10,10 +10,6 @@ using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
using System.Linq; using System.Linq;
using Flow.Launcher.Plugin.Explorer.Helper; using Flow.Launcher.Plugin.Explorer.Helper;
using MessageBox = System.Windows.Forms.MessageBox;
using MessageBoxIcon = System.Windows.Forms.MessageBoxIcon;
using MessageBoxButton = System.Windows.Forms.MessageBoxButtons;
using DialogResult = System.Windows.Forms.DialogResult;
using Flow.Launcher.Plugin.Explorer.ViewModels; using Flow.Launcher.Plugin.Explorer.ViewModels;
namespace Flow.Launcher.Plugin.Explorer namespace Flow.Launcher.Plugin.Explorer
@ -177,12 +173,12 @@ namespace Flow.Launcher.Plugin.Explorer
{ {
try try
{ {
if (MessageBox.Show( if (Context.API.ShowMsgBox(
string.Format(Context.API.GetTranslation("plugin_explorer_delete_folder_link"), record.FullPath), string.Format(Context.API.GetTranslation("plugin_explorer_delete_folder_link"), record.FullPath),
string.Empty, string.Empty,
MessageBoxButton.YesNo, MessageBoxButton.YesNo,
MessageBoxIcon.Warning) MessageBoxImage.Warning)
== DialogResult.No) == MessageBoxResult.No)
return false; return false;
if (isFile) if (isFile)

View file

@ -5,6 +5,7 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace Flow.Launcher.Plugin.Explorer.Search.Everything; namespace Flow.Launcher.Plugin.Explorer.Search.Everything;
@ -19,10 +20,10 @@ public static class EverythingDownloadHelper
if (string.IsNullOrEmpty(installedLocation)) if (string.IsNullOrEmpty(installedLocation))
{ {
if (System.Windows.Forms.MessageBox.Show( if (api.ShowMsgBox(
string.Format(api.GetTranslation("flowlauncher_plugin_everything_installing_select"), Environment.NewLine), string.Format(api.GetTranslation("flowlauncher_plugin_everything_installing_select"), Environment.NewLine),
api.GetTranslation("flowlauncher_plugin_everything_installing_title"), api.GetTranslation("flowlauncher_plugin_everything_installing_title"),
System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
var dlg = new System.Windows.Forms.OpenFileDialog var dlg = new System.Windows.Forms.OpenFileDialog
{ {
@ -50,7 +51,7 @@ public static class EverythingDownloadHelper
installedLocation = "C:\\Program Files\\Everything\\Everything.exe"; installedLocation = "C:\\Program Files\\Everything\\Everything.exe";
FilesFolders.OpenPath(installedLocation); FilesFolders.OpenPath(installedLocation, (string str) => api.ShowMsgBox(str));
return installedLocation; return installedLocation;

View file

@ -5,7 +5,6 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.Everything;
using System.Windows.Input; using System.Windows.Input;
using Path = System.IO.Path; using Path = System.IO.Path;
@ -123,7 +122,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
} }
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error")); Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error"));
return false; return false;
} }
} }
@ -137,7 +136,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
} }
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error")); Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error"));
return false; return false;
} }
} }
@ -152,7 +151,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
} }
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error")); Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error"));
return false; return false;
} }
} }
@ -315,7 +314,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
} }
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(ex.Message, Context.API.GetTranslation("plugin_explorer_openfile_error")); Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_openfile_error"));
} }
return true; return true;
@ -337,7 +336,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
private static void OpenFile(string filePath, string workingDir = "", bool asAdmin = false) private static void OpenFile(string filePath, string workingDir = "", bool asAdmin = false)
{ {
IncrementEverythingRunCounterIfNeeded(filePath); IncrementEverythingRunCounterIfNeeded(filePath);
FilesFolders.OpenFile(filePath, workingDir, asAdmin); FilesFolders.OpenFile(filePath, workingDir, asAdmin, (string str) => Context.API.ShowMsgBox(str));
} }
private static void OpenFolder(string folderPath, string fileNameOrFilePath = null) private static void OpenFolder(string folderPath, string fileNameOrFilePath = null)

View file

@ -14,7 +14,6 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using MessageBox = System.Windows.Forms.MessageBox;
namespace Flow.Launcher.Plugin.Explorer.ViewModels namespace Flow.Launcher.Plugin.Explorer.ViewModels
{ {
@ -358,7 +357,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
private void ShowUnselectedMessage() private void ShowUnselectedMessage()
{ {
var warning = Context.API.GetTranslation("plugin_explorer_make_selection_warning"); var warning = Context.API.GetTranslation("plugin_explorer_make_selection_warning");
MessageBox.Show(warning); Context.API.ShowMsgBox(warning);
} }

View file

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
@ -62,10 +62,10 @@ namespace Flow.Launcher.Plugin.Explorer.Views
switch (CurrentActionKeyword.KeywordProperty, KeywordEnabled) switch (CurrentActionKeyword.KeywordProperty, KeywordEnabled)
{ {
case (Settings.ActionKeyword.FileContentSearchActionKeyword, true): case (Settings.ActionKeyword.FileContentSearchActionKeyword, true):
MessageBox.Show(api.GetTranslation("plugin_explorer_globalActionKeywordInvalid")); api.ShowMsgBox(api.GetTranslation("plugin_explorer_globalActionKeywordInvalid"));
return; return;
case (Settings.ActionKeyword.QuickAccessActionKeyword, true): case (Settings.ActionKeyword.QuickAccessActionKeyword, true):
MessageBox.Show(api.GetTranslation("plugin_explorer_quickaccess_globalActionKeywordInvalid")); api.ShowMsgBox(api.GetTranslation("plugin_explorer_quickaccess_globalActionKeywordInvalid"));
return; return;
} }
@ -77,7 +77,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views
} }
// The keyword is not valid, so show message // The keyword is not valid, so show message
MessageBox.Show(api.GetTranslation("newActionKeywordsHasBeenAssigned")); api.ShowMsgBox(api.GetTranslation("newActionKeywordsHasBeenAssigned"));
} }
private void BtnCancel_OnClick(object sender, RoutedEventArgs e) private void BtnCancel_OnClick(object sender, RoutedEventArgs e)

View file

@ -131,7 +131,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Environment.NewLine); Environment.NewLine);
} }
if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_install_title"), if (Context.API.ShowMsgBox(message, Context.API.GetTranslation("plugin_pluginsmanager_install_title"),
MessageBoxButton.YesNo) == MessageBoxResult.No) MessageBoxButton.YesNo) == MessageBoxResult.No)
return; return;
@ -265,7 +265,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Environment.NewLine); Environment.NewLine);
} }
if (MessageBox.Show(message, if (Context.API.ShowMsgBox(message,
Context.API.GetTranslation("plugin_pluginsmanager_update_title"), Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
MessageBoxButton.YesNo) != MessageBoxResult.Yes) MessageBoxButton.YesNo) != MessageBoxResult.Yes)
{ {
@ -360,7 +360,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
resultsForUpdate.Count()); resultsForUpdate.Count());
} }
if (MessageBox.Show(message, if (Context.API.ShowMsgBox(message,
Context.API.GetTranslation("plugin_pluginsmanager_update_title"), Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
MessageBoxButton.YesNo) == MessageBoxResult.No) MessageBoxButton.YesNo) == MessageBoxResult.No)
{ {
@ -474,7 +474,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (Settings.WarnFromUnknownSource) if (Settings.WarnFromUnknownSource)
{ {
if (!InstallSourceKnown(plugin.UrlDownload) if (!InstallSourceKnown(plugin.UrlDownload)
&& MessageBox.Show(string.Format( && Context.API.ShowMsgBox(string.Format(
Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning"), Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning"),
Environment.NewLine), Environment.NewLine),
Context.API.GetTranslation( Context.API.GetTranslation(
@ -511,7 +511,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (Settings.WarnFromUnknownSource) if (Settings.WarnFromUnknownSource)
{ {
if (!InstallSourceKnown(plugin.Website) if (!InstallSourceKnown(plugin.Website)
&& MessageBox.Show(string.Format( && Context.API.ShowMsgBox(string.Format(
Context.API.GetTranslation( Context.API.GetTranslation(
"plugin_pluginsmanager_install_unknown_source_warning"), "plugin_pluginsmanager_install_unknown_source_warning"),
Environment.NewLine), Environment.NewLine),
@ -648,7 +648,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Environment.NewLine); Environment.NewLine);
} }
if (MessageBox.Show(message, if (Context.API.ShowMsgBox(message,
Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"), Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes) MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {

View file

@ -32,7 +32,7 @@ namespace Flow.Launcher.Plugin.Program
var (modified, msg) = ViewModel.AddOrUpdate(); var (modified, msg) = ViewModel.AddOrUpdate();
if (modified == false && msg != null) if (modified == false && msg != null)
{ {
MessageBox.Show(msg); // Invalid ViewModel.API.ShowMsgBox(msg); // Invalid
return; return;
} }
DialogResult = modified; DialogResult = modified;

View file

@ -60,7 +60,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="ini-parser" Version="2.5.2" /> <PackageReference Include="ini-parser" Version="2.5.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -60,15 +60,26 @@ namespace Flow.Launcher.Plugin.Program
var result = await cache.GetOrCreateAsync(query.Search, async entry => var result = await cache.GetOrCreateAsync(query.Search, async entry =>
{ {
var resultList = await Task.Run(() => var resultList = await Task.Run(() =>
_win32s.Cast<IProgram>() {
.Concat(_uwps) try
.AsParallel() {
.WithCancellation(token) return _win32s.Cast<IProgram>()
.Where(HideUninstallersFilter) .Concat(_uwps)
.Where(p => p.Enabled) .AsParallel()
.Select(p => p.Result(query.Search, Context.API)) .WithCancellation(token)
.Where(r => r?.Score > 0) .Where(HideUninstallersFilter)
.ToList()); .Where(p => p.Enabled)
.Select(p => p.Result(query.Search, Context.API))
.Where(r => r?.Score > 0)
.ToList();
}
catch (OperationCanceledException)
{
Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled");
return emptyResults;
}
}, token);
resultList = resultList.Any() ? resultList : emptyResults; resultList = resultList.Any() ? resultList : emptyResults;

View file

@ -39,14 +39,14 @@ namespace Flow.Launcher.Plugin.Program
if (suffixes.Length == 0 && UseCustomSuffixes) if (suffixes.Length == 0 && UseCustomSuffixes)
{ {
string warning = context.API.GetTranslation("flowlauncher_plugin_program_suffixes_cannot_empty"); string warning = context.API.GetTranslation("flowlauncher_plugin_program_suffixes_cannot_empty");
MessageBox.Show(warning); context.API.ShowMsgBox(warning);
return; return;
} }
if (protocols.Length == 0 && UseCustomProtocols) if (protocols.Length == 0 && UseCustomProtocols)
{ {
string warning = context.API.GetTranslation("flowlauncher_plugin_protocols_cannot_empty"); string warning = context.API.GetTranslation("flowlauncher_plugin_protocols_cannot_empty");
MessageBox.Show(warning); context.API.ShowMsgBox(warning);
return; return;
} }

View file

@ -178,7 +178,7 @@ namespace Flow.Launcher.Plugin.Program.Views
if (selectedProgramSource == null) if (selectedProgramSource == null)
{ {
string msg = context.API.GetTranslation("flowlauncher_plugin_program_pls_select_program_source"); string msg = context.API.GetTranslation("flowlauncher_plugin_program_pls_select_program_source");
MessageBox.Show(msg); context.API.ShowMsgBox(msg);
} }
else else
{ {
@ -283,7 +283,7 @@ namespace Flow.Launcher.Plugin.Program.Views
if (selectedItems.Count == 0) if (selectedItems.Count == 0)
{ {
string msg = context.API.GetTranslation("flowlauncher_plugin_program_pls_select_program_source"); string msg = context.API.GetTranslation("flowlauncher_plugin_program_pls_select_program_source");
MessageBox.Show(msg); context.API.ShowMsgBox(msg);
return; return;
} }
@ -292,7 +292,7 @@ namespace Flow.Launcher.Plugin.Program.Views
var msg = string.Format( var msg = string.Format(
context.API.GetTranslation("flowlauncher_plugin_program_delete_program_source")); context.API.GetTranslation("flowlauncher_plugin_program_delete_program_source"));
if (MessageBox.Show(msg, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) if (context.API.ShowMsgBox(msg, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No)
{ {
return; return;
} }

View file

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
@ -14,7 +13,6 @@ using Flow.Launcher.Plugin.SharedCommands;
using Application = System.Windows.Application; using Application = System.Windows.Application;
using Control = System.Windows.Controls.Control; using Control = System.Windows.Controls.Control;
using FormsApplication = System.Windows.Forms.Application; using FormsApplication = System.Windows.Forms.Application;
using MessageBox = System.Windows.MessageBox;
namespace Flow.Launcher.Plugin.Sys namespace Flow.Launcher.Plugin.Sys
{ {
@ -143,7 +141,7 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\shutdown.png", IcoPath = "Images\\shutdown.png",
Action = c => Action = c =>
{ {
var result = MessageBox.Show( var result = context.API.ShowMsgBox(
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"),
context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"),
MessageBoxButton.YesNo, MessageBoxImage.Warning); MessageBoxButton.YesNo, MessageBoxImage.Warning);
@ -163,7 +161,7 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\restart.png", IcoPath = "Images\\restart.png",
Action = c => Action = c =>
{ {
var result = MessageBox.Show( var result = context.API.ShowMsgBox(
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"),
context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"),
MessageBoxButton.YesNo, MessageBoxImage.Warning); MessageBoxButton.YesNo, MessageBoxImage.Warning);
@ -183,7 +181,7 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\restart_advanced.png", IcoPath = "Images\\restart_advanced.png",
Action = c => Action = c =>
{ {
var result = MessageBox.Show( var result = context.API.ShowMsgBox(
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer_advanced"), context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer_advanced"),
context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"),
MessageBoxButton.YesNo, MessageBoxImage.Warning); MessageBoxButton.YesNo, MessageBoxImage.Warning);
@ -202,7 +200,7 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\logoff.png", IcoPath = "Images\\logoff.png",
Action = c => Action = c =>
{ {
var result = MessageBox.Show( var result = context.API.ShowMsgBox(
context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_logoff_computer"), context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_logoff_computer"),
context.API.GetTranslation("flowlauncher_plugin_sys_log_off"), context.API.GetTranslation("flowlauncher_plugin_sys_log_off"),
MessageBoxButton.YesNo, MessageBoxImage.Warning); MessageBoxButton.YesNo, MessageBoxImage.Warning);
@ -279,7 +277,7 @@ namespace Flow.Launcher.Plugin.Sys
var result = SHEmptyRecycleBin(new WindowInteropHelper(Application.Current.MainWindow).Handle, 0); var result = SHEmptyRecycleBin(new WindowInteropHelper(Application.Current.MainWindow).Handle, 0);
if (result != (uint) HRESULT.S_OK && result != (uint) 0x8000FFFF) if (result != (uint) HRESULT.S_OK && result != (uint) 0x8000FFFF)
{ {
MessageBox.Show($"Error emptying recycle bin, error code: {result}\n" + context.API.ShowMsgBox($"Error emptying recycle bin, error code: {result}\n" +
"please refer to https://msdn.microsoft.com/en-us/library/windows/desktop/aa378137", "please refer to https://msdn.microsoft.com/en-us/library/windows/desktop/aa378137",
"Error", "Error",
MessageBoxButton.OK, MessageBoxImage.Error); MessageBoxButton.OK, MessageBoxImage.Error);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -31,7 +31,8 @@
Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q} Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q}
</system:String> </system:String>
<system:String x:Key="flowlauncher_plugin_websearch_copyurl_title">Copy URL</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_copyurl_subtitle">Copy search URL to clipboard</system:String>
<!-- web search edit --> <!-- web search edit -->
<system:String x:Key="flowlauncher_plugin_websearch_title">Title</system:String> <system:String x:Key="flowlauncher_plugin_websearch_title">Title</system:String>

View file

@ -29,7 +29,8 @@
Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q} Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q}
</system:String> </system:String>
<system:String x:Key="flowlauncher_plugin_websearch_copyurl_title">Скопировать URL-адрес</system:String>
<system:String x:Key="flowlauncher_plugin_websearch_copyurl_subtitle">Скопировать URL поиска в буфер обмена</system:String>
<!-- web search edit --> <!-- web search edit -->
<system:String x:Key="flowlauncher_plugin_websearch_title">Title</system:String> <system:String x:Key="flowlauncher_plugin_websearch_title">Title</system:String>

View file

@ -11,9 +11,9 @@ using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Plugin.WebSearch namespace Flow.Launcher.Plugin.WebSearch
{ {
public class Main : IAsyncPlugin, ISettingProvider, IPluginI18n, IResultUpdated public class Main : IAsyncPlugin, ISettingProvider, IPluginI18n, IResultUpdated, IContextMenu
{ {
private PluginInitContext _context; internal static PluginInitContext _context;
private Settings _settings; private Settings _settings;
private SettingsViewModel _viewModel; private SettingsViewModel _viewModel;
@ -76,7 +76,8 @@ namespace Flow.Launcher.Plugin.WebSearch
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword))); _context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword)));
return true; return true;
} },
ContextData = searchSource.Url.Replace("{q}", Uri.EscapeDataString(keyword)),
}; };
results.Add(result); results.Add(result);
@ -139,11 +140,31 @@ namespace Flow.Launcher.Plugin.WebSearch
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o))); _context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
return true; return true;
} },
ContextData = searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)),
}); });
return resultsFromSuggestion; return resultsFromSuggestion;
} }
public List<Result> LoadContextMenus(Result selected)
{
if (selected?.ContextData == null || selected.ContextData is not string) return new List<Result>();
return new List<Result>() {
new Result
{
Title = _context.API.GetTranslation("flowlauncher_plugin_websearch_copyurl_title"),
SubTitle = _context.API.GetTranslation("flowlauncher_plugin_websearch_copyurl_subtitle"),
IcoPath = "Images/copylink.png",
Action = c =>
{
_context.API.CopyToClipboard(selected.ContextData as string);
return true;
}
},
};
}
public Task InitAsync(PluginInitContext context) public Task InitAsync(PluginInitContext context)
{ {
return Task.Run(Init); return Task.Run(Init);

View file

@ -55,17 +55,17 @@ namespace Flow.Launcher.Plugin.WebSearch
if (string.IsNullOrEmpty(_searchSource.Title)) if (string.IsNullOrEmpty(_searchSource.Title))
{ {
var warning = _api.GetTranslation("flowlauncher_plugin_websearch_input_title"); var warning = _api.GetTranslation("flowlauncher_plugin_websearch_input_title");
MessageBox.Show(warning); _context.API.ShowMsgBox(warning);
} }
else if (string.IsNullOrEmpty(_searchSource.Url)) else if (string.IsNullOrEmpty(_searchSource.Url))
{ {
var warning = _api.GetTranslation("flowlauncher_plugin_websearch_input_url"); var warning = _api.GetTranslation("flowlauncher_plugin_websearch_input_url");
MessageBox.Show(warning); _context.API.ShowMsgBox(warning);
} }
else if (string.IsNullOrEmpty(_searchSource.ActionKeyword)) else if (string.IsNullOrEmpty(_searchSource.ActionKeyword))
{ {
var warning = _api.GetTranslation("flowlauncher_plugin_websearch_input_action_keyword"); var warning = _api.GetTranslation("flowlauncher_plugin_websearch_input_action_keyword");
MessageBox.Show(warning); _context.API.ShowMsgBox(warning);
} }
else if (_action == Action.Add) else if (_action == Action.Add)
{ {
@ -92,7 +92,7 @@ namespace Flow.Launcher.Plugin.WebSearch
else else
{ {
var warning = _api.GetTranslation("newActionKeywordsHasBeenAssigned"); var warning = _api.GetTranslation("newActionKeywordsHasBeenAssigned");
MessageBox.Show(warning); _context.API.ShowMsgBox(warning);
} }
} }
@ -113,7 +113,7 @@ namespace Flow.Launcher.Plugin.WebSearch
else else
{ {
var warning = _api.GetTranslation("newActionKeywordsHasBeenAssigned"); var warning = _api.GetTranslation("newActionKeywordsHasBeenAssigned");
MessageBox.Show(warning); _context.API.ShowMsgBox(warning);
} }
if (!string.IsNullOrEmpty(selectedNewIconImageFullPath)) if (!string.IsNullOrEmpty(selectedNewIconImageFullPath))
@ -138,7 +138,7 @@ namespace Flow.Launcher.Plugin.WebSearch
if (!string.IsNullOrEmpty(selectedNewIconImageFullPath)) if (!string.IsNullOrEmpty(selectedNewIconImageFullPath))
{ {
if (_viewModel.ShouldProvideHint(selectedNewIconImageFullPath)) if (_viewModel.ShouldProvideHint(selectedNewIconImageFullPath))
MessageBox.Show(_api.GetTranslation("flowlauncher_plugin_websearch_iconpath_hint")); _context.API.ShowMsgBox(_api.GetTranslation("flowlauncher_plugin_websearch_iconpath_hint"));
imgPreviewIcon.Source = await _viewModel.LoadPreviewIconAsync(selectedNewIconImageFullPath); imgPreviewIcon.Source = await _viewModel.LoadPreviewIconAsync(selectedNewIconImageFullPath);
} }

View file

@ -41,7 +41,7 @@ namespace Flow.Launcher.Plugin.WebSearch
#if DEBUG #if DEBUG
throw; throw;
#else #else
MessageBox.Show(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath)); Main._context.API.ShowMsgBox(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath));
UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage); UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage);
#endif #endif
} }

View file

@ -1,4 +1,4 @@
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using Flow.Launcher.Core.Plugin; using Flow.Launcher.Core.Plugin;
using System.ComponentModel; using System.ComponentModel;
@ -36,7 +36,7 @@ namespace Flow.Launcher.Plugin.WebSearch
var warning = _context.API.GetTranslation("flowlauncher_plugin_websearch_delete_warning"); var warning = _context.API.GetTranslation("flowlauncher_plugin_websearch_delete_warning");
var formated = string.Format(warning, selected.Title); var formated = string.Format(warning, selected.Title);
var result = MessageBox.Show(formated, string.Empty, MessageBoxButton.YesNo); var result = _context.API.ShowMsgBox(formated, string.Empty, MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes) if (result == MessageBoxResult.Yes)
{ {
var id = _context.CurrentPluginMetadata.ID; var id = _context.CurrentPluginMetadata.ID;