This commit is contained in:
Jean-Philippe HAUTIN 2024-07-16 09:48:50 +02:00 committed by GitHub
commit 650ec8b99f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 794 additions and 4 deletions

View file

@ -320,6 +320,11 @@ namespace Ryujinx
} }
} }
if (ConfigurationState.Instance.UI.ShowProfilesAtStartup)
{
mainWindow.ShowProfilesSelector();
}
if (CommandLineState.LaunchPathArg != null) if (CommandLineState.LaunchPathArg != null)
{ {
mainWindow.RunApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg); mainWindow.RunApplication(CommandLineState.LaunchPathArg, CommandLineState.StartFullscreenArg);

View file

@ -887,6 +887,12 @@ namespace Ryujinx.UI
return false; return false;
} }
public void ShowProfilesSelector()
{
var window = new UserProfilesSelectorWindow(_accountManager, _contentManager, _virtualFileSystem);
window.Show();
}
public void RunApplication(string path, bool startFullscreen = false) public void RunApplication(string path, bool startFullscreen = false)
{ {
if (_gameLoaded) if (_gameLoaded)

View file

@ -52,6 +52,7 @@ namespace Ryujinx.UI.Windows
[GUI] CheckButton _dockedModeToggle; [GUI] CheckButton _dockedModeToggle;
[GUI] CheckButton _discordToggle; [GUI] CheckButton _discordToggle;
[GUI] CheckButton _checkUpdatesToggle; [GUI] CheckButton _checkUpdatesToggle;
[GUI] CheckButton _showProfileToggle;
[GUI] CheckButton _showConfirmExitToggle; [GUI] CheckButton _showConfirmExitToggle;
[GUI] RadioButton _hideCursorNever; [GUI] RadioButton _hideCursorNever;
[GUI] RadioButton _hideCursorOnIdle; [GUI] RadioButton _hideCursorOnIdle;
@ -225,6 +226,11 @@ namespace Ryujinx.UI.Windows
_checkUpdatesToggle.Click(); _checkUpdatesToggle.Click();
} }
if (ConfigurationState.Instance.UI.ShowProfilesAtStartup)
{
_showProfileToggle.Click();
}
if (ConfigurationState.Instance.ShowConfirmExit) if (ConfigurationState.Instance.ShowConfirmExit)
{ {
_showConfirmExitToggle.Click(); _showConfirmExitToggle.Click();
@ -626,6 +632,7 @@ namespace Ryujinx.UI.Windows
ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active; ConfigurationState.Instance.System.EnableDockedMode.Value = _dockedModeToggle.Active;
ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active; ConfigurationState.Instance.EnableDiscordIntegration.Value = _discordToggle.Active;
ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active; ConfigurationState.Instance.CheckUpdatesOnStart.Value = _checkUpdatesToggle.Active;
ConfigurationState.Instance.UI.ShowProfilesAtStartup.Value = _showProfileToggle.Active;
ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active; ConfigurationState.Instance.ShowConfirmExit.Value = _showConfirmExitToggle.Active;
ConfigurationState.Instance.HideCursor.Value = hideCursor; ConfigurationState.Instance.HideCursor.Value = hideCursor;
ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active; ConfigurationState.Instance.Graphics.EnableVsync.Value = _vSyncToggle.Active;

View file

@ -143,6 +143,22 @@
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="_showProfileToggle">
<property name="label" translatable="yes">Show Profiles on Launch</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="halign">start</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">2</property>
</packing>
</child>
<child> <child>
<object class="GtkCheckButton" id="_showConfirmExitToggle"> <object class="GtkCheckButton" id="_showConfirmExitToggle">
<property name="label" translatable="yes">Show "Confirm Exit" Dialog</property> <property name="label" translatable="yes">Show "Confirm Exit" Dialog</property>
@ -156,7 +172,7 @@
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="padding">5</property> <property name="padding">5</property>
<property name="position">2</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>

View file

@ -0,0 +1,160 @@
using Gtk;
using Pango;
using System;
namespace Ryujinx.UI.Windows
{
public partial class UserProfilesSelectorWindow : Window
{
private Box _mainBox;
private Label _selectedLabel;
private Box _selectedUserBox;
private Image _selectedUserImage;
private Box _selectedUserInfoBox;
private Entry _selectedUserNameEntry;
private Label _selectedUserIdLabel;
private Box _selectedUserButtonsBox;
private Button _saveProfileNameButton;
private Button _changeProfileImageButton;
private Box _usersTreeViewBox;
private Label _availableUsersLabel;
private ScrolledWindow _usersTreeViewWindow;
private ListStore _tableStore;
private TreeView _usersTreeView;
private Box _bottomBox;
private Button _addButton;
private Button _deleteButton;
private Button _closeButton;
private void InitializeComponent()
{
//
// UserProfilesManagerWindow
//
CanFocus = false;
Resizable = false;
Modal = true;
WindowPosition = WindowPosition.Center;
DefaultWidth = 620;
DefaultHeight = 548;
TypeHint = Gdk.WindowTypeHint.Dialog;
//
// _mainBox
//
_mainBox = new Box(Orientation.Vertical, 0);
//
// _viewBox
//
_usersTreeViewBox = new Box(Orientation.Vertical, 0);
//
// _saveProfileNameButton
//
_saveProfileNameButton = new Button()
{
Label = "Save Profile Name",
CanFocus = true,
ReceivesDefault = true,
Sensitive = false,
};
_saveProfileNameButton.Clicked += EditProfileNameButton_Pressed;
//
// _changeProfileImageButton
//
_changeProfileImageButton = new Button()
{
Label = "Change Profile Image",
CanFocus = true,
ReceivesDefault = true,
MarginTop = 10,
};
_changeProfileImageButton.Clicked += ChangeProfileImageButton_Pressed;
//
// _availableUsersLabel
//
_availableUsersLabel = new Label("Available User Profiles:")
{
Margin = 15,
Attributes = new AttrList(),
Halign = Align.Start,
};
_availableUsersLabel.Attributes.Insert(new Pango.AttrWeight(Weight.Bold));
//
// _usersTreeViewWindow
//
_usersTreeViewWindow = new ScrolledWindow()
{
ShadowType = ShadowType.In,
CanFocus = true,
Expand = true,
MarginStart = 30,
MarginEnd = 30,
MarginBottom = 15,
};
//
// _tableStore
//
_tableStore = new ListStore(typeof(bool), typeof(Gdk.Pixbuf), typeof(string), typeof(Gdk.RGBA));
//
// _usersTreeView
//
_usersTreeView = new TreeView(_tableStore)
{
HoverSelection = true,
HeadersVisible = false,
};
_usersTreeView.RowActivated += UsersTreeView_Activated;
//
// _bottomBox
//
_bottomBox = new Box(Orientation.Horizontal, 0)
{
MarginStart = 30,
MarginEnd = 30,
MarginBottom = 15,
};
//
// _closeButton
//
_closeButton = new Button()
{
Label = "Close",
CanFocus = true,
ReceivesDefault = true,
HeightRequest = 35,
WidthRequest = 80,
};
_closeButton.Clicked += CloseButton_Pressed;
ShowComponent();
}
private void ShowComponent()
{
_usersTreeViewWindow.Add(_usersTreeView);
_usersTreeViewBox.Add(_usersTreeViewWindow);
_bottomBox.PackStart(_addButton, false, false, 0);
_bottomBox.PackEnd(_closeButton, false, false, 0);
_mainBox.PackStart(_availableUsersLabel, false, false, 0);
_mainBox.Add(_usersTreeViewBox);
_mainBox.Add(_bottomBox);
Add(_mainBox);
ShowAll();
}
}
}

View file

@ -0,0 +1,271 @@
using Gtk;
using Ryujinx.Common.Memory;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Widgets;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Image = SixLabors.ImageSharp.Image;
namespace Ryujinx.UI.Windows
{
public partial class UserProfilesSelectorWindow : Window
{
private readonly AccountManager _accountManager;
private readonly ContentManager _contentManager;
private byte[] _bufferImageProfile;
private string _tempNewProfileName;
private Gdk.RGBA _selectedColor;
private readonly ManualResetEvent _avatarsPreloadingEvent = new(false);
public UserProfilesSelectorWindow(AccountManager accountManager, ContentManager contentManager, VirtualFileSystem virtualFileSystem) : base($"Ryujinx {Program.Version} - Manage User Profiles")
{
Icon = new Gdk.Pixbuf(Assembly.GetAssembly(typeof(ConfigurationState)), "Ryujinx.UI.Common.Resources.Logo_Ryujinx.png");
InitializeComponent();
_selectedColor.Red = 0.212;
_selectedColor.Green = 0.843;
_selectedColor.Blue = 0.718;
_selectedColor.Alpha = 1;
_accountManager = accountManager;
_contentManager = contentManager;
CellRendererToggle userSelectedToggle = new();
userSelectedToggle.Toggled += UserSelectedToggle_Toggled;
// NOTE: Uncomment following line when multiple selection of user profiles is supported.
//_usersTreeView.AppendColumn("Selected", userSelectedToggle, "active", 0);
_usersTreeView.AppendColumn("User Icon", new CellRendererPixbuf(), "pixbuf", 1);
_usersTreeView.AppendColumn("User Info", new CellRendererText(), "text", 2, "background-rgba", 3);
_tableStore.SetSortColumnId(0, SortType.Descending);
RefreshList();
if (_contentManager.GetCurrentFirmwareVersion() != null)
{
Task.Run(() =>
{
AvatarWindow.PreloadAvatars(contentManager, virtualFileSystem);
_avatarsPreloadingEvent.Set();
});
}
}
public void RefreshList()
{
_tableStore.Clear();
foreach (UserProfile userProfile in _accountManager.GetAllUsers())
{
_tableStore.AppendValues(userProfile.AccountState == AccountState.Open, new Gdk.Pixbuf(userProfile.Image, 96, 96), $"{userProfile.Name}\n{userProfile.UserId}", Gdk.RGBA.Zero);
if (userProfile.AccountState == AccountState.Open)
{
_usersTreeView.Model.GetIterFirst(out TreeIter firstIter);
_tableStore.SetValue(firstIter, 3, _selectedColor);
}
}
}
//
// Events
//
private void UsersTreeView_Activated(object o, RowActivatedArgs args)
{
SelectUserTreeView();
}
private void UserSelectedToggle_Toggled(object o, ToggledArgs args)
{
SelectUserTreeView();
}
private void SelectUserTreeView()
{
// Get selected item informations.
_usersTreeView.Selection.GetSelected(out TreeIter selectedIter);
string userId = _tableStore.GetValue(selectedIter, 2).ToString().Split("\n")[1];
// Open the selected one.
_accountManager.OpenUser(new UserId(userId));
Close();
}
private void EditProfileNameButton_Pressed(object sender, EventArgs e)
{
_saveProfileNameButton.Sensitive = false;
_accountManager.SetUserName(GetSelectedUserId(), _selectedUserNameEntry.Text);
RefreshList();
}
private void ProcessProfileImage(byte[] buffer)
{
using Image image = Image.Load(buffer);
image.Mutate(x => x.Resize(256, 256));
using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
image.SaveAsJpeg(streamJpg);
_bufferImageProfile = streamJpg.ToArray();
}
private void ProfileImageFileChooser()
{
FileChooserNative fileChooser = new("Import Custom Profile Image", this, FileChooserAction.Open, "Import", "Cancel")
{
SelectMultiple = false,
};
FileFilter filter = new()
{
Name = "Custom Profile Images",
};
filter.AddPattern("*.jpg");
filter.AddPattern("*.jpeg");
filter.AddPattern("*.png");
filter.AddPattern("*.bmp");
fileChooser.AddFilter(filter);
if (fileChooser.Run() == (int)ResponseType.Accept)
{
ProcessProfileImage(File.ReadAllBytes(fileChooser.Filename));
}
fileChooser.Dispose();
}
private void SelectProfileImage(bool newUser = false)
{
if (_contentManager.GetCurrentFirmwareVersion() == null)
{
ProfileImageFileChooser();
}
else
{
Dictionary<int, string> buttons = new()
{
{ 0, "Import Image File" },
{ 1, "Select Firmware Avatar" },
};
ResponseType responseDialog = GtkDialog.CreateCustomDialog("Profile Image Selection",
"Choose a Profile Image",
"You may import a custom profile image, or select an avatar from the system firmware.",
buttons, MessageType.Question);
if (responseDialog == 0)
{
ProfileImageFileChooser();
}
else if (responseDialog == (ResponseType)1)
{
AvatarWindow avatarWindow = new()
{
NewUser = newUser,
};
avatarWindow.DeleteEvent += AvatarWindow_DeleteEvent;
avatarWindow.SetSizeRequest((int)(avatarWindow.DefaultWidth * Program.WindowScaleFactor), (int)(avatarWindow.DefaultHeight * Program.WindowScaleFactor));
avatarWindow.Show();
}
}
}
private void ChangeProfileImageButton_Pressed(object sender, EventArgs e)
{
if (_contentManager.GetCurrentFirmwareVersion() != null)
{
_avatarsPreloadingEvent.WaitOne();
}
SelectProfileImage();
if (_bufferImageProfile != null)
{
SetUserImage();
}
}
private void AvatarWindow_DeleteEvent(object sender, DeleteEventArgs args)
{
_bufferImageProfile = ((AvatarWindow)sender).SelectedProfileImage;
if (_bufferImageProfile != null)
{
if (((AvatarWindow)sender).NewUser)
{
AddUser();
}
else
{
SetUserImage();
}
}
}
private void AddUser()
{
_accountManager.AddUser(_tempNewProfileName, _bufferImageProfile);
_bufferImageProfile = null;
_tempNewProfileName = "";
RefreshList();
}
private void SetUserImage()
{
_accountManager.SetUserImage(GetSelectedUserId(), _bufferImageProfile);
_bufferImageProfile = null;
RefreshList();
}
private UserId GetSelectedUserId()
{
if (_usersTreeView.Model.GetIterFirst(out TreeIter iter))
{
do
{
if ((bool)_tableStore.GetValue(iter, 0))
{
break;
}
}
while (_usersTreeView.Model.IterNext(ref iter));
}
return new UserId(_tableStore.GetValue(iter, 2).ToString().Split("\n")[1]);
}
private void CloseButton_Pressed(object sender, EventArgs e)
{
Close();
}
}
}

View file

@ -15,7 +15,7 @@ namespace Ryujinx.UI.Common.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 51; public const int CurrentVersion = 52;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format
@ -162,6 +162,11 @@ namespace Ryujinx.UI.Common.Configuration
/// </summary> /// </summary>
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
/// <summary>
/// Show Profiles Dialog at Startup
/// </summary>
public bool ShowProfilesAtStartup { get; set; }
/// <summary> /// <summary>
/// Enables or disables save window size, position and state on close. /// Enables or disables save window size, position and state on close.
/// </summary> /// </summary>

View file

@ -187,6 +187,12 @@ namespace Ryujinx.UI.Common.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> IsAscendingOrder { get; private set; } public ReactiveObject<bool> IsAscendingOrder { get; private set; }
/// <summary>
/// Sets if Grid is ordered in Ascending Order
/// </summary>
public ReactiveObject<bool> ShowProfilesAtStartup { get; private set; }
public UISection() public UISection()
{ {
GuiColumns = new Columns(); GuiColumns = new Columns();
@ -205,6 +211,7 @@ namespace Ryujinx.UI.Common.Configuration
IsAscendingOrder = new ReactiveObject<bool>(); IsAscendingOrder = new ReactiveObject<bool>();
LanguageCode = new ReactiveObject<string>(); LanguageCode = new ReactiveObject<string>();
ShowConsole = new ReactiveObject<bool>(); ShowConsole = new ReactiveObject<bool>();
ShowProfilesAtStartup = new ReactiveObject<bool>();
ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); }; ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); };
} }
} }
@ -766,6 +773,7 @@ namespace Ryujinx.UI.Common.Configuration
PreferredGpu = Graphics.PreferredGpu, PreferredGpu = Graphics.PreferredGpu,
MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId, MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId,
MultiplayerMode = Multiplayer.Mode, MultiplayerMode = Multiplayer.Mode,
ShowProfilesAtStartup = UI.ShowProfilesAtStartup,
}; };
return configurationFile; return configurationFile;
@ -853,6 +861,7 @@ namespace Ryujinx.UI.Common.Configuration
UI.IsAscendingOrder.Value = true; UI.IsAscendingOrder.Value = true;
UI.StartFullscreen.Value = false; UI.StartFullscreen.Value = false;
UI.ShowConsole.Value = true; UI.ShowConsole.Value = true;
UI.ShowProfilesAtStartup.Value = false;
UI.WindowStartup.WindowSizeWidth.Value = 1280; UI.WindowStartup.WindowSizeWidth.Value = 1280;
UI.WindowStartup.WindowSizeHeight.Value = 760; UI.WindowStartup.WindowSizeHeight.Value = 760;
UI.WindowStartup.WindowPositionX.Value = 0; UI.WindowStartup.WindowPositionX.Value = 0;
@ -1477,6 +1486,15 @@ namespace Ryujinx.UI.Common.Configuration
configurationFileUpdated = true; configurationFileUpdated = true;
} }
if (configurationFileFormat.Version < 52)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 52.");
configurationFileFormat.ShowProfilesAtStartup = false;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
@ -1555,6 +1573,7 @@ namespace Ryujinx.UI.Common.Configuration
UI.ApplicationSort.Value = configurationFileFormat.ApplicationSort; UI.ApplicationSort.Value = configurationFileFormat.ApplicationSort;
UI.StartFullscreen.Value = configurationFileFormat.StartFullscreen; UI.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
UI.ShowConsole.Value = configurationFileFormat.ShowConsole; UI.ShowConsole.Value = configurationFileFormat.ShowConsole;
UI.ShowProfilesAtStartup.Value = configurationFileFormat.ShowProfilesAtStartup;
UI.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth; UI.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth;
UI.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight; UI.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight;
UI.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX; UI.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX;

