mirror of
https://github.com/GreemDev/Ryujinx
synced 2024-11-21 17:40:52 +01:00
misc: Canary-specific naming & other small changes I had that I need to push.
This commit is contained in:
parent
36c374cc7a
commit
730ba44043
11 changed files with 200 additions and 229 deletions
|
@ -23,8 +23,10 @@ namespace Ryujinx.Ava
|
|||
{
|
||||
internal static string FormatTitle(LocaleKeys? windowTitleKey = null)
|
||||
=> windowTitleKey is null
|
||||
? $"Ryujinx {Program.Version}"
|
||||
: $"Ryujinx {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}";
|
||||
? $"{FullAppName} {Program.Version}"
|
||||
: $"{FullAppName} {Program.Version} - {LocaleManager.Instance[windowTitleKey.Value]}";
|
||||
|
||||
public static readonly string FullAppName = ReleaseInformation.IsCanaryBuild ? "Ryujinx Canary" : "Ryujinx";
|
||||
|
||||
public static MainWindow MainWindow => Current!
|
||||
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()
|
||||
|
|
|
@ -2,19 +2,38 @@
|
|||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
|
||||
using Gommon;
|
||||
using System;
|
||||
// ReSharper disable VirtualMemberNeverOverridden.Global
|
||||
// ReSharper disable MemberCanBeProtected.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Ryujinx.Ava.Common.Markup
|
||||
{
|
||||
internal abstract class BasicMarkupExtension : MarkupExtension
|
||||
internal abstract class BasicMarkupExtension<T> : MarkupExtension
|
||||
{
|
||||
protected abstract ClrPropertyInfo PropertyInfo { get; }
|
||||
public virtual string Name => "Item";
|
||||
public virtual Action<object, T?>? Setter => null;
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) =>
|
||||
new CompiledBindingExtension(
|
||||
protected abstract T? GetValue();
|
||||
|
||||
protected virtual void ConfigureBindingExtension(CompiledBindingExtension _) { }
|
||||
|
||||
private ClrPropertyInfo PropertyInfo =>
|
||||
new(Name,
|
||||
_ => GetValue(),
|
||||
Setter as Action<object, object?>,
|
||||
typeof(T));
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
=> new CompiledBindingExtension(
|
||||
new CompiledBindingPathBuilder()
|
||||
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
|
||||
.Build()
|
||||
).ProvideValue(serviceProvider);
|
||||
)
|
||||
.Apply(ConfigureBindingExtension)
|
||||
.ProvideValue(serviceProvider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,51 +1,24 @@
|
|||
using Avalonia.Data.Core;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings;
|
||||
using Projektanker.Icons.Avalonia;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.Common.Markup
|
||||
{
|
||||
internal class IconExtension(string iconString) : BasicMarkupExtension
|
||||
internal class IconExtension(string iconString) : BasicMarkupExtension<Icon>
|
||||
{
|
||||
protected override ClrPropertyInfo PropertyInfo
|
||||
=> new(
|
||||
"Item",
|
||||
_ => new Icon { Value = iconString },
|
||||
null,
|
||||
typeof(Icon)
|
||||
);
|
||||
protected override Icon GetValue() => new() { Value = iconString };
|
||||
}
|
||||
|
||||
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension
|
||||
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon>
|
||||
{
|
||||
protected override ClrPropertyInfo PropertyInfo
|
||||
=> new(
|
||||
"Item",
|
||||
_ => new Icon { Value = iconString, Animation = IconAnimation.Spin },
|
||||
null,
|
||||
typeof(Icon)
|
||||
);
|
||||
protected override Icon GetValue() => new() { Value = iconString, Animation = IconAnimation.Spin };
|
||||
}
|
||||
|
||||
internal class LocaleExtension(LocaleKeys key) : MarkupExtension
|
||||
internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string>
|
||||
{
|
||||
private ClrPropertyInfo PropertyInfo
|
||||
=> new(
|
||||
"Item",
|
||||
_ => LocaleManager.Instance[key],
|
||||
null,
|
||||
typeof(string)
|
||||
);
|
||||
protected override string GetValue() => LocaleManager.Instance[key];
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider) =>
|
||||
new CompiledBindingExtension(
|
||||
new CompiledBindingPathBuilder()
|
||||
.Property(PropertyInfo, PropertyInfoAccessorFactory.CreateInpcPropertyAccessor)
|
||||
.Build()
|
||||
) { Source = LocaleManager.Instance }
|
||||
.ProvideValue(serviceProvider);
|
||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||
=> bindingExtension.Source = LocaleManager.Instance;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,21 +23,15 @@ namespace Ryujinx.Ava.Input
|
|||
public bool IsConnected => true;
|
||||
public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
|
||||
|
||||
private class ButtonMappingEntry
|
||||
private class ButtonMappingEntry(GamepadButtonInputId to, Key from)
|
||||
{
|
||||
public readonly Key From;
|
||||
public readonly GamepadButtonInputId To;
|
||||
|
||||
public ButtonMappingEntry(GamepadButtonInputId to, Key from)
|
||||
{
|
||||
To = to;
|
||||
From = from;
|
||||
}
|
||||
public readonly GamepadButtonInputId To = to;
|
||||
public readonly Key From = from;
|
||||
}
|
||||
|
||||
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
|
||||
{
|
||||
_buttonsUserMapping = new List<ButtonMappingEntry>();
|
||||
_buttonsUserMapping = [];
|
||||
|
||||
_driver = driver;
|
||||
Id = id;
|
||||
|
|
|
@ -127,11 +127,11 @@ namespace Ryujinx.Ava.UI.Applet
|
|||
try
|
||||
{
|
||||
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||
var response = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
|
||||
(UserResult result, string userInput) = await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.SoftwareKeyboard], args);
|
||||
|
||||
if (response.Result == UserResult.Ok)
|
||||
if (result == UserResult.Ok)
|
||||
{
|
||||
inputText = response.Input;
|
||||
inputText = userInput;
|
||||
okPressed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
{
|
||||
base.OnPointerReleased(e);
|
||||
|
||||
if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver)
|
||||
if (_currentAssigner is { ToggledButton.IsPointerOver: false })
|
||||
{
|
||||
_currentAssigner.Cancel();
|
||||
}
|
||||
|
@ -41,9 +41,10 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
|
||||
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton button)
|
||||
{
|
||||
if ((bool)button.IsChecked)
|
||||
if (sender is not ToggleButton button)
|
||||
return;
|
||||
|
||||
if (button.IsChecked is true)
|
||||
{
|
||||
if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
|
||||
{
|
||||
|
@ -58,12 +59,15 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
|
||||
PointerPressed += MouseClick;
|
||||
|
||||
var viewModel = (DataContext as KeyboardInputViewModel);
|
||||
if (DataContext is not KeyboardInputViewModel viewModel)
|
||||
return;
|
||||
|
||||
IKeyboard keyboard = (IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IButtonAssigner assigner = CreateButtonAssigner();
|
||||
IKeyboard keyboard =
|
||||
(IKeyboard)viewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
|
||||
IButtonAssigner assigner =
|
||||
new KeyboardKeyAssigner((IKeyboard)viewModel.ParentModel.SelectedGamepad);
|
||||
|
||||
_currentAssigner.ButtonAssigned += (sender, e) =>
|
||||
_currentAssigner.ButtonAssigned += (_, e) =>
|
||||
{
|
||||
if (e.ButtonValue.HasValue)
|
||||
{
|
||||
|
@ -178,7 +182,6 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
_currentAssigner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MouseClick(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
|
@ -189,15 +192,6 @@ namespace Ryujinx.Ava.UI.Views.Input
|
|||
PointerPressed -= MouseClick;
|
||||
}
|
||||
|
||||
private IButtonAssigner CreateButtonAssigner()
|
||||
{
|
||||
IButtonAssigner assigner;
|
||||
|
||||
assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).ParentModel.SelectedGamepad);
|
||||
|
||||
return assigner;
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
|
|
|
@ -273,8 +273,8 @@
|
|||
</MenuItem>
|
||||
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarView}">
|
||||
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}">
|
||||
<MenuItem Header="{ext:Locale MenuBarViewWindow720}" Tag="720 1280" Click="ChangeWindowSize_Click" />
|
||||
<MenuItem Header="{ext:Locale MenuBarViewWindow1080}" Tag="1080 1920" Click="ChangeWindowSize_Click" />
|
||||
<MenuItem Header="{ext:Locale MenuBarViewWindow720}" Tag="1280 720" Click="ChangeWindowSize_Click" />
|
||||
<MenuItem Header="{ext:Locale MenuBarViewWindow1080}" Tag="1920 1080" Click="ChangeWindowSize_Click" />
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}">
|
||||
|
|
|
@ -184,8 +184,10 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
if (sender is not MenuItem { Tag: string resolution })
|
||||
return;
|
||||
|
||||
(int height, int width) = resolution.Split(' ')
|
||||
.Into(parts => (int.Parse(parts[0]), int.Parse(parts[1])));
|
||||
(int width, int height) = resolution.Split(' ', 2)
|
||||
.Into(parts =>
|
||||
(int.Parse(parts[0]), int.Parse(parts[1]))
|
||||
);
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
|
@ -200,7 +202,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
public async void CheckForUpdates(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Updater.CanUpdate(true))
|
||||
await Updater.BeginParse(Window, true);
|
||||
await Window.BeginUpdateAsync(true);
|
||||
}
|
||||
|
||||
public async void OpenXCITrimmerWindow(object sender, RoutedEventArgs e) => await XCITrimmerWindow.Show(ViewModel);
|
||||
|
|
|
@ -63,8 +63,7 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
|
||||
private async void Import_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.GetVisualRoot() as Window;
|
||||
var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
var result = await ((Window)this.GetVisualRoot()!).StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
AllowMultiple = false,
|
||||
FileTypeFilter = new List<FilePickerFileType>
|
||||
|
|
|
@ -28,6 +28,7 @@ using Ryujinx.UI.Common.Configuration;
|
|||
using Ryujinx.UI.Common.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
|
@ -349,12 +350,12 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
await Dispatcher.UIThread.InvokeAsync(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
|
||||
}
|
||||
|
||||
if (ConfigurationState.Instance.CheckUpdatesOnStart && Updater.CanUpdate(false))
|
||||
if (ConfigurationState.Instance.CheckUpdatesOnStart && Updater.CanUpdate())
|
||||
{
|
||||
await Updater.BeginParse(this, false).ContinueWith(task =>
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}");
|
||||
}, TaskContinuationOptions.OnlyOnFaulted);
|
||||
await this.BeginUpdateAsync()
|
||||
.ContinueWith(
|
||||
task => Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}"),
|
||||
TaskContinuationOptions.OnlyOnFaulted);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,30 +393,17 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
|
||||
ViewModel.WindowState = ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value ? WindowState.Maximized : WindowState.Normal;
|
||||
|
||||
if (CheckScreenBounds(savedPoint))
|
||||
if (Screens.All.Any(screen => screen.Bounds.Contains(savedPoint)))
|
||||
{
|
||||
Position = savedPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "Failed to find valid start-up coordinates. Defaulting to primary monitor center.");
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckScreenBounds(PixelPoint configPoint)
|
||||
{
|
||||
for (int i = 0; i < Screens.ScreenCount; i++)
|
||||
{
|
||||
if (Screens.All[i].Bounds.Contains(configPoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Warning?.Print(LogClass.Application, "Failed to find valid start-up coordinates. Defaulting to primary monitor center.");
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SaveWindowSizePosition()
|
||||
{
|
||||
ConfigurationState.Instance.UI.WindowStartup.WindowMaximized.Value = WindowState == WindowState.Maximized;
|
||||
|
@ -507,8 +495,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
|
||||
private void VolumeStatus_CheckedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var volumeSplitButton = sender as ToggleSplitButton;
|
||||
if (ViewModel.IsGameRunning)
|
||||
if (ViewModel.IsGameRunning && sender is ToggleSplitButton volumeSplitButton)
|
||||
{
|
||||
if (!volumeSplitButton.IsChecked)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace Ryujinx.Ava
|
|||
internal static class Updater
|
||||
{
|
||||
private const string GitHubApiUrl = "https://api.github.com";
|
||||
private const string LatestReleaseUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
|
||||
|
||||
private static readonly GithubReleasesJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
private static readonly string _homeDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
@ -46,9 +48,9 @@ namespace Ryujinx.Ava
|
|||
private static bool _updateSuccessful;
|
||||
private static bool _running;
|
||||
|
||||
private static readonly string[] _windowsDependencyDirs = Array.Empty<string>();
|
||||
private static readonly string[] _windowsDependencyDirs = [];
|
||||
|
||||
public static async Task BeginParse(Window mainWindow, bool showVersionUpToDate)
|
||||
public static async Task BeginUpdateAsync(this Window mainWindow, bool showVersionUpToDate = false)
|
||||
{
|
||||
if (_running)
|
||||
{
|
||||
|
@ -97,8 +99,7 @@ namespace Ryujinx.Ava
|
|||
{
|
||||
using HttpClient jsonClient = ConstructHttpClient();
|
||||
|
||||
string buildInfoUrl = $"{GitHubApiUrl}/repos/{ReleaseInformation.ReleaseChannelOwner}/{ReleaseInformation.ReleaseChannelRepo}/releases/latest";
|
||||
string fetchedJson = await jsonClient.GetStringAsync(buildInfoUrl);
|
||||
string fetchedJson = await jsonClient.GetStringAsync(LatestReleaseUrl);
|
||||
var fetched = JsonHelper.Deserialize(fetchedJson, _serializerContext.GithubReleasesJsonResponse);
|
||||
_buildVer = fetched.Name;
|
||||
|
||||
|
@ -159,7 +160,7 @@ namespace Ryujinx.Ava
|
|||
}
|
||||
catch
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!");
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {App.FullAppName} version from GitHub!");
|
||||
|
||||
await ContentDialogHelper.CreateWarningDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
|
||||
|
@ -636,7 +637,7 @@ namespace Ryujinx.Ava
|
|||
taskDialog.Hide();
|
||||
}
|
||||
|
||||
public static bool CanUpdate(bool showWarnings)
|
||||
public static bool CanUpdate(bool showWarnings = false)
|
||||
{
|
||||
#if !DISABLE_UPDATER
|
||||
if (!NetworkInterface.GetIsNetworkAvailable())
|
||||
|
|
Loading…
Reference in a new issue