mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into FixProgramSource
This commit is contained in:
commit
21c5c776c6
3 changed files with 158 additions and 126 deletions
|
|
@ -57,7 +57,7 @@ namespace Flow.Launcher
|
|||
DataContext = mainVM;
|
||||
_viewModel = mainVM;
|
||||
_settings = settings;
|
||||
|
||||
|
||||
InitializeComponent();
|
||||
InitializePosition();
|
||||
animationSound.Open(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav"));
|
||||
|
|
@ -67,7 +67,7 @@ namespace Flow.Launcher
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private void OnCopy(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
if (QueryTextBox.SelectionLength == 0)
|
||||
|
|
@ -115,6 +115,8 @@ namespace Flow.Launcher
|
|||
switch (e.PropertyName)
|
||||
{
|
||||
case nameof(MainViewModel.MainWindowVisibilityStatus):
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (_viewModel.MainWindowVisibilityStatus)
|
||||
{
|
||||
|
|
@ -140,7 +142,7 @@ namespace Flow.Launcher
|
|||
isProgressBarStoryboardPaused = false;
|
||||
}
|
||||
|
||||
if(_settings.UseAnimation)
|
||||
if (_settings.UseAnimation)
|
||||
WindowAnimator();
|
||||
}
|
||||
else if (!isProgressBarStoryboardPaused)
|
||||
|
|
@ -148,27 +150,27 @@ namespace Flow.Launcher
|
|||
_progressBarStoryboard.Stop(ProgressBar);
|
||||
isProgressBarStoryboardPaused = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case nameof(MainViewModel.ProgressBarVisibility):
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
|
||||
{
|
||||
if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
|
||||
{
|
||||
_progressBarStoryboard.Stop(ProgressBar);
|
||||
isProgressBarStoryboardPaused = true;
|
||||
}
|
||||
else if (_viewModel.MainWindowVisibilityStatus &&
|
||||
isProgressBarStoryboardPaused)
|
||||
{
|
||||
_progressBarStoryboard.Begin(ProgressBar, true);
|
||||
isProgressBarStoryboardPaused = false;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
_progressBarStoryboard.Stop(ProgressBar);
|
||||
isProgressBarStoryboardPaused = true;
|
||||
}
|
||||
else if (_viewModel.MainWindowVisibilityStatus &&
|
||||
isProgressBarStoryboardPaused)
|
||||
{
|
||||
_progressBarStoryboard.Begin(ProgressBar, true);
|
||||
isProgressBarStoryboardPaused = false;
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case nameof(MainViewModel.QueryTextCursorMovedToEnd):
|
||||
if (_viewModel.QueryTextCursorMovedToEnd)
|
||||
{
|
||||
|
|
@ -251,35 +253,45 @@ 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
|
||||
Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", Icon = openIcon
|
||||
};
|
||||
var gamemodeIcon = new FontIcon
|
||||
{
|
||||
Glyph = "\ue7fc"
|
||||
};
|
||||
var gamemodeIcon = new FontIcon { Glyph = "\ue7fc" };
|
||||
var gamemode = new MenuItem
|
||||
{
|
||||
Header = InternationalizationManager.Instance.GetTranslation("GameMode"),
|
||||
Icon = gamemodeIcon
|
||||
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
|
||||
Header = InternationalizationManager.Instance.GetTranslation("PositionReset"), Icon = positionresetIcon
|
||||
};
|
||||
var settingsIcon = new FontIcon
|
||||
{
|
||||
Glyph = "\ue713"
|
||||
};
|
||||
var settingsIcon = new FontIcon { Glyph = "\ue713" };
|
||||
var settings = new MenuItem
|
||||
{
|
||||
Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"),
|
||||
Icon = settingsIcon
|
||||
Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"), Icon = settingsIcon
|
||||
};
|
||||
var exitIcon = new FontIcon
|
||||
{
|
||||
Glyph = "\ue7e8"
|
||||
};
|
||||
var exitIcon = new FontIcon { Glyph = "\ue7e8" };
|
||||
var exit = new MenuItem
|
||||
{
|
||||
Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"),
|
||||
Icon = exitIcon
|
||||
Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"), Icon = exitIcon
|
||||
};
|
||||
|
||||
open.Click += (o, e) => _viewModel.ToggleFlowLauncher();
|
||||
|
|
@ -342,15 +354,15 @@ namespace Flow.Launcher
|
|||
}
|
||||
private async void PositionReset()
|
||||
{
|
||||
_viewModel.Show();
|
||||
await Task.Delay(300); // If don't give a time, Positioning will be weird.
|
||||
Left = HorizonCenter();
|
||||
Top = VerticalCenter();
|
||||
_viewModel.Show();
|
||||
await Task.Delay(300); // If don't give a time, Positioning will be weird.
|
||||
Left = HorizonCenter();
|
||||
Top = VerticalCenter();
|
||||
}
|
||||
private void InitProgressbarAnimation()
|
||||
{
|
||||
var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 150,
|
||||
new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
|
||||
new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
|
||||
var da1 = new DoubleAnimation(ProgressBar.X1, ActualWidth + 50, new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
|
||||
Storyboard.SetTargetProperty(da, new PropertyPath("(Line.X2)"));
|
||||
Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X1)"));
|
||||
|
|
@ -392,11 +404,11 @@ namespace Flow.Launcher
|
|||
};
|
||||
var IconMotion = new DoubleAnimation
|
||||
{
|
||||
From = 12,
|
||||
To = 0,
|
||||
EasingFunction = easing,
|
||||
Duration = TimeSpan.FromSeconds(0.36),
|
||||
FillBehavior = FillBehavior.Stop
|
||||
From = 12,
|
||||
To = 0,
|
||||
EasingFunction = easing,
|
||||
Duration = TimeSpan.FromSeconds(0.36),
|
||||
FillBehavior = FillBehavior.Stop
|
||||
};
|
||||
|
||||
var ClockOpacity = new DoubleAnimation
|
||||
|
|
@ -468,10 +480,10 @@ namespace Flow.Launcher
|
|||
private async void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_viewModel.Hide();
|
||||
|
||||
if(_settings.UseAnimation)
|
||||
|
||||
if (_settings.UseAnimation)
|
||||
await Task.Delay(100);
|
||||
|
||||
|
||||
App.API.OpenSettingDialog();
|
||||
}
|
||||
|
||||
|
|
@ -489,7 +501,7 @@ namespace Flow.Launcher
|
|||
// and always after Settings window is closed.
|
||||
if (_settings.UseAnimation)
|
||||
await Task.Delay(100);
|
||||
|
||||
|
||||
if (_settings.HideWhenDeactive)
|
||||
{
|
||||
_viewModel.Hide();
|
||||
|
|
@ -527,7 +539,7 @@ namespace Flow.Launcher
|
|||
_viewModel.Show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public double HorizonCenter()
|
||||
{
|
||||
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
|
||||
|
|
@ -609,9 +621,9 @@ namespace Flow.Launcher
|
|||
&& QueryTextBox.Text.Length > 0
|
||||
&& QueryTextBox.CaretIndex == QueryTextBox.Text.Length)
|
||||
{
|
||||
var queryWithoutActionKeyword =
|
||||
var queryWithoutActionKeyword =
|
||||
QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.NonGlobalPlugins)?.Search;
|
||||
|
||||
|
||||
if (FilesFolders.IsLocationPathString(queryWithoutActionKeyword))
|
||||
{
|
||||
_viewModel.BackspaceCommand.Execute(null);
|
||||
|
|
@ -663,7 +675,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, System.Windows.Threading.DispatcherPriority.ContextIdle);
|
||||
Dispatcher.Invoke(() => QueryTextBox.CaretIndex = QueryTextBox.Text.Length);
|
||||
}
|
||||
|
||||
public void InitializeColorScheme()
|
||||
|
|
@ -680,7 +692,7 @@ namespace Flow.Launcher
|
|||
|
||||
private void QueryTextBox_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if(_viewModel.QueryText != QueryTextBox.Text)
|
||||
if (_viewModel.QueryText != QueryTextBox.Text)
|
||||
{
|
||||
BindingExpression be = QueryTextBox.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty);
|
||||
be.UpdateSource();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ using System.IO;
|
|||
using System.Collections.Specialized;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Globalization;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
|
|
@ -65,7 +66,8 @@ namespace Flow.Launcher.ViewModel
|
|||
Settings = settings;
|
||||
Settings.PropertyChanged += (_, args) =>
|
||||
{
|
||||
switch (args.PropertyName) {
|
||||
switch (args.PropertyName)
|
||||
{
|
||||
case nameof(Settings.WindowSize):
|
||||
OnPropertyChanged(nameof(MainWindowWidth));
|
||||
break;
|
||||
|
|
@ -365,6 +367,7 @@ namespace Flow.Launcher.ViewModel
|
|||
set
|
||||
{
|
||||
_queryText = value;
|
||||
OnPropertyChanged();
|
||||
Query();
|
||||
}
|
||||
}
|
||||
|
|
@ -426,19 +429,24 @@ namespace Flow.Launcher.ViewModel
|
|||
/// <param name="reQuery">Force query even when Query Text doesn't change</param>
|
||||
public void ChangeQueryText(string queryText, bool reQuery = false)
|
||||
{
|
||||
if (QueryText != queryText)
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// 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 (reQuery)
|
||||
{
|
||||
Query();
|
||||
}
|
||||
QueryTextCursorMovedToEnd = true;
|
||||
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 (reQuery)
|
||||
{
|
||||
Query();
|
||||
}
|
||||
QueryTextCursorMovedToEnd = true;
|
||||
});
|
||||
}
|
||||
|
||||
public bool LastQuerySelected { get; set; }
|
||||
|
|
@ -752,11 +760,14 @@ namespace Flow.Launcher.ViewModel
|
|||
queryBuilder.Replace('@' + shortcut.Key, shortcut.Expand());
|
||||
}
|
||||
|
||||
foreach (var shortcut in builtInShortcuts)
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
queryBuilder.Replace(shortcut.Key, shortcut.Expand());
|
||||
queryBuilderTmp.Replace(shortcut.Key, shortcut.Expand());
|
||||
}
|
||||
foreach (var shortcut in builtInShortcuts)
|
||||
{
|
||||
queryBuilder.Replace(shortcut.Key, shortcut.Expand());
|
||||
queryBuilderTmp.Replace(shortcut.Key, shortcut.Expand());
|
||||
}
|
||||
});
|
||||
|
||||
// show expanded builtin shortcuts
|
||||
// use private field to avoid infinite recursion
|
||||
|
|
@ -879,11 +890,14 @@ namespace Flow.Launcher.ViewModel
|
|||
|
||||
public void Show()
|
||||
{
|
||||
MainWindowVisibility = Visibility.Visible;
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
MainWindowVisibility = Visibility.Visible;
|
||||
|
||||
MainWindowVisibilityStatus = true;
|
||||
MainWindowOpacity = 1;
|
||||
|
||||
MainWindowOpacity = 1;
|
||||
MainWindowVisibilityStatus = true;
|
||||
});
|
||||
}
|
||||
|
||||
public async void Hide()
|
||||
|
|
|
|||
|
|
@ -61,15 +61,15 @@ namespace Flow.Launcher.Plugin.Shell
|
|||
|
||||
if (basedir != null)
|
||||
{
|
||||
var autocomplete =
|
||||
var autocomplete =
|
||||
Directory.GetFileSystemEntries(basedir)
|
||||
.Select(o => dir + Path.GetFileName(o))
|
||||
.Where(o => o.StartsWith(cmd, StringComparison.OrdinalIgnoreCase) &&
|
||||
!results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase)) &&
|
||||
!results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase))).ToList();
|
||||
|
||||
!results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase)) &&
|
||||
!results.Any(p => o.Equals(p.Title, StringComparison.OrdinalIgnoreCase))).ToList();
|
||||
|
||||
autocomplete.Sort();
|
||||
|
||||
|
||||
results.AddRange(autocomplete.ConvertAll(m => new Result
|
||||
{
|
||||
Title = m,
|
||||
|
|
@ -194,72 +194,74 @@ namespace Flow.Launcher.Plugin.Shell
|
|||
|
||||
ProcessStartInfo info = new()
|
||||
{
|
||||
Verb = runAsAdministratorArg,
|
||||
WorkingDirectory = workingDirectory,
|
||||
Verb = runAsAdministratorArg, WorkingDirectory = workingDirectory,
|
||||
};
|
||||
switch (_settings.Shell)
|
||||
{
|
||||
case Shell.Cmd:
|
||||
{
|
||||
info.FileName = "cmd.exe";
|
||||
info.Arguments = $"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command}";
|
||||
{
|
||||
info.FileName = "cmd.exe";
|
||||
info.Arguments = $"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command}";
|
||||
|
||||
//// Use info.Arguments instead of info.ArgumentList to enable users better control over the arguments they are writing.
|
||||
//// Previous code using ArgumentList, commands needed to be seperated correctly:
|
||||
//// Incorrect:
|
||||
// info.ArgumentList.Add(_settings.LeaveShellOpen ? "/k" : "/c");
|
||||
// info.ArgumentList.Add(command); //<== info.ArgumentList.Add("mkdir \"c:\\test new\"");
|
||||
//// Use info.Arguments instead of info.ArgumentList to enable users better control over the arguments they are writing.
|
||||
//// Previous code using ArgumentList, commands needed to be seperated correctly:
|
||||
//// Incorrect:
|
||||
// info.ArgumentList.Add(_settings.LeaveShellOpen ? "/k" : "/c");
|
||||
// info.ArgumentList.Add(command); //<== info.ArgumentList.Add("mkdir \"c:\\test new\"");
|
||||
|
||||
//// Correct version should be:
|
||||
//info.ArgumentList.Add(_settings.LeaveShellOpen ? "/k" : "/c");
|
||||
//info.ArgumentList.Add("mkdir");
|
||||
//info.ArgumentList.Add(@"c:\test new");
|
||||
//// Correct version should be:
|
||||
//info.ArgumentList.Add(_settings.LeaveShellOpen ? "/k" : "/c");
|
||||
//info.ArgumentList.Add("mkdir");
|
||||
//info.ArgumentList.Add(@"c:\test new");
|
||||
|
||||
//https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-6.0#remarks
|
||||
//https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-6.0#remarks
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Shell.Powershell:
|
||||
{
|
||||
info.FileName = "powershell.exe";
|
||||
if (_settings.LeaveShellOpen)
|
||||
{
|
||||
info.FileName = "powershell.exe";
|
||||
if (_settings.LeaveShellOpen)
|
||||
{
|
||||
info.ArgumentList.Add("-NoExit");
|
||||
info.ArgumentList.Add(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.ArgumentList.Add("-Command");
|
||||
info.ArgumentList.Add(command);
|
||||
}
|
||||
break;
|
||||
info.ArgumentList.Add("-NoExit");
|
||||
info.ArgumentList.Add(command);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.ArgumentList.Add("-Command");
|
||||
info.ArgumentList.Add(command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Shell.RunCommand:
|
||||
{
|
||||
var parts = command.Split(new[]
|
||||
{
|
||||
var parts = command.Split(new[] { ' ' }, 2);
|
||||
if (parts.Length == 2)
|
||||
' '
|
||||
}, 2);
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var filename = parts[0];
|
||||
if (ExistInPath(filename))
|
||||
{
|
||||
var filename = parts[0];
|
||||
if (ExistInPath(filename))
|
||||
{
|
||||
var arguments = parts[1];
|
||||
info.FileName = filename;
|
||||
info.ArgumentList.Add(arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.FileName = command;
|
||||
}
|
||||
var arguments = parts[1];
|
||||
info.FileName = filename;
|
||||
info.ArgumentList.Add(arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.FileName = command;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.FileName = command;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -350,8 +352,12 @@ namespace Flow.Launcher.Plugin.Shell
|
|||
private void OnWinRPressed()
|
||||
{
|
||||
// show the main window and set focus to the query box
|
||||
context.API.ShowMainWindow();
|
||||
context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}");
|
||||
Task.Run(() =>
|
||||
{
|
||||
context.API.ShowMainWindow();
|
||||
context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public Control CreateSettingPanel()
|
||||
|
|
|
|||
Loading…
Reference in a new issue