View file

@ -14,4 +14,4 @@
<sty:FluentAvaloniaTheme PreferSystemTheme="False" /> <sty:FluentAvaloniaTheme PreferSystemTheme="False" />
<StyleInclude Source="/Assets/Styles/Styles.xaml"/> <StyleInclude Source="/Assets/Styles/Styles.xaml"/>
</Application.Styles> </Application.Styles>
</Application> </Application>

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "تمكين وجود ديسكورد الغني", "SettingsTabGeneralEnableDiscordRichPresence": "تمكين وجود ديسكورد الغني",
"SettingsTabGeneralCheckUpdatesOnLaunch": "التحقق من وجود تحديثات عند التشغيل", "SettingsTabGeneralCheckUpdatesOnLaunch": "التحقق من وجود تحديثات عند التشغيل",
"SettingsTabGeneralShowConfirmExitDialog": "إظهار مربع حوار \"تأكيد الخروج\"", "SettingsTabGeneralShowConfirmExitDialog": "إظهار مربع حوار \"تأكيد الخروج\"",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "تذكر حجم/موضع النافذة", "SettingsTabGeneralRememberWindowState": "تذكر حجم/موضع النافذة",
"SettingsTabGeneralHideCursor": "إخفاء المؤشر:", "SettingsTabGeneralHideCursor": "إخفاء المؤشر:",
"SettingsTabGeneralHideCursorNever": "مطلقا", "SettingsTabGeneralHideCursorNever": "مطلقا",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Aktiviere die Statusanzeige für Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Aktiviere die Statusanzeige für Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Beim Start nach Updates suchen", "SettingsTabGeneralCheckUpdatesOnLaunch": "Beim Start nach Updates suchen",
"SettingsTabGeneralShowConfirmExitDialog": "Zeige den \"Beenden bestätigen\"-Dialog", "SettingsTabGeneralShowConfirmExitDialog": "Zeige den \"Beenden bestätigen\"-Dialog",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Fenstergröße/-position merken", "SettingsTabGeneralRememberWindowState": "Fenstergröße/-position merken",
"SettingsTabGeneralHideCursor": "Mauszeiger ausblenden", "SettingsTabGeneralHideCursor": "Mauszeiger ausblenden",
"SettingsTabGeneralHideCursorNever": "Niemals", "SettingsTabGeneralHideCursorNever": "Niemals",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Ενεργοποίηση Εμπλουτισμένης Παρουσίας Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Ενεργοποίηση Εμπλουτισμένης Παρουσίας Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Έλεγχος για Ενημερώσεις στην Εκκίνηση", "SettingsTabGeneralCheckUpdatesOnLaunch": "Έλεγχος για Ενημερώσεις στην Εκκίνηση",
"SettingsTabGeneralShowConfirmExitDialog": "Εμφάνιση διαλόγου \"Επιβεβαίωση Εξόδου\".", "SettingsTabGeneralShowConfirmExitDialog": "Εμφάνιση διαλόγου \"Επιβεβαίωση Εξόδου\".",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Απόκρυψη Κέρσορα:", "SettingsTabGeneralHideCursor": "Απόκρυψη Κέρσορα:",
"SettingsTabGeneralHideCursorNever": "Ποτέ", "SettingsTabGeneralHideCursorNever": "Ποτέ",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence", "SettingsTabGeneralEnableDiscordRichPresence": "Enable Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Check for Updates on Launch", "SettingsTabGeneralCheckUpdatesOnLaunch": "Check for Updates on Launch",
"SettingsTabGeneralShowConfirmExitDialog": "Show \"Confirm Exit\" Dialog", "SettingsTabGeneralShowConfirmExitDialog": "Show \"Confirm Exit\" Dialog",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Hide Cursor:", "SettingsTabGeneralHideCursor": "Hide Cursor:",
"SettingsTabGeneralHideCursorNever": "Never", "SettingsTabGeneralHideCursorNever": "Never",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Habilitar estado en Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Habilitar estado en Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Buscar actualizaciones al iniciar", "SettingsTabGeneralCheckUpdatesOnLaunch": "Buscar actualizaciones al iniciar",
"SettingsTabGeneralShowConfirmExitDialog": "Mostrar diálogo de confirmación al cerrar", "SettingsTabGeneralShowConfirmExitDialog": "Mostrar diálogo de confirmación al cerrar",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Esconder el cursor:", "SettingsTabGeneralHideCursor": "Esconder el cursor:",
"SettingsTabGeneralHideCursorNever": "Nunca", "SettingsTabGeneralHideCursorNever": "Nunca",

