diff --git a/Nebula.Launcher/App.axaml.cs b/Nebula.Launcher/App.axaml.cs index 1b1ea20..286a19d 100644 --- a/Nebula.Launcher/App.axaml.cs +++ b/Nebula.Launcher/App.axaml.cs @@ -1,22 +1,19 @@ using System; +using System.Linq; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Data.Core; using Avalonia.Data.Core.Plugins; -using System.Linq; -using System.Reflection; using Avalonia.Markup.Xaml; using Microsoft.Extensions.DependencyInjection; -using Nebula.Launcher.ViewModels; using Nebula.Launcher.Views; using Nebula.Shared; namespace Nebula.Launcher; -public partial class App : Application +public class App : Application { private IServiceProvider _serviceProvider = null!; - + public override void Initialize() { AvaloniaXamlLoader.Load(this); @@ -26,11 +23,11 @@ public partial class App : Application { var services = new ServiceCollection(); services.AddAvaloniaServices(); - services.AddViews(); services.AddServices(); - + services.AddViews(); + _serviceProvider = services.BuildServiceProvider(); - + switch (ApplicationLifetime) { case IClassicDesktopStyleApplicationLifetime desktop: @@ -52,9 +49,6 @@ public partial class App : Application BindingPlugins.DataValidators.OfType().ToArray(); // remove each entry found - foreach (var plugin in dataValidationPluginsToRemove) - { - BindingPlugins.DataValidators.Remove(plugin); - } + foreach (var plugin in dataValidationPluginsToRemove) BindingPlugins.DataValidators.Remove(plugin); } } \ No newline at end of file diff --git a/Nebula.Launcher/Assets/Style.axaml b/Nebula.Launcher/Assets/Style.axaml index af8a340..812d78a 100644 --- a/Nebula.Launcher/Assets/Style.axaml +++ b/Nebula.Launcher/Assets/Style.axaml @@ -57,7 +57,7 @@ - + - + - + \ No newline at end of file diff --git a/Nebula.Launcher/Converters/TypeConverters.cs b/Nebula.Launcher/Converters/TypeConverters.cs index 61909a2..c58571a 100644 --- a/Nebula.Launcher/Converters/TypeConverters.cs +++ b/Nebula.Launcher/Converters/TypeConverters.cs @@ -9,7 +9,7 @@ public class TypeConverters { private const string StreamGeometryNotFound = "M24 4C35.0457 4 44 12.9543 44 24C44 35.0457 35.0457 44 24 44C12.9543 44 4 35.0457 4 24C4 12.9543 12.9543 4 24 4ZM24 6.5C14.335 6.5 6.5 14.335 6.5 24C6.5 33.665 14.335 41.5 24 41.5C33.665 41.5 41.5 33.665 41.5 24C41.5 14.335 33.665 6.5 24 6.5ZM24.25 32C25.0784 32 25.75 32.6716 25.75 33.5C25.75 34.3284 25.0784 35 24.25 35C23.4216 35 22.75 34.3284 22.75 33.5C22.75 32.6716 23.4216 32 24.25 32ZM24.25 13C27.6147 13 30.5 15.8821 30.5 19.2488C30.502 21.3691 29.7314 22.7192 27.8216 24.7772L26.8066 25.8638C25.7842 27.0028 25.3794 27.7252 25.3409 28.5793L25.3379 28.7411L25.3323 28.8689L25.3143 28.9932C25.2018 29.5636 24.7009 29.9957 24.0968 30.0001C23.4065 30.0049 22.8428 29.4493 22.8379 28.7589C22.8251 26.9703 23.5147 25.7467 25.1461 23.9739L26.1734 22.8762C27.5312 21.3837 28.0012 20.503 28 19.25C28 17.2634 26.2346 15.5 24.25 15.5C22.3307 15.5 20.6142 17.1536 20.5055 19.0587L20.4935 19.3778C20.4295 20.0081 19.8972 20.5 19.25 20.5C18.5596 20.5 18 19.9404 18 19.25C18 15.8846 20.8864 13 24.25 13Z"; - + public static FuncValueConverter IconConverter { get; } = new(iconKey => { diff --git a/Nebula.Launcher/GlobalUsing.cs b/Nebula.Launcher/GlobalUsing.cs new file mode 100644 index 0000000..895122c --- /dev/null +++ b/Nebula.Launcher/GlobalUsing.cs @@ -0,0 +1,2 @@ +global using SourceGen; +global using Nebula.Launcher.ViewHelper; \ No newline at end of file diff --git a/Nebula.Launcher/Nebula.Launcher.csproj b/Nebula.Launcher/Nebula.Launcher.csproj index 3392f9d..dd855bf 100644 --- a/Nebula.Launcher/Nebula.Launcher.csproj +++ b/Nebula.Launcher/Nebula.Launcher.csproj @@ -10,33 +10,33 @@ - + - - - - - + + + + + None All - - - - + + + + - - ServerListTab.axaml - Code - + + ServerListTab.axaml + Code + - + @@ -45,6 +45,7 @@ - + + diff --git a/Nebula.Launcher/Program.cs b/Nebula.Launcher/Program.cs index 987e1bb..db6eff8 100644 --- a/Nebula.Launcher/Program.cs +++ b/Nebula.Launcher/Program.cs @@ -4,13 +4,18 @@ namespace Nebula.Launcher; public static class Program { - public static void Main(string[] args) => BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); + public static void Main(string[] args) + { + BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + } // Avalonia configuration, don't remove; also used by visual designer. private static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() + { + return AppBuilder.Configure() .UsePlatformDetect() .WithInterFont() .LogToTrace(); + } } \ No newline at end of file diff --git a/Nebula.Launcher/ServiceCollectionExtensions.cs b/Nebula.Launcher/ServiceCollectionExtensions.cs index e15a463..3e7a4d1 100644 --- a/Nebula.Launcher/ServiceCollectionExtensions.cs +++ b/Nebula.Launcher/ServiceCollectionExtensions.cs @@ -6,10 +6,7 @@ using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Threading; using Microsoft.Extensions.DependencyInjection; -using Nebula.Launcher.ViewHelper; -using Nebula.Launcher.ViewModels; using Nebula.Launcher.Views; -using Nebula.Launcher.Views.Pages; namespace Nebula.Launcher; @@ -18,14 +15,20 @@ public static class ServiceCollectionExtensions public static void AddAvaloniaServices(this IServiceCollection services) { services.AddSingleton(_ => Dispatcher.UIThread); - services.AddSingleton(_ => Application.Current?.ApplicationLifetime ?? throw new InvalidOperationException("No application lifetime is set")); + services.AddSingleton(_ => + Application.Current?.ApplicationLifetime ?? + throw new InvalidOperationException("No application lifetime is set")); services.AddSingleton(sp => sp.GetRequiredService() switch { - IClassicDesktopStyleApplicationLifetime desktop => desktop.MainWindow ?? throw new InvalidOperationException("No main window set"), - ISingleViewApplicationLifetime singleViewPlatform => TopLevel.GetTopLevel(singleViewPlatform.MainView) ?? throw new InvalidOperationException("Could not find top level element for single view"), - _ => throw new InvalidOperationException($"Could not find {nameof(TopLevel)} element"), + IClassicDesktopStyleApplicationLifetime desktop => desktop.MainWindow ?? + throw new InvalidOperationException( + "No main window set"), + ISingleViewApplicationLifetime singleViewPlatform => + TopLevel.GetTopLevel(singleViewPlatform.MainView) ?? + throw new InvalidOperationException("Could not find top level element for single view"), + _ => throw new InvalidOperationException($"Could not find {nameof(TopLevel)} element") } ); @@ -38,20 +41,18 @@ public static class ServiceCollectionExtensions foreach (var (viewModel, view, isSingleton) in GetTypesWithHelpAttribute(Assembly.GetExecutingAssembly())) { - if(isSingleton)services.AddSingleton(viewModel); + if (isSingleton) services.AddSingleton(viewModel); else services.AddTransient(viewModel); if (view != null) services.AddTransient(view); } } - - private static IEnumerable<(Type,Type?,bool)> GetTypesWithHelpAttribute(Assembly assembly) { - foreach(Type type in assembly.GetTypes()) + + private static IEnumerable<(Type, Type?, bool)> GetTypesWithHelpAttribute(Assembly assembly) + { + foreach (var type in assembly.GetTypes()) { var attr = type.GetCustomAttribute(); - if (attr is not null) { - yield return (type, attr.Type, attr.IsSingleton); - } + if (attr is not null) yield return (type, attr.Type, attr.IsSingleton); } } -} - +} \ No newline at end of file diff --git a/Nebula.Launcher/Services/ViewHelperService.cs b/Nebula.Launcher/Services/ViewHelperService.cs new file mode 100644 index 0000000..4242c40 --- /dev/null +++ b/Nebula.Launcher/Services/ViewHelperService.cs @@ -0,0 +1,42 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Avalonia.Controls; +using Nebula.Launcher.ViewModels; +using Nebula.Shared; + +namespace Nebula.Launcher.Services; + +[ServiceRegister, ConstructGenerator] +public sealed partial class ViewHelperService +{ + [GenerateProperty] private IServiceProvider ServiceProvider { get; } = default!; + + public bool TryGetViewModel(Type type, [NotNullWhen(true)] out ViewModelBase? viewModelBase) + { + viewModelBase = null; + var vm = Design.IsDesignMode + ? Activator.CreateInstance(type) + : ServiceProvider.GetService(type); + + if (vm is not ViewModelBase vmb) return false; + + viewModelBase = vmb; + return true; + } + + public bool TryGetViewModel([NotNullWhen(true)] out T? viewModelBase) where T : ViewModelBase + { + var success = TryGetViewModel(typeof(T), out var vmb); + viewModelBase = (T?)vmb; + return success; + } + + public T GetViewModel() where T : ViewModelBase + { + TryGetViewModel(out var viewModelBase); + return viewModelBase!; + } + + private void Initialise(){} + private void InitialiseInDesignMode(){} +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewHelper/ViewModelRegisterAttribute.cs b/Nebula.Launcher/ViewHelper/ViewModelRegisterAttribute.cs index f5e2774..7757113 100644 --- a/Nebula.Launcher/ViewHelper/ViewModelRegisterAttribute.cs +++ b/Nebula.Launcher/ViewHelper/ViewModelRegisterAttribute.cs @@ -5,12 +5,12 @@ namespace Nebula.Launcher.ViewHelper; [AttributeUsage(AttributeTargets.Class)] public class ViewModelRegisterAttribute : Attribute { - public Type? Type { get; } - public bool IsSingleton { get; } - public ViewModelRegisterAttribute(Type? type = null, bool isSingleton = true) { Type = type; IsSingleton = isSingleton; } + + public Type? Type { get; } + public bool IsSingleton { get; } } \ No newline at end of file diff --git a/Nebula.Launcher/ViewLocator.cs b/Nebula.Launcher/ViewLocator.cs index 471747e..0329e76 100644 --- a/Nebula.Launcher/ViewLocator.cs +++ b/Nebula.Launcher/ViewLocator.cs @@ -2,7 +2,6 @@ using System; using System.Reflection; using Avalonia.Controls; using Avalonia.Controls.Templates; -using Nebula.Launcher.ViewHelper; using Nebula.Launcher.ViewModels; namespace Nebula.Launcher; @@ -13,15 +12,12 @@ public class ViewLocator : IDataTemplate { if (param is null) return null; - + var type = param.GetType().GetCustomAttribute()?.Type; - if (type != null) - { - return (Control)Activator.CreateInstance(type)!; - } + if (type != null) return (Control)Activator.CreateInstance(type)!; - return new TextBlock { Text = "Not Found: " + param.GetType()}; + return new TextBlock { Text = "Not Found: " + param.GetType() }; } public bool Match(object? data) diff --git a/Nebula.Launcher/ViewModels/InfoPopupViewModel.cs b/Nebula.Launcher/ViewModels/InfoPopupViewModel.cs deleted file mode 100644 index 7ded051..0000000 --- a/Nebula.Launcher/ViewModels/InfoPopupViewModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using CommunityToolkit.Mvvm.ComponentModel; -using Nebula.Launcher.ViewHelper; -using Nebula.Launcher.Views.Popup; - -namespace Nebula.Launcher.ViewModels; - -[ViewModelRegister(typeof(InfoPopupView), false)] -public partial class InfoPopupViewModel : PopupViewModelBase -{ - public InfoPopupViewModel() - { - } - - public InfoPopupViewModel(IServiceProvider serviceProvider) : base(serviceProvider) - { - } - - public override string Title => "Info"; - public override bool IsClosable => true; - - [ObservableProperty] - private string _infoText = "Test"; -} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/MainViewModel.cs b/Nebula.Launcher/ViewModels/MainViewModel.cs index afdb140..52faa0a 100644 --- a/Nebula.Launcher/ViewModels/MainViewModel.cs +++ b/Nebula.Launcher/ViewModels/MainViewModel.cs @@ -4,8 +4,9 @@ using System.Collections.ObjectModel; using System.Linq; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using JetBrains.Annotations; -using Nebula.Launcher.ViewHelper; +using Nebula.Launcher.Services; +using Nebula.Launcher.ViewModels.Pages; +using Nebula.Launcher.ViewModels.Popup; using Nebula.Launcher.Views; using Nebula.Shared.Models; using Nebula.Shared.Services; @@ -14,34 +15,9 @@ using Nebula.Shared.Utils; namespace Nebula.Launcher.ViewModels; [ViewModelRegister(typeof(MainView))] +[ConstructGenerator] public partial class MainViewModel : ViewModelBase { - public MainViewModel() - { - TryGetViewModel(typeof(AccountInfoViewModel), out var model); - _currentPage = model!; - - Items = new ObservableCollection(_templates); - - SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel)); - } - - [UsedImplicitly] - public MainViewModel(AccountInfoViewModel accountInfoViewModel,DebugService debugService, PopupMessageService popupMessageService, - IServiceProvider serviceProvider): base(serviceProvider) - { - _currentPage = accountInfoViewModel; - _debugService = debugService; - Items = new ObservableCollection(_templates); - - popupMessageService.OnPopupRequired += OnPopupRequired; - popupMessageService.OnCloseRequired += OnPopupCloseRequired; - - SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel)); - } - - private readonly List _viewQueue = new(); - private readonly List _templates = [ new ListItemTemplate(typeof(AccountInfoViewModel), "Account", "Account"), @@ -49,41 +25,57 @@ public partial class MainViewModel : ViewModelBase new ListItemTemplate(typeof(ContentBrowserViewModel), "GridRegular", "Content") ]; - [ObservableProperty] - private bool _isPaneOpen; + private readonly List _viewQueue = new(); - [ObservableProperty] - private ViewModelBase _currentPage; + [ObservableProperty] private ViewModelBase _currentPage; - private readonly DebugService _debugService; + [ObservableProperty] private PopupViewModelBase? _currentPopup; + + [ObservableProperty] private string _currentTitle = "Default"; [ObservableProperty] private bool _isEnabled = true; - [ObservableProperty] private bool _popup; - - [ObservableProperty] - private PopupViewModelBase? _currentPopup; - [ObservableProperty] - private string _currentTitle = "Default"; + + [ObservableProperty] private bool _isPaneOpen; [ObservableProperty] private bool _isPopupClosable = true; + [ObservableProperty] private bool _popup; - [ObservableProperty] - private ListItemTemplate? _selectedListItem; + [ObservableProperty] private ListItemTemplate? _selectedListItem; + + [GenerateProperty] private DebugService DebugService { get; } = default!; + [GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!; + [GenerateProperty] private ViewHelperService ViewHelperService { get; } = default!; + + public ObservableCollection Items { get; private set; } + + protected override void InitialiseInDesignMode() + { + CurrentPage = ViewHelperService.GetViewModel(); + Items = new ObservableCollection(_templates); + SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel)); + } + + protected override void Initialise() + { + CurrentPage = ViewHelperService.GetViewModel(); + + Items = new ObservableCollection(_templates); + + PopupMessageService.OnPopupRequired += OnPopupRequired; + PopupMessageService.OnCloseRequired += OnPopupCloseRequired; + + SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel)); + } partial void OnSelectedListItemChanged(ListItemTemplate? value) { if (value is null) return; - if(!TryGetViewModel(value.ModelType, out var vmb)) - { - return; - } - + if (!ViewHelperService.TryGetViewModel(value.ModelType, out var vmb)) return; + CurrentPage = vmb; } - public ObservableCollection Items { get; } - public void PopupMessage(PopupViewModelBase viewModelBase) { if (CurrentPopup == null) @@ -98,7 +90,7 @@ public partial class MainViewModel : ViewModelBase _viewQueue.Add(viewModelBase); } } - + private void OnCloseRequired() { IsEnabled = true; @@ -122,7 +114,7 @@ public partial class MainViewModel : ViewModelBase { case string str: { - var view = GetViewModel(); + var view = ViewHelperService.GetViewModel(); view.InfoText = str; PopupMessage(view); break; @@ -131,21 +123,18 @@ public partial class MainViewModel : ViewModelBase PopupMessage(@base); break; case Exception error: - var err = GetViewModel(); - _debugService.Error(error); + var err = ViewHelperService.GetViewModel(); + DebugService.Error(error); err.AppendError(error); PopupMessage(err); break; } } - + private void OnPopupCloseRequired(object obj) { - if(obj is not PopupViewModelBase viewModelBase) - { - return; - } - + if (obj is not PopupViewModelBase viewModelBase) return; + if (obj == CurrentPopup) ClosePopup(); else @@ -158,20 +147,21 @@ public partial class MainViewModel : ViewModelBase { IsPaneOpen = !IsPaneOpen; } - + [RelayCommand] public void ClosePopup() { var viewModelBase = _viewQueue.FirstOrDefault(); if (viewModelBase is null) + { OnCloseRequired(); + } else { CurrentTitle = viewModelBase.Title; _viewQueue.RemoveAt(0); } - + CurrentPopup = viewModelBase; } -} - +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/AccountInfoViewModel.cs b/Nebula.Launcher/ViewModels/Pages/AccountInfoViewModel.cs similarity index 58% rename from Nebula.Launcher/ViewModels/AccountInfoViewModel.cs rename to Nebula.Launcher/ViewModels/Pages/AccountInfoViewModel.cs index c771660..87bae81 100644 --- a/Nebula.Launcher/ViewModels/AccountInfoViewModel.cs +++ b/Nebula.Launcher/ViewModels/Pages/AccountInfoViewModel.cs @@ -1,46 +1,44 @@ -using System; using System.Collections.ObjectModel; using System.Linq; using System.Windows.Input; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using Nebula.Launcher.ViewHelper; +using Nebula.Launcher.Services; +using Nebula.Launcher.ViewModels.Popup; using Nebula.Launcher.Views.Pages; using Nebula.Shared; using Nebula.Shared.Services; using Nebula.Shared.Utils; -namespace Nebula.Launcher.ViewModels; +namespace Nebula.Launcher.ViewModels.Pages; [ViewModelRegister(typeof(AccountInfoView))] +[ConstructGenerator] public partial class AccountInfoViewModel : ViewModelBase { - private readonly PopupMessageService _popupMessageService; - private readonly ConfigurationService _configurationService; - private readonly AuthService _authService; - - public ObservableCollection Accounts { get; } = new(); - public ObservableCollection AuthUrls { get; } = new(); - - [ObservableProperty] - private string _currentLogin = String.Empty; - - [ObservableProperty] - private string _currentPassword = String.Empty; - - [ObservableProperty] - private string _currentAuthServer = String.Empty; + [ObservableProperty] private bool _authMenuExpand; [ObservableProperty] private bool _authUrlConfigExpand; [ObservableProperty] private int _authViewSpan = 1; - - [ObservableProperty] private bool _authMenuExpand; - private bool _isProfilesEmpty; + [ObservableProperty] private string _currentAuthServer = string.Empty; + + [ObservableProperty] private string _currentLogin = string.Empty; + + [ObservableProperty] private string _currentPassword = string.Empty; [ObservableProperty] private bool _isLogged; + private bool _isProfilesEmpty; + [GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!; + [GenerateProperty] private ConfigurationService ConfigurationService { get; } = default!; + [GenerateProperty] private AuthService AuthService { get; } = default!; + [GenerateProperty] private ViewHelperService ViewHelperService { get; } = default!; + + public ObservableCollection Accounts { get; } = new(); + public ObservableCollection AuthUrls { get; } = new(); + private AuthLoginPassword CurrentAlp { get => new(CurrentLogin, CurrentPassword, CurrentAuthServer); @@ -51,24 +49,23 @@ public partial class AccountInfoViewModel : ViewModelBase CurrentAuthServer = value.AuthServer; } } - - //Design think - public AccountInfoViewModel() + + public string AuthItemSelect { - AddAccount(new AuthLoginPassword("Binka","12341","")); + set => CurrentAuthServer = value; + } + + //Design think + protected override void InitialiseInDesignMode() + { + AddAccount(new AuthLoginPassword("Binka", "12341", "")); AuthUrls.Add("https://cinka.ru"); AuthUrls.Add("https://cinka.ru"); } - - //Real think - public AccountInfoViewModel(IServiceProvider serviceProvider, PopupMessageService popupMessageService, - ConfigurationService configurationService, AuthService authService) : base(serviceProvider) - { - //_popupMessageService = mainViewModel; - _popupMessageService = popupMessageService; - _configurationService = configurationService; - _authService = authService; + //Real think + protected override void Initialise() + { ReadAuthConfig(); } @@ -80,88 +77,75 @@ public partial class AccountInfoViewModel : ViewModelBase public async void DoAuth() { - var message = GetViewModel(); + var message = ViewHelperService.GetViewModel(); message.InfoText = "Auth think, please wait..."; - _popupMessageService.Popup(message); - - if(await _authService.Auth(CurrentAlp)) + PopupMessageService.Popup(message); + + if (await AuthService.Auth(CurrentAlp)) { message.Dispose(); IsLogged = true; - _configurationService.SetConfigValue(CurrentConVar.AuthCurrent, CurrentAlp); + ConfigurationService.SetConfigValue(CurrentConVar.AuthCurrent, CurrentAlp); } else { message.Dispose(); Logout(); - _popupMessageService.Popup("Well, shit is happened: " + _authService.Reason); + PopupMessageService.Popup("Well, shit is happened: " + AuthService.Reason); } } public void Logout() { IsLogged = false; - //CurrentAlp = new AuthLoginPassword("", "", ""); - _authService.ClearAuth(); + AuthService.ClearAuth(); } private void UpdateAuthMenu() { if (AuthMenuExpand || _isProfilesEmpty) - { AuthViewSpan = 2; - } else - { AuthViewSpan = 1; - } } private void AddAccount(AuthLoginPassword authLoginPassword) { var onDelete = new DelegateCommand(OnDeleteProfile); var onSelect = new DelegateCommand(AuthByAlp); - + var alpm = new AuthLoginPasswordModel( - authLoginPassword.Login, + authLoginPassword.Login, authLoginPassword.Password, - authLoginPassword.AuthServer, - onSelect, + authLoginPassword.AuthServer, + onSelect, onDelete); onDelete.TRef.Value = alpm; onSelect.TRef.Value = alpm; - + Accounts.Add(alpm); } private void ReadAuthConfig() { - foreach (var profile in - _configurationService.GetConfigValue(CurrentConVar.AuthProfiles)!) - { + foreach (var profile in + ConfigurationService.GetConfigValue(CurrentConVar.AuthProfiles)!) AddAccount(profile); - } - if (Accounts.Count == 0) - { - UpdateAuthMenu(); - } + if (Accounts.Count == 0) UpdateAuthMenu(); - var currProfile = _configurationService.GetConfigValue(CurrentConVar.AuthCurrent); + var currProfile = ConfigurationService.GetConfigValue(CurrentConVar.AuthCurrent); if (currProfile != null) { CurrentAlp = currProfile; DoAuth(); } - + AuthUrls.Clear(); - var authUrls = _configurationService.GetConfigValue(CurrentConVar.AuthServers)!; - foreach (var url in authUrls) - { - AuthUrls.Add(url); - } + var authUrls = ConfigurationService.GetConfigValue(CurrentConVar.AuthServers)!; + foreach (var url in authUrls) AuthUrls.Add(url); } [RelayCommand] @@ -172,7 +156,7 @@ public partial class AccountInfoViewModel : ViewModelBase UpdateAuthMenu(); DirtyProfile(); } - + private void OnDeleteProfile(AuthLoginPasswordModel account) { Accounts.Remove(account); @@ -196,15 +180,15 @@ public partial class AccountInfoViewModel : ViewModelBase private void DirtyProfile() { - _configurationService.SetConfigValue(CurrentConVar.AuthProfiles, - Accounts.Select(a => (AuthLoginPassword) a).ToArray()); - } - - public string AuthItemSelect - { - set => CurrentAuthServer = value; + ConfigurationService.SetConfigValue(CurrentConVar.AuthProfiles, + Accounts.Select(a => (AuthLoginPassword)a).ToArray()); } } -public record AuthLoginPasswordModel(string Login, string Password, string AuthServer, ICommand OnSelect = default!, ICommand OnDelete = default!) +public record AuthLoginPasswordModel( + string Login, + string Password, + string AuthServer, + ICommand OnSelect = default!, + ICommand OnDelete = default!) : AuthLoginPassword(Login, Password, AuthServer); \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/ContentBrowserViewModel.cs b/Nebula.Launcher/ViewModels/Pages/ContentBrowserViewModel.cs similarity index 67% rename from Nebula.Launcher/ViewModels/ContentBrowserViewModel.cs rename to Nebula.Launcher/ViewModels/Pages/ContentBrowserViewModel.cs index 768f8f5..31e2385 100644 --- a/Nebula.Launcher/ViewModels/ContentBrowserViewModel.cs +++ b/Nebula.Launcher/ViewModels/Pages/ContentBrowserViewModel.cs @@ -11,35 +11,37 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Avalonia.Platform; using CommunityToolkit.Mvvm.ComponentModel; -using Microsoft.Extensions.DependencyInjection; -using Nebula.Launcher.ViewHelper; +using Nebula.Launcher.Services; +using Nebula.Launcher.ViewModels.Popup; using Nebula.Launcher.Views.Pages; -using Nebula.Shared; using Nebula.Shared.Models; using Nebula.Shared.Services; using Nebula.Shared.Utils; -namespace Nebula.Launcher.ViewModels; +namespace Nebula.Launcher.ViewModels.Pages; [ViewModelRegister(typeof(ContentBrowserView))] +[ConstructGenerator] public sealed partial class ContentBrowserViewModel : ViewModelBase { - private readonly IServiceProvider _provider; - private readonly ContentService _contentService; - private readonly CancellationService _cancellationService; - private readonly FileService _fileService; - private readonly DebugService _debugService; - private readonly PopupMessageService _popupService; - public ObservableCollection Entries { get; } = new(); private readonly List _root = new(); - private List _history = new(); - + private readonly List _history = new(); + [ObservableProperty] private string _message = ""; [ObservableProperty] private string _searchText = ""; - [ObservableProperty] private string _serverText = ""; private ContentEntry? _selectedEntry; + [ObservableProperty] private string _serverText = ""; + [GenerateProperty] private ContentService ContentService { get; } = default!; + [GenerateProperty] private CancellationService CancellationService { get; } = default!; + [GenerateProperty] private FileService FileService { get; } = default!; + [GenerateProperty] private DebugService DebugService { get; } = default!; + [GenerateProperty] private PopupMessageService PopupService { get; } = default!; + [GenerateProperty] private HubService HubService { get; } = default!; + [GenerateProperty] private ViewHelperService ViewHelperService { get; } = default!; + + public ObservableCollection Entries { get; } = new(); public ContentEntry? SelectedEntry { @@ -48,94 +50,73 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase { if (value is { Item: not null }) { - if (_fileService.ContentFileApi.TryOpen(value.Item.Value.Hash, out var stream)) + if (FileService.ContentFileApi.TryOpen(value.Item.Value.Hash, out var stream)) { var ext = Path.GetExtension(value.Item.Value.Path); - - var myTempFile = Path.Combine(Path.GetTempPath(), "tempie"+ ext); - - using(var sw = new FileStream(myTempFile, FileMode.Create, FileAccess.Write, FileShare.None)) + + var myTempFile = Path.Combine(Path.GetTempPath(), "tempie" + ext); + + using (var sw = new FileStream(myTempFile, FileMode.Create, FileAccess.Write, FileShare.None)) { stream.CopyTo(sw); } + stream.Dispose(); - + var startInfo = new ProcessStartInfo(myTempFile) { - UseShellExecute = true + UseShellExecute = true }; Process.Start(startInfo); } + return; } - + Entries.Clear(); _selectedEntry = value; if (value == null) return; - - foreach (var (_, entryCh) in value.Childs) - { - Entries.Add(entryCh); - } + + foreach (var (_, entryCh) in value.Childs) Entries.Add(entryCh); } } - public ContentBrowserViewModel() : base() + protected override void InitialiseInDesignMode() { - var a = new ContentEntry(this, "A:","A", ""); - var b = new ContentEntry(this, "B","B", ""); + var a = new ContentEntry(this, "A:", "A", ""); + var b = new ContentEntry(this, "B", "B", ""); a.TryAddChild(b); - Entries.Add(a); + Entries.Add(a); } - public ContentBrowserViewModel(IServiceProvider provider, ContentService contentService, CancellationService cancellationService, - FileService fileService, HubService hubService, DebugService debugService, PopupMessageService popupService) : base(provider) + protected override void Initialise() { - _provider = provider; - _contentService = contentService; - _cancellationService = cancellationService; - _fileService = fileService; - _debugService = debugService; - _popupService = popupService; - - FillRoot(hubService.ServerList); + FillRoot(HubService.ServerList); - hubService.HubServerChangedEventArgs += HubServerChangedEventArgs; - hubService.HubServerLoaded += GoHome; - - if (!hubService.IsUpdating) - { - GoHome(); - } + HubService.HubServerChangedEventArgs += HubServerChangedEventArgs; + HubService.HubServerLoaded += GoHome; + + if (!HubService.IsUpdating) GoHome(); } private void GoHome() { SelectedEntry = null; - foreach (var entry in _root) - { - Entries.Add(entry); - } + foreach (var entry in _root) Entries.Add(entry); } private void HubServerChangedEventArgs(HubServerChangedEventArgs obj) { - if(obj.Action == HubServerChangeAction.Clear) _root.Clear(); - if (obj.Action == HubServerChangeAction.Add) - { - FillRoot(obj.Items); - }; + if (obj.Action == HubServerChangeAction.Clear) _root.Clear(); + if (obj.Action == HubServerChangeAction.Add) FillRoot(obj.Items); } private void FillRoot(IEnumerable infos) { - foreach (var info in infos) - { - _root.Add(new ContentEntry(this, info.StatusData.Name,info.Address,info.Address)); - } + foreach (var info in infos) _root.Add(new ContentEntry(this, info.StatusData.Name, info.Address, info.Address)); } public async void Go(ContentPath path, bool appendHistory = true) @@ -145,42 +126,34 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase ServerText = path.Pathes[0]; path = new ContentPath(""); } - + if (string.IsNullOrEmpty(ServerText)) { SearchText = ""; GoHome(); return; } - - if (ServerText != SelectedEntry?.ServerName) - { - SelectedEntry = await CreateEntry(ServerText); - } - - _debugService.Debug("Going to:" + path.Path); - + + if (ServerText != SelectedEntry?.ServerName) SelectedEntry = await CreateEntry(ServerText); + + DebugService.Debug("Going to:" + path.Path); + var oriPath = path.Clone(); try { if (SelectedEntry == null || !SelectedEntry.GetRoot().TryGetEntry(path, out var centry)) - { throw new Exception("Not found! " + oriPath.Path); - } - - if (appendHistory) - { - AppendHistory(SearchText); - } + + if (appendHistory) AppendHistory(SearchText); SearchText = oriPath.Path; - + SelectedEntry = centry; } catch (Exception e) { Console.WriteLine(e); SearchText = oriPath.Path; - _popupService.Popup(e); + PopupService.Popup(e); } } @@ -189,7 +162,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase { Go(new ContentPath(GetHistory()), false); } - + public void OnGoEnter() { Go(new ContentPath(SearchText)); @@ -198,21 +171,21 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase private async Task CreateEntry(string serverUrl) { var rurl = serverUrl.ToRobustUrl(); - var info = await _contentService.GetBuildInfo(rurl, _cancellationService.Token); - var loading = _provider.GetService()!; + var info = await ContentService.GetBuildInfo(rurl, CancellationService.Token); + var loading = ViewHelperService.GetViewModel(); loading.LoadingName = "Loading entry"; - _popupService.Popup(loading); - var items = await _contentService.EnsureItems(info.RobustManifestInfo, loading, - _cancellationService.Token); + PopupService.Popup(loading); + var items = await ContentService.EnsureItems(info.RobustManifestInfo, loading, + CancellationService.Token); - var rootEntry = new ContentEntry(this,"","", serverUrl); + var rootEntry = new ContentEntry(this, "", "", serverUrl); foreach (var item in items) { var path = new ContentPath(item.Path); rootEntry.CreateItem(path, item); } - + loading.Dispose(); return rootEntry; @@ -220,7 +193,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase private void AppendHistory(string str) { - if(_history.Count >= 10) _history.RemoveAt(9); + if (_history.Count >= 10) _history.RemoveAt(9); _history.Insert(0, str); } @@ -235,41 +208,13 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase public class ContentEntry { - private readonly ContentBrowserViewModel _viewModel; - public static IImage DirImage = new Bitmap(AssetLoader.Open(new Uri("avares://Nebula.Launcher/Assets/dir.png"))); public static IImage IconImage = new Bitmap(AssetLoader.Open(new Uri("avares://Nebula.Launcher/Assets/file.png"))); - public RobustManifestItem? Item; - public bool IsDirectory => Item == null; - - public string Name { get; private set; } - public string PathName { get; private set; } - public string ServerName { get; private set; } - public IImage IconPath { get; set; } = DirImage; - - public ContentEntry? Parent { get; private set; } - public bool IsRoot => Parent == null; - private readonly Dictionary _childs = new(); + private readonly ContentBrowserViewModel _viewModel; - public IReadOnlyDictionary Childs => _childs.ToFrozenDictionary(); - - public bool TryGetChild(string name,[NotNullWhen(true)] out ContentEntry? child) - { - return _childs.TryGetValue(name, out child); - } - - public bool TryAddChild(ContentEntry contentEntry) - { - if(_childs.TryAdd(contentEntry.PathName, contentEntry)) - { - contentEntry.Parent = this; - return true; - } - - return false; - } + public RobustManifestItem? Item; internal ContentEntry(ContentBrowserViewModel viewModel, string name, string pathName, string serverName) { @@ -279,6 +224,34 @@ public class ContentEntry _viewModel = viewModel; } + public bool IsDirectory => Item == null; + + public string Name { get; private set; } + public string PathName { get; } + public string ServerName { get; } + public IImage IconPath { get; set; } = DirImage; + + public ContentEntry? Parent { get; private set; } + public bool IsRoot => Parent == null; + + public IReadOnlyDictionary Childs => _childs.ToFrozenDictionary(); + + public bool TryGetChild(string name, [NotNullWhen(true)] out ContentEntry? child) + { + return _childs.TryGetValue(name, out child); + } + + public bool TryAddChild(ContentEntry contentEntry) + { + if (_childs.TryAdd(contentEntry.PathName, contentEntry)) + { + contentEntry.Parent = this; + return true; + } + + return false; + } + public ContentPath GetPath() { if (Parent != null) @@ -287,6 +260,7 @@ public class ContentEntry path.Pathes.Add(PathName); return path; } + return new ContentPath([PathName]); } @@ -295,8 +269,8 @@ public class ContentEntry if (rootPath.Pathes.Count == 0) return this; var fName = rootPath.GetNext(); - - if(!TryGetChild(fName, out var child)) + + if (!TryGetChild(fName, out var child)) { child = new ContentEntry(_viewModel, fName, fName, ServerName); TryAddChild(child); @@ -321,7 +295,7 @@ public class ContentEntry { Item = item }; - + dirEntry.TryAddChild(entry); entry.IconPath = IconImage; return entry; @@ -330,7 +304,7 @@ public class ContentEntry public bool TryGetEntry(ContentPath path, out ContentEntry? entry) { entry = null; - + if (path.Pathes.Count == 0) { entry = this; @@ -338,11 +312,8 @@ public class ContentEntry } var fName = path.GetNext(); - - if(!TryGetChild(fName, out var child)) - { - return false; - } + + if (!TryGetChild(fName, out var child)) return false; return child.TryGetEntry(path, out entry); } @@ -353,14 +324,13 @@ public class ContentEntry } } - public struct ContentPath { - public List Pathes { get; private set; } + public List Pathes { get; } public ContentPath(List pathes) { - Pathes = pathes ?? new List(); + Pathes = pathes; } public ContentPath(string path) diff --git a/Nebula.Launcher/ViewModels/FavoriteServerListViewModel.cs b/Nebula.Launcher/ViewModels/Pages/FavoriteServerListViewModel.cs similarity index 50% rename from Nebula.Launcher/ViewModels/FavoriteServerListViewModel.cs rename to Nebula.Launcher/ViewModels/Pages/FavoriteServerListViewModel.cs index f202e9c..3fea05b 100644 --- a/Nebula.Launcher/ViewModels/FavoriteServerListViewModel.cs +++ b/Nebula.Launcher/ViewModels/Pages/FavoriteServerListViewModel.cs @@ -1,13 +1,17 @@ -using System; using System.Collections.ObjectModel; using Nebula.Shared.Models; -namespace Nebula.Launcher.ViewModels; +namespace Nebula.Launcher.ViewModels.Pages; public class FavoriteServerListViewModel : ViewModelBase { - public FavoriteServerListViewModel() : base(){} - public FavoriteServerListViewModel(IServiceProvider provider) : base(provider){} - public ObservableCollection Servers = new(); + + protected override void Initialise() + { + } + + protected override void InitialiseInDesignMode() + { + } } \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/ServerListViewModel.cs b/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs similarity index 62% rename from Nebula.Launcher/ViewModels/ServerListViewModel.cs rename to Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs index 7f7f41b..9a46f31 100644 --- a/Nebula.Launcher/ViewModels/ServerListViewModel.cs +++ b/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs @@ -4,50 +4,42 @@ using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; -using Nebula.Launcher.ViewHelper; +using Nebula.Launcher.Services; using Nebula.Launcher.Views.Pages; using Nebula.Shared.Models; using Nebula.Shared.Services; -namespace Nebula.Launcher.ViewModels; +namespace Nebula.Launcher.ViewModels.Pages; [ViewModelRegister(typeof(ServerListView))] +[ConstructGenerator] public partial class ServerListViewModel : ViewModelBase { - private readonly IServiceProvider _serviceProvider; - private readonly HubService _hubService; - public ObservableCollection ServerInfos { get; } = new(); + [ObservableProperty] private string _searchText = string.Empty; public Action? OnSearchChange; - - [ObservableProperty] private string _searchText; + [GenerateProperty] private HubService HubService { get; } = default!; + [GenerateProperty] private ViewHelperService ViewHelperService { get; } = default!; + public ObservableCollection ServerInfos { get; } = new(); private List UnsortedServers { get; } = new(); - + //Design think - public ServerListViewModel() + protected override void InitialiseInDesignMode() { - ServerInfos.Add(CreateServerView(new ServerHubInfo("ss14://localhost",new ServerStatus("Nebula","TestCraft", ["16+","RU"], "super", 12,55,1,false,DateTime.Now, 20),[]))); + ServerInfos.Add(CreateServerView(new ServerHubInfo("ss14://localhost", + new ServerStatus("Nebula", "TestCraft", ["16+", "RU"], "super", 12, 55, 1, false, DateTime.Now, 20), []))); } - + //real think - public ServerListViewModel(IServiceProvider serviceProvider, HubService hubService) : base(serviceProvider) + protected override void Initialise() { - _serviceProvider = serviceProvider; - _hubService = hubService; - - foreach (var info in _hubService.ServerList) - { - UnsortedServers.Add(info); - } - - hubService.HubServerChangedEventArgs += HubServerChangedEventArgs; - hubService.HubServerLoaded += HubServerLoaded; + foreach (var info in HubService.ServerList) UnsortedServers.Add(info); + + HubService.HubServerChangedEventArgs += HubServerChangedEventArgs; + HubService.HubServerLoaded += HubServerLoaded; OnSearchChange += OnChangeSearch; - if (!hubService.IsUpdating) - { - SortServers(); - } + if (!HubService.IsUpdating) SortServers(); } private void HubServerLoaded() @@ -63,23 +55,12 @@ public partial class ServerListViewModel : ViewModelBase private void HubServerChangedEventArgs(HubServerChangedEventArgs obj) { if (obj.Action == HubServerChangeAction.Add) - { foreach (var info in obj.Items) - { UnsortedServers.Add(info); - } - } - if(obj.Action == HubServerChangeAction.Remove) - { + if (obj.Action == HubServerChangeAction.Remove) foreach (var info in obj.Items) - { UnsortedServers.Remove(info); - } - } - if(obj.Action == HubServerChangeAction.Clear) - { - UnsortedServers.Clear(); - } + if (obj.Action == HubServerChangeAction.Clear) UnsortedServers.Clear(); } private void SortServers() @@ -88,10 +69,7 @@ public partial class ServerListViewModel : ViewModelBase { ServerInfos.Clear(); UnsortedServers.Sort(new ServerComparer()); - foreach (var server in UnsortedServers.Where(CheckServerThink)) - { - ServerInfos.Add(CreateServerView(server)); - } + foreach (var server in UnsortedServers.Where(CheckServerThink)) ServerInfos.Add(CreateServerView(server)); }); } @@ -103,19 +81,18 @@ public partial class ServerListViewModel : ViewModelBase private ServerEntryModelView CreateServerView(ServerHubInfo serverHubInfo) { - var svn = GetViewModel(); + var svn = ViewHelperService.GetViewModel(); svn.ServerHubInfo = serverHubInfo; return svn; } public void FilterRequired() { - } public void UpdateRequired() { - Task.Run(_hubService.UpdateHub); + Task.Run(HubService.UpdateHub); } } @@ -131,6 +108,5 @@ public class ServerComparer : IComparer return -1; return y.StatusData.Players.CompareTo(x.StatusData.Players); - } } \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/ExceptionViewModel.cs b/Nebula.Launcher/ViewModels/Popup/ExceptionViewModel.cs similarity index 57% rename from Nebula.Launcher/ViewModels/ExceptionViewModel.cs rename to Nebula.Launcher/ViewModels/Popup/ExceptionViewModel.cs index f1d5d06..a77d0ec 100644 --- a/Nebula.Launcher/ViewModels/ExceptionViewModel.cs +++ b/Nebula.Launcher/ViewModels/Popup/ExceptionViewModel.cs @@ -1,31 +1,34 @@ using System; using System.Collections.ObjectModel; -using Nebula.Launcher.ViewHelper; using Nebula.Launcher.Views.Popup; +using Nebula.Shared.Services; -namespace Nebula.Launcher.ViewModels; +namespace Nebula.Launcher.ViewModels.Popup; [ViewModelRegister(typeof(ExceptionView), false)] -public class ExceptionViewModel : PopupViewModelBase +[ConstructGenerator] +public sealed partial class ExceptionViewModel : PopupViewModelBase { - public ExceptionViewModel() : base() - { - var e = new Exception("TEST"); - - AppendError(e); - } - - public ExceptionViewModel(IServiceProvider serviceProvider) : base(serviceProvider){} - + [GenerateProperty] public override PopupMessageService PopupMessageService { get; } public override string Title => "Oopsie! Some shit is happened now!"; public override bool IsClosable => true; public ObservableCollection Errors { get; } = new(); + protected override void Initialise() + { + } + + protected override void InitialiseInDesignMode() + { + var e = new Exception("TEST"); + AppendError(e); + } + public void AppendError(Exception exception) { Errors.Add(exception); - if(exception.InnerException != null) + if (exception.InnerException != null) AppendError(exception.InnerException); } -} +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/Popup/InfoPopupViewModel.cs b/Nebula.Launcher/ViewModels/Popup/InfoPopupViewModel.cs new file mode 100644 index 0000000..0f35e69 --- /dev/null +++ b/Nebula.Launcher/ViewModels/Popup/InfoPopupViewModel.cs @@ -0,0 +1,25 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using Nebula.Launcher.Views.Popup; +using Nebula.Shared.Services; + +namespace Nebula.Launcher.ViewModels.Popup; + +[ViewModelRegister(typeof(InfoPopupView), false)] +[ConstructGenerator] +public partial class InfoPopupViewModel : PopupViewModelBase +{ + [GenerateProperty] public override PopupMessageService PopupMessageService { get; } + + [ObservableProperty] private string _infoText = "Test"; + + public override string Title => "Info"; + public override bool IsClosable => true; + + protected override void Initialise() + { + } + + protected override void InitialiseInDesignMode() + { + } +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/LoadingContextViewModel.cs b/Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs similarity index 64% rename from Nebula.Launcher/ViewModels/LoadingContextViewModel.cs rename to Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs index 5dd981d..bde49c7 100644 --- a/Nebula.Launcher/ViewModels/LoadingContextViewModel.cs +++ b/Nebula.Launcher/ViewModels/Popup/LoadingContextViewModel.cs @@ -1,27 +1,25 @@ -using System; using CommunityToolkit.Mvvm.ComponentModel; -using Nebula.Launcher.ViewHelper; using Nebula.Launcher.Views.Popup; using Nebula.Shared.Models; +using Nebula.Shared.Services; -namespace Nebula.Launcher.ViewModels; +namespace Nebula.Launcher.ViewModels.Popup; [ViewModelRegister(typeof(LoadingContextView), false)] +[ConstructGenerator] public sealed partial class LoadingContextViewModel : PopupViewModelBase, ILoadingHandler { - public LoadingContextViewModel() :base(){} - public LoadingContextViewModel(IServiceProvider provider) : base(provider){} + [GenerateProperty] public override PopupMessageService PopupMessageService { get; } + [ObservableProperty] private int _currJobs; + + [ObservableProperty] private int _resolvedJobs; + public string LoadingName { get; set; } = "Loading..."; public override bool IsClosable => false; public override string Title => LoadingName; - - [ObservableProperty] - private int _currJobs; - [ObservableProperty] - private int _resolvedJobs; - + public void SetJobsCount(int count) { CurrJobs = count; @@ -35,11 +33,18 @@ public sealed partial class LoadingContextViewModel : PopupViewModelBase, ILoadi public void SetResolvedJobsCount(int count) { ResolvedJobs = count; - } public int GetResolvedJobsCount() { return ResolvedJobs; } + + protected override void Initialise() + { + } + + protected override void InitialiseInDesignMode() + { + } } \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/Popup/LogPopupModelView.cs b/Nebula.Launcher/ViewModels/Popup/LogPopupModelView.cs new file mode 100644 index 0000000..bbc9cf7 --- /dev/null +++ b/Nebula.Launcher/ViewModels/Popup/LogPopupModelView.cs @@ -0,0 +1,38 @@ +using System.Collections.ObjectModel; +using Nebula.Launcher.Views.Popup; +using Nebula.Shared.Services; + +namespace Nebula.Launcher.ViewModels.Popup; + +[ViewModelRegister(typeof(LogPopupView), false)] +[ConstructGenerator] +public sealed partial class LogPopupModelView : PopupViewModelBase +{ + [GenerateProperty] public override PopupMessageService PopupMessageService { get; } + public override string Title => "LOG"; + public override bool IsClosable => true; + + public ObservableCollection Logs { get; } = new(); + + protected override void InitialiseInDesignMode() + { + Logs.Add(new LogInfo + { + Category = "DEBG", Message = "MEOW MEOW TEST" + }); + + Logs.Add(new LogInfo + { + Category = "ERRO", Message = "MEOW MEOW TEST 11\naaaaa" + }); + } + + protected override void Initialise() + { + } + + public void Append(string str) + { + Logs.Add(LogInfo.FromString(str)); + } +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/Popup/PopupViewModelBase.cs b/Nebula.Launcher/ViewModels/Popup/PopupViewModelBase.cs new file mode 100644 index 0000000..d9d6a62 --- /dev/null +++ b/Nebula.Launcher/ViewModels/Popup/PopupViewModelBase.cs @@ -0,0 +1,17 @@ +using System; +using Nebula.Shared.Services; + +namespace Nebula.Launcher.ViewModels.Popup; + +public abstract class PopupViewModelBase : ViewModelBase, IDisposable +{ + public abstract PopupMessageService PopupMessageService { get; } + + public abstract string Title { get; } + public abstract bool IsClosable { get; } + + public void Dispose() + { + PopupMessageService.ClosePopup(this); + } +} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/PopupViewModelBase.cs b/Nebula.Launcher/ViewModels/PopupViewModelBase.cs deleted file mode 100644 index d3f9509..0000000 --- a/Nebula.Launcher/ViewModels/PopupViewModelBase.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; -using Nebula.Shared.Services; - -namespace Nebula.Launcher.ViewModels; - -public abstract class PopupViewModelBase : ViewModelBase, IDisposable -{ - private readonly IServiceProvider _serviceProvider; - public abstract string Title { get; } - public abstract bool IsClosable { get; } - - public PopupViewModelBase() - { - } - - public PopupViewModelBase(IServiceProvider serviceProvider) : base(serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public void Dispose() - { - _serviceProvider.GetService()?.ClosePopup(this); - } -} \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/ServerEntryModelView.cs b/Nebula.Launcher/ViewModels/ServerEntryModelView.cs index 16f7cdb..765056b 100644 --- a/Nebula.Launcher/ViewModels/ServerEntryModelView.cs +++ b/Nebula.Launcher/ViewModels/ServerEntryModelView.cs @@ -1,37 +1,40 @@ using System; -using System.Collections.ObjectModel; using System.Diagnostics; +using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Avalonia.Media; -using CommunityToolkit.Mvvm.ComponentModel; -using Nebula.Launcher.ViewHelper; -using Nebula.Launcher.Views.Popup; +using Nebula.Launcher.Services; +using Nebula.Launcher.ViewModels.Popup; using Nebula.Shared.Models; using Nebula.Shared.Services; namespace Nebula.Launcher.ViewModels; -[ViewModelRegister(isSingleton:false)] +[ViewModelRegister(isSingleton: false)] +[ConstructGenerator] public partial class ServerEntryModelView : ViewModelBase { - private readonly AuthService _authService = default!; - private readonly ContentService _contentService = default!; - private readonly CancellationService _cancellationService = default!; - private readonly DebugService _debugService = default!; - private readonly RunnerService _runnerService = default!; - private readonly PopupMessageService _popupMessageService; + private Process? _p; + + + public LogPopupModelView CurrLog; + [GenerateProperty] private AuthService AuthService { get; } = default!; + [GenerateProperty] private ContentService ContentService { get; } = default!; + [GenerateProperty] private CancellationService CancellationService { get; } = default!; + [GenerateProperty] private DebugService DebugService { get; } = default!; + [GenerateProperty] private RunnerService RunnerService { get; } = default!; + [GenerateProperty] private PopupMessageService PopupMessageService { get; } = default!; + [GenerateProperty] private ViewHelperService ViewHelperService { get; } = default!; public bool RunVisible => Process == null; public ServerHubInfo ServerHubInfo { get; set; } = default!; - - private Process? _p; private Process? Process { - get { return _p; } + get => _p; set { _p = value; @@ -39,32 +42,14 @@ public partial class ServerEntryModelView : ViewModelBase } } - - - public LogPopupModelView CurrLog; - - public ServerEntryModelView() : base() + protected override void InitialiseInDesignMode() { - CurrLog = GetViewModel(); + CurrLog = ViewHelperService.GetViewModel(); } - public ServerEntryModelView( - IServiceProvider serviceProvider, - AuthService authService, - ContentService contentService, - CancellationService cancellationService, - DebugService debugService, - RunnerService runnerService, PopupMessageService popupMessageService - ) : base(serviceProvider) + protected override void Initialise() { - _authService = authService; - _contentService = contentService; - _cancellationService = cancellationService; - _debugService = debugService; - _runnerService = runnerService; - _popupMessageService = popupMessageService; - - CurrLog = GetViewModel(); + CurrLog = ViewHelperService.GetViewModel(); } public void RunInstance() @@ -74,84 +59,77 @@ public partial class ServerEntryModelView : ViewModelBase public async Task RunAsync() { - try - { - var authProv = _authService.SelectedAuth; + try + { + var authProv = AuthService.SelectedAuth; - var buildInfo = - await _contentService.GetBuildInfo(new RobustUrl(ServerHubInfo.Address), _cancellationService.Token); - - using (var loadingContext = GetViewModel()) - { - loadingContext.LoadingName = "Loading instance..."; - ((ILoadingHandler)loadingContext).AppendJob(); - - _popupMessageService.Popup(loadingContext); - - - await _runnerService.PrepareRun(buildInfo, loadingContext, _cancellationService.Token); + var buildInfo = + await ContentService.GetBuildInfo(new RobustUrl(ServerHubInfo.Address), CancellationService.Token); - Process = Process.Start(new ProcessStartInfo() - { - FileName = "dotnet.exe", - Arguments = "./Nebula.Runner.dll", - Environment = - { - { "ROBUST_AUTH_USERID", authProv?.UserId.ToString() }, - { "ROBUST_AUTH_TOKEN", authProv?.Token.Token }, - { "ROBUST_AUTH_SERVER", authProv?.AuthLoginPassword.AuthServer }, - { "ROBUST_AUTH_PUBKEY", buildInfo.BuildInfo.Auth.PublicKey }, - { "GAME_URL", ServerHubInfo.Address }, - { "AUTH_LOGIN", authProv?.AuthLoginPassword.Login }, - }, - CreateNoWindow = true, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - StandardOutputEncoding = Encoding.UTF8 - }); - - ((ILoadingHandler)loadingContext).AppendResolvedJob(); - } - - if (Process is null) - { - return; - } - - Process.EnableRaisingEvents = true; - - Process.BeginOutputReadLine(); - Process.BeginErrorReadLine(); + using (var loadingContext = ViewHelperService.GetViewModel()) + { + loadingContext.LoadingName = "Loading instance..."; + ((ILoadingHandler)loadingContext).AppendJob(); - Process.OutputDataReceived += OnOutputDataReceived; - Process.ErrorDataReceived += OnErrorDataReceived; + PopupMessageService.Popup(loadingContext); - Process.Exited += OnExited; - } - catch (TaskCanceledException e) - { - _popupMessageService.Popup("Task canceled"); - } - catch (Exception e) - { - _popupMessageService.Popup(e); - } + await RunnerService.PrepareRun(buildInfo, loadingContext, CancellationService.Token); + + Process = Process.Start(new ProcessStartInfo + { + FileName = "dotnet.exe", + Arguments = "./Nebula.Runner.dll", + Environment = + { + { "ROBUST_AUTH_USERID", authProv?.UserId.ToString() }, + { "ROBUST_AUTH_TOKEN", authProv?.Token.Token }, + { "ROBUST_AUTH_SERVER", authProv?.AuthLoginPassword.AuthServer }, + { "ROBUST_AUTH_PUBKEY", buildInfo.BuildInfo.Auth.PublicKey }, + { "GAME_URL", ServerHubInfo.Address }, + { "AUTH_LOGIN", authProv?.AuthLoginPassword.Login } + }, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + StandardOutputEncoding = Encoding.UTF8 + }); + + ((ILoadingHandler)loadingContext).AppendResolvedJob(); + } + + if (Process is null) return; + + Process.EnableRaisingEvents = true; + + Process.BeginOutputReadLine(); + Process.BeginErrorReadLine(); + + Process.OutputDataReceived += OnOutputDataReceived; + Process.ErrorDataReceived += OnErrorDataReceived; + + Process.Exited += OnExited; + } + catch (TaskCanceledException _) + { + PopupMessageService.Popup("Task canceled"); + } + catch (Exception e) + { + PopupMessageService.Popup(e); + } } private void OnExited(object? sender, EventArgs e) { - if (Process is null) - { - return; - } - + if (Process is null) return; + Process.OutputDataReceived -= OnOutputDataReceived; Process.ErrorDataReceived -= OnErrorDataReceived; Process.Exited -= OnExited; - - _debugService.Log("PROCESS EXIT WITH CODE " + Process.ExitCode); - + + DebugService.Log("PROCESS EXIT WITH CODE " + Process.ExitCode); + Process.Dispose(); Process = null; } @@ -160,7 +138,7 @@ public partial class ServerEntryModelView : ViewModelBase { if (e.Data != null) { - _debugService.Error(e.Data); + DebugService.Error(e.Data); CurrLog.Append(e.Data); } } @@ -169,7 +147,7 @@ public partial class ServerEntryModelView : ViewModelBase { if (e.Data != null) { - _debugService.Log(e.Data); + DebugService.Log(e.Data); CurrLog.Append(e.Data); } } @@ -177,29 +155,24 @@ public partial class ServerEntryModelView : ViewModelBase public void ReadLog() { - _popupMessageService.Popup(CurrLog); + PopupMessageService.Popup(CurrLog); } public void StopInstance() { Process?.CloseMainWindow(); } - - static string FindDotnetPath() + + private static string FindDotnetPath() { var pathEnv = Environment.GetEnvironmentVariable("PATH"); - var paths = pathEnv?.Split(System.IO.Path.PathSeparator); + var paths = pathEnv?.Split(Path.PathSeparator); if (paths != null) - { foreach (var path in paths) { - var dotnetPath = System.IO.Path.Combine(path, "dotnet"); - if (System.IO.File.Exists(dotnetPath)) - { - return dotnetPath; - } + var dotnetPath = Path.Combine(path, "dotnet"); + if (File.Exists(dotnetPath)) return dotnetPath; } - } throw new Exception("Dotnet not found!"); } @@ -207,19 +180,16 @@ public partial class ServerEntryModelView : ViewModelBase public sealed class LogInfo { - public string Category { get; set; } = "LOG"; + public string Category { get; set; } = "LOG"; public IBrush CategoryColor { get; set; } = Brush.Parse("#424242"); public string Message { get; set; } = ""; public static LogInfo FromString(string input) { var matches = Regex.Matches(input, @"(\[(?.*)\] (?.*))|(?.*)"); - string category = "All"; + var category = "All"; - if( matches[0].Groups.TryGetValue("c", out var c)) - { - category = c.Value; - } + if (matches[0].Groups.TryGetValue("c", out var c)) category = c.Value; var color = Brush.Parse("#444444"); @@ -235,42 +205,11 @@ public sealed class LogInfo color = Brush.Parse("#0ab3c9"); break; } - + var message = matches[0].Groups["m"].Value; - return new LogInfo() + return new LogInfo { Category = category, Message = message, CategoryColor = color }; } -} - -[ViewModelRegister(typeof(LogPopupView), false)] -public sealed class LogPopupModelView : PopupViewModelBase -{ - public LogPopupModelView() : base() - { - Logs.Add(new LogInfo() - { - Category = "DEBG", Message = "MEOW MEOW TEST" - }); - - Logs.Add(new LogInfo() - { - Category = "ERRO", Message = "MEOW MEOW TEST 11\naaaaa" - }); - } - - public LogPopupModelView(IServiceProvider serviceProvider) : base(serviceProvider) - { - } - - public override string Title => "LOG"; - public override bool IsClosable => true; - - public ObservableCollection Logs { get; } = new(); - - public void Append(string str) - { - Logs.Add(LogInfo.FromString(str)); - } } \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/ViewModelBase.cs b/Nebula.Launcher/ViewModels/ViewModelBase.cs index 90ea18d..917d8c1 100644 --- a/Nebula.Launcher/ViewModels/ViewModelBase.cs +++ b/Nebula.Launcher/ViewModels/ViewModelBase.cs @@ -1,51 +1,9 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using Avalonia.Controls; -using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.ComponentModel; namespace Nebula.Launcher.ViewModels; public abstract class ViewModelBase : ObservableObject { - private readonly IServiceProvider _serviceProvider; - public ViewModelBase() - { - AssertDesignMode(); - _serviceProvider = default!; - } - public ViewModelBase(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public bool TryGetViewModel(Type type,[NotNullWhen(true)] out ViewModelBase? viewModelBase) - { - viewModelBase = null; - var vm = Design.IsDesignMode - ? Activator.CreateInstance(type) - : _serviceProvider.GetService(type); - - if (vm is not ViewModelBase vmb) return false; - - viewModelBase = vmb; - return true; - } - - public bool TryGetViewModel([NotNullWhen(true)] out T? viewModelBase) where T: ViewModelBase - { - var success = TryGetViewModel(typeof(T), out var vmb); - viewModelBase = (T?)vmb; - return success; - } - - public T GetViewModel() where T: ViewModelBase - { - TryGetViewModel(out var viewModelBase); - return viewModelBase!; - } - - public void AssertDesignMode() - { - if (!Design.IsDesignMode) throw new Exception(); - } + protected abstract void InitialiseInDesignMode(); + protected abstract void Initialise(); } \ No newline at end of file diff --git a/Nebula.Launcher/Views/MainView.axaml b/Nebula.Launcher/Views/MainView.axaml index fe6e17e..e51dfc0 100644 --- a/Nebula.Launcher/Views/MainView.axaml +++ b/Nebula.Launcher/Views/MainView.axaml @@ -85,7 +85,8 @@ Padding="5">