From 22b4dda3aab46956c67daa2ac266383384fc7c05 Mon Sep 17 00:00:00 2001 From: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com> Date: Mon, 2 Mar 2026 15:26:31 -0500 Subject: [PATCH] [Light Switch] Add 10s timeout and pre-check for location detection (#45887) - Add 10-second timeout to GetGeopositionAsync to prevent infinite spinner - Pre-check location services availability when dialog opens; disable Detect Location button with message if unavailable - Show user-friendly error messages for timeout and unavailable scenarios - Add LocationErrorText UI element and localized string resources ## PR Checklist - [x] Closes: #45860 - [x] Closes: #42852 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../SettingsXAML/Views/LightSwitchPage.xaml | 6 +++ .../Views/LightSwitchPage.xaml.cs | 49 +++++++++++++++---- .../Settings.UI/Strings/en-us/Resources.resw | 6 +++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml index 6941258e06..a532cf18dd 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/LightSwitchPage.xaml @@ -376,6 +376,12 @@ VerticalAlignment="Center" IsActive="False" Visibility="Collapsed" /> + sendConfigMsg = ShellPage.SendDefaultIPCMessage; @@ -101,6 +104,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views this.SyncLoader.IsActive = true; this.SyncLoader.Visibility = Visibility.Visible; this.LocationResultPanel.Visibility = Visibility.Collapsed; + this.LocationErrorText.Visibility = Visibility.Collapsed; try { @@ -108,13 +112,15 @@ namespace Microsoft.PowerToys.Settings.UI.Views var accessStatus = await Geolocator.RequestAccessAsync(); if (accessStatus != GeolocationAccessStatus.Allowed) { - // User denied location or it's not available + ShowLocationError(ResourceLoaderInstance.ResourceLoader.GetString("LightSwitch_LocationError_Unavailable")); return; } var geolocator = new Geolocator { DesiredAccuracy = PositionAccuracy.Default }; - Geoposition pos = await geolocator.GetGeopositionAsync(); + using var cts = new CancellationTokenSource(GeoLocationTimeout); + var positionTask = geolocator.GetGeopositionAsync().AsTask(cts.Token); + Geoposition pos = await positionTask; double latitude = Math.Round(pos.Coordinate.Point.Position.Latitude); double longitude = Math.Round(pos.Coordinate.Point.Position.Longitude); @@ -130,7 +136,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views // Since we use this mode, we can remove the selected city data. this.ViewModel.SelectedCity = null; - // ViewModel.CityTimesText = $"Sunrise: {result.SunriseHour}:{result.SunriseMinute:D2}\n" + $"Sunset: {result.SunsetHour}:{result.SunsetMinute:D2}"; this.SyncButton.IsEnabled = true; this.SyncLoader.IsActive = false; this.SyncLoader.Visibility = Visibility.Collapsed; @@ -139,18 +144,29 @@ namespace Microsoft.PowerToys.Settings.UI.Views this.LongitudeBox.IsEnabled = true; this.LocationResultPanel.Visibility = Visibility.Visible; } + catch (OperationCanceledException) + { + ShowLocationError(ResourceLoaderInstance.ResourceLoader.GetString("LightSwitch_LocationError_Timeout")); + } catch (Exception ex) { - this.SyncButton.IsEnabled = true; - this.SyncLoader.IsActive = false; - this.SyncLoader.Visibility = Visibility.Collapsed; - this.LocationResultPanel.Visibility = Visibility.Collapsed; - this.LatitudeBox.IsEnabled = true; - this.LongitudeBox.IsEnabled = true; + ShowLocationError(ResourceLoaderInstance.ResourceLoader.GetString("LightSwitch_LocationError_Timeout")); Logger.LogInfo($"Location error: " + ex.Message); } } + private void ShowLocationError(string message) + { + this.SyncButton.IsEnabled = true; + this.SyncLoader.IsActive = false; + this.SyncLoader.Visibility = Visibility.Collapsed; + this.LocationResultPanel.Visibility = Visibility.Collapsed; + this.LatitudeBox.IsEnabled = true; + this.LongitudeBox.IsEnabled = true; + this.LocationErrorText.Text = message; + this.LocationErrorText.Visibility = Visibility.Visible; + } + private void LatLonBox_ValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args) { double latitude = this.LatitudeBox.Value; @@ -301,6 +317,21 @@ namespace Microsoft.PowerToys.Settings.UI.Views { this.LocationDialog.IsPrimaryButtonEnabled = false; this.LocationResultPanel.Visibility = Visibility.Collapsed; + this.LocationErrorText.Visibility = Visibility.Collapsed; + + // Pre-check location services availability + var accessStatus = await Geolocator.RequestAccessAsync(); + if (accessStatus != GeolocationAccessStatus.Allowed) + { + this.SyncButton.IsEnabled = false; + this.LocationErrorText.Text = ResourceLoaderInstance.ResourceLoader.GetString("LightSwitch_LocationError_Unavailable"); + this.LocationErrorText.Visibility = Visibility.Visible; + } + else + { + this.SyncButton.IsEnabled = true; + } + await this.LocationDialog.ShowAsync(); } diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index 8c9bed2782..c90423c39d 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -5150,6 +5150,12 @@ The break timer font matches the text font. Sunset + + Unable to connect to location services. Please try again or enter your coordinates manually. + + + Location services unavailable. Please enter your coordinates manually. + Close PowerToys Don't loc "PowerToys"