View file

@ -95,6 +95,7 @@
"SettingsTabGeneralGeneral": "Général", "SettingsTabGeneralGeneral": "Général",
"SettingsTabGeneralEnableDiscordRichPresence": "Activer Discord Rich Presence", "SettingsTabGeneralEnableDiscordRichPresence": "Activer Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Vérifier les mises à jour au démarrage", "SettingsTabGeneralCheckUpdatesOnLaunch": "Vérifier les mises à jour au démarrage",
"SettingsTabGeneralShoProfilesAtStartup": "Afficher les profiles au démarrage",
"SettingsTabGeneralShowConfirmExitDialog": "Afficher le message de \"Confirmation de sortie\"", "SettingsTabGeneralShowConfirmExitDialog": "Afficher le message de \"Confirmation de sortie\"",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Masquer le Curseur :", "SettingsTabGeneralHideCursor": "Masquer le Curseur :",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "הפעלת תצוגה עשירה בדיסקורד", "SettingsTabGeneralEnableDiscordRichPresence": "הפעלת תצוגה עשירה בדיסקורד",
"SettingsTabGeneralCheckUpdatesOnLaunch": "בדוק אם קיימים עדכונים בהפעלה", "SettingsTabGeneralCheckUpdatesOnLaunch": "בדוק אם קיימים עדכונים בהפעלה",
"SettingsTabGeneralShowConfirmExitDialog": "הראה דיאלוג \"אשר יציאה\"", "SettingsTabGeneralShowConfirmExitDialog": "הראה דיאלוג \"אשר יציאה\"",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "הסתר את הסמן", "SettingsTabGeneralHideCursor": "הסתר את הסמן",
"SettingsTabGeneralHideCursorNever": "אף פעם", "SettingsTabGeneralHideCursorNever": "אף פעם",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Attiva Discord Rich Presence", "SettingsTabGeneralEnableDiscordRichPresence": "Attiva Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Controlla aggiornamenti all'avvio", "SettingsTabGeneralCheckUpdatesOnLaunch": "Controlla aggiornamenti all'avvio",
"SettingsTabGeneralShowConfirmExitDialog": "Mostra dialogo \"Conferma Uscita\"", "SettingsTabGeneralShowConfirmExitDialog": "Mostra dialogo \"Conferma Uscita\"",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Nascondi il cursore:", "SettingsTabGeneralHideCursor": "Nascondi il cursore:",
"SettingsTabGeneralHideCursorNever": "Mai", "SettingsTabGeneralHideCursorNever": "Mai",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Discord リッチプレゼンスを有効にする", "SettingsTabGeneralEnableDiscordRichPresence": "Discord リッチプレゼンスを有効にする",
"SettingsTabGeneralCheckUpdatesOnLaunch": "起動時にアップデートを確認する", "SettingsTabGeneralCheckUpdatesOnLaunch": "起動時にアップデートを確認する",
"SettingsTabGeneralShowConfirmExitDialog": "\"終了を確認\" ダイアログを表示する", "SettingsTabGeneralShowConfirmExitDialog": "\"終了を確認\" ダイアログを表示する",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "マウスカーソルを非表示", "SettingsTabGeneralHideCursor": "マウスカーソルを非表示",
"SettingsTabGeneralHideCursorNever": "決して", "SettingsTabGeneralHideCursorNever": "決して",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "디스코드 활동 상태 활성화", "SettingsTabGeneralEnableDiscordRichPresence": "디스코드 활동 상태 활성화",
"SettingsTabGeneralCheckUpdatesOnLaunch": "시작 시, 업데이트 확인", "SettingsTabGeneralCheckUpdatesOnLaunch": "시작 시, 업데이트 확인",
"SettingsTabGeneralShowConfirmExitDialog": "\"종료 확인\" 대화 상자 표시", "SettingsTabGeneralShowConfirmExitDialog": "\"종료 확인\" 대화 상자 표시",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "창 크기/위치 기억", "SettingsTabGeneralRememberWindowState": "창 크기/위치 기억",
"SettingsTabGeneralHideCursor": "마우스 커서 숨기기", "SettingsTabGeneralHideCursor": "마우스 커서 숨기기",
"SettingsTabGeneralHideCursorNever": "절대 안 함", "SettingsTabGeneralHideCursorNever": "절대 안 함",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Włącz Bogatą Obecność Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Włącz Bogatą Obecność Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Sprawdzaj aktualizacje przy uruchomieniu", "SettingsTabGeneralCheckUpdatesOnLaunch": "Sprawdzaj aktualizacje przy uruchomieniu",
"SettingsTabGeneralShowConfirmExitDialog": "Pokazuj okno dialogowe \"Potwierdź wyjście\"", "SettingsTabGeneralShowConfirmExitDialog": "Pokazuj okno dialogowe \"Potwierdź wyjście\"",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Ukryj kursor:", "SettingsTabGeneralHideCursor": "Ukryj kursor:",
"SettingsTabGeneralHideCursorNever": "Nigdy", "SettingsTabGeneralHideCursorNever": "Nigdy",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Habilitar Rich Presence do Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Habilitar Rich Presence do Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Verificar se há atualizações ao iniciar", "SettingsTabGeneralCheckUpdatesOnLaunch": "Verificar se há atualizações ao iniciar",
"SettingsTabGeneralShowConfirmExitDialog": "Exibir diálogo de confirmação ao sair", "SettingsTabGeneralShowConfirmExitDialog": "Exibir diálogo de confirmação ao sair",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Lembrar tamanho/posição da Janela", "SettingsTabGeneralRememberWindowState": "Lembrar tamanho/posição da Janela",
"SettingsTabGeneralHideCursor": "Esconder o cursor do mouse:", "SettingsTabGeneralHideCursor": "Esconder o cursor do mouse:",
"SettingsTabGeneralHideCursorNever": "Nunca", "SettingsTabGeneralHideCursorNever": "Nunca",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Статус активности в Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Статус активности в Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Проверять наличие обновлений при запуске", "SettingsTabGeneralCheckUpdatesOnLaunch": "Проверять наличие обновлений при запуске",
"SettingsTabGeneralShowConfirmExitDialog": "Подтверждать выход из приложения", "SettingsTabGeneralShowConfirmExitDialog": "Подтверждать выход из приложения",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Запомнить размер/положение окна", "SettingsTabGeneralRememberWindowState": "Запомнить размер/положение окна",
"SettingsTabGeneralHideCursor": "Скрывать курсор", "SettingsTabGeneralHideCursor": "Скрывать курсор",
"SettingsTabGeneralHideCursorNever": "Никогда", "SettingsTabGeneralHideCursorNever": "Никогда",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "เปิดใช้งาน Discord Rich Presence", "SettingsTabGeneralEnableDiscordRichPresence": "เปิดใช้งาน Discord Rich Presence",
"SettingsTabGeneralCheckUpdatesOnLaunch": "ตรวจหาการอัปเดตเมื่อเปิดโปรแกรม", "SettingsTabGeneralCheckUpdatesOnLaunch": "ตรวจหาการอัปเดตเมื่อเปิดโปรแกรม",
"SettingsTabGeneralShowConfirmExitDialog": "แสดง \"ยืนยันการออก\" กล่องข้อความโต้ตอบ", "SettingsTabGeneralShowConfirmExitDialog": "แสดง \"ยืนยันการออก\" กล่องข้อความโต้ตอบ",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "ซ่อน เคอร์เซอร์:", "SettingsTabGeneralHideCursor": "ซ่อน เคอร์เซอร์:",
"SettingsTabGeneralHideCursorNever": "ไม่มี", "SettingsTabGeneralHideCursorNever": "ไม่มี",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Discord Zengin İçerik'i Etkinleştir", "SettingsTabGeneralEnableDiscordRichPresence": "Discord Zengin İçerik'i Etkinleştir",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Her Açılışta Güncellemeleri Denetle", "SettingsTabGeneralCheckUpdatesOnLaunch": "Her Açılışta Güncellemeleri Denetle",
"SettingsTabGeneralShowConfirmExitDialog": "\"Çıkışı Onayla\" Diyaloğunu Göster", "SettingsTabGeneralShowConfirmExitDialog": "\"Çıkışı Onayla\" Diyaloğunu Göster",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "İşaretçiyi Gizle:", "SettingsTabGeneralHideCursor": "İşaretçiyi Gizle:",
"SettingsTabGeneralHideCursorNever": "Hiçbir Zaman", "SettingsTabGeneralHideCursorNever": "Hiçbir Zaman",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "Увімкнути розширену присутність Discord", "SettingsTabGeneralEnableDiscordRichPresence": "Увімкнути розширену присутність Discord",
"SettingsTabGeneralCheckUpdatesOnLaunch": "Перевіряти наявність оновлень під час запуску", "SettingsTabGeneralCheckUpdatesOnLaunch": "Перевіряти наявність оновлень під час запуску",
"SettingsTabGeneralShowConfirmExitDialog": "Показати діалогове вікно «Підтвердити вихід».", "SettingsTabGeneralShowConfirmExitDialog": "Показати діалогове вікно «Підтвердити вихід».",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "Remember Window Size/Position", "SettingsTabGeneralRememberWindowState": "Remember Window Size/Position",
"SettingsTabGeneralHideCursor": "Сховати вказівник:", "SettingsTabGeneralHideCursor": "Сховати вказівник:",
"SettingsTabGeneralHideCursorNever": "Ніколи", "SettingsTabGeneralHideCursorNever": "Ніколи",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "启用 Discord 在线状态展示", "SettingsTabGeneralEnableDiscordRichPresence": "启用 Discord 在线状态展示",
"SettingsTabGeneralCheckUpdatesOnLaunch": "启动时检查更新", "SettingsTabGeneralCheckUpdatesOnLaunch": "启动时检查更新",
"SettingsTabGeneralShowConfirmExitDialog": "退出游戏时需要确认", "SettingsTabGeneralShowConfirmExitDialog": "退出游戏时需要确认",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "记住窗口大小和位置", "SettingsTabGeneralRememberWindowState": "记住窗口大小和位置",
"SettingsTabGeneralHideCursor": "隐藏鼠标指针:", "SettingsTabGeneralHideCursor": "隐藏鼠标指针:",
"SettingsTabGeneralHideCursorNever": "从不隐藏", "SettingsTabGeneralHideCursorNever": "从不隐藏",

