diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs
index acc693ed5..4bafa95e1 100644
--- a/Flow.Launcher.Core/Resource/Internationalization.cs
+++ b/Flow.Launcher.Core/Resource/Internationalization.cs
@@ -134,6 +134,7 @@ namespace Flow.Launcher.Core.Resource
private void RemoveOldLanguageFiles()
{
+ return;
var dicts = Application.Current.Resources.MergedDictionaries;
foreach (var r in _oldResources)
{
@@ -143,6 +144,7 @@ namespace Flow.Launcher.Core.Resource
private void LoadLanguage(Language language)
{
+ return;
var dicts = Application.Current.Resources.MergedDictionaries;
var filename = $"{language.LanguageCode}{Extension}";
var files = _languageDirectories
@@ -171,6 +173,7 @@ namespace Flow.Launcher.Core.Resource
public string GetTranslation(string key)
{
+ return "";
var translation = Application.Current.TryFindResource(key);
if (translation is string)
{
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index 96338cf6a..ac22cd410 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -38,6 +38,8 @@ namespace Flow.Launcher.Core.Resource
_themeDirectories.Add(UserDirectoryPath);
MakeSureThemeDirectoriesExist();
+ return;
+
var dicts = Application.Current.Resources.MergedDictionaries;
_oldResource = dicts.First(d =>
{
@@ -72,6 +74,7 @@ namespace Flow.Launcher.Core.Resource
public bool ChangeTheme(string theme)
{
+ return false;
const string defaultTheme = Constant.DefaultTheme;
string path = GetThemePath(theme);
@@ -125,6 +128,8 @@ namespace Flow.Launcher.Core.Resource
private void UpdateResourceDictionary(ResourceDictionary dictionaryToUpdate)
{
+ return;
+
var dicts = Application.Current.Resources.MergedDictionaries;
dicts.Remove(_oldResource);
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index ca1674315..e0a57826d 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -193,8 +193,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool AutoUpdates { get; set; } = false;
- public double WindowLeft { get; set; }
- public double WindowTop { get; set; }
+ public int WindowLeft { get; set; }
+ public int WindowTop { get; set; }
///
/// Custom left position on selected monitor
diff --git a/Flow.Launcher/App.axaml b/Flow.Launcher/App.axaml
new file mode 100644
index 000000000..d54b69230
--- /dev/null
+++ b/Flow.Launcher/App.axaml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/App.axaml.cs b/Flow.Launcher/App.axaml.cs
new file mode 100644
index 000000000..534a2563d
--- /dev/null
+++ b/Flow.Launcher/App.axaml.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using Avalonia.ReactiveUI;
+using Flow.Launcher.Core;
+using Flow.Launcher.Core.Configuration;
+using Flow.Launcher.Core.ExternalPlugins.Environments;
+using Flow.Launcher.Core.Plugin;
+using Flow.Launcher.Core.Resource;
+using Flow.Launcher.Helper;
+using Flow.Launcher.Infrastructure;
+using Flow.Launcher.Infrastructure.Http;
+using Flow.Launcher.Infrastructure.Image;
+using Flow.Launcher.Infrastructure.Logger;
+using Flow.Launcher.Infrastructure.UserSettings;
+using Flow.Launcher.ViewModel;
+using Microsoft.VisualStudio.Threading;
+using PropertyChanged;
+using Application = Avalonia.Application;
+using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
+
+namespace Flow.Launcher
+{
+ [DoNotNotify]
+ public partial class App : Application, IDisposable, ISingleInstanceApp
+ {
+ public static PublicAPIInstance API { get; private set; }
+ private const string Unique = "Flow.Launcher_Unique_Application_Mutex";
+ private static bool _disposed;
+ private Settings _settings;
+ private MainViewModel _mainVM;
+ private SettingWindowViewModel _settingsVM;
+ private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo);
+ private readonly Portable _portable = new Portable();
+ private readonly PinyinAlphabet _alphabet = new PinyinAlphabet();
+ private StringMatcher _stringMatcher;
+
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args)
+ {
+ if (!SingleInstance.InitializeAsFirstInstance(Unique))
+ {
+ return;
+ }
+ BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+ }
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace()
+ .UseReactiveUI();
+
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ new JoinableTaskFactory(new JoinableTaskContext()).Run(() => Stopwatch.NormalAsync(
+ "|App.OnStartup|Startup cost",
+ async () =>
+ {
+ _portable.PreStartCleanUpAfterPortabilityUpdate();
+
+ Log.Info(
+ "|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
+ Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}");
+ RegisterAppDomainExceptions();
+
+ var imageLoadertask = ImageLoader.InitializeAsync();
+
+ _settingsVM = new SettingWindowViewModel(_updater, _portable);
+ _settings = _settingsVM.Settings;
+
+ AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate(_settings);
+
+ _alphabet.Initialize(_settings);
+ _stringMatcher = new StringMatcher(_alphabet);
+ StringMatcher.Instance = _stringMatcher;
+ _stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
+
+ PluginManager.LoadPlugins(_settings.PluginSettings);
+ _mainVM = new MainViewModel(_settings);
+
+ API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);
+
+ Http.API = API;
+ Http.Proxy = _settings.Proxy;
+
+ await PluginManager.InitializePluginsAsync(API);
+ await imageLoadertask;
+
+ var window = new MainWindow(_settings, _mainVM);
+
+ Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
+
+ if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
+ throw new NotSupportedException("desktop is not IClassicDesktopStyleApplicationLifetime");
+
+ desktop.MainWindow = window;
+ desktop.MainWindow.Title = Constant.FlowLauncher;
+ // desktop.Exit += (s, e) => Dispose();
+
+ HotKeyMapper.Initialize(_mainVM);
+
+ // todo temp fix for instance code logic
+ // load plugin before change language, because plugin language also needs be changed
+ InternationalizationManager.Instance.Settings = _settings;
+ InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
+ // main windows needs initialized before theme change because of blur settings
+ ThemeManager.Instance.Settings = _settings;
+ ThemeManager.Instance.ChangeTheme(_settings.Theme);
+
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+
+ RegisterExitEvents();
+
+ AutoStartup();
+ AutoUpdates();
+
+ API.SaveAppAllSettings();
+ Log.Info(
+ "|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- ");
+ }));
+ base.OnFrameworkInitializationCompleted();
+ }
+
+ private void AutoStartup()
+ {
+ // we try to enable auto-startup on first launch, or reenable if it was removed
+ // but the user still has the setting set
+ if (_settings.StartFlowLauncherOnSystemStartup && !Helper.AutoStartup.IsEnabled)
+ {
+ try
+ {
+ Helper.AutoStartup.Enable();
+ }
+ catch (Exception e)
+ {
+ // but if it fails (permissions, etc) then don't keep retrying
+ // this also gives the user a visual indication in the Settings widget
+ _settings.StartFlowLauncherOnSystemStartup = false;
+ Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"),
+ e.Message);
+ }
+ }
+ }
+
+ //[Conditional("RELEASE")]
+ private void AutoUpdates()
+ {
+ _ = Task.Run(async () =>
+ {
+ if (_settings.AutoUpdates)
+ {
+ // check update every 5 hours
+ var timer = new PeriodicTimer(TimeSpan.FromHours(5));
+ await _updater.UpdateAppAsync(API);
+
+ while (await timer.WaitForNextTickAsync())
+ // check updates on startup
+ await _updater.UpdateAppAsync(API);
+ }
+ });
+ }
+
+
+ private void RegisterExitEvents()
+ {
+ AppDomain.CurrentDomain.ProcessExit += (s, e) => Dispose();
+ }
+
+ ///
+ /// let exception throw as normal is better for Debug
+ ///
+ [Conditional("RELEASE")]
+ private static void RegisterAppDomainExceptions()
+ {
+ AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle;
+ }
+
+ public void Dispose()
+ {
+ // if sessionending is called, exit proverbially be called when log off / shutdown
+ // but if sessionending is not called, exit won't be called when log off / shutdown
+ if (!_disposed)
+ {
+ API.SaveAppAllSettings();
+ _disposed = true;
+ }
+ }
+
+ public void OnSecondAppStarted()
+ {
+ _mainVM.Show();
+ }
+ }
+}
diff --git a/Flow.Launcher/App.xaml b/Flow.Launcher/App.xaml
deleted file mode 100644
index b8e2a1cfe..000000000
--- a/Flow.Launcher/App.xaml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
deleted file mode 100644
index f4a17761f..000000000
--- a/Flow.Launcher/App.xaml.cs
+++ /dev/null
@@ -1,194 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows;
-using Flow.Launcher.Core;
-using Flow.Launcher.Core.Configuration;
-using Flow.Launcher.Core.ExternalPlugins.Environments;
-using Flow.Launcher.Core.Plugin;
-using Flow.Launcher.Core.Resource;
-using Flow.Launcher.Helper;
-using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Image;
-using Flow.Launcher.Infrastructure.Logger;
-using Flow.Launcher.Infrastructure.UserSettings;
-using Flow.Launcher.ViewModel;
-using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
-
-namespace Flow.Launcher
-{
- public partial class App : IDisposable, ISingleInstanceApp
- {
- public static PublicAPIInstance API { get; private set; }
- private const string Unique = "Flow.Launcher_Unique_Application_Mutex";
- private static bool _disposed;
- private Settings _settings;
- private MainViewModel _mainVM;
- private SettingWindowViewModel _settingsVM;
- private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo);
- private readonly Portable _portable = new Portable();
- private readonly PinyinAlphabet _alphabet = new PinyinAlphabet();
- private StringMatcher _stringMatcher;
-
- [STAThread]
- public static void Main()
- {
- if (SingleInstance.InitializeAsFirstInstance(Unique))
- {
- using (var application = new App())
- {
- application.InitializeComponent();
- application.Run();
- }
- }
- }
-
- private async void OnStartupAsync(object sender, StartupEventArgs e)
- {
- await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
- {
- _portable.PreStartCleanUpAfterPortabilityUpdate();
-
- Log.Info(
- "|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
- Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}");
- RegisterAppDomainExceptions();
- RegisterDispatcherUnhandledException();
-
- var imageLoadertask = ImageLoader.InitializeAsync();
-
- _settingsVM = new SettingWindowViewModel(_updater, _portable);
- _settings = _settingsVM.Settings;
-
- AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate(_settings);
-
- _alphabet.Initialize(_settings);
- _stringMatcher = new StringMatcher(_alphabet);
- StringMatcher.Instance = _stringMatcher;
- _stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
-
- PluginManager.LoadPlugins(_settings.PluginSettings);
- _mainVM = new MainViewModel(_settings);
-
- API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);
-
- Http.API = API;
- Http.Proxy = _settings.Proxy;
-
- await PluginManager.InitializePluginsAsync(API);
- await imageLoadertask;
-
- var window = new MainWindow(_settings, _mainVM);
-
- Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
-
- Current.MainWindow = window;
- Current.MainWindow.Title = Constant.FlowLauncher;
-
- HotKeyMapper.Initialize(_mainVM);
-
- // todo temp fix for instance code logic
- // load plugin before change language, because plugin language also needs be changed
- InternationalizationManager.Instance.Settings = _settings;
- InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
- // main windows needs initialized before theme change because of blur settings
- ThemeManager.Instance.Settings = _settings;
- ThemeManager.Instance.ChangeTheme(_settings.Theme);
-
- Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
-
- RegisterExitEvents();
-
- AutoStartup();
- AutoUpdates();
-
- API.SaveAppAllSettings();
- Log.Info(
- "|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- ");
- });
- }
-
- private void AutoStartup()
- {
- // we try to enable auto-startup on first launch, or reenable if it was removed
- // but the user still has the setting set
- if (_settings.StartFlowLauncherOnSystemStartup && !Helper.AutoStartup.IsEnabled)
- {
- try
- {
- Helper.AutoStartup.Enable();
- }
- catch (Exception e)
- {
- // but if it fails (permissions, etc) then don't keep retrying
- // this also gives the user a visual indication in the Settings widget
- _settings.StartFlowLauncherOnSystemStartup = false;
- Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"),
- e.Message);
- }
- }
- }
-
- //[Conditional("RELEASE")]
- private void AutoUpdates()
- {
- _ = Task.Run(async () =>
- {
- if (_settings.AutoUpdates)
- {
- // check update every 5 hours
- var timer = new PeriodicTimer(TimeSpan.FromHours(5));
- await _updater.UpdateAppAsync(API);
-
- while (await timer.WaitForNextTickAsync())
- // check updates on startup
- await _updater.UpdateAppAsync(API);
- }
- });
- }
-
- private void RegisterExitEvents()
- {
- AppDomain.CurrentDomain.ProcessExit += (s, e) => Dispose();
- Current.Exit += (s, e) => Dispose();
- Current.SessionEnding += (s, e) => Dispose();
- }
-
- ///
- /// let exception throw as normal is better for Debug
- ///
- [Conditional("RELEASE")]
- private void RegisterDispatcherUnhandledException()
- {
- DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException;
- }
-
- ///
- /// let exception throw as normal is better for Debug
- ///
- [Conditional("RELEASE")]
- private static void RegisterAppDomainExceptions()
- {
- AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle;
- }
-
- public void Dispose()
- {
- // if sessionending is called, exit proverbially be called when log off / shutdown
- // but if sessionending is not called, exit won't be called when log off / shutdown
- if (!_disposed)
- {
- API.SaveAppAllSettings();
- _disposed = true;
- }
- }
-
- public void OnSecondAppStarted()
- {
- _mainVM.Show();
- }
- }
-}
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 15729d9c5..055123b1a 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -4,6 +4,7 @@
WinExe
net8.0-windows10.0.19041.0
true
+ true
true
Flow.Launcher.App
Resources\app.ico
@@ -12,6 +13,7 @@
false
false
en
+ true
@@ -23,7 +25,6 @@
DEBUG;TRACE
prompt
4
- true
false
@@ -42,10 +43,6 @@
-
-
-
-
@@ -83,7 +80,13 @@
+
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher/Helper/SingleInstance.cs b/Flow.Launcher/Helper/SingleInstance.cs
index 739fed378..cb457857c 100644
--- a/Flow.Launcher/Helper/SingleInstance.cs
+++ b/Flow.Launcher/Helper/SingleInstance.cs
@@ -8,7 +8,8 @@ using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using System.Windows;
+using Avalonia;
+using Avalonia.Threading;
// http://blogs.microsoft.co.il/arik/2010/05/28/wpf-single-instance-application/
// modified to allow single instace restart
@@ -119,8 +120,10 @@ namespace Flow.Launcher.Helper
DWMWINDOWMAXIMIZEDCHANGE = 0x0321,
#region Windows 7
+
DWMSENDICONICTHUMBNAIL = 0x0323,
DWMSENDICONICLIVEPREVIEWBITMAP = 0x0326,
+
#endregion
USER = 0x0400,
@@ -140,7 +143,8 @@ namespace Flow.Launcher.Helper
public delegate IntPtr MessageHandler(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled);
[DllImport("shell32.dll", EntryPoint = "CommandLineToArgvW", CharSet = CharSet.Unicode)]
- private static extern IntPtr _CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string cmdLine, out int numArgs);
+ private static extern IntPtr _CommandLineToArgvW([MarshalAs(UnmanagedType.LPWStr)] string cmdLine,
+ out int numArgs);
[DllImport("kernel32.dll", EntryPoint = "LocalFree", SetLastError = true)]
@@ -159,6 +163,7 @@ namespace Flow.Launcher.Helper
{
throw new Win32Exception();
}
+
var result = new string[numArgs];
for (int i = 0; i < numArgs; i++)
@@ -171,19 +176,17 @@ namespace Flow.Launcher.Helper
}
finally
{
-
IntPtr p = _LocalFree(argv);
// Otherwise LocalFree failed.
// Assert.AreEqual(IntPtr.Zero, p);
}
}
+ }
- }
-
- public interface ISingleInstanceApp
- {
- void OnSecondAppStarted();
- }
+ public interface ISingleInstanceApp
+ {
+ void OnSecondAppStarted();
+ }
///
/// This class checks to make sure that only one instance of
@@ -196,9 +199,9 @@ namespace Flow.Launcher.Helper
/// running as Administrator, can activate it with command line arguments.
/// For most apps, this will not be much of an issue.
///
- public static class SingleInstance
- where TApplication: Application , ISingleInstanceApp
-
+ public static class SingleInstance
+ where TApplication : Avalonia.Application, ISingleInstanceApp
+
{
#region Private Fields
@@ -230,7 +233,7 @@ namespace Flow.Launcher.Helper
/// If not, activates the first instance.
///
/// True if this is the first instance of the application.
- public static bool InitializeAsFirstInstance( string uniqueName )
+ public static bool InitializeAsFirstInstance(string uniqueName)
{
// Build unique application Id and the IPC channel name.
string applicationIdentifier = uniqueName + Environment.UserName;
@@ -268,7 +271,7 @@ namespace Flow.Launcher.Helper
/// Gets command line args - for ClickOnce deployed applications, command line args may not be passed directly, they have to be retrieved.
///
/// List of command line arg strings.
- private static IList GetCommandLineArgs( string uniqueApplicationName )
+ private static IList GetCommandLineArgs(string uniqueApplicationName)
{
string[] args = null;
@@ -279,7 +282,6 @@ namespace Flow.Launcher.Helper
}
catch (NotSupportedException)
{
-
// The application was clickonce deployed
// Clickonce deployed apps cannot recieve traditional commandline arguments
// As a workaround commandline arguments can be written to a shared location before
@@ -323,15 +325,17 @@ namespace Flow.Launcher.Helper
{
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream(channelName, PipeDirection.In))
{
- while(true)
+ while (true)
{
// Wait for connection to the pipe
await pipeServer.WaitForConnectionAsync();
if (Application.Current != null)
{
+
// Do an asynchronous call to ActivateFirstInstance function
- Application.Current.Dispatcher.Invoke(ActivateFirstInstance);
+ Dispatcher.UIThread.Invoke(ActivateFirstInstance);
}
+
// Disconect client
pipeServer.Disconnect();
}
@@ -378,7 +382,7 @@ namespace Flow.Launcher.Helper
return;
}
- ((TApplication)Application.Current).OnSecondAppStarted();
+ ((TApplication)Application.Current)!.OnSecondAppStarted();
}
#endregion
diff --git a/Flow.Launcher/MainWindow.axaml b/Flow.Launcher/MainWindow.axaml
new file mode 100644
index 000000000..a8af8bf90
--- /dev/null
+++ b/Flow.Launcher/MainWindow.axaml
@@ -0,0 +1,454 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.axaml.cs
similarity index 59%
rename from Flow.Launcher/MainWindow.xaml.cs
rename to Flow.Launcher/MainWindow.axaml.cs
index 7d1a68125..de7f2fe6c 100644
--- a/Flow.Launcher/MainWindow.xaml.cs
+++ b/Flow.Launcher/MainWindow.axaml.cs
@@ -1,10 +1,6 @@
using System;
using System.ComponentModel;
using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Input;
-using System.Windows.Media.Animation;
-using System.Windows.Controls;
using System.Windows.Forms;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Core.Resource;
@@ -19,20 +15,30 @@ using NotifyIcon = System.Windows.Forms.NotifyIcon;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin.SharedCommands;
-using System.Windows.Threading;
-using System.Windows.Data;
using ModernWpf.Controls;
using Key = System.Windows.Input.Key;
using System.Media;
+using System.Windows;
+using Avalonia;
+using Avalonia.Input;
+using Avalonia.Threading;
+using PropertyChanged;
using static Flow.Launcher.ViewModel.SettingWindowViewModel;
+using ContextMenu = System.Windows.Controls.ContextMenu;
+using MenuItem = System.Windows.Controls.MenuItem;
+using MouseButton = System.Windows.Input.MouseButton;
+using RoutedEventArgs = Avalonia.Interactivity.RoutedEventArgs;
+using Thickness = System.Windows.Thickness;
+using Window = Avalonia.Controls.Window;
namespace Flow.Launcher
{
- public partial class MainWindow
+ [DoNotNotify]
+ public partial class MainWindow : Window
{
#region Private Fields
- private readonly Storyboard _progressBarStoryboard = new Storyboard();
+ // private readonly Storyboard _progressBarStoryboard = new Storyboard();
private bool isProgressBarStoryboardPaused;
private Settings _settings;
private NotifyIcon _notifyIcon;
@@ -50,7 +56,7 @@ namespace Flow.Launcher
_settings = settings;
InitializeComponent();
- InitializePosition();
+ // InitializePosition();
}
public MainWindow()
@@ -58,30 +64,31 @@ namespace Flow.Launcher
InitializeComponent();
}
- private void OnCopy(object sender, ExecutedRoutedEventArgs e)
- {
- var result = _viewModel.Results.SelectedItem?.Result;
- if (QueryTextBox.SelectionLength == 0 && result != null)
- {
- string copyText = result.CopyText;
- App.API.CopyToClipboard(copyText, directCopy: true);
- }
- else if (!string.IsNullOrEmpty(QueryTextBox.Text))
- {
- App.API.CopyToClipboard(QueryTextBox.SelectedText, showDefaultNotification: false);
- }
- }
+ // private void OnCopy(object sender, ExecutedRoutedEventArgs e)
+ // {
+ // var result = _viewModel.Results.SelectedItem?.Result;
+ // if (QueryTextBox.SelectionLength == 0 && result != null)
+ // {
+ // string copyText = result.CopyText;
+ // App.API.CopyToClipboard(copyText, directCopy: true);
+ // }
+ // else if (!string.IsNullOrEmpty(QueryTextBox.Text))
+ // {
+ // App.API.CopyToClipboard(QueryTextBox.SelectedText, showDefaultNotification: false);
+ // }
+ // }
+ //
+ // private void OnPaste(object sender, ExecutedRoutedEventArgs e)
+ // {
+ // if (System.Windows.Clipboard.ContainsText())
+ // {
+ // _viewModel.ChangeQueryText(System.Windows.Clipboard.GetText().Replace("\n", String.Empty)
+ // .Replace("\r", String.Empty));
+ // e.Handled = true;
+ // }
+ // }
- private void OnPaste(object sender, ExecutedRoutedEventArgs e)
- {
- if (System.Windows.Clipboard.ContainsText())
- {
- _viewModel.ChangeQueryText(System.Windows.Clipboard.GetText().Replace("\n", String.Empty).Replace("\r", String.Empty));
- e.Handled = true;
- }
- }
-
- private async void OnClosing(object sender, CancelEventArgs e)
+ public async void OnClosing(object sender, CancelEventArgs e)
{
_notifyIcon.Visible = false;
App.API.SaveAppAllSettings();
@@ -91,20 +98,20 @@ namespace Flow.Launcher
Environment.Exit(0);
}
- private void OnInitialized(object sender, EventArgs e)
+ public void OnInitialized(object sender, EventArgs e)
{
}
- private void OnLoaded(object sender, RoutedEventArgs _)
+ public void OnLoaded(object sender, RoutedEventArgs _)
{
CheckFirstLaunch();
HideStartup();
// show notify icon when flowlauncher is hidden
InitializeNotifyIcon();
InitializeColorScheme();
- WindowsInteropHelper.DisableControlBox(this);
+ // WindowsInteropHelper.DisableControlBox(this);
InitProgressbarAnimation();
- InitializePosition();
+ // InitializePosition();
PreviewReset();
// since the default main window visibility is visible
// so we need set focus during startup
@@ -116,7 +123,7 @@ namespace Flow.Launcher
{
case nameof(MainViewModel.MainWindowVisibilityStatus):
{
- Dispatcher.Invoke(() =>
+ Dispatcher.UIThread.Invoke(() =>
{
if (_viewModel.MainWindowVisibilityStatus)
{
@@ -124,6 +131,7 @@ namespace Flow.Launcher
{
animationSound.Play();
}
+
UpdatePosition();
PreviewReset();
Activate();
@@ -135,18 +143,18 @@ namespace Flow.Launcher
_viewModel.LastQuerySelected = true;
}
- if (_viewModel.ProgressBarVisibility == Visibility.Visible && isProgressBarStoryboardPaused)
+ if (_viewModel.ProgressBarVisibility && isProgressBarStoryboardPaused)
{
- _progressBarStoryboard.Begin(ProgressBar, true);
+ // _progressBarStoryboard.Begin(ProgressBar, true);
isProgressBarStoryboardPaused = false;
}
- if (_settings.UseAnimation)
- WindowAnimator();
+ // if (_settings.UseAnimation)
+ // WindowAnimator();
}
else if (!isProgressBarStoryboardPaused)
{
- _progressBarStoryboard.Stop(ProgressBar);
+ // _progressBarStoryboard.Stop(ProgressBar);
isProgressBarStoryboardPaused = true;
}
});
@@ -154,17 +162,17 @@ namespace Flow.Launcher
}
case nameof(MainViewModel.ProgressBarVisibility):
{
- Dispatcher.Invoke(() =>
+ Dispatcher.UIThread.Invoke(() =>
{
- if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
+ if (!_viewModel.ProgressBarVisibility && !isProgressBarStoryboardPaused)
{
- _progressBarStoryboard.Stop(ProgressBar);
+ // _progressBarStoryboard.Stop(ProgressBar);
isProgressBarStoryboardPaused = true;
}
else if (_viewModel.MainWindowVisibilityStatus &&
isProgressBarStoryboardPaused)
{
- _progressBarStoryboard.Begin(ProgressBar, true);
+ // _progressBarStoryboard.Begin(ProgressBar, true);
isProgressBarStoryboardPaused = false;
}
});
@@ -176,9 +184,12 @@ namespace Flow.Launcher
MoveQueryTextToEnd();
_viewModel.QueryTextCursorMovedToEnd = false;
}
+
break;
case nameof(MainViewModel.GameModeStatus):
- _notifyIcon.Icon = _viewModel.GameModeStatus ? Properties.Resources.gamemode : Properties.Resources.app;
+ _notifyIcon.Icon = _viewModel.GameModeStatus
+ ? Properties.Resources.gamemode
+ : Properties.Resources.app;
break;
}
};
@@ -197,10 +208,10 @@ namespace Flow.Launcher
UpdateNotifyIconText();
break;
case nameof(Settings.WindowLeft):
- Left = _settings.WindowLeft;
+ Position = new PixelPoint(_settings.WindowLeft, _settings.WindowTop);
break;
case nameof(Settings.WindowTop):
- Top = _settings.WindowTop;
+ Position = new PixelPoint(_settings.WindowLeft, _settings.WindowTop);
break;
}
};
@@ -210,8 +221,7 @@ namespace Flow.Launcher
{
if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation)
{
- Top = _settings.WindowTop;
- Left = _settings.WindowLeft;
+ Position = new PixelPoint(_settings.WindowLeft, _settings.WindowTop);
}
else
{
@@ -219,39 +229,36 @@ namespace Flow.Launcher
switch (_settings.SearchWindowAlign)
{
case SearchWindowAligns.Center:
- Left = HorizonCenter(screen);
- Top = VerticalCenter(screen);
+ Position = new PixelPoint(HorizonCenter(screen), VerticalCenter(screen));
break;
case SearchWindowAligns.CenterTop:
- Left = HorizonCenter(screen);
- Top = 10;
+ Position = new PixelPoint(HorizonCenter(screen), 10);
break;
case SearchWindowAligns.LeftTop:
- Left = HorizonLeft(screen);
- Top = 10;
+ Position = new PixelPoint(HorizonLeft(screen), 10);
break;
case SearchWindowAligns.RightTop:
- Left = HorizonRight(screen);
- Top = 10;
+ Position = new PixelPoint(HorizonRight(screen), 10);
break;
case SearchWindowAligns.Custom:
- Left = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X + _settings.CustomWindowLeft, 0).X;
- Top = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y + _settings.CustomWindowTop).Y;
+ // Left = WindowsInteropHelper
+ // .TransformPixelsToDIP(this, screen.WorkingArea.X + _settings.CustomWindowLeft, 0).X;
+ // Top = WindowsInteropHelper
+ // .TransformPixelsToDIP(this, 0, screen.WorkingArea.Y + _settings.CustomWindowTop).Y;
break;
}
}
-
}
private void UpdateNotifyIconText()
{
var menu = contextMenu;
- ((MenuItem)menu.Items[0]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")";
+ ((MenuItem)menu.Items[0]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") +
+ " (" + _settings.Hotkey + ")";
((MenuItem)menu.Items[1]).Header = InternationalizationManager.Instance.GetTranslation("GameMode");
((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("PositionReset");
((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings");
((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit");
-
}
private void InitializeNotifyIcon()
@@ -265,42 +272,31 @@ namespace Flow.Launcher
contextMenu = new ContextMenu();
- var openIcon = new FontIcon
- {
- Glyph = "\ue71e"
- };
+ var openIcon = new FontIcon { Glyph = "\ue71e" };
var open = new MenuItem
{
- Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", Icon = openIcon
- };
- var gamemodeIcon = new FontIcon
- {
- Glyph = "\ue7fc"
+ Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" +
+ _settings.Hotkey + ")",
+ Icon = openIcon
};
+ var gamemodeIcon = new FontIcon { Glyph = "\ue7fc" };
var gamemode = new MenuItem
{
Header = InternationalizationManager.Instance.GetTranslation("GameMode"), Icon = gamemodeIcon
};
- var positionresetIcon = new FontIcon
- {
- Glyph = "\ue73f"
- };
+ var positionresetIcon = new FontIcon { Glyph = "\ue73f" };
var positionreset = new MenuItem
{
- Header = InternationalizationManager.Instance.GetTranslation("PositionReset"), Icon = positionresetIcon
- };
- var settingsIcon = new FontIcon
- {
- Glyph = "\ue713"
+ Header = InternationalizationManager.Instance.GetTranslation("PositionReset"),
+ Icon = positionresetIcon
};
+ var settingsIcon = new FontIcon { Glyph = "\ue713" };
var settings = new MenuItem
{
- Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"), Icon = settingsIcon
- };
- var exitIcon = new FontIcon
- {
- Glyph = "\ue7e8"
+ Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"),
+ Icon = settingsIcon
};
+ var exitIcon = new FontIcon { Glyph = "\ue7e8" };
var exit = new MenuItem
{
Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"), Icon = exitIcon
@@ -321,7 +317,8 @@ namespace Flow.Launcher
contextMenu.Items.Add(settings);
contextMenu.Items.Add(exit);
- _notifyIcon.ContextMenuStrip = new ContextMenuStrip(); // it need for close the context menu. if not, context menu can't close.
+ _notifyIcon.ContextMenuStrip =
+ new ContextMenuStrip(); // it need for close the context menu. if not, context menu can't close.
_notifyIcon.MouseClick += (o, e) =>
{
switch (e.Button)
@@ -358,128 +355,130 @@ namespace Flow.Launcher
_viewModel.Show();
await Task.Delay(300); // If don't give a time, Positioning will be weird.
var screen = SelectedScreen();
- Left = HorizonCenter(screen);
- Top = VerticalCenter(screen);
+ Position = new PixelPoint(HorizonCenter(screen), VerticalCenter(screen));
}
private void InitProgressbarAnimation()
{
- var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 100, new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
- var da1 = new DoubleAnimation(ProgressBar.X1, ActualWidth + 0, new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
- Storyboard.SetTargetProperty(da, new PropertyPath("(Line.X2)"));
- Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X1)"));
- _progressBarStoryboard.Children.Add(da);
- _progressBarStoryboard.Children.Add(da1);
- _progressBarStoryboard.RepeatBehavior = RepeatBehavior.Forever;
- _viewModel.ProgressBarVisibility = Visibility.Hidden;
- isProgressBarStoryboardPaused = true;
+ // var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 100,
+ // new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
+ // var da1 = new DoubleAnimation(ProgressBar.X1, ActualWidth + 0,
+ // new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
+ // Storyboard.SetTargetProperty(da, new PropertyPath("(Line.X2)"));
+ // Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X1)"));
+ // _progressBarStoryboard.Children.Add(da);
+ // _progressBarStoryboard.Children.Add(da1);
+ // _progressBarStoryboard.RepeatBehavior = RepeatBehavior.Forever;
+ // _viewModel.ProgressBarVisibility = Visibility.Hidden;
+ // isProgressBarStoryboardPaused = true;
}
- public void WindowAnimator()
+ // public void WindowAnimator()
+ // {
+ // if (_animating)
+ // return;
+ //
+ // _animating = true;
+ // UpdatePosition();
+ //
+ // Storyboard windowsb = new Storyboard();
+ // Storyboard clocksb = new Storyboard();
+ // Storyboard iconsb = new Storyboard();
+ // CircleEase easing = new CircleEase();
+ // easing.EasingMode = EasingMode.EaseInOut;
+ //
+ // var animationLength = _settings.AnimationSpeed switch
+ // {
+ // AnimationSpeeds.Slow => 560,
+ // AnimationSpeeds.Medium => 360,
+ // AnimationSpeeds.Fast => 160,
+ // _ => _settings.CustomAnimationLength
+ // };
+ //
+ // var WindowOpacity = new DoubleAnimation
+ // {
+ // From = 0,
+ // To = 1,
+ // Duration = TimeSpan.FromMilliseconds(animationLength * 2 / 3),
+ // FillBehavior = FillBehavior.Stop
+ // };
+ //
+ // var WindowMotion = new DoubleAnimation
+ // {
+ // From = Top + 10,
+ // To = Top,
+ // Duration = TimeSpan.FromMilliseconds(animationLength * 2 / 3),
+ // FillBehavior = FillBehavior.Stop
+ // };
+ // var IconMotion = new DoubleAnimation
+ // {
+ // From = 12,
+ // To = 0,
+ // EasingFunction = easing,
+ // Duration = TimeSpan.FromMilliseconds(animationLength),
+ // FillBehavior = FillBehavior.Stop
+ // };
+ //
+ // var ClockOpacity = new DoubleAnimation
+ // {
+ // From = 0,
+ // To = 1,
+ // EasingFunction = easing,
+ // Duration = TimeSpan.FromMilliseconds(animationLength),
+ // FillBehavior = FillBehavior.Stop
+ // };
+ // double TargetIconOpacity = SearchIcon.Opacity; // Animation Target Opacity from Style
+ // var IconOpacity = new DoubleAnimation
+ // {
+ // From = 0,
+ // To = TargetIconOpacity,
+ // EasingFunction = easing,
+ // Duration = TimeSpan.FromMilliseconds(animationLength),
+ // FillBehavior = FillBehavior.Stop
+ // };
+ //
+ // double right = ClockPanel.Margin.Right;
+ // var thicknessAnimation = new ThicknessAnimation
+ // {
+ // From = new Thickness(0, 12, right, 0),
+ // To = new Thickness(0, 0, right, 0),
+ // EasingFunction = easing,
+ // Duration = TimeSpan.FromMilliseconds(animationLength),
+ // FillBehavior = FillBehavior.Stop
+ // };
+ //
+ // Storyboard.SetTargetProperty(ClockOpacity, new PropertyPath(OpacityProperty));
+ // Storyboard.SetTargetName(thicknessAnimation, "ClockPanel");
+ // Storyboard.SetTargetProperty(thicknessAnimation, new PropertyPath(MarginProperty));
+ // Storyboard.SetTarget(WindowOpacity, this);
+ // Storyboard.SetTargetProperty(WindowOpacity, new PropertyPath(Window.OpacityProperty));
+ // Storyboard.SetTargetProperty(WindowMotion, new PropertyPath(Window.TopProperty));
+ // Storyboard.SetTargetProperty(IconMotion, new PropertyPath(TopProperty));
+ // Storyboard.SetTargetProperty(IconOpacity, new PropertyPath(OpacityProperty));
+ //
+ // clocksb.Children.Add(thicknessAnimation);
+ // clocksb.Children.Add(ClockOpacity);
+ // windowsb.Children.Add(WindowOpacity);
+ // windowsb.Children.Add(WindowMotion);
+ // iconsb.Children.Add(IconMotion);
+ // iconsb.Children.Add(IconOpacity);
+ //
+ // windowsb.Completed += (_, _) => _animating = false;
+ // _settings.WindowLeft = Left;
+ // _settings.WindowTop = Top;
+ //
+ // if (QueryTextBox.Text.Length == 0)
+ // {
+ // clocksb.Begin(ClockPanel);
+ // }
+ //
+ // iconsb.Begin(SearchIcon);
+ // windowsb.Begin(FlowMainWindow);
+ // }
+
+ private void OnMouseDown(object sender, PointerPressedEventArgs e)
{
- if (_animating)
- return;
-
- _animating = true;
- UpdatePosition();
-
- Storyboard windowsb = new Storyboard();
- Storyboard clocksb = new Storyboard();
- Storyboard iconsb = new Storyboard();
- CircleEase easing = new CircleEase();
- easing.EasingMode = EasingMode.EaseInOut;
-
- var animationLength = _settings.AnimationSpeed switch
- {
- AnimationSpeeds.Slow => 560,
- AnimationSpeeds.Medium => 360,
- AnimationSpeeds.Fast => 160,
- _ => _settings.CustomAnimationLength
- };
-
- var WindowOpacity = new DoubleAnimation
- {
- From = 0,
- To = 1,
- Duration = TimeSpan.FromMilliseconds(animationLength * 2 / 3),
- FillBehavior = FillBehavior.Stop
- };
-
- var WindowMotion = new DoubleAnimation
- {
- From = Top + 10,
- To = Top,
- Duration = TimeSpan.FromMilliseconds(animationLength * 2 / 3),
- FillBehavior = FillBehavior.Stop
- };
- var IconMotion = new DoubleAnimation
- {
- From = 12,
- To = 0,
- EasingFunction = easing,
- Duration = TimeSpan.FromMilliseconds(animationLength),
- FillBehavior = FillBehavior.Stop
- };
-
- var ClockOpacity = new DoubleAnimation
- {
- From = 0,
- To = 1,
- EasingFunction = easing,
- Duration = TimeSpan.FromMilliseconds(animationLength),
- FillBehavior = FillBehavior.Stop
- };
- double TargetIconOpacity = SearchIcon.Opacity; // Animation Target Opacity from Style
- var IconOpacity = new DoubleAnimation
- {
- From = 0,
- To = TargetIconOpacity,
- EasingFunction = easing,
- Duration = TimeSpan.FromMilliseconds(animationLength),
- FillBehavior = FillBehavior.Stop
- };
-
- double right = ClockPanel.Margin.Right;
- var thicknessAnimation = new ThicknessAnimation
- {
- From = new Thickness(0, 12, right, 0),
- To = new Thickness(0, 0, right, 0),
- EasingFunction = easing,
- Duration = TimeSpan.FromMilliseconds(animationLength),
- FillBehavior = FillBehavior.Stop
- };
-
- Storyboard.SetTargetProperty(ClockOpacity, new PropertyPath(OpacityProperty));
- Storyboard.SetTargetName(thicknessAnimation, "ClockPanel");
- Storyboard.SetTargetProperty(thicknessAnimation, new PropertyPath(MarginProperty));
- Storyboard.SetTarget(WindowOpacity, this);
- Storyboard.SetTargetProperty(WindowOpacity, new PropertyPath(Window.OpacityProperty));
- Storyboard.SetTargetProperty(WindowMotion, new PropertyPath(Window.TopProperty));
- Storyboard.SetTargetProperty(IconMotion, new PropertyPath(TopProperty));
- Storyboard.SetTargetProperty(IconOpacity, new PropertyPath(OpacityProperty));
-
- clocksb.Children.Add(thicknessAnimation);
- clocksb.Children.Add(ClockOpacity);
- windowsb.Children.Add(WindowOpacity);
- windowsb.Children.Add(WindowMotion);
- iconsb.Children.Add(IconMotion);
- iconsb.Children.Add(IconOpacity);
-
- windowsb.Completed += (_, _) => _animating = false;
- _settings.WindowLeft = Left;
- _settings.WindowTop = Top;
-
- if (QueryTextBox.Text.Length == 0)
- {
- clocksb.Begin(ClockPanel);
- }
- iconsb.Begin(SearchIcon);
- windowsb.Begin(FlowMainWindow);
- }
-
- private void OnMouseDown(object sender, MouseButtonEventArgs e)
- {
- if (e.ChangedButton == MouseButton.Left) DragMove();
+ // if (e.Pointer.IsPrimary) DragMove();
}
private void OnPreviewDragOver(object sender, DragEventArgs e)
@@ -499,8 +498,9 @@ namespace Flow.Launcher
private async void OnDeactivated(object sender, EventArgs e)
{
- _settings.WindowLeft = Left;
- _settings.WindowTop = Top;
+ return;
+ _settings.WindowLeft = Position.X;
+ _settings.WindowTop = Position.Y;
//This condition stops extra hide call when animator is on,
// which causes the toggling to occasional hide instead of show.
if (_viewModel.MainWindowVisibilityStatus)
@@ -522,7 +522,7 @@ namespace Flow.Launcher
{
if (_animating)
return;
- InitializePosition();
+ // InitializePosition();
}
private void OnLocationChanged(object sender, EventArgs e)
@@ -531,8 +531,8 @@ namespace Flow.Launcher
return;
if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation)
{
- _settings.WindowLeft = Left;
- _settings.WindowTop = Top;
+ _settings.WindowLeft = Position.X;
+ _settings.WindowTop = Position.Y;
}
}
@@ -552,7 +552,7 @@ namespace Flow.Launcher
public Screen SelectedScreen()
{
Screen screen = null;
- switch(_settings.SearchWindowScreen)
+ switch (_settings.SearchWindowScreen)
{
case SearchWindowScreens.Cursor:
screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
@@ -574,38 +574,39 @@ namespace Flow.Launcher
screen = Screen.AllScreens[0];
break;
}
+
return screen ?? Screen.AllScreens[0];
}
-
- public double HorizonCenter(Screen screen)
+
+ public int HorizonCenter(Screen screen)
{
- var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
- var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
- var left = (dip2.X - ActualWidth) / 2 + dip1.X;
- return left;
+ var dip1 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
+ var dip2 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
+ var left = (dip2.X - Width) / 2 + dip1.X;
+ return (int) left;
}
- public double VerticalCenter(Screen screen)
+ public int VerticalCenter(Screen screen)
{
- var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
- var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
- var top = (dip2.Y - QueryTextBox.ActualHeight) / 4 + dip1.Y;
- return top;
+ var dip1 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
+ var dip2 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
+ var top = (dip2.Y - QueryTextBox.Height) / 4 + dip1.Y;
+ return (int)top;
}
- public double HorizonRight(Screen screen)
+ public int HorizonRight(Screen screen)
{
- var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
- var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
- var left = (dip1.X + dip2.X - ActualWidth) - 10;
- return left;
+ var dip1 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
+ var dip2 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
+ var left = (dip1.X + dip2.X - Width) - 10;
+ return (int) left;
}
- public double HorizonLeft(Screen screen)
+ public int HorizonLeft(Screen screen)
{
- var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
+ var dip1 = new PixelPoint(0,0); // WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
var left = dip1.X + 10;
- return left;
+ return (int) left;
}
///
@@ -641,6 +642,7 @@ namespace Flow.Launcher
_viewModel.LoadContextMenuCommand.Execute(null);
e.Handled = true;
}
+
break;
case Key.Left:
if (!_viewModel.SelectedIsFromQueryResults() && QueryTextBox.CaretIndex == 0)
@@ -648,6 +650,7 @@ namespace Flow.Launcher
_viewModel.EscCommand.Execute(null);
e.Handled = true;
}
+
break;
case Key.Back:
if (specialKeyState.CtrlPressed)
@@ -666,10 +669,10 @@ namespace Flow.Launcher
}
}
}
+
break;
default:
break;
-
}
}
@@ -682,7 +685,7 @@ namespace Flow.Launcher
{
// QueryTextBox seems to be update with a DispatcherPriority as low as ContextIdle.
// To ensure QueryTextBox is up to date with QueryText from the View, we need to Dispatch with such a priority
- Dispatcher.Invoke(() => QueryTextBox.CaretIndex = QueryTextBox.Text.Length);
+ Dispatcher.UIThread.Invoke(() => QueryTextBox.CaretIndex = QueryTextBox.Text.Length);
}
public void InitializeColorScheme()
@@ -701,8 +704,8 @@ namespace Flow.Launcher
{
if (_viewModel.QueryText != QueryTextBox.Text)
{
- BindingExpression be = QueryTextBox.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty);
- be.UpdateSource();
+ // BindingExpression be = QueryTextBox.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty);
+ // be.UpdateSource();
}
}
}
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
deleted file mode 100644
index b65fbc7bb..000000000
--- a/Flow.Launcher/MainWindow.xaml
+++ /dev/null
@@ -1,501 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 36309a22a..0809c74fd 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -25,6 +25,7 @@ using Flow.Launcher.Infrastructure.Storage;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Collections.Specialized;
+using Avalonia.Threading;
namespace Flow.Launcher
{
@@ -102,7 +103,7 @@ namespace Flow.Launcher
public void OpenSettingDialog()
{
- Application.Current.Dispatcher.Invoke(() =>
+ Dispatcher.UIThread.Invoke(() =>
{
SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM);
});
@@ -147,9 +148,9 @@ namespace Flow.Launcher
}
}
- public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible;
+ public void StartLoadingBar() => _mainVM.ProgressBarVisibility = true;
- public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed;
+ public void StopLoadingBar() => _mainVM.ProgressBarVisibility = false;
public string GetTranslation(string key) => InternationalizationManager.Instance.GetTranslation(key);
diff --git a/Flow.Launcher/ResultListBox.axaml b/Flow.Launcher/ResultListBox.axaml
new file mode 100644
index 000000000..e047f58dd
--- /dev/null
+++ b/Flow.Launcher/ResultListBox.axaml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/ResultListBox.axaml.cs b/Flow.Launcher/ResultListBox.axaml.cs
new file mode 100644
index 000000000..c07dba536
--- /dev/null
+++ b/Flow.Launcher/ResultListBox.axaml.cs
@@ -0,0 +1,162 @@
+using System;
+using System.IO;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Flow.Launcher.ViewModel;
+using PropertyChanged;
+
+namespace Flow.Launcher
+{
+ [DoNotNotify]
+ public partial class ResultListBox : UserControl
+ {
+ protected object _lock = new object();
+ private PixelPoint _lastpos;
+ private ListBoxItem curItem = null;
+ public ResultListBox()
+ {
+ InitializeComponent();
+ }
+ //
+ // public static readonly DependencyProperty RightClickResultCommandProperty =
+ // DependencyProperty.Register("RightClickResultCommand", typeof(ICommand), typeof(ResultListBox), new UIPropertyMetadata(null));
+ //
+ // public ICommand RightClickResultCommand
+ // {
+ // get
+ // {
+ // return (ICommand)GetValue(RightClickResultCommandProperty);
+ // }
+ // set
+ // {
+ // SetValue(RightClickResultCommandProperty, value);
+ // }
+ // }
+ //
+ // public static readonly DependencyProperty LeftClickResultCommandProperty =
+ // DependencyProperty.Register("LeftClickResultCommand", typeof(ICommand), typeof(ResultListBox), new UIPropertyMetadata(null));
+ //
+ // public ICommand LeftClickResultCommand
+ // {
+ // get
+ // {
+ // return (ICommand)GetValue(LeftClickResultCommandProperty);
+ // }
+ // set
+ // {
+ // SetValue(LeftClickResultCommandProperty, value);
+ // }
+ // }
+
+ //
+ // private void OnMouseEnter(object sender, MouseEventArgs e)
+ // {
+ // lock (_lock)
+ // {
+ // curItem = (ListBoxItem)sender;
+ // var p = e.GetPosition((IInputElement)sender);
+ // _lastpos = p;
+ // }
+ // }
+ //
+ // private void OnMouseMove(object sender, MouseEventArgs e)
+ // {
+ // lock (_lock)
+ // {
+ // var p = e.GetPosition((IInputElement)sender);
+ // if (_lastpos != p)
+ // {
+ // ((ListBoxItem)sender).IsSelected = true;
+ // }
+ // }
+ // }
+
+ private void ListBox_PreviewMouseDown(object sender, PointerPressedEventArgs e)
+ {
+ lock (_lock)
+ {
+ if (curItem != null)
+ {
+ curItem.IsSelected = true;
+ }
+ }
+ }
+
+
+ private Point start;
+ private string path;
+ private string query;
+ // this method is called by the UI thread, which is single threaded, so we can be sloppy with locking
+ private bool isDragging;
+ //
+ // private void ResultList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ // {
+ // if (Mouse.DirectlyOver is not FrameworkElement
+ // {
+ // DataContext: ResultViewModel
+ // {
+ // Result:
+ // {
+ // CopyText: { } copyText,
+ // OriginQuery.RawQuery: { } rawQuery
+ // }
+ // }
+ // }) return;
+ //
+ // path = copyText;
+ // query = rawQuery;
+ // start = e.GetPosition(null);
+ // isDragging = true;
+ // }
+ // private void ResultList_MouseMove(object sender, MouseEventArgs e)
+ // {
+ // if (e.LeftButton != MouseButtonState.Pressed || !isDragging)
+ // {
+ // start = default;
+ // path = string.Empty;
+ // query = string.Empty;
+ // isDragging = false;
+ // return;
+ // }
+ //
+ // if (!File.Exists(path) && !Directory.Exists(path))
+ // return;
+ //
+ // Point mousePosition = e.GetPosition(null);
+ // Vector diff = this.start - mousePosition;
+ //
+ // if (Math.Abs(diff.X) < SystemParameters.MinimumHorizontalDragDistance
+ // || Math.Abs(diff.Y) < SystemParameters.MinimumVerticalDragDistance)
+ // return;
+ //
+ // isDragging = false;
+ //
+ // var data = new DataObject(DataFormats.FileDrop, new[]
+ // {
+ // path
+ // });
+ //
+ // // Reassigning query to a new variable because for some reason
+ // // after DragDrop.DoDragDrop call, 'query' loses its content, i.e. becomes empty string
+ // var rawQuery = query;
+ // var effect = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move | DragDropEffects.Copy);
+ // if (effect == DragDropEffects.Move)
+ // App.API.ChangeQuery(rawQuery, true);
+ // }
+ // private void ResultListBox_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
+ // {
+ // if (Mouse.DirectlyOver is not FrameworkElement { DataContext: ResultViewModel result })
+ // return;
+ //
+ // RightClickResultCommand?.Execute(result.Result);
+ // }
+ // private void ResultListBox_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
+ // {
+ // if (Mouse.DirectlyOver is not FrameworkElement { DataContext: ResultViewModel result })
+ // return;
+ //
+ // LeftClickResultCommand?.Execute(null);
+ // }
+ }
+}
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
deleted file mode 100644
index ba4c9e9a4..000000000
--- a/Flow.Launcher/ResultListBox.xaml
+++ /dev/null
@@ -1,255 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Flow.Launcher/ResultListBox.xaml.cs b/Flow.Launcher/ResultListBox.xaml.cs
deleted file mode 100644
index 78720e86a..000000000
--- a/Flow.Launcher/ResultListBox.xaml.cs
+++ /dev/null
@@ -1,167 +0,0 @@
-using System;
-using System.IO;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using Flow.Launcher.ViewModel;
-
-namespace Flow.Launcher
-{
- public partial class ResultListBox
- {
- protected object _lock = new object();
- private Point _lastpos;
- private ListBoxItem curItem = null;
- public ResultListBox()
- {
- InitializeComponent();
- }
-
- public static readonly DependencyProperty RightClickResultCommandProperty =
- DependencyProperty.Register("RightClickResultCommand", typeof(ICommand), typeof(ResultListBox), new UIPropertyMetadata(null));
-
- public ICommand RightClickResultCommand
- {
- get
- {
- return (ICommand)GetValue(RightClickResultCommandProperty);
- }
- set
- {
- SetValue(RightClickResultCommandProperty, value);
- }
- }
-
- public static readonly DependencyProperty LeftClickResultCommandProperty =
- DependencyProperty.Register("LeftClickResultCommand", typeof(ICommand), typeof(ResultListBox), new UIPropertyMetadata(null));
-
- public ICommand LeftClickResultCommand
- {
- get
- {
- return (ICommand)GetValue(LeftClickResultCommandProperty);
- }
- set
- {
- SetValue(LeftClickResultCommandProperty, value);
- }
- }
-
- private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (e.AddedItems.Count > 0 && e.AddedItems[0] != null)
- {
- ScrollIntoView(e.AddedItems[0]);
- }
- }
-
- private void OnMouseEnter(object sender, MouseEventArgs e)
- {
- lock (_lock)
- {
- curItem = (ListBoxItem)sender;
- var p = e.GetPosition((IInputElement)sender);
- _lastpos = p;
- }
- }
-
- private void OnMouseMove(object sender, MouseEventArgs e)
- {
- lock (_lock)
- {
- var p = e.GetPosition((IInputElement)sender);
- if (_lastpos != p)
- {
- ((ListBoxItem)sender).IsSelected = true;
- }
- }
- }
-
- private void ListBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
- {
- lock (_lock)
- {
- if (curItem != null)
- {
- curItem.IsSelected = true;
- }
- }
- }
-
-
- private Point start;
- private string path;
- private string query;
- // this method is called by the UI thread, which is single threaded, so we can be sloppy with locking
- private bool isDragging;
-
- private void ResultList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (Mouse.DirectlyOver is not FrameworkElement
- {
- DataContext: ResultViewModel
- {
- Result:
- {
- CopyText: { } copyText,
- OriginQuery.RawQuery: { } rawQuery
- }
- }
- }) return;
-
- path = copyText;
- query = rawQuery;
- start = e.GetPosition(null);
- isDragging = true;
- }
- private void ResultList_MouseMove(object sender, MouseEventArgs e)
- {
- if (e.LeftButton != MouseButtonState.Pressed || !isDragging)
- {
- start = default;
- path = string.Empty;
- query = string.Empty;
- isDragging = false;
- return;
- }
-
- if (!File.Exists(path) && !Directory.Exists(path))
- return;
-
- Point mousePosition = e.GetPosition(null);
- Vector diff = this.start - mousePosition;
-
- if (Math.Abs(diff.X) < SystemParameters.MinimumHorizontalDragDistance
- || Math.Abs(diff.Y) < SystemParameters.MinimumVerticalDragDistance)
- return;
-
- isDragging = false;
-
- var data = new DataObject(DataFormats.FileDrop, new[]
- {
- path
- });
-
- // Reassigning query to a new variable because for some reason
- // after DragDrop.DoDragDrop call, 'query' loses its content, i.e. becomes empty string
- var rawQuery = query;
- var effect = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move | DragDropEffects.Copy);
- if (effect == DragDropEffects.Move)
- App.API.ChangeQuery(rawQuery, true);
- }
- private void ResultListBox_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (Mouse.DirectlyOver is not FrameworkElement { DataContext: ResultViewModel result })
- return;
-
- RightClickResultCommand?.Execute(result.Result);
- }
- private void ResultListBox_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
- {
- if (Mouse.DirectlyOver is not FrameworkElement { DataContext: ResultViewModel result })
- return;
-
- LeftClickResultCommand?.Execute(null);
- }
- }
-}
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index 1e886c022..3a2450431 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -1975,10 +1975,10 @@
-
+
+
+
+
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 61bf0c4dc..5c674a756 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -25,6 +25,7 @@ using CommunityToolkit.Mvvm.Input;
using System.Globalization;
using System.Windows.Input;
using System.ComponentModel;
+using Avalonia.Threading;
namespace Flow.Launcher.ViewModel
{
@@ -93,7 +94,7 @@ namespace Flow.Launcher.ViewModel
{
LeftClickResultCommand = OpenResultCommand, RightClickResultCommand = LoadContextMenuCommand
};
- Results = new ResultsViewModel(Settings)
+ ResultsVM = new ResultsViewModel(Settings)
{
LeftClickResultCommand = OpenResultCommand, RightClickResultCommand = LoadContextMenuCommand
};
@@ -101,13 +102,13 @@ namespace Flow.Launcher.ViewModel
{
LeftClickResultCommand = OpenResultCommand, RightClickResultCommand = LoadContextMenuCommand
};
- _selectedResults = Results;
+ _selectedResults = ResultsVM;
- Results.PropertyChanged += (_, args) =>
+ ResultsVM.PropertyChanged += (_, args) =>
{
switch (args.PropertyName)
{
- case nameof(Results.SelectedItem):
+ case nameof(ResultsVM.SelectedItem):
UpdatePreview();
break;
}
@@ -174,7 +175,8 @@ namespace Flow.Launcher.ViewModel
var token = e.Token == default ? _updateToken : e.Token;
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
- if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, token)))
+ if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query,
+ token)))
{
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
}
@@ -188,7 +190,8 @@ namespace Flow.Launcher.ViewModel
Hide();
await PluginManager.ReloadDataAsync().ConfigureAwait(false);
- Notification.Show(InternationalizationManager.Instance.GetTranslation("success"), InternationalizationManager.Instance.GetTranslation("completedSuccessfully"));
+ Notification.Show(InternationalizationManager.Instance.GetTranslation("success"),
+ InternationalizationManager.Instance.GetTranslation("completedSuccessfully"));
}
[RelayCommand]
@@ -201,7 +204,7 @@ namespace Flow.Launcher.ViewModel
}
else
{
- SelectedResults = Results;
+ SelectedResults = ResultsVM;
}
}
@@ -226,7 +229,7 @@ namespace Flow.Launcher.ViewModel
}
else
{
- SelectedResults = Results;
+ SelectedResults = ResultsVM;
}
}
@@ -278,11 +281,13 @@ namespace Flow.Launcher.ViewModel
{
results.SelectedIndex = int.Parse(index);
}
+
var result = results.SelectedItem?.Result;
if (result == null)
{
return;
}
+
var hideWindow = await result.ExecuteAsync(new ActionContext
{
// not null means pressing modifier key + number, should ignore the modifier key
@@ -350,7 +355,7 @@ namespace Flow.Launcher.ViewModel
{
if (!SelectedIsFromQueryResults())
{
- SelectedResults = Results;
+ SelectedResults = ResultsVM;
}
else
{
@@ -386,7 +391,7 @@ namespace Flow.Launcher.ViewModel
}
}
- public ResultsViewModel Results { get; private set; }
+ public ResultsViewModel ResultsVM { get; private set; }
public ResultsViewModel ContextMenu { get; private set; }
@@ -395,6 +400,7 @@ namespace Flow.Launcher.ViewModel
public bool GameModeStatus { get; set; } = false;
private string _queryText;
+
public string QueryText
{
get => _queryText;
@@ -418,6 +424,7 @@ namespace Flow.Launcher.ViewModel
Settings.WindowSize += 100;
Settings.WindowLeft -= 50;
}
+
OnPropertyChanged();
}
@@ -433,6 +440,7 @@ namespace Flow.Launcher.ViewModel
Settings.WindowLeft += 50;
Settings.WindowSize -= 100;
}
+
OnPropertyChanged();
}
@@ -471,7 +479,7 @@ namespace Flow.Launcher.ViewModel
{
ResultAreaColumn = 1;
PreviewVisible = true;
- Results.SelectedItem?.LoadPreviewImage();
+ ResultsVM.SelectedItem?.LoadPreviewImage();
}
private void HidePreview()
@@ -496,7 +504,7 @@ namespace Flow.Launcher.ViewModel
{
if (PreviewVisible)
{
- Results.SelectedItem?.LoadPreviewImage();
+ ResultsVM.SelectedItem?.LoadPreviewImage();
}
}
@@ -508,22 +516,21 @@ namespace Flow.Launcher.ViewModel
/// Force query even when Query Text doesn't change
public void ChangeQueryText(string queryText, bool isReQuery = false)
{
- Application.Current.Dispatcher.Invoke(() =>
+ Dispatcher.UIThread.Invoke(() =>
{
if (QueryText != queryText)
{
-
// re-query is done in QueryText's setter method
QueryText = queryText;
// set to false so the subsequent set true triggers
// PropertyChanged and MoveQueryTextToEnd is called
QueryTextCursorMovedToEnd = false;
-
}
else if (isReQuery)
{
Query(isReQuery: true);
}
+
QueryTextCursorMovedToEnd = true;
});
}
@@ -543,13 +550,13 @@ namespace Flow.Launcher.ViewModel
_selectedResults = value;
if (SelectedIsFromQueryResults())
{
- ContextMenu.Visibility = Visibility.Collapsed;
- History.Visibility = Visibility.Collapsed;
+ ContextMenu.Visibility = false;
+ History.Visibility = false;
ChangeQueryText(_queryTextBeforeLeaveResults);
}
else
{
- Results.Visibility = Visibility.Collapsed;
+ ResultsVM.Visibility = false;
_queryTextBeforeLeaveResults = QueryText;
@@ -567,12 +574,12 @@ namespace Flow.Launcher.ViewModel
}
}
- _selectedResults.Visibility = Visibility.Visible;
+ _selectedResults.Visibility = true;
}
}
- public Visibility ProgressBarVisibility { get; set; }
- public Visibility MainWindowVisibility { get; set; }
+ public bool ProgressBarVisibility { get; set; }
+ public bool MainWindowVisibility { get; set; }
public double MainWindowOpacity { get; set; } = 1;
// This is to be used for determining the visibility status of the mainwindow instead of MainWindowVisibility
@@ -581,7 +588,7 @@ namespace Flow.Launcher.ViewModel
public event VisibilityChangedEventHandler VisibilityChanged;
- public Visibility SearchIconVisibility { get; set; }
+ public bool SearchIconVisibility { get; set; }
public double MainWindowWidth
{
@@ -593,8 +600,8 @@ namespace Flow.Launcher.ViewModel
public string OpenResultCommandModifiers => Settings.OpenResultModifiers;
- public string PreviewHotkey
- {
+ public string PreviewHotkey
+ {
get
{
// TODO try to patch issue #1755
@@ -608,6 +615,7 @@ namespace Flow.Launcher.ViewModel
{
Settings.PreviewHotkey = "F1";
}
+
return Settings.PreviewHotkey;
}
}
@@ -646,7 +654,7 @@ namespace Flow.Launcher.ViewModel
var query = QueryText.ToLower().Trim();
ContextMenu.Clear();
- var selected = Results.SelectedItem?.Result;
+ var selected = ResultsVM.SelectedItem?.Result;
if (selected != null) // SelectedItem returns null if selection is empty.
{
@@ -670,7 +678,6 @@ namespace Flow.Launcher.ViewModel
r.Score = match.Score;
return true;
-
}).ToList();
ContextMenu.AddResults(filtered, id);
}
@@ -697,13 +704,10 @@ namespace Flow.Launcher.ViewModel
Title = string.Format(title, h.Query),
SubTitle = string.Format(time, h.ExecutedDateTime),
IcoPath = "Images\\history.png",
- OriginQuery = new Query
- {
- RawQuery = h.Query
- },
+ OriginQuery = new Query { RawQuery = h.Query },
Action = _ =>
{
- SelectedResults = Results;
+ SelectedResults = ResultsVM;
ChangeQueryText(h.Query);
return false;
}
@@ -736,10 +740,10 @@ namespace Flow.Launcher.ViewModel
if (query == null) // shortcut expanded
{
- Results.Clear();
- Results.Visibility = Visibility.Collapsed;
+ ResultsVM.Clear();
+ ResultsVM.Visibility = false;
PluginIconPath = null;
- SearchIconVisibility = Visibility.Visible;
+ SearchIconVisibility = true;
return;
}
@@ -750,7 +754,7 @@ namespace Flow.Launcher.ViewModel
var currentCancellationToken = _updateSource.Token;
_updateToken = currentCancellationToken;
- ProgressBarVisibility = Visibility.Hidden;
+ ProgressBarVisibility = false;
_isQueryRunning = true;
// Switch to ThreadPool thread
@@ -772,12 +776,12 @@ namespace Flow.Launcher.ViewModel
if (plugins.Count == 1)
{
PluginIconPath = plugins.Single().Metadata.IcoPath;
- SearchIconVisibility = Visibility.Hidden;
+ SearchIconVisibility = false;
}
else
{
PluginIconPath = null;
- SearchIconVisibility = Visibility.Visible;
+ SearchIconVisibility = true;
}
@@ -795,7 +799,7 @@ namespace Flow.Launcher.ViewModel
// start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
if (!currentCancellationToken.IsCancellationRequested && _isQueryRunning)
{
- ProgressBarVisibility = Visibility.Visible;
+ ProgressBarVisibility = true;
}
}, currentCancellationToken, TaskContinuationOptions.NotOnCanceled, TaskScheduler.Default);
@@ -827,7 +831,7 @@ namespace Flow.Launcher.ViewModel
if (!currentCancellationToken.IsCancellationRequested)
{
// update to hidden if this is still the current query
- ProgressBarVisibility = Visibility.Hidden;
+ ProgressBarVisibility = false;
}
// Local function
@@ -837,20 +841,23 @@ namespace Flow.Launcher.ViewModel
// Task.Yield will force it to run in ThreadPool
await Task.Yield();
- IReadOnlyList results = await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken);
+ IReadOnlyList results =
+ await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken);
currentCancellationToken.ThrowIfCancellationRequested();
results ??= _emptyResult;
- if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken)))
+ if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query,
+ currentCancellationToken)))
{
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
}
}
}
- private Query ConstructQuery(string queryText, IEnumerable customShortcuts, IEnumerable builtInShortcuts)
+ private Query ConstructQuery(string queryText, IEnumerable customShortcuts,
+ IEnumerable builtInShortcuts)
{
if (string.IsNullOrWhiteSpace(queryText))
{
@@ -872,7 +879,7 @@ namespace Flow.Launcher.ViewModel
string customExpanded = queryBuilder.ToString();
- Application.Current.Dispatcher.Invoke(() =>
+ Dispatcher.UIThread.Invoke(() =>
{
foreach (var shortcut in builtInShortcuts)
{
@@ -887,7 +894,9 @@ namespace Flow.Launcher.ViewModel
}
catch (Exception e)
{
- Log.Exception($"{nameof(MainViewModel)}.{nameof(ConstructQuery)}|Error when expanding shortcut {shortcut.Key}", e);
+ Log.Exception(
+ $"{nameof(MainViewModel)}.{nameof(ConstructQuery)}|Error when expanding shortcut {shortcut.Key}",
+ e);
}
}
});
@@ -904,7 +913,7 @@ namespace Flow.Launcher.ViewModel
{
if (_lastQuery?.ActionKeyword != query?.ActionKeyword)
{
- Results.Clear();
+ ResultsVM.Clear();
}
}
@@ -976,7 +985,7 @@ namespace Flow.Launcher.ViewModel
internal bool SelectedIsFromQueryResults()
{
- var selected = SelectedResults == Results;
+ var selected = SelectedResults == ResultsVM;
return selected;
}
@@ -1010,9 +1019,9 @@ namespace Flow.Launcher.ViewModel
public void Show()
{
- Application.Current.Dispatcher.Invoke(() =>
+ Dispatcher.UIThread.Invoke(() =>
{
- MainWindowVisibility = Visibility.Visible;
+ MainWindowVisibility = true;
MainWindowOpacity = 1;
@@ -1028,8 +1037,9 @@ namespace Flow.Launcher.ViewModel
if (!SelectedIsFromQueryResults())
{
- SelectedResults = Results;
+ SelectedResults = ResultsVM;
}
+
switch (Settings.LastQueryMode)
{
case LastQueryMode.Empty:
@@ -1051,7 +1061,7 @@ namespace Flow.Launcher.ViewModel
}
MainWindowVisibilityStatus = false;
- MainWindowVisibility = Visibility.Collapsed;
+ MainWindowVisibility = false;
VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = false });
}
@@ -1116,7 +1126,7 @@ namespace Flow.Launcher.ViewModel
}
}
- Results.AddResults(resultsForUpdates, token);
+ ResultsVM.AddResults(resultsForUpdates, token);
}
#endregion
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 3f204c16c..d86a1d990 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -25,6 +25,7 @@ namespace Flow.Launcher.ViewModel
{
return;
}
+
Result = result;
if (Result.Glyph is { FontFamily: not null } glyph)
@@ -41,19 +42,14 @@ namespace Flow.Launcher.ViewModel
if (fonts.ContainsKey(fontFamilyPath))
{
- Glyph = glyph with
- {
- FontFamily = fonts[fontFamilyPath]
- };
+ Glyph = glyph with { FontFamily = fonts[fontFamilyPath] };
}
else
{
fontCollection.AddFontFile(fontFamilyPath);
- fonts[fontFamilyPath] = $"{Path.GetDirectoryName(fontFamilyPath)}/#{fontCollection.Families[^1].Name}";
- Glyph = glyph with
- {
- FontFamily = fonts[fontFamilyPath]
- };
+ fonts[fontFamilyPath] =
+ $"{Path.GetDirectoryName(fontFamilyPath)}/#{fontCollection.Families[^1].Name}";
+ Glyph = glyph with { FontFamily = fonts[fontFamilyPath] };
}
}
else
@@ -61,42 +57,40 @@ namespace Flow.Launcher.ViewModel
Glyph = glyph;
}
}
-
}
private Settings Settings { get; }
- public Visibility ShowOpenResultHotkey =>
- Settings.ShowOpenResultHotkey ? Visibility.Visible : Visibility.Collapsed;
+ public bool ShowOpenResultHotkey => Settings.ShowOpenResultHotkey;
- public Visibility ShowDefaultPreview => Result.PreviewPanel == null ? Visibility.Visible : Visibility.Collapsed;
+ public bool ShowDefaultPreview => Result.PreviewPanel != null;
- public Visibility ShowCustomizedPreview => Result.PreviewPanel == null ? Visibility.Collapsed : Visibility.Visible;
+ public bool ShowCustomizedPreview => Result.PreviewPanel != null;
- public Visibility ShowIcon
+ public bool ShowIcon
{
get
{
// If both glyph and image icons are not available, it will then be the default icon
if (!ImgIconAvailable && !GlyphAvailable)
- return Visibility.Visible;
+ return true;
// Although user can choose to use glyph icons, plugins may choose to supply only image icons.
// In this case we ignore the setting because otherwise icons will not display as intended
if (Settings.UseGlyphIcons && !GlyphAvailable && ImgIconAvailable)
- return Visibility.Visible;
+ return true;
- return !Settings.UseGlyphIcons && ImgIconAvailable ? Visibility.Visible : Visibility.Hidden;
+ return !Settings.UseGlyphIcons && ImgIconAvailable;
}
}
- public Visibility ShowPreviewImage
+ public bool ShowPreviewImage
{
get
{
if (PreviewImageAvailable)
{
- return Visibility.Visible;
+ return true;
}
else
{
@@ -114,21 +108,21 @@ namespace Flow.Launcher.ViewModel
{
return IconXY / 2;
}
+
return IconXY;
}
-
}
- public Visibility ShowGlyph
+ public bool ShowGlyph
{
get
{
// Although user can choose to not use glyph icons, plugins may choose to supply only glyph icons.
// In this case we ignore the setting because otherwise icons will not display as intended
if (!Settings.UseGlyphIcons && !ImgIconAvailable && GlyphAvailable)
- return Visibility.Visible;
+ return true;
- return Settings.UseGlyphIcons && GlyphAvailable ? Visibility.Visible : Visibility.Collapsed;
+ return Settings.UseGlyphIcons && GlyphAvailable;
}
}
@@ -136,7 +130,8 @@ namespace Flow.Launcher.ViewModel
private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPath) || Result.Icon is not null;
- private bool PreviewImageAvailable => !string.IsNullOrEmpty(Result.Preview.PreviewImagePath) || Result.Preview.PreviewDelegate != null;
+ private bool PreviewImageAvailable => !string.IsNullOrEmpty(Result.Preview.PreviewImagePath) ||
+ Result.Preview.PreviewDelegate != null;
public string OpenResultModifiers => Settings.OpenResultModifiers;
@@ -182,7 +177,8 @@ namespace Flow.Launcher.ViewModel
public GlyphInfo Glyph { get; set; }
- private async Task LoadImageInternalAsync(string imagePath, Result.IconDelegate icon, bool loadFullImage)
+ private async Task LoadImageInternalAsync(string imagePath, Result.IconDelegate icon,
+ bool loadFullImage)
{
if (string.IsNullOrEmpty(imagePath) && icon != null)
{
@@ -234,9 +230,9 @@ namespace Flow.Launcher.ViewModel
public void LoadPreviewImage()
{
- if (ShowDefaultPreview == Visibility.Visible)
+ if (ShowDefaultPreview)
{
- if (!PreviewImageLoaded && ShowPreviewImage == Visibility.Visible)
+ if (!PreviewImageLoaded && ShowPreviewImage)
{
PreviewImageLoaded = true;
_ = LoadPreviewImageAsync();
@@ -245,6 +241,7 @@ namespace Flow.Launcher.ViewModel
}
public Result Result { get; }
+
public int ResultProgress
{
get
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index bb07ce085..cdd781249 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -27,6 +27,7 @@ namespace Flow.Launcher.ViewModel
Results = new ResultCollection();
BindingOperations.EnableCollectionSynchronization(Results, _collectionLock);
}
+
public ResultsViewModel(Settings settings) : this()
{
_settings = settings;
@@ -43,14 +44,14 @@ namespace Flow.Launcher.ViewModel
#region Properties
- public double MaxHeight => MaxResults * (double)Application.Current.FindResource("ResultItemHeight")!;
+ public double MaxHeight => MaxResults * 52;
public int SelectedIndex { get; set; }
public ResultViewModel SelectedItem { get; set; }
public Thickness Margin { get; set; }
- public Visibility Visibility { get; set; } = Visibility.Collapsed;
-
+ public bool Visibility { get; set; } = true;
+
public ICommand RightClickResultCommand { get; init; }
public ICommand LeftClickResultCommand { get; init; }
@@ -69,6 +70,7 @@ namespace Flow.Launcher.ViewModel
break;
}
}
+
return index;
}
@@ -87,7 +89,6 @@ namespace Flow.Launcher.ViewModel
}
}
-
#endregion
#region Public Methods
@@ -144,6 +145,7 @@ namespace Flow.Launcher.ViewModel
UpdateResults(newResults);
}
+
///
/// To avoid deadlock, this method should not called from main thread
///
@@ -169,12 +171,12 @@ namespace Flow.Launcher.ViewModel
switch (Visibility)
{
- case Visibility.Collapsed when Results.Count > 0:
+ case false when Results.Count > 0:
SelectedIndex = 0;
- Visibility = Visibility.Visible;
+ Visibility = true;
break;
- case Visibility.Visible when Results.Count == 0:
- Visibility = Visibility.Collapsed;
+ case true when Results.Count == 0:
+ Visibility = false;
break;
}
}
@@ -199,28 +201,30 @@ namespace Flow.Launcher.ViewModel
return Results;
return Results.Where(r => r != null && !resultsForUpdates.Any(u => u.ID == r.Result.PluginID))
- .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings)))
- .OrderByDescending(rv => rv.Result.Score)
- .ToList();
+ .Concat(resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings)))
+ .OrderByDescending(rv => rv.Result.Score)
+ .ToList();
}
+
#endregion
#region FormattedText Dependency Property
- public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
- "FormattedText",
- typeof(Inline),
- typeof(ResultsViewModel),
- new PropertyMetadata(null, FormattedTextPropertyChanged));
- public static void SetFormattedText(DependencyObject textBlock, IList value)
- {
- textBlock.SetValue(FormattedTextProperty, value);
- }
+ // public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
+ // "FormattedText",
+ // typeof(Inline),
+ // typeof(ResultsViewModel),
+ // new PropertyMetadata(null, FormattedTextPropertyChanged));
+ //
+ // public static void SetFormattedText(DependencyObject textBlock, IList value)
+ // {
+ // textBlock.SetValue(FormattedTextProperty, value);
+ // }
- public static Inline GetFormattedText(DependencyObject textBlock)
- {
- return (Inline)textBlock.GetValue(FormattedTextProperty);
- }
+ // public static Inline GetFormattedText(DependencyObject textBlock)
+ // {
+ // return (Inline)textBlock.GetValue(FormattedTextProperty);
+ // }
private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
@@ -234,6 +238,7 @@ namespace Flow.Launcher.ViewModel
textBlock.Inlines.Add(inline);
}
+
#endregion
public class ResultCollection : List, INotifyCollectionChanged
@@ -262,6 +267,7 @@ namespace Flow.Launcher.ViewModel
// wpf use DirectX / double buffered already, so just reset all won't cause ui flickering
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
+
private void AddAll(List Items)
{
for (int i = 0; i < Items.Count; i++)
@@ -270,9 +276,11 @@ namespace Flow.Launcher.ViewModel
if (_token.IsCancellationRequested)
return;
Add(item);
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, i));
+ OnCollectionChanged(
+ new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, i));
}
}
+
public void RemoveAll(int Capacity = 512)
{
Clear();
@@ -307,6 +315,7 @@ namespace Flow.Launcher.ViewModel
{
Capacity = newItems.Count;
}
+
editTime++;
}
}