Skip to content

Commit 659af9e

Browse files
authored
Merge branch 'dev' into l10n_dev
2 parents 87c1040 + ac8a979 commit 659af9e

31 files changed

+722
-142
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,19 @@ public static async Task InitializePluginsAsync()
220220
catch (Exception e)
221221
{
222222
API.LogException(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e);
223-
pair.Metadata.Disabled = true;
224-
pair.Metadata.HomeDisabled = true;
225-
failedPlugins.Enqueue(pair);
223+
if (pair.Metadata.Disabled && pair.Metadata.HomeDisabled)
224+
{
225+
// If this plugin is already disabled, do not show error message again
226+
// Or else it will be shown every time
227+
API.LogDebug(ClassName, $"Skipped init for <{pair.Metadata.Name}> due to error");
228+
}
229+
else
230+
{
231+
pair.Metadata.Disabled = true;
232+
pair.Metadata.HomeDisabled = true;
233+
failedPlugins.Enqueue(pair);
234+
API.LogDebug(ClassName, $"Disable plugin <{pair.Metadata.Name}> because init failed");
235+
}
226236
}
227237
}));
228238

Flow.Launcher.Infrastructure/Storage/JsonStorage.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,22 @@ public JsonStorage(string filePath)
4545
FilesFolders.ValidateDirectory(DirectoryPath);
4646
}
4747

48+
public bool Exists()
49+
{
50+
return File.Exists(FilePath);
51+
}
52+
53+
public void Delete()
54+
{
55+
foreach (var path in new[] { FilePath, BackupFilePath, TempFilePath })
56+
{
57+
if (File.Exists(path))
58+
{
59+
File.Delete(path);
60+
}
61+
}
62+
}
63+
4864
public async Task<T> LoadAsync()
4965
{
5066
if (Data != null)

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ public SearchPrecisionScore QuerySearchPrecision
293293

294294
public double WindowLeft { get; set; }
295295
public double WindowTop { get; set; }
296+
public double PreviousScreenWidth { get; set; }
297+
public double PreviousScreenHeight { get; set; }
298+
public double PreviousDpiX { get; set; }
299+
public double PreviousDpiY { get; set; }
296300

297301
/// <summary>
298302
/// Custom left position on selected monitor

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using Flow.Launcher.Infrastructure.UserSettings;
2323
using Flow.Launcher.Plugin.SharedCommands;
2424
using Flow.Launcher.ViewModel;
25+
using Microsoft.Win32;
2526
using ModernWpf.Controls;
2627
using DataObject = System.Windows.DataObject;
2728
using Key = System.Windows.Input.Key;
@@ -88,6 +89,8 @@ public MainWindow()
8889

8990
InitSoundEffects();
9091
DataObject.AddPastingHandler(QueryTextBox, QueryTextBox_OnPaste);
92+
ModernWpf.ThemeManager.Current.ActualApplicationThemeChanged += ThemeManager_ActualApplicationThemeChanged;
93+
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
9194
}
9295

9396
#endregion
@@ -96,6 +99,11 @@ public MainWindow()
9699

97100
#pragma warning disable VSTHRD100 // Avoid async void methods
98101

