Browse Source

UI: Add keybinds to useful things

Evan Husted 1 năm trước cách đây
mục cha
commit
741eba2798

+ 1 - 1
src/Ryujinx/UI/Models/SaveModel.cs

@@ -47,7 +47,7 @@ namespace Ryujinx.Ava.UI.Models
             TitleId = info.ProgramId;
             UserId = info.UserId;
 
-            var appData = MainWindow.MainWindowViewModel.Applications.FirstOrDefault(x => x.IdString.Equals(TitleIdString, StringComparison.OrdinalIgnoreCase));
+            var appData = App.MainWindow.ViewModel.Applications.FirstOrDefault(x => x.IdString.Equals(TitleIdString, StringComparison.OrdinalIgnoreCase));
 
             InGameList = appData != null;
 

+ 18 - 2
src/Ryujinx/UI/ViewModels/AmiiboWindowViewModel.cs

@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private readonly string _amiiboJsonPath;
         private readonly byte[] _amiiboLogoBytes;
         private readonly HttpClient _httpClient;
-        private readonly StyleableAppWindow _owner;
+        private readonly AmiiboWindow _owner;
 
         private Bitmap _amiiboImage;
         private List<AmiiboApi> _amiiboList;
@@ -49,7 +49,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
-        public AmiiboWindowViewModel(StyleableAppWindow owner, string lastScannedAmiiboId, string titleId)
+        public AmiiboWindowViewModel(AmiiboWindow owner, string lastScannedAmiiboId, string titleId)
         {
             _owner = owner;
 
@@ -186,6 +186,22 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
+        public void Scan()
+        {
+            if (AmiiboSelectedIndex > -1)
+            {
+                _owner.ScannedAmiibo = AmiiboList[AmiiboSelectedIndex];
+                _owner.IsScanned = true;
+                _owner.Close();
+            }
+        }
+
+        public void Cancel()
+        {
+            _owner.IsScanned = false;
+            _owner.Close();
+        }
+
         public void Dispose()
         {
             GC.SuppressFinalize(this);

+ 28 - 4
src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs

@@ -110,6 +110,8 @@ namespace Ryujinx.Ava.UI.ViewModels
         public ApplicationData ListSelectedApplication;
         public ApplicationData GridSelectedApplication;
 
+        public MainWindow Window { get; init; }
+
         internal AppHost AppHost { get; set; }
 
         public MainWindowViewModel()
@@ -1424,7 +1426,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async Task ExitCurrentState()
         {
-            if (WindowState == WindowState.FullScreen)
+            if (WindowState == MainWindow.FullScreenWindowState)
             {
                 ToggleFullscreen();
             }
@@ -1710,6 +1712,28 @@ namespace Ryujinx.Ava.UI.ViewModels
             });
         }
 
+        public async Task OpenAmiiboWindow()
+        {
+            if (!IsAmiiboRequested)
+                return;
+
+            if (AppHost.Device.System.SearchingForAmiibo(out int deviceId))
+            {
+                string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
+                AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId);
+
+                await window.ShowDialog(Window);
+
+                if (window.IsScanned)
+                {
+                    ShowAll = window.ViewModel.ShowAllAmiibo;
+                    LastScannedAmiiboId = window.ScannedAmiibo.GetId();
+
+                    AppHost.Device.System.ScanAmiibo(deviceId, LastScannedAmiiboId, window.ViewModel.UseRandomUuid);
+                }
+            }
+        }
+
         public void ToggleFullscreen()
         {
             if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs)
@@ -1719,7 +1743,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             LastFullscreenToggle = Environment.TickCount64;
 