View file

@ -96,6 +96,7 @@
"SettingsTabGeneralEnableDiscordRichPresence": "啟用 Discord 動態狀態展示", "SettingsTabGeneralEnableDiscordRichPresence": "啟用 Discord 動態狀態展示",
"SettingsTabGeneralCheckUpdatesOnLaunch": "啟動時檢查更新", "SettingsTabGeneralCheckUpdatesOnLaunch": "啟動時檢查更新",
"SettingsTabGeneralShowConfirmExitDialog": "顯示「確認結束」對話方塊", "SettingsTabGeneralShowConfirmExitDialog": "顯示「確認結束」對話方塊",
"SettingsTabGeneralShoProfilesAtStartup": "Show Profiles at Startup",
"SettingsTabGeneralRememberWindowState": "記住視窗大小/位置", "SettingsTabGeneralRememberWindowState": "記住視窗大小/位置",
"SettingsTabGeneralHideCursor": "隱藏滑鼠游標:", "SettingsTabGeneralHideCursor": "隱藏滑鼠游標:",
"SettingsTabGeneralHideCursorNever": "從不", "SettingsTabGeneralHideCursorNever": "從不",

View file

@ -164,4 +164,10 @@
<ItemGroup> <ItemGroup>
<AdditionalFiles Include="Assets\Locales\en_US.json" /> <AdditionalFiles Include="Assets\Locales\en_US.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Update="UI\Views\User\UserSimpleSelectorView.axaml.cs">
<DependentUpon>UserSimpleSelectorView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project> </Project>

