Skip to content

Commit 8d8719a

Browse files
committed
Merge branch 'dev' into 050328-NewHotkeyDesign
2 parents b4c790e + 697fb72 commit 8d8719a

File tree

3 files changed

+124
-96
lines changed

3 files changed

+124
-96
lines changed

Flow.Launcher/MainWindow.xaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
Left="{Binding Settings.WindowLeft, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
2525
Loaded="OnLoaded"
2626
LocationChanged="OnLocationChanged"
27-
Opacity="{Binding MainWindowOpacity, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
2827
PreviewKeyDown="OnKeyDown"
2928
PreviewKeyUp="OnKeyUp"
3029
PreviewMouseMove="OnPreviewMouseMove"
@@ -290,7 +289,9 @@
290289
<StackPanel
291290
x:Name="ClockPanel"
292291
IsHitTestVisible="False"
293-
Style="{DynamicResource ClockPanel}">
292+
Opacity="{Binding ClockPanelOpacity}"
293+
Style="{DynamicResource ClockPanel}"
294+
Visibility="{Binding ClockPanelVisibility}">
294295
<TextBlock
295296
x:Name="ClockBox"
296297
Style="{DynamicResource ClockBox}"
@@ -318,6 +319,7 @@
318319
Name="SearchIcon"
319320
Margin="0"
320321
Data="{DynamicResource SearchIconImg}"
322+
Opacity="{Binding SearchIconOpacity}"
321323
Stretch="Fill"
322324
Style="{DynamicResource SearchIconStyle}"
323325
Visibility="{Binding SearchIconVisibility}" />

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,18 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
101101
// Check first launch
102102
if (_settings.FirstLaunch)
103103
{
104+
// Set First Launch to false
104105
_settings.FirstLaunch = false;
106+
107+
// Set Backdrop Type to Acrylic for Windows 11 when First Launch. Default is None
108+
if (Win32Helper.IsBackdropSupported()) _settings.BackdropType = BackdropTypes.Acrylic;
109+
110+
// Save settings
105111
App.API.SaveAppAllSettings();
106-
/* Set Backdrop Type to Acrylic for Windows 11 when First Launch. Default is None. */
107-
if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000))
108-
_settings.BackdropType = BackdropTypes.Acrylic;
109-
var WelcomeWindow = new WelcomeWindow();
110-
WelcomeWindow.Show();
112+
113+
// Show Welcome Window
114+
var welcomeWindow = new WelcomeWindow();
115+
welcomeWindow.Show();
111116
}
112117

113118
// Hide window if need
@@ -161,24 +166,37 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
161166
{
162167
if (_viewModel.MainWindowVisibilityStatus)
163168
{
169+
// Play sound effect before activing the window
164170
if (_settings.UseSound)
165171
{
166172
SoundPlay();
167173
}
168174

175+
// Update position & Activate
169176
UpdatePosition();
170-
_viewModel.ResetPreview();
171177
Activate();
172-
QueryTextBox.Focus();
173-
_settings.ActivateTimes++;
178+
179+
// Reset preview
180+
_viewModel.ResetPreview();
181+
182+
// Select last query if need
174183
if (!_viewModel.LastQuerySelected)
175184
{
176185
QueryTextBox.SelectAll();
177186
_viewModel.LastQuerySelected = true;
178187
}
179188

189+
// Focus query box
190+
QueryTextBox.Focus();
191+
192+
// Play window animation
180193
if (_settings.UseAnimation)
194+
{
181195
WindowAnimation();
196+
}
197+
198+
// Update activate times
199+
_settings.ActivateTimes++;
182200
}
183201
});
184202
break;
@@ -191,7 +209,6 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
191209
Dispatcher.Invoke(() => QueryTextBox.CaretIndex = QueryTextBox.Text.Length);
192210
_viewModel.QueryTextCursorMovedToEnd = false;
193211
}
194-
195212
break;
196213
case nameof(MainViewModel.GameModeStatus):
197214
_notifyIcon.Icon = _viewModel.GameModeStatus
@@ -224,7 +241,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
224241
};
225242

226243
// QueryTextBox.Text change detection (modified to only work when character count is 1 or higher)
227-
QueryTextBox.TextChanged += (sender, e) => UpdateClockPanelVisibility();
244+
QueryTextBox.TextChanged += (s, e) => UpdateClockPanelVisibility();
228245

