refactor(app): replace nested settings submenu with in-app overlay

The Impostazioni menu now opens a single overlay (same pattern as
address/server overlays) instead of nested OS popup menus, which are
slow to respond under WSLg.

The overlay groups language (RadioButton) and unit (RadioButton) in one
panel, with a button to open the server overlay. Esc and backdrop tap
close it. OpenServerSettings() closes the settings overlay first so the
two overlays never stack.
This commit is contained in:
2026-06-12 09:09:25 +02:00
parent 28cb4ce6ae
commit 51c87a7dc9
3 changed files with 98 additions and 42 deletions
+17 -2
View File
@@ -231,16 +231,31 @@ public partial class MainWindowViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private bool useSsl = true; private bool useSsl = true;
/// <summary>Overlay impostazioni server: aperto da menu Impostazioni → Server.</summary> /// <summary>Overlay impostazioni server: aperto dall'overlay Impostazioni.</summary>
[ObservableProperty] [ObservableProperty]
private bool isServerSettingsOpen; private bool isServerSettingsOpen;
[RelayCommand] [RelayCommand]
private void OpenServerSettings() => IsServerSettingsOpen = true; private void OpenServerSettings()
{
IsSettingsOpen = false;
IsServerSettingsOpen = true;
}
[RelayCommand] [RelayCommand]
private void CloseServerSettings() => IsServerSettingsOpen = false; private void CloseServerSettings() => IsServerSettingsOpen = false;
/// <summary>Overlay impostazioni (lingua, unità, server): in-app per evitare
/// i popup di menu annidati, lenti su WSLg.</summary>
[ObservableProperty]
private bool isSettingsOpen;
[RelayCommand]
private void OpenSettings() => IsSettingsOpen = true;
[RelayCommand]
private void CloseSettings() => IsSettingsOpen = false;
[ObservableProperty] [ObservableProperty]
private string connectionStatus = Loc.Tr("conn.none"); private string connectionStatus = Loc.Tr("conn.none");
+73 -40
View File
@@ -30,46 +30,8 @@
<MenuItem Header="{Binding Loc[menu.net.discover]}" Command="{Binding DiscoverServersCommand}"/> <MenuItem Header="{Binding Loc[menu.net.discover]}" Command="{Binding DiscoverServersCommand}"/>
<MenuItem Header="{Binding Loc[menu.net.resetcerts]}" Command="{Binding ResetCertificatesCommand}"/> <MenuItem Header="{Binding Loc[menu.net.resetcerts]}" Command="{Binding ResetCertificatesCommand}"/>
</MenuItem> </MenuItem>
<MenuItem Header="{Binding Loc[menu.settings]}"> <MenuItem Header="{Binding Loc[menu.settings]}"
<MenuItem Header="{Binding Loc[settings.language]}"> Command="{Binding OpenSettingsCommand}"/>
<MenuItem Header="Italiano" ToggleType="Radio"
IsChecked="{Binding IsLangIt, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="it"/>
<MenuItem Header="English" ToggleType="Radio"
IsChecked="{Binding IsLangEn, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="en"/>
<MenuItem Header="Español" ToggleType="Radio"
IsChecked="{Binding IsLangEs, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="es"/>
<MenuItem Header="Français" ToggleType="Radio"
IsChecked="{Binding IsLangFr, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="fr"/>
<MenuItem Header="Português" ToggleType="Radio"
IsChecked="{Binding IsLangPt, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="pt"/>
<MenuItem Header="Deutsch" ToggleType="Radio"
IsChecked="{Binding IsLangDe, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="de"/>
</MenuItem>
<MenuItem Header="{Binding Loc[settings.unit.short]}">
<MenuItem Header="PLM" ToggleType="Radio"
IsChecked="{Binding IsUnitPlm, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="PLM"/>
<MenuItem Header="mPLM" ToggleType="Radio"
IsChecked="{Binding IsUnitMilli, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="mPLM"/>
<MenuItem Header="µPLM" ToggleType="Radio"
IsChecked="{Binding IsUnitMicro, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="µPLM"/>
<MenuItem Header="sat" ToggleType="Radio"
IsChecked="{Binding IsUnitSat, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="sat"/>
</MenuItem>
<Separator/>
<MenuItem Header="{Binding Loc[settings.server]}"
Command="{Binding OpenServerSettingsCommand}"
IsEnabled="{Binding IsWalletOpen}"/>
</MenuItem>
</Menu> </Menu>
<!-- ============ WIZARD DI SETUP (§15): un passo alla volta ============ --> <!-- ============ WIZARD DI SETUP (§15): un passo alla volta ============ -->
@@ -498,5 +460,76 @@
</StackPanel> </StackPanel>
</Border> </Border>
</Border> </Border>
<!-- ============ OVERLAY IMPOSTAZIONI ============ -->
<!-- In-app invece dei sottomenu annidati: niente popup OS lenti su WSLg. -->
<Border Grid.Row="0" Grid.RowSpan="3"
Background="#99000000"
Tapped="OnSettingsOverlayBackdropTapped"
IsVisible="{Binding IsSettingsOpen}">
<Border Background="{DynamicResource SystemControlBackgroundChromeMediumLowBrush}"
BorderBrush="Gray" BorderThickness="1" CornerRadius="8"
Width="460"
HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Margin="24" Spacing="16">
<TextBlock Text="{Binding Loc[settings.title]}"
FontSize="18" FontWeight="Bold"/>
<!-- Lingua -->
<StackPanel Spacing="6">
<TextBlock Text="{Binding Loc[settings.language]}" FontSize="11" Foreground="Gray"/>
<WrapPanel>
<RadioButton GroupName="lang" Content="Italiano" Margin="0,0,14,4"
IsChecked="{Binding IsLangIt, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="it"/>
<RadioButton GroupName="lang" Content="English" Margin="0,0,14,4"
IsChecked="{Binding IsLangEn, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="en"/>
<RadioButton GroupName="lang" Content="Español" Margin="0,0,14,4"
IsChecked="{Binding IsLangEs, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="es"/>
<RadioButton GroupName="lang" Content="Français" Margin="0,0,14,4"
IsChecked="{Binding IsLangFr, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="fr"/>
<RadioButton GroupName="lang" Content="Português" Margin="0,0,14,4"
IsChecked="{Binding IsLangPt, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="pt"/>
<RadioButton GroupName="lang" Content="Deutsch" Margin="0,0,14,4"
IsChecked="{Binding IsLangDe, Mode=OneWay}"
Command="{Binding SetLanguageCommand}" CommandParameter="de"/>
</WrapPanel>
</StackPanel>
<!-- Unità -->
<StackPanel Spacing="6">
<TextBlock Text="{Binding Loc[settings.unit]}" FontSize="11" Foreground="Gray"/>
<WrapPanel>
<RadioButton GroupName="unit" Content="PLM" Margin="0,0,14,4"
IsChecked="{Binding IsUnitPlm, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="PLM"/>
<RadioButton GroupName="unit" Content="mPLM" Margin="0,0,14,4"
IsChecked="{Binding IsUnitMilli, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="mPLM"/>
<RadioButton GroupName="unit" Content="µPLM" Margin="0,0,14,4"
IsChecked="{Binding IsUnitMicro, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="µPLM"/>
<RadioButton GroupName="unit" Content="sat" Margin="0,0,14,4"
IsChecked="{Binding IsUnitSat, Mode=OneWay}"
Command="{Binding SetUnitCommand}" CommandParameter="sat"/>
</WrapPanel>
</StackPanel>
<!-- Server di indicizzazione -->
<Button Content="{Binding Loc[settings.server]}"
HorizontalAlignment="Left"
Command="{Binding OpenServerSettingsCommand}"
IsEnabled="{Binding IsWalletOpen}"/>
<Button Content="{Binding Loc[addr.close]}"
HorizontalAlignment="Right"
Command="{Binding CloseSettingsCommand}"/>
</StackPanel>
</Border>
</Border>
</Grid> </Grid>
</Window> </Window>
+8
View File
@@ -72,12 +72,20 @@ public partial class MainWindow : Window
vm.IsServerSettingsOpen = false; vm.IsServerSettingsOpen = false;
} }
private void OnSettingsOverlayBackdropTapped(object? sender, TappedEventArgs e)
{
if (!ReferenceEquals(e.Source, sender)) return;
if (DataContext is MainWindowViewModel vm)
vm.IsSettingsOpen = false;
}
protected override void OnKeyDown(KeyEventArgs e) protected override void OnKeyDown(KeyEventArgs e)
{ {
if (e.Key == Key.Escape && DataContext is MainWindowViewModel vm) if (e.Key == Key.Escape && DataContext is MainWindowViewModel vm)
{ {
if (vm.AddressInfo is not null) { vm.AddressInfo = null; e.Handled = true; return; } if (vm.AddressInfo is not null) { vm.AddressInfo = null; e.Handled = true; return; }
if (vm.IsServerSettingsOpen) { vm.IsServerSettingsOpen = false; e.Handled = true; return; } if (vm.IsServerSettingsOpen) { vm.IsServerSettingsOpen = false; e.Handled = true; return; }
if (vm.IsSettingsOpen) { vm.IsSettingsOpen = false; e.Handled = true; return; }
} }
base.OnKeyDown(e); base.OnKeyDown(e);
} }