View file

@ -0,0 +1,50 @@
using Avalonia.Collections;
using System;
using System.Collections.Generic;
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
namespace Ryujinx.Ava.UI.ViewModels
{
public class ProfilesViewModel : BaseModel
{
private UserProfile _selectedProfile;
public event Action CloseWindow;
public event Action ApplyProfile;
public ProfilesViewModel()
{
Profiles = new AvaloniaList<UserProfile>();
Profiles.Clear();
}
public ProfilesViewModel(IEnumerable<UserProfile> profiles)
{
Profiles = new AvaloniaList<UserProfile>();
Profiles.Clear();
Profiles.AddRange(profiles);
}
public AvaloniaList<UserProfile> Profiles
{
get; set;
}
public UserProfile SelectedProfile
{
get => _selectedProfile;
set
{
_selectedProfile = value;
OnPropertyChanged();
}
}
public void Close()
{
CloseWindow?.Invoke();
}
}
}

View file

@ -130,6 +130,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableDiscordIntegration { get; set; } public bool EnableDiscordIntegration { get; set; }
public bool CheckUpdatesOnStart { get; set; } public bool CheckUpdatesOnStart { get; set; }
public bool ShowProfilesAtStartup { get; set; }
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
public bool RememberWindowState { get; set; } public bool RememberWindowState { get; set; }
public int HideCursor { get; set; } public int HideCursor { get; set; }
@ -391,6 +393,7 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableDiscordIntegration = config.EnableDiscordIntegration; EnableDiscordIntegration = config.EnableDiscordIntegration;
CheckUpdatesOnStart = config.CheckUpdatesOnStart; CheckUpdatesOnStart = config.CheckUpdatesOnStart;
ShowConfirmExit = config.ShowConfirmExit; ShowConfirmExit = config.ShowConfirmExit;
ShowProfilesAtStartup = config.UI.ShowProfilesAtStartup;
RememberWindowState = config.RememberWindowState; RememberWindowState = config.RememberWindowState;
HideCursor = (int)config.HideCursor.Value; HideCursor = (int)config.HideCursor.Value;
@ -483,6 +486,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.EnableDiscordIntegration.Value = EnableDiscordIntegration; config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart; config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
config.ShowConfirmExit.Value = ShowConfirmExit; config.ShowConfirmExit.Value = ShowConfirmExit;
config.UI.ShowProfilesAtStartup.Value = ShowProfilesAtStartup;
config.RememberWindowState.Value = RememberWindowState; config.RememberWindowState.Value = RememberWindowState;
config.HideCursor.Value = (HideCursorMode)HideCursor; config.HideCursor.Value = (HideCursorMode)HideCursor;