229246
// Detecting ContextMenu.Visibility changes
230247
DependencyPropertyDescriptor
@@ -248,7 +265,8 @@ private async void OnClosing(object sender, CancelEventArgs e)
248265
Notification.Uninstall();
249266
// After plugins are all disposed, we can close the main window
250267
_canClose = true;
251-
Close();
268+
// Use this instead of Close() to avoid InvalidOperationException when calling Close() in OnClosing event
269+
Application.Current.Shutdown();
252270
}
253271
}
254272

@@ -280,8 +298,8 @@ private async void OnDeactivated(object sender, EventArgs e)
280298
_settings.WindowLeft = Left;
281299
_settings.WindowTop = Top;
282300

283-
ClockPanel.Opacity = 0;
284-
SearchIcon.Opacity = 0;
301+
_viewModel.ClockPanelOpacity = 0.0;
302+
_viewModel.SearchIconOpacity = 0.0;
285303

286304
// This condition stops extra hide call when animator is on,
287305
// which causes the toggling to occasional hide instead of show.
@@ -291,7 +309,9 @@ private async void OnDeactivated(object sender, EventArgs e)
291309
// This also stops the mainwindow from flickering occasionally after Settings window is opened
292310
// and always after Settings window is closed.
293311
if (_settings.UseAnimation)
312+
{
294313
await Task.Delay(100);
314+
}
295315