-            if (WindowState == WindowState.FullScreen)
+            if (WindowState is not WindowState.Normal)
             {
                 WindowState = WindowState.Normal;
 
@@ -1730,7 +1754,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
             else
             {
-                WindowState = WindowState.FullScreen;
+                WindowState = MainWindow.FullScreenWindowState;
 
                 if (IsGameRunning)
                 {
@@ -1738,7 +1762,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 }
             }
 
-            IsFullScreen = WindowState == WindowState.FullScreen;
+            IsFullScreen = WindowState == MainWindow.FullScreenWindowState;
         }
 
         public static void SaveConfig()

+ 1 - 0
src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml

@@ -240,6 +240,7 @@
                     Click="OpenAmiiboWindow"
                     Header="{locale:Locale MenuBarActionsScanAmiibo}"
                     Icon="{icon:Icon mdi-cube-scan}"
+                    InputGesture="Ctrl + A"
                     IsEnabled="{Binding IsAmiiboRequested}" />
                 <MenuItem
                     Command="{Binding TakeScreenshot}"

+ 2 - 21
src/Ryujinx/UI/Views/Main/MainMenuBarView.axaml.cs

@@ -143,27 +143,8 @@ namespace Ryujinx.Ava.UI.Views.Main
             }
         }
 
-        public async void OpenAmiiboWindow(object sender, RoutedEventArgs e)
-        {
-            if (!ViewModel.IsAmiiboRequested)
-                return;
-
-            if (ViewModel.AppHost.Device.System.SearchingForAmiibo(out int deviceId))
-            {
-                string titleId = ViewModel.AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper();
-                AmiiboWindow window = new(ViewModel.ShowAll, ViewModel.LastScannedAmiiboId, titleId);
-
-                await window.ShowDialog(Window);
-
-                if (window.IsScanned)
-                {
-                    ViewModel.ShowAll = window.ViewModel.ShowAllAmiibo;
-                    ViewModel.LastScannedAmiiboId = window.ScannedAmiibo.GetId();
-
-                    ViewModel.AppHost.Device.System.ScanAmiibo(deviceId, ViewModel.LastScannedAmiiboId, window.ViewModel.UseRandomUuid);
-                }
-            }
-        }
+        public async void OpenAmiiboWindow(object sender, RoutedEventArgs e) 
+            => await ViewModel.OpenAmiiboWindow();
 
         public async void OpenCheatManagerForCurrentApp(object sender, RoutedEventArgs e)
         {

+ 11 - 4
src/Ryujinx/UI/Windows/AmiiboWindow.axaml

@@ -45,16 +45,23 @@
             <CheckBox Margin="10" Grid.Column="0" VerticalContentAlignment="Center" 
                       IsChecked="{Binding ShowAllAmiibo}"
                       Content="{locale:Locale AmiiboOptionsShowAllLabel}" />
-            <CheckBox Margin="10" VerticalContentAlignment="Center" Grid.Column="1" IsChecked="{Binding UseRandomUuid}"
+            <CheckBox HotKey="H" 
+                      Margin="10" VerticalContentAlignment="Center" Grid.Column="1" 
+                      IsChecked="{Binding UseRandomUuid}"
                       Content="{locale:Locale AmiiboOptionsUsRandomTagLabel}" />
-
-            <Button Grid.Column="3" IsEnabled="{Binding EnableScanning}" Width="80"
-                    Content="{locale:Locale AmiiboScanButtonLabel}" Name="ScanButton"
+            <Button Grid.Column="3" 
+                    IsEnabled="{Binding EnableScanning}" 
+                    Width="80"
+                    Name="ScanButton"
+                    HotKey="Return"
+                    Content="{locale:Locale AmiiboScanButtonLabel}"
                     Click="ScanButton_Click" />
             <Button Grid.Column="4" 
                     Margin="10,0" 
                     Width="80"
                     Name="CancelButton"
+                    HotKey="Escape"
+                    Content="{locale:Locale InputDialogCancel}"
                     Click="CancelButton_Click" />
         </Grid>
     </Grid>

+ 5 - 22
src/Ryujinx/UI/Windows/AmiiboWindow.axaml.cs

@@ -9,13 +9,11 @@ namespace Ryujinx.Ava.UI.Windows
     {
         public AmiiboWindow(bool showAll, string lastScannedAmiiboId, string titleId)
         {
-            ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId)
+            DataContext = ViewModel = new AmiiboWindowViewModel(this, lastScannedAmiiboId, titleId)
             {
                 ShowAllAmiibo = showAll,
             };
 
-            DataContext = ViewModel;
-
             InitializeComponent();
 
             Title = App.FormatTitle(LocaleKeys.Amiibo);
@@ -23,9 +21,7 @@ namespace Ryujinx.Ava.UI.Windows
 
         public AmiiboWindow()
         {
-            ViewModel = new AmiiboWindowViewModel(this, string.Empty, string.Empty);
-
-            DataContext = ViewModel;
+            DataContext = ViewModel = new AmiiboWindowViewModel(this, string.Empty, string.Empty);
 
             InitializeComponent();
 
@@ -37,23 +33,10 @@ namespace Ryujinx.Ava.UI.Windows
 
         public bool IsScanned { get; set; }
         public AmiiboApi ScannedAmiibo { get; set; }
-        public AmiiboWindowViewModel ViewModel { get; set; }
+        public AmiiboWindowViewModel ViewModel;
 
-        private void ScanButton_Click(object sender, RoutedEventArgs e)
-        {
-            if (ViewModel.AmiiboSelectedIndex > -1)
-            {
-                ScannedAmiibo = ViewModel.AmiiboList[ViewModel.AmiiboSelectedIndex];
-                IsScanned = true;
-                Close();
-            }
-        }
-
-        private void CancelButton_Click(object sender, RoutedEventArgs e)
-        {
-            IsScanned = false;
+        private void ScanButton_Click(object sender, RoutedEventArgs e) => ViewModel.Scan();
 
-            Close();
-        }
+        private void CancelButton_Click(object sender, RoutedEventArgs e) => ViewModel.Cancel();
     }
 }

+ 3 - 1
src/Ryujinx/UI/Windows/CheatWindow.axaml

@@ -1,4 +1,4 @@
-<window:StyleableAppWindow
+<window:StyleableAppWindow
     x:Class="Ryujinx.Ava.UI.Windows.CheatWindow"
     xmlns="https://github.com/avaloniaui"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -98,6 +98,7 @@
                     Name="SaveButton"
                     MinWidth="90"
                     Margin="5"
+                    HotKey="Ctrl+S"
                     Command="{Binding Save}"
                     IsVisible="{Binding !NoCheatsFound}">
                     <TextBlock Text="{locale:Locale SettingsButtonSave}" />
@@ -106,6 +107,7 @@
                     Name="CancelButton"
                     MinWidth="90"
                     Margin="5"
+                    HotKey="Escape"
                     Command="{Binding Close}">
                     <TextBlock Text="{locale:Locale InputDialogCancel}" />
                 </Button>

+ 1 - 0
src/Ryujinx/UI/Windows/MainWindow.axaml

@@ -40,6 +40,7 @@
         <KeyBinding Gesture="Ctrl+Cmd+F" Command="{Binding ToggleFullscreen}" />
         <KeyBinding Gesture="F9" Command="{Binding ToggleDockMode}" />
         <KeyBinding Gesture="Escape" Command="{Binding ExitCurrentState}" />
+        <KeyBinding Gesture="Ctrl+A" Command="{Binding OpenAmiiboWindow}" />
     </Window.KeyBindings>
     <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDefinitions="*">
         <helpers:OffscreenTextBox IsEnabled="False" Opacity="0" Name="HiddenTextBox" IsHitTestVisible="False" IsTabStop="False" />

+ 14 - 5
src/Ryujinx/UI/Windows/MainWindow.axaml.cs

@@ -37,8 +37,6 @@ namespace Ryujinx.Ava.UI.Windows
 {
     public partial class MainWindow : StyleableAppWindow
     {
-        internal static MainWindowViewModel MainWindowViewModel { get; private set; }
-
         public MainWindowViewModel ViewModel { get; }
 
         internal readonly AvaHostUIHandler UiHandler;
@@ -69,9 +67,20 @@ namespace Ryujinx.Ava.UI.Windows
         public readonly double StatusBarHeight;
         public readonly double MenuBarHeight;
 
+        // The special window decoration from AppWindow in FluentAvalonia is only present on Windows;
+        // and as such optimizing for the fact that the menu bar and the title bar are the same is only needed on Windows.
+        // Maximized is considered superior to FullScreen on Windows in this case because you get the benefits of being in full screen,
+        // while still being able to use the standard 3 window controls in the top right to minimize, make the window smaller, or close the app.
+
+        public static readonly WindowState FullScreenWindowState =
+            OperatingSystem.IsWindows() ? WindowState.Maximized : WindowState.FullScreen;
+
         public MainWindow()
         {
-            DataContext = ViewModel = MainWindowViewModel = new MainWindowViewModel();
+            DataContext = ViewModel = new MainWindowViewModel
+            {
+                Window = this
+            };
 
             InitializeComponent();
             Load();
@@ -184,7 +193,7 @@ namespace Ryujinx.Ava.UI.Windows
             ViewModel.ShowContent = true;
             ViewModel.IsLoadingIndeterminate = false;
 
-            if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
+            if (startFullscreen && ViewModel.WindowState != MainWindow.FullScreenWindowState)
             {
                 ViewModel.ToggleFullscreen();
             }
@@ -196,7 +205,7 @@ namespace Ryujinx.Ava.UI.Windows
             ViewModel.ShowLoadProgress = true;
             ViewModel.IsLoadingIndeterminate = true;
 
-            if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
+            if (startFullscreen && ViewModel.WindowState != MainWindow.FullScreenWindowState)
             {
                 ViewModel.ToggleFullscreen();
             }

+ 1 - 1
src/Ryujinx/UI/Windows/ModManagerWindow.axaml.cs

@@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.Windows
 {
     public partial class ModManagerWindow : UserControl
     {
-        public ModManagerViewModel ViewModel;
+        public readonly ModManagerViewModel ViewModel;
 
         public ModManagerWindow()
         {

+ 3 - 5
src/Ryujinx/UI/Windows/SettingsWindow.axaml.cs

@@ -10,14 +10,13 @@ namespace Ryujinx.Ava.UI.Windows
 {
     public partial class SettingsWindow : StyleableAppWindow
     {
-        internal SettingsViewModel ViewModel { get; set; }
+        internal readonly SettingsViewModel ViewModel;
 
         public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager)
         {
             Title = App.FormatTitle(LocaleKeys.Settings);
 
-            ViewModel = new SettingsViewModel(virtualFileSystem, contentManager);
-            DataContext = ViewModel;
+            DataContext = ViewModel = new SettingsViewModel(virtualFileSystem, contentManager);
 
             ViewModel.CloseWindow += Close;
             ViewModel.SaveSettingsEvent += SaveSettings;
@@ -28,8 +27,7 @@ namespace Ryujinx.Ava.UI.Windows
 
         public SettingsWindow()
         {
-            ViewModel = new SettingsViewModel();
-            DataContext = ViewModel;
+            DataContext = ViewModel = new SettingsViewModel();
 
             InitializeComponent();
             Load();

+ 0 - 4
src/Ryujinx/UI/Windows/StyleableWindow.cs

@@ -1,13 +1,9 @@
 using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
 using Avalonia.Media;
-using Avalonia.Media.Imaging;
 using Avalonia.Platform;
 using FluentAvalonia.UI.Windowing;
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.UI.Common.Configuration;
-using System.IO;
-using System.Reflection;
 
 namespace Ryujinx.Ava.UI.Windows
 {