View file

@ -1,4 +1,4 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsUiView" x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsUiView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -33,6 +33,9 @@
<CheckBox IsChecked="{Binding CheckUpdatesOnStart}"> <CheckBox IsChecked="{Binding CheckUpdatesOnStart}">
<TextBlock Text="{locale:Locale SettingsTabGeneralCheckUpdatesOnLaunch}" /> <TextBlock Text="{locale:Locale SettingsTabGeneralCheckUpdatesOnLaunch}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding ShowProfilesAtStartup}">
<TextBlock Text="{locale:Locale SettingsTabGeneralShoProfilesAtStartup}" />
</CheckBox>
<CheckBox IsChecked="{Binding ShowConfirmExit}"> <CheckBox IsChecked="{Binding ShowConfirmExit}">
<TextBlock Text="{locale:Locale SettingsTabGeneralShowConfirmExitDialog}" /> <TextBlock Text="{locale:Locale SettingsTabGeneralShowConfirmExitDialog}" />
</CheckBox> </CheckBox>

View file

@ -0,0 +1,104 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Views.User.UserSimpleSelectorView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
d:DesignHeight="450"
MinWidth="500"
d:DesignWidth="800"
mc:Ignorable="d"
Focusable="True"
x:DataType="viewModels:ProfilesViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
</UserControl.Resources>
<Design.DataContext>
<viewModels:ProfilesViewModel />
</Design.DataContext>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
CornerRadius="5"
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
BorderThickness="1">
<ListBox
MaxHeight="300"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
SelectionChanged="ProfilesList_SelectionChanged"
Background="Transparent"
ItemsSource="{Binding Profiles}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Margin" Value="5 5 0 5" />
<Setter Property="CornerRadius" Value="5" />
</Style>
<Style Selector="Rectangle#SelectionIndicator">
<Setter Property="Opacity" Value="0" />
</Style>
</ListBox.Styles>
<ListBox.DataTemplates>
<DataTemplate
DataType="models:UserProfile">
<Grid
PointerEntered="Grid_PointerEntered"
PointerExited="Grid_OnPointerExited">
<Border
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ClipToBounds="True"
CornerRadius="5"
Background="{Binding BackgroundColor}">
<StackPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image
Width="96"
Height="96"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Source="{Binding Image, Converter={StaticResource ByteImage}}" />
<TextBlock
HorizontalAlignment="Stretch"
MaxWidth="90"
Text="{Binding Name}"
TextAlignment="Center"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis"
MaxLines="2"
Margin="5" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</ListBox.DataTemplates>
</ListBox>
</Border>
<StackPanel
Grid.Row="1"
Margin="0 24 0 0"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
Command="{Binding Close}"
Content="{locale:Locale UserProfilesClose}" />
</StackPanel>
</Grid>
</UserControl>