296316
if (_settings.HideWhenDeactivated && !_viewModel.ExternalPreviewVisible)
297317
{
@@ -331,15 +351,13 @@ private void OnKeyDown(object sender, KeyEventArgs e)
331351
_viewModel.LoadContextMenuCommand.Execute(null);
332352
e.Handled = true;
333353
}
334-
335354
break;
336355
case Key.Left:
337356
if (!_viewModel.QueryResultsSelected() && QueryTextBox.CaretIndex == 0)
338357
{
339358
_viewModel.EscCommand.Execute(null);
340359
e.Handled = true;
341360
}
342-
343361
break;
344362
case Key.Back:
345363
if (specialKeyState.CtrlPressed)
@@ -358,7 +376,6 @@ private void OnKeyDown(object sender, KeyEventArgs e)
358376
}
359377
}
360378
}
361-
362379
break;
363380
default:
364381
break;
@@ -765,12 +782,6 @@ private void WindowAnimation()
765782
{
766783
_isArrowKeyPressed = true;
767784

768-
UpdatePosition();
769-
770-
var opacity = _settings.UseAnimation ? 0.0 : 1.0;
771-
ClockPanel.Opacity = opacity;
772-
SearchIcon.Opacity = opacity;
773-
774785
var clocksb = new Storyboard();
775786
var iconsb = new Storyboard();
776787
var easing = new CircleEase { EasingMode = EasingMode.EaseInOut };
@@ -850,41 +861,49 @@ private void WindowAnimation()
850861
private void UpdateClockPanelVisibility()
851862
{
852863
if (QueryTextBox == null || ContextMenu == null || History == null || ClockPanel == null)
864+
{
853865
return;
866+
}
854867

868+
// ✅ Initialize animation length & duration
855869
var animationLength = _settings.AnimationSpeed switch
856870
{
857871
AnimationSpeeds.Slow => 560,
858872
AnimationSpeeds.Medium => 360,
859873
AnimationSpeeds.Fast => 160,
860874
_ => _settings.CustomAnimationLength
861875
};
862-
863876
var animationDuration = TimeSpan.FromMilliseconds(animationLength * 2 / 3);
864877

865878
// ✅ Conditions for showing ClockPanel (No query input & ContextMenu, History are closed)
866-
bool shouldShowClock = QueryTextBox.Text.Length == 0 &&
879+
var shouldShowClock = QueryTextBox.Text.Length == 0 &&
867880
ContextMenu.Visibility != Visibility.Visible &&
868881
History.Visibility != Visibility.Visible;
869882

870883
// ✅ 1. When ContextMenu opens, immediately set Visibility.Hidden (force hide without animation)
871884
if (ContextMenu.Visibility == Visibility.Visible)
872885
{
873-
ClockPanel.Visibility = Visibility.Hidden;
874-
ClockPanel.Opacity = 0.0; // Set to 0 in case Opacity animation affects it
886+
_viewModel.ClockPanelVisibility = Visibility.Hidden;
887+
_viewModel.ClockPanelOpacity = 0.0; // Set to 0 in case Opacity animation affects it
875888
return;
876889
}
877890

878891
// ✅ 2. When ContextMenu is closed, keep it Hidden if there's text in the query (remember previous state)
879-
if (ContextMenu.Visibility != Visibility.Visible && QueryTextBox.Text.Length > 0)
892+
else if (QueryTextBox.Text.Length > 0)
893+
{
894+
_viewModel.ClockPanelVisibility = Visibility.Hidden;
895+
_viewModel.ClockPanelOpacity = 0.0;
896+
return;
897+
}
898+
899+
// ✅ Prevent multiple animations
900+
if (_isClockPanelAnimating)
880901
{
881-
ClockPanel.Visibility = Visibility.Hidden;
882-
ClockPanel.Opacity = 0.0;
883902
return;
884903
}
885904

886905
// ✅ 3. When hiding ClockPanel (apply fade-out animation)
887-
if ((!shouldShowClock) && ClockPanel.Visibility == Visibility.Visible && !_isClockPanelAnimating)
906+
if ((!shouldShowClock) && _viewModel.ClockPanelVisibility == Visibility.Visible)
888907
{
889908
_isClockPanelAnimating = true;
890909

@@ -898,40 +917,40 @@ private void UpdateClockPanelVisibility()
898917

899918
fadeOut.Completed += (s, e) =>
900919
{
901-
ClockPanel.Visibility = Visibility.Hidden; // ✅ Completely hide after animation
920+
_viewModel.ClockPanelVisibility = Visibility.Hidden; // ✅ Completely hide after animation
902921
_isClockPanelAnimating = false;
903922
};
904923

905924
ClockPanel.BeginAnimation(OpacityProperty, fadeOut);
906925
}
926+
907927
// ✅ 4. When showing ClockPanel (apply fade-in animation)
908-
else if (shouldShowClock && ClockPanel.Visibility != Visibility.Visible && !_isClockPanelAnimating)
928+
else if (shouldShowClock && _viewModel.ClockPanelVisibility != Visibility.Visible)
909929
{
910930
_isClockPanelAnimating = true;
911931

912-
Application.Current.Dispatcher.Invoke(() =>
932+
_viewModel.ClockPanelVisibility = Visibility.Visible; // ✅ Set Visibility to Visible first
933+
934+
var fadeIn = new DoubleAnimation
913935
{
914-
ClockPanel.Visibility = Visibility.Visible; // ✅ Set Visibility to Visible first
936+
From = 0.0,
937+
To = 1.0,
938+
Duration = animationDuration,
939+
FillBehavior = FillBehavior.HoldEnd
940+
};
915941

916-
var fadeIn = new DoubleAnimation
917-
{
918-
From = 0.0,
919-
To = 1.0,
920-
Duration = animationDuration,
921-
FillBehavior = FillBehavior.HoldEnd
922-
};
923-
924-
fadeIn.Completed += (s, e) => _isClockPanelAnimating = false;
925-
ClockPanel.BeginAnimation(OpacityProperty, fadeIn);
926-
}, DispatcherPriority.Render);
942+
fadeIn.Completed += (s, e) => _isClockPanelAnimating = false;
943+
944+
ClockPanel.BeginAnimation(OpacityProperty, fadeIn);
927945
}
928946
}
929947

930-
931948
private static double GetOpacityFromStyle(Style style, double defaultOpacity = 1.0)
932949
{
933950
if (style == null)
951+
{
934952
return defaultOpacity;
953+
}
935954

936955
foreach (Setter setter in style.Setters.Cast<Setter>())
937956
{
@@ -947,7 +966,9 @@ private static double GetOpacityFromStyle(Style style, double defaultOpacity = 1
947966
private static Thickness GetThicknessFromStyle(Style style, Thickness defaultThickness)
948967
{
949968
if (style == null)
969+
{
950970
return defaultThickness;
971+
}
951972

952973
foreach (Setter setter in style.Setters.Cast<Setter>())
953974
{

0 commit comments

Comments
 (0)