102+
private void ThemeManager_ActualApplicationThemeChanged(ModernWpf.ThemeManager sender, object args)
103+
{
104+
_theme.RefreshFrameAsync();
105+
}
106+
99107
private void OnSourceInitialized(object sender, EventArgs e)
100108
{
101109
var handle = Win32Helper.GetWindowHandle(this, true);
@@ -540,16 +548,29 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b
540548

541549
#region Window Sound Effects
542550

551+
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
552+
{
553+
// Fix for sound not playing after sleep / hibernate
554+
// https://stackoverflow.com/questions/64805186/mediaplayer-doesnt-play-after-computer-sleeps
555+
if (e.Mode == PowerModes.Resume)
556+
{
557+
InitSoundEffects();
558+
}
559+
}
560+
543561
private void InitSoundEffects()
544562
{
545563
if (_settings.WMPInstalled)
546564
{
565+
animationSoundWMP?.Close();
547566
animationSoundWMP = new MediaPlayer();
548567
animationSoundWMP.Open(new Uri(AppContext.BaseDirectory + "Resources\\open.wav"));
549568
}
550569
else
551570
{
571+
animationSoundWPF?.Dispose();
552572
animationSoundWPF = new SoundPlayer(AppContext.BaseDirectory + "Resources\\open.wav");
573+
animationSoundWPF.Load();
553574
}
554575
}
555576

@@ -695,8 +716,26 @@ void InitializePositionInner()
695716
{
696717
if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation)
697718
{
698-
Top = _settings.WindowTop;
719+
var previousScreenWidth = _settings.PreviousScreenWidth;
720+
var previousScreenHeight = _settings.PreviousScreenHeight;
721+
GetDpi(out var previousDpiX, out var previousDpiY);
722+
723+
_settings.PreviousScreenWidth = SystemParameters.VirtualScreenWidth;
724+
_settings.PreviousScreenHeight = SystemParameters.VirtualScreenHeight;
725+
GetDpi(out var currentDpiX, out var currentDpiY);
726+
727+
if (previousScreenWidth != 0 && previousScreenHeight != 0 &&
728+
previousDpiX != 0 && previousDpiY != 0 &&
729+
(previousScreenWidth != SystemParameters.VirtualScreenWidth ||
730+
previousScreenHeight != SystemParameters.VirtualScreenHeight ||
731+
previousDpiX != currentDpiX || previousDpiY != currentDpiY))
732+
{
733+
AdjustPositionForResolutionChange();
734+
return;
735+
}
736+
699737
Left = _settings.WindowLeft;
738+
Top = _settings.WindowTop;
700739
}
701740
else
702741
{
@@ -709,27 +748,73 @@ void InitializePositionInner()
709748
break;
710749
case SearchWindowAligns.CenterTop:
711750
Left = HorizonCenter(screen);
712-
Top = 10;
751+
Top = VerticalTop(screen);
713752
break;
714753
case SearchWindowAligns.LeftTop:
715754
Left = HorizonLeft(screen);
716-
Top = 10;
755+
Top = VerticalTop(screen);
717756
break;
718757
case SearchWindowAligns.RightTop:
719758
Left = HorizonRight(screen);
720-
Top = 10;
759+
Top = VerticalTop(screen);
721760
break;
722761
case SearchWindowAligns.Custom:
723-
Left = Win32Helper.TransformPixelsToDIP(this,
724-
screen.WorkingArea.X + _settings.CustomWindowLeft, 0).X;
725-
Top = Win32Helper.TransformPixelsToDIP(this, 0,
726-
screen.WorkingArea.Y + _settings.CustomWindowTop).Y;
762+
var customLeft = Win32Helper.TransformPixelsToDIP(this,
763+
screen.WorkingArea.X + _settings.CustomWindowLeft, 0);
764+
var customTop = Win32Helper.TransformPixelsToDIP(this, 0,
765+
screen.WorkingArea.Y + _settings.CustomWindowTop);
766+
Left = customLeft.X;
767+
Top = customTop.Y;
727768
break;
728769
}
729770
}
730771
}
731772
}
732773

774+
private void AdjustPositionForResolutionChange()
775+
{
776+
var screenWidth = SystemParameters.VirtualScreenWidth;
777+
var screenHeight = SystemParameters.VirtualScreenHeight;
778+
GetDpi(out var currentDpiX, out var currentDpiY);
779+
780+
var previousLeft = _settings.WindowLeft;
781+
var previousTop = _settings.WindowTop;
782+
GetDpi(out var previousDpiX, out var previousDpiY);
783+
784+
var widthRatio = screenWidth / _settings.PreviousScreenWidth;
785+
var heightRatio = screenHeight / _settings.PreviousScreenHeight;
786+
var dpiXRatio = currentDpiX / previousDpiX;
787+
var dpiYRatio = currentDpiY / previousDpiY;
788+
789+
var newLeft = previousLeft * widthRatio * dpiXRatio;
790+
var newTop = previousTop * heightRatio * dpiYRatio;
791+
792+
var screenLeft = SystemParameters.VirtualScreenLeft;
793+
var screenTop = SystemParameters.VirtualScreenTop;
794+
795+
var maxX = screenLeft + screenWidth - ActualWidth;
796+
var maxY = screenTop + screenHeight - ActualHeight;
797+
798+
Left = Math.Max(screenLeft, Math.Min(newLeft, maxX));
799+
Top = Math.Max(screenTop, Math.Min(newTop, maxY));
800+
}
801+
802+
private void GetDpi(out double dpiX, out double dpiY)
803+
{
804+
var source = PresentationSource.FromVisual(this);
805+
if (source != null && source.CompositionTarget != null)
806+
{
807+
var matrix = source.CompositionTarget.TransformToDevice;
808+
dpiX = 96 * matrix.M11;
809+
dpiY = 96 * matrix.M22;
810+
}
811+
else
812+
{
813+
dpiX = 96;
814+
dpiY = 96;
815+
}
816+
}
817+
733818
private Screen SelectedScreen()
734819
{
735820
Screen screen;
@@ -790,6 +875,13 @@ private double HorizonLeft(Screen screen)
790875
return left;
791876
}
792877

878+
public double VerticalTop(Screen screen)
879+
{
880+
var dip1 = Win32Helper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
881+
var top = dip1.Y + 10;
882+
return top;
883+
}
884+
793885
#endregion
794886

795887
#region Window Animation
@@ -816,7 +908,7 @@ private void InitProgressbarAnimation()
816908
{
817909
Name = progressBarAnimationName, Storyboard = progressBarStoryBoard
818910
};
819-
911+
820912
var stopStoryboard = new StopStoryboard()
821913
{
822914
BeginStoryboardName = progressBarAnimationName
@@ -837,7 +929,7 @@ private void InitProgressbarAnimation()
837929
progressStyle.Triggers.Add(trigger);
838930

839931
ProgressBar.Style = progressStyle;
840-
932+
841933
_viewModel.ProgressBarVisibility = Visibility.Hidden;
842934
}
843935