View file

@ -0,0 +1,84 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Navigation;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using System.Linq;
using Button = Avalonia.Controls.Button;
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
namespace Ryujinx.Ava.UI.Views.User
{
public partial class UserSimpleSelectorView : UserControl
{
public ProfilesViewModel ViewModel { get; set; }
private readonly AccountManager _accountManager;
public UserSimpleSelectorView(AccountManager accountManager)
{
_accountManager = accountManager;
ViewModel = new ProfilesViewModel();
var profiles = _accountManager
.GetAllUsers()
.Select(p => new Models.UserProfile(p, null))
.OrderBy(p => p.Name);
ViewModel.Profiles.AddRange(profiles);
InitializeComponent();
}
private void Grid_PointerEntered(object sender, PointerEventArgs e)
{
if (sender is Grid grid)
{
if (grid.DataContext is UserProfile profile)
{
profile.IsPointerOver = true;
}
}
}
private void Grid_OnPointerExited(object sender, PointerEventArgs e)
{
if (sender is Grid grid)
{
if (grid.DataContext is UserProfile profile)
{
profile.IsPointerOver = false;
}
}
}
private void ProfilesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is ListBox listBox)
{
int selectedIndex = listBox.SelectedIndex;
if (selectedIndex >= 0 && selectedIndex < ViewModel.Profiles.Count)
{
if (ViewModel.Profiles[selectedIndex] is UserProfile userProfile)
{
_accountManager?.OpenUser(userProfile.UserId);
foreach (BaseModel profile in ViewModel.Profiles)
{
if (profile is UserProfile uProfile)
{
uProfile.UpdateState();
}
}
}
}
}
}
}
}

