@@ -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