@@ -885,7 +977,7 @@ private void WindowAnimation()
885977
Duration = TimeSpan.FromMilliseconds(animationLength),
886978
FillBehavior = FillBehavior.HoldEnd
887979
};
888-
980+
889981
var rightMargin = GetThicknessFromStyle(ClockPanel.Style, new Thickness(0, 0, DefaultRightMargin, 0)).Right;
890982

891983
var thicknessAnimation = new ThicknessAnimation
@@ -913,10 +1005,10 @@ private void WindowAnimation()
9131005
clocksb.Children.Add(ClockOpacity);
9141006
iconsb.Children.Add(IconMotion);
9151007
iconsb.Children.Add(IconOpacity);
916-
1008+
9171009
_settings.WindowLeft = Left;
9181010
_isArrowKeyPressed = false;
919-
1011+
9201012
clocksb.Begin(ClockPanel);
9211013
iconsb.Begin(SearchIcon);
9221014
}
@@ -1088,7 +1180,7 @@ private void QueryTextBox_OnPreviewDragOver(object sender, DragEventArgs e)
10881180
{
10891181
e.Handled = true;
10901182
}
1091-
1183+
10921184
#endregion
10931185

10941186
#region Placeholder
@@ -1140,7 +1232,7 @@ private void SetupResizeMode()
11401232
}
11411233

11421234
#endregion
1143-
1235+
11441236
#region Search Delay
11451237

11461238
private void QueryTextBox_TextChanged1(object sender, TextChangedEventArgs e)
@@ -1162,6 +1254,10 @@ protected virtual void Dispose(bool disposing)
11621254
{
11631255
_hwndSource?.Dispose();
11641256
_notifyIcon?.Dispose();
1257+
animationSoundWMP?.Close();
1258+
animationSoundWPF?.Dispose();
1259+
ModernWpf.ThemeManager.Current.ActualApplicationThemeChanged -= ThemeManager_ActualApplicationThemeChanged;
1260+
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
11651261
}
11661262

11671263
_disposed = true;

Flow.Launcher/PublicAPIInstance.cs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -318,19 +318,37 @@ public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null
318318
{
319319
using var explorer = new Process();
320320
var explorerInfo = _settings.CustomExplorer;
321-
322-
explorer.StartInfo = new ProcessStartInfo
321+
var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant();
322+
var targetPath = FileNameOrFilePath is null
323+
? DirectoryPath
324+
: Path.IsPathRooted(FileNameOrFilePath)
325+
? FileNameOrFilePath
326+
: Path.Combine(DirectoryPath, FileNameOrFilePath);
327+
328+
if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer")
323329
{
324-
FileName = explorerInfo.Path.Replace("%d", DirectoryPath),
325-
UseShellExecute = true,
326-
Arguments = FileNameOrFilePath is null
327-
? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath)
328-
: explorerInfo.FileArgument
329-
.Replace("%d", DirectoryPath)
330-
.Replace("%f",
331-
Path.IsPathRooted(FileNameOrFilePath) ? FileNameOrFilePath : Path.Combine(DirectoryPath, FileNameOrFilePath)
332-
)
333-
};
330+
// Windows File Manager
331+
// We should ignore and pass only the path to Shell to prevent zombie explorer.exe processes
332+
explorer.StartInfo = new ProcessStartInfo
333+
{
334+
FileName = targetPath, // Not explorer, Only path.
335+
UseShellExecute = true // Must be true to open folder
336+
};
337+
}
338+
else
339+
{
340+
// Custom File Manager
341+
explorer.StartInfo = new ProcessStartInfo
342+
{
343+
FileName = explorerInfo.Path.Replace("%d", DirectoryPath),
344+
UseShellExecute = true,
345+
Arguments = FileNameOrFilePath is null
346+
? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath)
347+
: explorerInfo.FileArgument
348+
.Replace("%d", DirectoryPath)
349+
.Replace("%f", targetPath)
350+
};
351+
}
334352
explorer.Start();
335353
}
336354

Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,19 @@ namespace Flow.Launcher.Resources.Pages
99
{
1010
public partial class WelcomePage1
1111
{
12-
public Settings Settings { get; private set; }
13-
private WelcomeViewModel _viewModel;
12+
public Settings Settings { get; } = Ioc.Default.GetRequiredService<Settings>();
13+
private readonly WelcomeViewModel _viewModel = Ioc.Default.GetRequiredService<WelcomeViewModel>();
1414

1515
protected override void OnNavigatedTo(NavigationEventArgs e)
1616
{
17+
// Sometimes the navigation is not triggered by button click,
18+
// so we need to reset the page number
19+
_viewModel.PageNum = 1;
20+
1721
if (!IsInitialized)
1822
{
19-
Settings = Ioc.Default.GetRequiredService<Settings>();
20-
_viewModel = Ioc.Default.GetRequiredService<WelcomeViewModel>();
2123
InitializeComponent();
2224
}
23-
// Sometimes the navigation is not triggered by button click,
24-
// so we need to reset the page number
25-
_viewModel.PageNum = 1;
2625
base.OnNavigatedTo(e);
2726
}
2827

0 commit comments

Comments
 (0)