View file

@ -3,6 +3,7 @@ using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
@ -11,6 +12,7 @@ using Ryujinx.Ava.Input;
using Ryujinx.Ava.UI.Applet; using Ryujinx.Ava.UI.Applet;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.User;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
@ -292,8 +294,38 @@ namespace Ryujinx.Ava.UI.Windows
} }
} }
private async Task ShowProfilesDialog()
{
await Dispatcher.UIThread.InvokeAsync(async () =>
{
//await ContentDialogHelper.ShowWindowAsync(new ProfilesWindows(AccountManager)));
var content = new UserSimpleSelectorView(AccountManager);
ContentDialog contentDialog = new()
{
Title = LocaleManager.Instance[LocaleKeys.UserProfileWindowTitle],
PrimaryButtonText = "",
SecondaryButtonText = "",
CloseButtonText = "",
DataContext = content.ViewModel,
Content = content,
Padding = new Thickness(0),
};
content.ViewModel.CloseWindow += contentDialog.Hide;
Style footer = new(x => x.Name("DialogSpace").Child().OfType<Border>());
footer.Setters.Add(new Setter(IsVisibleProperty, false));
contentDialog.Styles.Add(footer);
await contentDialog.ShowAsync();
});
}
private async Task CheckLaunchState() private async Task CheckLaunchState()
{ {
if (ConfigurationState.Instance.UI.ShowProfilesAtStartup)
{
await ShowProfilesDialog();
}
if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount) if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount)
{ {
Logger.Warning?.Print(LogClass.Application, $"The value of vm.max_map_count is lower than {LinuxHelper.RecommendedVmMaxMapCount}. ({LinuxHelper.VmMaxMapCount})"); Logger.Warning?.Print(LogClass.Application, $"The value of vm.max_map_count is lower than {LinuxHelper.RecommendedVmMaxMapCount}. ({LinuxHelper.VmMaxMapCount})");