- shit: Cleanup this mess
This commit is contained in:
@@ -1,19 +1,16 @@
|
||||
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!;
|
||||
|
||||
@@ -26,8 +23,8 @@ public partial class App : Application
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddAvaloniaServices();
|
||||
services.AddViews();
|
||||
services.AddServices();
|
||||
services.AddViews();
|
||||
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
@@ -52,9 +49,6 @@ public partial class App : Application
|
||||
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
|
||||
|
||||
// remove each entry found
|
||||
foreach (var plugin in dataValidationPluginsToRemove)
|
||||
{
|
||||
BindingPlugins.DataValidators.Remove(plugin);
|
||||
}
|
||||
foreach (var plugin in dataValidationPluginsToRemove) BindingPlugins.DataValidators.Remove(plugin);
|
||||
}
|
||||
}
|
||||
2
Nebula.Launcher/GlobalUsing.cs
Normal file
2
Nebula.Launcher/GlobalUsing.cs
Normal file
@@ -0,0 +1,2 @@
|
||||
global using SourceGen;
|
||||
global using Nebula.Launcher.ViewHelper;
|
||||
@@ -46,5 +46,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nebula.Shared\Nebula.Shared.csproj"/>
|
||||
<ProjectReference Include="..\Nebula.SourceGenerators\Nebula.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -4,13 +4,18 @@ namespace Nebula.Launcher;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
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<App>()
|
||||
{
|
||||
return AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.WithInterFont()
|
||||
.LogToTrace();
|
||||
}
|
||||
}
|
||||
@@ -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<IDispatcher>(_ => 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<IApplicationLifetime>() 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")
|
||||
}
|
||||
);
|
||||
|
||||
@@ -44,14 +47,12 @@ public static class ServiceCollectionExtensions
|
||||
}
|
||||
}
|
||||
|
||||
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<ViewModelRegisterAttribute>();
|
||||
if (attr is not null) {
|
||||
yield return (type, attr.Type, attr.IsSingleton);
|
||||
if (attr is not null) yield return (type, attr.Type, attr.IsSingleton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
42
Nebula.Launcher/Services/ViewHelperService.cs
Normal file
42
Nebula.Launcher/Services/ViewHelperService.cs
Normal file
@@ -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<T>([NotNullWhen(true)] out T? viewModelBase) where T : ViewModelBase
|
||||
{
|
||||
var success = TryGetViewModel(typeof(T), out var vmb);
|
||||
viewModelBase = (T?)vmb;
|
||||
return success;
|
||||
}
|
||||
|
||||
public T GetViewModel<T>() where T : ViewModelBase
|
||||
{
|
||||
TryGetViewModel<T>(out var viewModelBase);
|
||||
return viewModelBase!;
|
||||
}
|
||||
|
||||
private void Initialise(){}
|
||||
private void InitialiseInDesignMode(){}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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;
|
||||
@@ -16,10 +15,7 @@ public class ViewLocator : IDataTemplate
|
||||
|
||||
var type = param.GetType().GetCustomAttribute<ViewModelRegisterAttribute>()?.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() };
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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<ListItemTemplate>(_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<ListItemTemplate>(_templates);
|
||||
|
||||
popupMessageService.OnPopupRequired += OnPopupRequired;
|
||||
popupMessageService.OnCloseRequired += OnPopupCloseRequired;
|
||||
|
||||
SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel));
|
||||
}
|
||||
|
||||
private readonly List<PopupViewModelBase> _viewQueue = new();
|
||||
|
||||
private readonly List<ListItemTemplate> _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<PopupViewModelBase> _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<ListItemTemplate> Items { get; private set; }
|
||||
|
||||
protected override void InitialiseInDesignMode()
|
||||
{
|
||||
CurrentPage = ViewHelperService.GetViewModel<AccountInfoViewModel>();
|
||||
Items = new ObservableCollection<ListItemTemplate>(_templates);
|
||||
SelectedListItem = Items.First(vm => vm.ModelType == typeof(AccountInfoViewModel));
|
||||
}
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
CurrentPage = ViewHelperService.GetViewModel<AccountInfoViewModel>();
|
||||
|
||||
Items = new ObservableCollection<ListItemTemplate>(_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<ListItemTemplate> Items { get; }
|
||||
|
||||
public void PopupMessage(PopupViewModelBase viewModelBase)
|
||||
{
|
||||
if (CurrentPopup == null)
|
||||
@@ -122,7 +114,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
{
|
||||
case string str:
|
||||
{
|
||||
var view = GetViewModel<InfoPopupViewModel>();
|
||||
var view = ViewHelperService.GetViewModel<InfoPopupViewModel>();
|
||||
view.InfoText = str;
|
||||
PopupMessage(view);
|
||||
break;
|
||||
@@ -131,8 +123,8 @@ public partial class MainViewModel : ViewModelBase
|
||||
PopupMessage(@base);
|
||||
break;
|
||||
case Exception error:
|
||||
var err = GetViewModel<ExceptionViewModel>();
|
||||
_debugService.Error(error);
|
||||
var err = ViewHelperService.GetViewModel<ExceptionViewModel>();
|
||||
DebugService.Error(error);
|
||||
err.AppendError(error);
|
||||
PopupMessage(err);
|
||||
break;
|
||||
@@ -141,10 +133,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
|
||||
private void OnPopupCloseRequired(object obj)
|
||||
{
|
||||
if(obj is not PopupViewModelBase viewModelBase)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (obj is not PopupViewModelBase viewModelBase) return;
|
||||
|
||||
if (obj == CurrentPopup)
|
||||
ClosePopup();
|
||||
@@ -164,7 +153,9 @@ public partial class MainViewModel : ViewModelBase
|
||||
{
|
||||
var viewModelBase = _viewQueue.FirstOrDefault();
|
||||
if (viewModelBase is null)
|
||||
{
|
||||
OnCloseRequired();
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentTitle = viewModelBase.Title;
|
||||
@@ -174,4 +165,3 @@ public partial class MainViewModel : ViewModelBase
|
||||
CurrentPopup = viewModelBase;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<AuthLoginPasswordModel> Accounts { get; } = new();
|
||||
public ObservableCollection<string> 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;
|
||||
[ObservableProperty] private string _currentAuthServer = string.Empty;
|
||||
|
||||
private bool _isProfilesEmpty;
|
||||
[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<AuthLoginPasswordModel> Accounts { get; } = new();
|
||||
public ObservableCollection<string> AuthUrls { get; } = new();
|
||||
|
||||
private AuthLoginPassword CurrentAlp
|
||||
{
|
||||
get => new(CurrentLogin, CurrentPassword, CurrentAuthServer);
|
||||
@@ -52,8 +50,13 @@ public partial class AccountInfoViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
public string AuthItemSelect
|
||||
{
|
||||
set => CurrentAuthServer = value;
|
||||
}
|
||||
|
||||
//Design think
|
||||
public AccountInfoViewModel()
|
||||
protected override void InitialiseInDesignMode()
|
||||
{
|
||||
AddAccount(new AuthLoginPassword("Binka", "12341", ""));
|
||||
AuthUrls.Add("https://cinka.ru");
|
||||
@@ -61,14 +64,8 @@ public partial class AccountInfoViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
//Real think
|
||||
public AccountInfoViewModel(IServiceProvider serviceProvider, PopupMessageService popupMessageService,
|
||||
ConfigurationService configurationService, AuthService authService) : base(serviceProvider)
|
||||
protected override void Initialise()
|
||||
{
|
||||
//_popupMessageService = mainViewModel;
|
||||
_popupMessageService = popupMessageService;
|
||||
_configurationService = configurationService;
|
||||
_authService = authService;
|
||||
|
||||
ReadAuthConfig();
|
||||
}
|
||||
|
||||
@@ -80,42 +77,37 @@ public partial class AccountInfoViewModel : ViewModelBase
|
||||
|
||||
public async void DoAuth()
|
||||
{
|
||||
var message = GetViewModel<InfoPopupViewModel>();
|
||||
var message = ViewHelperService.GetViewModel<InfoPopupViewModel>();
|
||||
message.InfoText = "Auth think, please wait...";
|
||||
_popupMessageService.Popup(message);
|
||||
PopupMessageService.Popup(message);
|
||||
|
||||
if(await _authService.Auth(CurrentAlp))
|
||||
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)
|
||||
{
|
||||
@@ -138,17 +130,12 @@ public partial class AccountInfoViewModel : ViewModelBase
|
||||
private void ReadAuthConfig()
|
||||
{
|
||||
foreach (var profile in
|
||||
_configurationService.GetConfigValue(CurrentConVar.AuthProfiles)!)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -157,11 +144,8 @@ public partial class AccountInfoViewModel : ViewModelBase
|
||||
}
|
||||
|
||||
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]
|
||||
@@ -196,15 +180,15 @@ public partial class AccountInfoViewModel : ViewModelBase
|
||||
|
||||
private void DirtyProfile()
|
||||
{
|
||||
_configurationService.SetConfigValue(CurrentConVar.AuthProfiles,
|
||||
ConfigurationService.SetConfigValue(CurrentConVar.AuthProfiles,
|
||||
Accounts.Select(a => (AuthLoginPassword)a).ToArray());
|
||||
}
|
||||
|
||||
public string AuthItemSelect
|
||||
{
|
||||
set => CurrentAuthServer = value;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -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<ContentEntry> Entries { get; } = new();
|
||||
private readonly List<ContentEntry> _root = new();
|
||||
|
||||
private List<string> _history = new();
|
||||
private readonly List<string> _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<ContentEntry> Entries { get; } = new();
|
||||
|
||||
public ContentEntry? SelectedEntry
|
||||
{
|
||||
@@ -48,7 +50,7 @@ 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);
|
||||
|
||||
@@ -58,6 +60,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
{
|
||||
stream.CopyTo(sw);
|
||||
}
|
||||
|
||||
stream.Dispose();
|
||||
|
||||
var startInfo = new ProcessStartInfo(myTempFile)
|
||||
@@ -67,6 +70,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
|
||||
Process.Start(startInfo);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,15 +79,12 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
|
||||
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", "");
|
||||
@@ -91,51 +92,31 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
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;
|
||||
|
||||
hubService.HubServerChangedEventArgs += HubServerChangedEventArgs;
|
||||
hubService.HubServerLoaded += GoHome;
|
||||
|
||||
if (!hubService.IsUpdating)
|
||||
{
|
||||
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.Add) FillRoot(obj.Items);
|
||||
}
|
||||
|
||||
private void FillRoot(IEnumerable<ServerHubInfo> 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)
|
||||
@@ -153,25 +134,17 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
return;
|
||||
}
|
||||
|
||||
if (ServerText != SelectedEntry?.ServerName)
|
||||
{
|
||||
SelectedEntry = await CreateEntry(ServerText);
|
||||
}
|
||||
if (ServerText != SelectedEntry?.ServerName) SelectedEntry = await CreateEntry(ServerText);
|
||||
|
||||
_debugService.Debug("Going to:" + path.Path);
|
||||
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;
|
||||
@@ -180,7 +153,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
SearchText = oriPath.Path;
|
||||
_popupService.Popup(e);
|
||||
PopupService.Popup(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,12 +171,12 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase
|
||||
private async Task<ContentEntry> CreateEntry(string serverUrl)
|
||||
{
|
||||
var rurl = serverUrl.ToRobustUrl();
|
||||
var info = await _contentService.GetBuildInfo(rurl, _cancellationService.Token);
|
||||
var loading = _provider.GetService<LoadingContextViewModel>()!;
|
||||
var info = await ContentService.GetBuildInfo(rurl, CancellationService.Token);
|
||||
var loading = ViewHelperService.GetViewModel<LoadingContextViewModel>();
|
||||
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);
|
||||
|
||||
@@ -235,24 +208,32 @@ 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")));
|
||||
|
||||
private readonly Dictionary<string, ContentEntry> _childs = new();
|
||||
private readonly ContentBrowserViewModel _viewModel;
|
||||
|
||||
public RobustManifestItem? Item;
|
||||
|
||||
internal ContentEntry(ContentBrowserViewModel viewModel, string name, string pathName, string serverName)
|
||||
{
|
||||
Name = name;
|
||||
ServerName = serverName;
|
||||
PathName = pathName;
|
||||
_viewModel = viewModel;
|
||||
}
|
||||
|
||||
public bool IsDirectory => Item == null;
|
||||
|
||||
public string Name { get; private set; }
|
||||
public string PathName { get; private set; }
|
||||
public string ServerName { 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;
|
||||
|
||||
private readonly Dictionary<string, ContentEntry> _childs = new();
|
||||
|
||||
public IReadOnlyDictionary<string, ContentEntry> Childs => _childs.ToFrozenDictionary();
|
||||
|
||||
public bool TryGetChild(string name, [NotNullWhen(true)] out ContentEntry? child)
|
||||
@@ -271,14 +252,6 @@ public class ContentEntry
|
||||
return false;
|
||||
}
|
||||
|
||||
internal ContentEntry(ContentBrowserViewModel viewModel, string name, string pathName, string serverName)
|
||||
{
|
||||
Name = name;
|
||||
ServerName = serverName;
|
||||
PathName = pathName;
|
||||
_viewModel = viewModel;
|
||||
}
|
||||
|
||||
public ContentPath GetPath()
|
||||
{
|
||||
if (Parent != null)
|
||||
@@ -287,6 +260,7 @@ public class ContentEntry
|
||||
path.Pathes.Add(PathName);
|
||||
return path;
|
||||
}
|
||||
|
||||
return new ContentPath([PathName]);
|
||||
}
|
||||
|
||||
@@ -339,10 +313,7 @@ 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<string> Pathes { get; private set; }
|
||||
public List<string> Pathes { get; }
|
||||
|
||||
public ContentPath(List<string> pathes)
|
||||
{
|
||||
Pathes = pathes ?? new List<string>();
|
||||
Pathes = pathes;
|
||||
}
|
||||
|
||||
public ContentPath(string path)
|
||||
@@ -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<ServerHubInfo> Servers = new();
|
||||
|
||||
protected override void Initialise()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitialiseInDesignMode()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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<ServerEntryModelView> 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<ServerEntryModelView> ServerInfos { get; } = new();
|
||||
private List<ServerHubInfo> 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);
|
||||
|
||||
foreach (var info in _hubService.ServerList)
|
||||
{
|
||||
UnsortedServers.Add(info);
|
||||
}
|
||||
|
||||
hubService.HubServerChangedEventArgs += HubServerChangedEventArgs;
|
||||
hubService.HubServerLoaded += HubServerLoaded;
|
||||
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)
|
||||
{
|
||||
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<ServerEntryModelView>();
|
||||
var svn = ViewHelperService.GetViewModel<ServerEntryModelView>();
|
||||
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<ServerHubInfo>
|
||||
return -1;
|
||||
|
||||
return y.StatusData.Players.CompareTo(x.StatusData.Players);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,30 @@
|
||||
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<Exception> 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);
|
||||
25
Nebula.Launcher/ViewModels/Popup/InfoPopupViewModel.cs
Normal file
25
Nebula.Launcher/ViewModels/Popup/InfoPopupViewModel.cs
Normal file
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
38
Nebula.Launcher/ViewModels/Popup/LogPopupModelView.cs
Normal file
38
Nebula.Launcher/ViewModels/Popup/LogPopupModelView.cs
Normal file
@@ -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<LogInfo> 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));
|
||||
}
|
||||
}
|
||||
17
Nebula.Launcher/ViewModels/Popup/PopupViewModelBase.cs
Normal file
17
Nebula.Launcher/ViewModels/Popup/PopupViewModelBase.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<PopupMessageService>()?.ClosePopup(this);
|
||||
}
|
||||
}
|
||||
@@ -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)]
|
||||
[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<LogPopupModelView>();
|
||||
CurrLog = ViewHelperService.GetViewModel<LogPopupModelView>();
|
||||
}
|
||||
|
||||
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<LogPopupModelView>();
|
||||
CurrLog = ViewHelperService.GetViewModel<LogPopupModelView>();
|
||||
}
|
||||
|
||||
public void RunInstance()
|
||||
@@ -76,22 +61,21 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
{
|
||||
try
|
||||
{
|
||||
var authProv = _authService.SelectedAuth;
|
||||
var authProv = AuthService.SelectedAuth;
|
||||
|
||||
var buildInfo =
|
||||
await _contentService.GetBuildInfo(new RobustUrl(ServerHubInfo.Address), _cancellationService.Token);
|
||||
await ContentService.GetBuildInfo(new RobustUrl(ServerHubInfo.Address), CancellationService.Token);
|
||||
|
||||
using (var loadingContext = GetViewModel<LoadingContextViewModel>())
|
||||
using (var loadingContext = ViewHelperService.GetViewModel<LoadingContextViewModel>())
|
||||
{
|
||||
loadingContext.LoadingName = "Loading instance...";
|
||||
((ILoadingHandler)loadingContext).AppendJob();
|
||||
|
||||
_popupMessageService.Popup(loadingContext);
|
||||
PopupMessageService.Popup(loadingContext);
|
||||
|
||||
await RunnerService.PrepareRun(buildInfo, loadingContext, CancellationService.Token);
|
||||
|
||||
await _runnerService.PrepareRun(buildInfo, loadingContext, _cancellationService.Token);
|
||||
|
||||
Process = Process.Start(new ProcessStartInfo()
|
||||
Process = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "dotnet.exe",
|
||||
Arguments = "./Nebula.Runner.dll",
|
||||
@@ -102,7 +86,7 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
{ "ROBUST_AUTH_SERVER", authProv?.AuthLoginPassword.AuthServer },
|
||||
{ "ROBUST_AUTH_PUBKEY", buildInfo.BuildInfo.Auth.PublicKey },
|
||||
{ "GAME_URL", ServerHubInfo.Address },
|
||||
{ "AUTH_LOGIN", authProv?.AuthLoginPassword.Login },
|
||||
{ "AUTH_LOGIN", authProv?.AuthLoginPassword.Login }
|
||||
},
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
@@ -114,10 +98,7 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
((ILoadingHandler)loadingContext).AppendResolvedJob();
|
||||
}
|
||||
|
||||
if (Process is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Process is null) return;
|
||||
|
||||
Process.EnableRaisingEvents = true;
|
||||
|
||||
@@ -129,28 +110,25 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
|
||||
Process.Exited += OnExited;
|
||||
}
|
||||
catch (TaskCanceledException e)
|
||||
catch (TaskCanceledException _)
|
||||
{
|
||||
_popupMessageService.Popup("Task canceled");
|
||||
PopupMessageService.Popup("Task canceled");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_popupMessageService.Popup(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,7 +155,7 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
|
||||
public void ReadLog()
|
||||
{
|
||||
_popupMessageService.Popup(CurrLog);
|
||||
PopupMessageService.Popup(CurrLog);
|
||||
}
|
||||
|
||||
public void StopInstance()
|
||||
@@ -185,20 +163,15 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
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!");
|
||||
@@ -214,12 +187,9 @@ public sealed class LogInfo
|
||||
public static LogInfo FromString(string input)
|
||||
{
|
||||
var matches = Regex.Matches(input, @"(\[(?<c>.*)\] (?<m>.*))|(?<m>.*)");
|
||||
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");
|
||||
|
||||
@@ -237,40 +207,9 @@ public sealed class LogInfo
|
||||
}
|
||||
|
||||
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<LogInfo> Logs { get; } = new();
|
||||
|
||||
public void Append(string str)
|
||||
{
|
||||
Logs.Add(LogInfo.FromString(str));
|
||||
}
|
||||
}
|
||||
@@ -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<T>([NotNullWhen(true)] out T? viewModelBase) where T: ViewModelBase
|
||||
{
|
||||
var success = TryGetViewModel(typeof(T), out var vmb);
|
||||
viewModelBase = (T?)vmb;
|
||||
return success;
|
||||
}
|
||||
|
||||
public T GetViewModel<T>() where T: ViewModelBase
|
||||
{
|
||||
TryGetViewModel<T>(out var viewModelBase);
|
||||
return viewModelBase!;
|
||||
}
|
||||
|
||||
public void AssertDesignMode()
|
||||
{
|
||||
if (!Design.IsDesignMode) throw new Exception();
|
||||
}
|
||||
protected abstract void InitialiseInDesignMode();
|
||||
protected abstract void Initialise();
|
||||
}
|
||||
@@ -85,7 +85,8 @@
|
||||
Padding="5">
|
||||
<Label FontSize="10" Foreground="#777777">
|
||||
<Panel>
|
||||
<Button Command="{Binding OpenLink}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0" Padding="0" CornerRadius="0" Background="#00000000">
|
||||
<Button Command="{Binding OpenLink}" HorizontalAlignment="Left" VerticalAlignment="Center"
|
||||
Margin="0" Padding="0" CornerRadius="0" Background="#00000000">
|
||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center">https://cinka.ru/nebula-launcher/</TextBlock>
|
||||
</Button>
|
||||
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center">prototype-product-v0.01</TextBlock>
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
|
||||
namespace Nebula.Launcher.Views;
|
||||
|
||||
public partial class MainView : UserControl
|
||||
{
|
||||
|
||||
// This constructor is used when the view is created by the XAML Previewer
|
||||
public MainView()
|
||||
{
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Nebula.Launcher.Views.Pages.AccountInfoView"
|
||||
x:DataType="viewModels:AccountInfoViewModel"
|
||||
x:DataType="pages:AccountInfoViewModel"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages">
|
||||
<Design.DataContext>
|
||||
<viewModels:AccountInfoViewModel />
|
||||
<pages:AccountInfoViewModel />
|
||||
</Design.DataContext>
|
||||
<Grid
|
||||
ColumnDefinitions="*,1.5*"
|
||||
@@ -29,7 +29,7 @@
|
||||
ItemsSource="{Binding Accounts}"
|
||||
Padding="0">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type viewModels:AuthLoginPasswordModel}">
|
||||
<DataTemplate DataType="{x:Type pages:AuthLoginPasswordModel}">
|
||||
<Border
|
||||
CornerRadius="0,10,0,10"
|
||||
Margin="5,5,5,0"
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Avalonia.Controls;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using AccountInfoViewModel = Nebula.Launcher.ViewModels.Pages.AccountInfoViewModel;
|
||||
|
||||
namespace Nebula.Launcher.Views.Pages;
|
||||
|
||||
public interface ITab;
|
||||
|
||||
public partial class AccountInfoView : UserControl
|
||||
{
|
||||
public AccountInfoView()
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Nebula.Launcher.Views.Pages.ContentBrowserView"
|
||||
x:DataType="viewModels:ContentBrowserViewModel"
|
||||
x:DataType="pages:ContentBrowserViewModel"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages">
|
||||
<Design.DataContext>
|
||||
<viewModels:ContentBrowserViewModel />
|
||||
<pages:ContentBrowserViewModel />
|
||||
</Design.DataContext>
|
||||
|
||||
<Grid
|
||||
@@ -60,7 +60,7 @@
|
||||
ItemsSource="{Binding Entries}"
|
||||
Padding="0,0,0,0">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type viewModels:ContentEntry}">
|
||||
<DataTemplate DataType="{x:Type pages:ContentEntry}">
|
||||
<Button
|
||||
Command="{Binding OnPathGo}"
|
||||
CornerRadius="0"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using ContentBrowserViewModel = Nebula.Launcher.ViewModels.Pages.ContentBrowserViewModel;
|
||||
|
||||
namespace Nebula.Launcher.Views.Pages;
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Nebula.Launcher.Views.Pages;
|
||||
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Nebula.Launcher.Views.Pages.ServerListView"
|
||||
x:DataType="viewModels:ServerListViewModel"
|
||||
x:DataType="pages:ServerListViewModel"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:asyncImageLoader="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:pages="clr-namespace:Nebula.Launcher.ViewModels.Pages">
|
||||
|
||||
<Design.DataContext>
|
||||
<viewModels:ServerListViewModel />
|
||||
<pages:ServerListViewModel />
|
||||
</Design.DataContext>
|
||||
|
||||
<Grid
|
||||
@@ -67,7 +68,8 @@
|
||||
Grid.Row="1"
|
||||
MinHeight="50">
|
||||
<Border.Background>
|
||||
<ImageBrush Stretch="UniformToFill" asyncImageLoader:ImageBrushLoader.Source="https://t4.ftcdn.net/jpg/00/81/55/69/360_F_81556974_8sF8cKszJaRfBGd5sDt1RXE2QbzDtQqs.jpg" />
|
||||
<ImageBrush Stretch="UniformToFill"
|
||||
asyncImageLoader:ImageBrushLoader.Source="https://t4.ftcdn.net/jpg/00/81/55/69/360_F_81556974_8sF8cKszJaRfBGd5sDt1RXE2QbzDtQqs.jpg" />
|
||||
</Border.Background>
|
||||
<Border
|
||||
BorderThickness="0,2,2,0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Avalonia.Controls;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using ServerListViewModel = Nebula.Launcher.ViewModels.Pages.ServerListViewModel;
|
||||
|
||||
namespace Nebula.Launcher.Views.Pages;
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nebula.Launcher.Views.Popup.ExceptionView"
|
||||
x:DataType="viewModels:ExceptionViewModel">
|
||||
x:DataType="popup:ExceptionViewModel">
|
||||
<Design.DataContext>
|
||||
<viewModels:ExceptionViewModel />
|
||||
<popup:ExceptionViewModel />
|
||||
</Design.DataContext>
|
||||
<ScrollViewer Margin="10" Padding="0,0,8,0">
|
||||
<ItemsControl
|
||||
@@ -20,9 +20,13 @@
|
||||
<Border Background="#333333" CornerRadius="5" Margin="0,0,0,5">
|
||||
<StackPanel>
|
||||
<Border Background="#aa2222" CornerRadius="5,5,0,0">
|
||||
<Label Margin="4"><TextBlock Text="{Binding Message}"/></Label>
|
||||
<Label Margin="4">
|
||||
<TextBlock Text="{Binding Message}" />
|
||||
</Label>
|
||||
</Border>
|
||||
<Label Margin="4"><TextBlock Text="{Binding StackTrace}"/></Label>
|
||||
<Label Margin="4">
|
||||
<TextBlock Text="{Binding StackTrace}" />
|
||||
</Label>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using Nebula.Launcher.ViewModels.Popup;
|
||||
|
||||
namespace Nebula.Launcher.Views.Popup;
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Nebula.Launcher.Views.Popup.InfoPopupView"
|
||||
x:DataType="viewModels:InfoPopupViewModel"
|
||||
x:DataType="popup:InfoPopupViewModel"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup">
|
||||
<Design.DataContext>
|
||||
<viewModels:InfoPopupViewModel />
|
||||
<popup:InfoPopupViewModel />
|
||||
</Design.DataContext>
|
||||
|
||||
<Panel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using InfoPopupViewModel = Nebula.Launcher.ViewModels.Popup.InfoPopupViewModel;
|
||||
|
||||
namespace Nebula.Launcher.Views.Popup;
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nebula.Launcher.Views.Popup.LoadingContextView"
|
||||
x:DataType="viewModels:LoadingContextViewModel">
|
||||
x:DataType="popup:LoadingContextViewModel">
|
||||
<Design.DataContext>
|
||||
<viewModels:LoadingContextViewModel />
|
||||
<popup:LoadingContextViewModel />
|
||||
</Design.DataContext>
|
||||
<StackPanel Margin="25" Spacing="15">
|
||||
<ProgressBar Height="40" Maximum="{Binding CurrJobs}" Value="{Binding ResolvedJobs}" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Avalonia.Controls;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using LoadingContextViewModel = Nebula.Launcher.ViewModels.Popup.LoadingContextViewModel;
|
||||
|
||||
namespace Nebula.Launcher.Views.Popup;
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="clr-namespace:Nebula.Launcher.ViewModels"
|
||||
xmlns:popup="clr-namespace:Nebula.Launcher.ViewModels.Popup"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Nebula.Launcher.Views.Popup.LogPopupView"
|
||||
x:DataType="viewModels:LogPopupModelView">
|
||||
x:DataType="popup:LogPopupModelView">
|
||||
<Design.DataContext>
|
||||
<viewModels:LogPopupModelView />
|
||||
<popup:LogPopupModelView />
|
||||
</Design.DataContext>
|
||||
|
||||
<ScrollViewer Margin="10" Padding="0,0,8,0">
|
||||
@@ -24,11 +25,11 @@
|
||||
CornerRadius="5,0,0,5"
|
||||
Padding="10,0,12,0" BorderThickness="2,0,2,0">
|
||||
<Label FontSize="15" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Category }"></TextBlock>
|
||||
<TextBlock Text="{Binding Category }" />
|
||||
</Label>
|
||||
</Border>
|
||||
<Label FontSize="12" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Message }"></TextBlock>
|
||||
<TextBlock Text="{Binding Message }" />
|
||||
</Label>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
using Nebula.Launcher.ViewModels.Popup;
|
||||
|
||||
namespace Nebula.Launcher.Views.Popup;
|
||||
|
||||
|
||||
@@ -7,8 +7,13 @@ using Robust.LoaderApi;
|
||||
namespace Nebula.Runner;
|
||||
|
||||
[ServiceRegister]
|
||||
public sealed class App(DebugService debugService, RunnerService runnerService, ContentService contentService) : IRedialApi
|
||||
public sealed class App(DebugService debugService, RunnerService runnerService, ContentService contentService)
|
||||
: IRedialApi
|
||||
{
|
||||
public void Redial(Uri uri, string text = "")
|
||||
{
|
||||
}
|
||||
|
||||
public async Task Run(string[] args1)
|
||||
{
|
||||
debugService.Log("HELLO!!! ");
|
||||
@@ -49,19 +54,14 @@ public sealed class App(DebugService debugService, RunnerService runnerService,
|
||||
|
||||
await runnerService.Run(args.ToArray(), buildInfo, this, new ConsoleLoadingHandler(), cancelTokenSource.Token);
|
||||
}
|
||||
|
||||
public void Redial(Uri uri, string text = "")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ConsoleLoadingHandler : ILoadingHandler
|
||||
{
|
||||
private int _currJobs;
|
||||
private int _resolvedJobs;
|
||||
|
||||
private float _percent = 0f;
|
||||
private float _percent;
|
||||
private int _resolvedJobs;
|
||||
|
||||
public void SetJobsCount(int count)
|
||||
{
|
||||
@@ -110,17 +110,10 @@ public sealed class ConsoleLoadingHandler : ILoadingHandler
|
||||
|
||||
Console.Write("\r");
|
||||
|
||||
for (var i = 0; i < fullCount; i++)
|
||||
{
|
||||
Console.Write("#");
|
||||
}
|
||||
for (var i = 0; i < fullCount; i++) Console.Write("#");
|
||||
|
||||
for (var i = 0; i < emptyCount; i++)
|
||||
{
|
||||
Console.Write(" ");
|
||||
}
|
||||
for (var i = 0; i < emptyCount; i++) Console.Write(" ");
|
||||
|
||||
Console.Write($"\t {_resolvedJobs}/{_currJobs}");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nebula.Shared;
|
||||
|
||||
|
||||
@@ -6,20 +6,27 @@ public static class CurrentConVar
|
||||
{
|
||||
public static readonly ConVar<string> EngineManifestUrl =
|
||||
ConVarBuilder.Build("engine.manifestUrl", "https://robust-builds.cdn.spacestation14.com/manifest.json");
|
||||
|
||||
public static readonly ConVar<string> EngineModuleManifestUrl =
|
||||
ConVarBuilder.Build("engine.moduleManifestUrl", "https://robust-builds.cdn.spacestation14.com/modules.json");
|
||||
|
||||
public static readonly ConVar<int> ManifestDownloadProtocolVersion =
|
||||
ConVarBuilder.Build("engine.manifestDownloadProtocolVersion", 1);
|
||||
|
||||
public static readonly ConVar<string> RobustAssemblyName =
|
||||
ConVarBuilder.Build("engine.robustAssemblyName", "Robust.Client");
|
||||
|
||||
public static readonly ConVar<string[]> Hub = ConVarBuilder.Build<string[]>("launcher.hub", [
|
||||
"https://hub.spacestation14.com/api/servers"
|
||||
]);
|
||||
|
||||
public static readonly ConVar<string[]> AuthServers = ConVarBuilder.Build<string[]>("launcher.authServers", [
|
||||
"https://auth.spacestation14.com/"
|
||||
]);
|
||||
|
||||
public static readonly ConVar<AuthLoginPassword[]> AuthProfiles = ConVarBuilder.Build<AuthLoginPassword[]>("auth.profiles", []);
|
||||
public static readonly ConVar<AuthLoginPassword> AuthCurrent = ConVarBuilder.Build<AuthLoginPassword>("auth.current");
|
||||
public static readonly ConVar<AuthLoginPassword[]> AuthProfiles =
|
||||
ConVarBuilder.Build<AuthLoginPassword[]>("auth.profiles", []);
|
||||
|
||||
public static readonly ConVar<AuthLoginPassword> AuthCurrent =
|
||||
ConVarBuilder.Build<AuthLoginPassword>("auth.current");
|
||||
}
|
||||
@@ -15,7 +15,6 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
{
|
||||
var fullPath = Path.Join(RootPath, path);
|
||||
if (File.Exists(fullPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
@@ -26,7 +25,6 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
stream = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream = null;
|
||||
return false;
|
||||
@@ -66,6 +64,7 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
{
|
||||
// Log exception if necessary
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
namespace Nebula.Shared.Models;
|
||||
|
||||
public record ListItemTemplate(Type ModelType, string IconKey, string Label);
|
||||
@@ -4,18 +4,26 @@ namespace Nebula.Shared.Models;
|
||||
|
||||
public sealed record AuthInfo(
|
||||
[property: JsonPropertyName("mode")] string Mode,
|
||||
[property: JsonPropertyName("public_key")] string PublicKey);
|
||||
[property: JsonPropertyName("public_key")]
|
||||
string PublicKey);
|
||||
|
||||
public sealed record BuildInfo(
|
||||
[property: JsonPropertyName("engine_version")] string EngineVersion,
|
||||
[property: JsonPropertyName("fork_id")] string ForkId,
|
||||
[property: JsonPropertyName("version")] string Version,
|
||||
[property: JsonPropertyName("download_url")] string DownloadUrl,
|
||||
[property: JsonPropertyName("manifest_download_url")] string ManifestDownloadUrl,
|
||||
[property: JsonPropertyName("manifest_url")] string ManifestUrl,
|
||||
[property: JsonPropertyName("engine_version")]
|
||||
string EngineVersion,
|
||||
[property: JsonPropertyName("fork_id")]
|
||||
string ForkId,
|
||||
[property: JsonPropertyName("version")]
|
||||
string Version,
|
||||
[property: JsonPropertyName("download_url")]
|
||||
string DownloadUrl,
|
||||
[property: JsonPropertyName("manifest_download_url")]
|
||||
string ManifestDownloadUrl,
|
||||
[property: JsonPropertyName("manifest_url")]
|
||||
string ManifestUrl,
|
||||
[property: JsonPropertyName("acz")] bool Acz,
|
||||
[property: JsonPropertyName("hash")] string Hash,
|
||||
[property: JsonPropertyName("manifest_hash")] string ManifestHash);
|
||||
[property: JsonPropertyName("manifest_hash")]
|
||||
string ManifestHash);
|
||||
|
||||
public sealed record ServerLink(
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
@@ -23,16 +31,20 @@ public sealed record ServerLink(
|
||||
[property: JsonPropertyName("url")] string Url);
|
||||
|
||||
public sealed record ServerInfo(
|
||||
[property: JsonPropertyName("connect_address")] string ConnectAddress,
|
||||
[property: JsonPropertyName("connect_address")]
|
||||
string ConnectAddress,
|
||||
[property: JsonPropertyName("auth")] AuthInfo Auth,
|
||||
[property: JsonPropertyName("build")] BuildInfo Build,
|
||||
[property: JsonPropertyName("desc")] string Desc,
|
||||
[property: JsonPropertyName("links")] List<ServerLink> Links);
|
||||
|
||||
public sealed record EngineVersionInfo(
|
||||
[property: JsonPropertyName("insecure")] bool Insecure,
|
||||
[property: JsonPropertyName("redirect")] string? RedirectVersion,
|
||||
[property: JsonPropertyName("platforms")] Dictionary<string, EngineBuildInfo> Platforms);
|
||||
[property: JsonPropertyName("insecure")]
|
||||
bool Insecure,
|
||||
[property: JsonPropertyName("redirect")]
|
||||
string? RedirectVersion,
|
||||
[property: JsonPropertyName("platforms")]
|
||||
Dictionary<string, EngineBuildInfo> Platforms);
|
||||
|
||||
public sealed class EngineBuildInfo
|
||||
{
|
||||
@@ -47,27 +59,39 @@ public sealed class EngineBuildInfo
|
||||
}
|
||||
|
||||
public sealed record ServerHubInfo(
|
||||
[property: JsonPropertyName("address")] string Address,
|
||||
[property: JsonPropertyName("statusData")] ServerStatus StatusData,
|
||||
[property: JsonPropertyName("inferredTags")] List<string> InferredTags);
|
||||
[property: JsonPropertyName("address")]
|
||||
string Address,
|
||||
[property: JsonPropertyName("statusData")]
|
||||
ServerStatus StatusData,
|
||||
[property: JsonPropertyName("inferredTags")]
|
||||
List<string> InferredTags);
|
||||
|
||||
public sealed record ServerStatus(
|
||||
[property: JsonPropertyName("map")] string Map,
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
[property: JsonPropertyName("tags")] List<string> Tags,
|
||||
[property: JsonPropertyName("preset")] string Preset,
|
||||
[property: JsonPropertyName("players")] int Players,
|
||||
[property: JsonPropertyName("round_id")] int RoundId,
|
||||
[property: JsonPropertyName("run_level")] int RunLevel,
|
||||
[property: JsonPropertyName("panic_bunker")] bool PanicBunker,
|
||||
[property: JsonPropertyName("round_start_time")] DateTime? RoundStartTime,
|
||||
[property: JsonPropertyName("soft_max_players")] int SoftMaxPlayers);
|
||||
[property: JsonPropertyName("players")]
|
||||
int Players,
|
||||
[property: JsonPropertyName("round_id")]
|
||||
int RoundId,
|
||||
[property: JsonPropertyName("run_level")]
|
||||
int RunLevel,
|
||||
[property: JsonPropertyName("panic_bunker")]
|
||||
bool PanicBunker,
|
||||
[property: JsonPropertyName("round_start_time")]
|
||||
DateTime? RoundStartTime,
|
||||
[property: JsonPropertyName("soft_max_players")]
|
||||
int SoftMaxPlayers);
|
||||
|
||||
public sealed record ModulesInfo(
|
||||
[property: JsonPropertyName("modules")] Dictionary<string, Module> Modules);
|
||||
[property: JsonPropertyName("modules")]
|
||||
Dictionary<string, Module> Modules);
|
||||
|
||||
public sealed record Module(
|
||||
[property: JsonPropertyName("versions")] Dictionary<string, ModuleVersionInfo> Versions);
|
||||
[property: JsonPropertyName("versions")]
|
||||
Dictionary<string, ModuleVersionInfo> Versions);
|
||||
|
||||
public sealed record ModuleVersionInfo(
|
||||
[property: JsonPropertyName("platforms")] Dictionary<string, EngineBuildInfo> Platforms);
|
||||
[property: JsonPropertyName("platforms")]
|
||||
Dictionary<string, EngineBuildInfo> Platforms);
|
||||
@@ -17,6 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nebula.SourceGenerators\Nebula.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||
<ProjectReference Include="..\Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -7,10 +7,7 @@ public static class ServiceExt
|
||||
{
|
||||
public static void AddServices(this IServiceCollection services)
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
AddServices(services, assembly);
|
||||
}
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) AddServices(services, assembly);
|
||||
}
|
||||
|
||||
public static void AddServices(this IServiceCollection services, Assembly assembly)
|
||||
@@ -19,35 +16,30 @@ public static class ServiceExt
|
||||
{
|
||||
Console.WriteLine("[ServiceMng] ADD SERVICE " + type);
|
||||
if (inference is null)
|
||||
{
|
||||
services.AddSingleton(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton(inference, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<(Type,Type?)> GetServicesWithHelpAttribute(Assembly assembly) {
|
||||
foreach(Type type in assembly.GetTypes())
|
||||
private static IEnumerable<(Type, Type?)> GetServicesWithHelpAttribute(Assembly assembly)
|
||||
{
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
var attr = type.GetCustomAttribute<ServiceRegisterAttribute>();
|
||||
if (attr is not null) {
|
||||
yield return (type, attr.Inference);
|
||||
}
|
||||
if (attr is not null) yield return (type, attr.Inference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ServiceRegisterAttribute : Attribute
|
||||
{
|
||||
public Type? Inference { get; }
|
||||
public bool IsSingleton { get; }
|
||||
|
||||
public ServiceRegisterAttribute(Type? inference = null, bool isSingleton = true)
|
||||
{
|
||||
IsSingleton = isSingleton;
|
||||
Inference = inference;
|
||||
}
|
||||
|
||||
public Type? Inference { get; }
|
||||
public bool IsSingleton { get; }
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
|
||||
using System.Runtime.Loader;
|
||||
using Nebula.Shared.FileApis;
|
||||
using Robust.LoaderApi;
|
||||
using SharpZstd.Interop;
|
||||
|
||||
namespace Nebula.Shared.Services;
|
||||
|
||||
@@ -13,23 +14,23 @@ public class AssemblyService
|
||||
private readonly List<Assembly> _assemblies = new();
|
||||
private readonly DebugService _debugService;
|
||||
|
||||
private readonly HashSet<string> _resolvingAssemblies = new();
|
||||
|
||||
public AssemblyService(DebugService debugService)
|
||||
{
|
||||
_debugService = debugService;
|
||||
|
||||
SharpZstd.Interop.ZstdImportResolver.ResolveLibrary += (name, assembly1, path) =>
|
||||
ZstdImportResolver.ResolveLibrary += (name, assembly1, path) =>
|
||||
{
|
||||
if (name.Equals("SharpZstd.Native"))
|
||||
{
|
||||
_debugService.Debug("RESOLVING SHARPZSTD THINK: " + name + " " + path);
|
||||
GetRuntimeInfo(out string platform, out string architecture, out string extension);
|
||||
string fileName = GetDllName(platform, architecture, extension);
|
||||
GetRuntimeInfo(out var platform, out var architecture, out var extension);
|
||||
var fileName = GetDllName(platform, architecture, extension);
|
||||
|
||||
if (NativeLibrary.TryLoad(fileName, assembly1, path, out var nativeLibrary))
|
||||
{
|
||||
return nativeLibrary;
|
||||
}
|
||||
if (NativeLibrary.TryLoad(fileName, assembly1, path, out var nativeLibrary)) return nativeLibrary;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
};
|
||||
}
|
||||
@@ -99,8 +100,6 @@ public class AssemblyService
|
||||
return true;
|
||||
}
|
||||
|
||||
private readonly HashSet<string> _resolvingAssemblies = new HashSet<string>();
|
||||
|
||||
private Assembly? OnAssemblyResolving(AssemblyLoadContext context, AssemblyName name, AssemblyApi assemblyApi)
|
||||
{
|
||||
if (_resolvingAssemblies.Contains(name.FullName))
|
||||
@@ -141,7 +140,7 @@ public class AssemblyService
|
||||
string architecture,
|
||||
string extension)
|
||||
{
|
||||
string name = $"SharpZstd.Native.{extension}";
|
||||
var name = $"SharpZstd.Native.{extension}";
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -172,24 +171,14 @@ public class AssemblyService
|
||||
}
|
||||
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
{
|
||||
architecture = "x64";
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.X86)
|
||||
{
|
||||
architecture = "x86";
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)
|
||||
{
|
||||
architecture = "arm";
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
architecture = "arm64";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException("Unsupported process architecture.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,15 @@ using Nebula.Shared.Models.Auth;
|
||||
namespace Nebula.Shared.Services;
|
||||
|
||||
[ServiceRegister]
|
||||
public partial class AuthService(
|
||||
public class AuthService(
|
||||
RestService restService,
|
||||
DebugService debugService,
|
||||
CancellationService cancellationService)
|
||||
{
|
||||
private readonly HttpClient _httpClient = new();
|
||||
public CurrentAuthInfo? SelectedAuth { get; internal set; }
|
||||
|
||||
public string Reason = "";
|
||||
public CurrentAuthInfo? SelectedAuth { get; internal set; }
|
||||
|
||||
public async Task<bool> Auth(AuthLoginPassword authLoginPassword)
|
||||
{
|
||||
@@ -68,4 +68,5 @@ public partial class AuthService(
|
||||
}
|
||||
|
||||
public sealed record CurrentAuthInfo(Guid UserId, LoginToken Token, AuthLoginPassword AuthLoginPassword);
|
||||
|
||||
public record AuthLoginPassword(string Login, string Password, string AuthServer);
|
||||
@@ -5,15 +5,15 @@ namespace Nebula.Shared.Services;
|
||||
|
||||
public class ConVar<T>
|
||||
{
|
||||
public string Name { get; }
|
||||
public Type Type => typeof(T);
|
||||
public T? DefaultValue { get; }
|
||||
|
||||
public ConVar(string name, T? defaultValue = default)
|
||||
{
|
||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||
DefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public Type Type => typeof(T);
|
||||
public T? DefaultValue { get; }
|
||||
}
|
||||
|
||||
public static class ConVarBuilder
|
||||
@@ -30,8 +30,8 @@ public static class ConVarBuilder
|
||||
[ServiceRegister]
|
||||
public class ConfigurationService
|
||||
{
|
||||
private readonly FileService _fileService;
|
||||
private readonly DebugService _debugService;
|
||||
private readonly FileService _fileService;
|
||||
|
||||
public ConfigurationService(FileService fileService, DebugService debugService)
|
||||
{
|
||||
@@ -46,7 +46,6 @@ public class ConfigurationService
|
||||
try
|
||||
{
|
||||
if (_fileService.ConfigurationApi.TryOpen(GetFileName(conVar), out var stream))
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
var obj = JsonSerializer.Deserialize<T>(stream);
|
||||
@@ -57,7 +56,6 @@ public class ConfigurationService
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_debugService.Error($"Error loading config for {conVar.Name}: {e.Message}");
|
||||
@@ -74,7 +72,8 @@ public class ConfigurationService
|
||||
|
||||
if (!conVar.Type.IsInstanceOfType(value))
|
||||
{
|
||||
_debugService.Error($"Type mismatch for config {conVar.Name}. Expected {conVar.Type}, got {value.GetType()}.");
|
||||
_debugService.Error(
|
||||
$"Type mismatch for config {conVar.Name}. Expected {conVar.Type}, got {value.GetType()}.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +104,8 @@ public class ConfigurationService
|
||||
|
||||
public static class ConfigExtensions
|
||||
{
|
||||
public static bool TryGetConfigValue<T>(this ConfigurationService configurationService, ConVar<T> conVar, [NotNullWhen(true)] out T? value)
|
||||
public static bool TryGetConfigValue<T>(this ConfigurationService configurationService, ConVar<T> conVar,
|
||||
[NotNullWhen(true)] out T? value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(configurationService);
|
||||
ArgumentNullException.ThrowIfNull(conVar);
|
||||
|
||||
@@ -15,7 +15,8 @@ public partial class ContentService
|
||||
return fileService.ContentFileApi.Has(item.Hash);
|
||||
}
|
||||
|
||||
public async Task<List<RobustManifestItem>> EnsureItems(ManifestReader manifestReader, Uri downloadUri, ILoadingHandler loadingHandler,
|
||||
public async Task<List<RobustManifestItem>> EnsureItems(ManifestReader manifestReader, Uri downloadUri,
|
||||
ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<RobustManifestItem> allItems = [];
|
||||
@@ -66,7 +67,8 @@ public partial class ContentService
|
||||
return await EnsureItems(manifestReader, info.DownloadUri, loadingHandler, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task Unpack(RobustManifestInfo info, IWriteFileApi otherApi, ILoadingHandler loadingHandler, CancellationToken cancellationToken)
|
||||
public async Task Unpack(RobustManifestInfo info, IWriteFileApi otherApi, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Unpack manifest files");
|
||||
var items = await EnsureItems(info, loadingHandler, cancellationToken);
|
||||
@@ -83,11 +85,13 @@ public partial class ContentService
|
||||
{
|
||||
debugService.Error("OH FUCK!! " + item.Path);
|
||||
}
|
||||
|
||||
loadingHandler.AppendResolvedJob();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, ILoadingHandler loadingHandler, CancellationToken cancellationToken)
|
||||
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (toDownload.Count == 0 || cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -110,7 +114,8 @@ public partial class ContentService
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, contentCdn);
|
||||
request.Headers.Add(
|
||||
"X-Robust-Download-Protocol",
|
||||
varService.GetConfigValue(CurrentConVar.ManifestDownloadProtocolVersion).ToString(CultureInfo.InvariantCulture));
|
||||
varService.GetConfigValue(CurrentConVar.ManifestDownloadProtocolVersion)
|
||||
.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
request.Content = new ByteArrayContent(requestBody);
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
|
||||
@@ -5,10 +5,9 @@ namespace Nebula.Shared.Services;
|
||||
[ServiceRegister]
|
||||
public class DebugService : IDisposable
|
||||
{
|
||||
public ILogger Logger;
|
||||
|
||||
private static string LogPath = Path.Combine(FileService.RootPath, "log");
|
||||
public DateTime LogDate = DateTime.Now;
|
||||
public ILogger Logger;
|
||||
private FileStream LogStream;
|
||||
private StreamWriter LogWriter;
|
||||
|
||||
@@ -26,6 +25,12 @@ public class DebugService : IDisposable
|
||||
//LogWriter = new StreamWriter(LogStream);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogWriter.Dispose();
|
||||
LogStream.Dispose();
|
||||
}
|
||||
|
||||
public void Debug(string message)
|
||||
{
|
||||
Log(LoggerCategory.Debug, message);
|
||||
@@ -48,12 +53,6 @@ public class DebugService : IDisposable
|
||||
Error(e.InnerException);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogWriter.Dispose();
|
||||
LogStream.Dispose();
|
||||
}
|
||||
|
||||
private void Log(LoggerCategory category, string message)
|
||||
{
|
||||
Logger.Log(category, message);
|
||||
|
||||
@@ -15,11 +15,11 @@ public sealed class EngineService
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ConfigurationService _varService;
|
||||
|
||||
private readonly Task _currInfoTask;
|
||||
|
||||
public Dictionary<string, Module> ModuleInfos = default!;
|
||||
public Dictionary<string, EngineVersionInfo> VersionInfos = default!;
|
||||
|
||||
private Task _currInfoTask;
|
||||
|
||||
public EngineService(RestService restService, DebugService debugService, ConfigurationService varService,
|
||||
FileService fileService, IServiceProvider serviceProvider, AssemblyService assemblyService)
|
||||
{
|
||||
|
||||
@@ -14,11 +14,11 @@ public class FileService
|
||||
Environment.SpecialFolder.ApplicationData), "Datum");
|
||||
|
||||
private readonly DebugService _debugService;
|
||||
public readonly IReadWriteFileApi ConfigurationApi;
|
||||
|
||||
public readonly IReadWriteFileApi ContentFileApi;
|
||||
public readonly IReadWriteFileApi EngineFileApi;
|
||||
public readonly IReadWriteFileApi ManifestFileApi;
|
||||
public readonly IReadWriteFileApi ConfigurationApi;
|
||||
|
||||
private HashApi? _hashApi;
|
||||
|
||||
|
||||
@@ -8,14 +8,11 @@ public class HubService
|
||||
private readonly ConfigurationService _configurationService;
|
||||
private readonly RestService _restService;
|
||||
|
||||
private readonly List<ServerHubInfo> _serverList = new();
|
||||
|
||||
public Action<HubServerChangedEventArgs>? HubServerChangedEventArgs;
|
||||
public Action? HubServerLoaded;
|
||||
|
||||
private readonly List<ServerHubInfo> _serverList = new();
|
||||
public IReadOnlyList<ServerHubInfo> ServerList => _serverList;
|
||||
|
||||
private bool _isUpdating = false;
|
||||
public bool IsUpdating => _isUpdating;
|
||||
public HubService(ConfigurationService configurationService, RestService restService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
@@ -24,27 +21,30 @@ public class HubService
|
||||
UpdateHub();
|
||||
}
|
||||
|
||||
public IReadOnlyList<ServerHubInfo> ServerList => _serverList;
|
||||
public bool IsUpdating { get; private set; }
|
||||
|
||||
public async void UpdateHub()
|
||||
{
|
||||
if(_isUpdating) return;
|
||||
if (IsUpdating) return;
|
||||
|
||||
_serverList.Clear();
|
||||
|
||||
_isUpdating = true;
|
||||
IsUpdating = true;
|
||||
|
||||
HubServerChangedEventArgs?.Invoke(new HubServerChangedEventArgs([], HubServerChangeAction.Clear));
|
||||
|
||||
foreach (var urlStr in _configurationService.GetConfigValue(CurrentConVar.Hub)!)
|
||||
{
|
||||
var servers = await _restService.GetAsyncDefault<List<ServerHubInfo>>(new Uri(urlStr), [], CancellationToken.None);
|
||||
var servers =
|
||||
await _restService.GetAsyncDefault<List<ServerHubInfo>>(new Uri(urlStr), [], CancellationToken.None);
|
||||
_serverList.AddRange(servers);
|
||||
HubServerChangedEventArgs?.Invoke(new HubServerChangedEventArgs(servers, HubServerChangeAction.Add));
|
||||
}
|
||||
|
||||
_isUpdating = false;
|
||||
IsUpdating = false;
|
||||
HubServerLoaded?.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class HubServerChangedEventArgs : EventArgs
|
||||
@@ -61,5 +61,7 @@ public class HubServerChangedEventArgs : EventArgs
|
||||
|
||||
public enum HubServerChangeAction
|
||||
{
|
||||
Add, Remove, Clear,
|
||||
Add,
|
||||
Remove,
|
||||
Clear
|
||||
}
|
||||
@@ -3,12 +3,14 @@ namespace Nebula.Shared.Services;
|
||||
[ServiceRegister]
|
||||
public class PopupMessageService
|
||||
{
|
||||
public Action<object>? OnPopupRequired;
|
||||
public Action<object>? OnCloseRequired;
|
||||
public Action<object>? OnPopupRequired;
|
||||
|
||||
public void Popup(object obj)
|
||||
{
|
||||
OnPopupRequired?.Invoke(obj);
|
||||
}
|
||||
|
||||
public void ClosePopup(object obj)
|
||||
{
|
||||
OnCloseRequired?.Invoke(obj);
|
||||
|
||||
@@ -12,7 +12,8 @@ public sealed class RunnerService(
|
||||
EngineService engineService,
|
||||
AssemblyService assemblyService)
|
||||
{
|
||||
public async Task PrepareRun(RobustBuildInfo buildInfo, ILoadingHandler loadingHandler, CancellationToken cancellationToken)
|
||||
public async Task PrepareRun(RobustBuildInfo buildInfo, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Prepare Content!");
|
||||
|
||||
@@ -25,7 +26,8 @@ public sealed class RunnerService(
|
||||
await engineService.EnsureEngineModules("Robust.Client.WebView", buildInfo.BuildInfo.Build.EngineVersion);
|
||||
}
|
||||
|
||||
public async Task Run(string[] runArgs, RobustBuildInfo buildInfo, IRedialApi redialApi, ILoadingHandler loadingHandler,
|
||||
public async Task Run(string[] runArgs, RobustBuildInfo buildInfo, IRedialApi redialApi,
|
||||
ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Start Content!");
|
||||
@@ -49,7 +51,8 @@ public sealed class RunnerService(
|
||||
|
||||
var args = new MainArgs(runArgs, engine, redialApi, extraMounts);
|
||||
|
||||
if (!assemblyService.TryOpenAssembly(varService.GetConfigValue(CurrentConVar.RobustAssemblyName)!, engine, out var clientAssembly))
|
||||
if (!assemblyService.TryOpenAssembly(varService.GetConfigValue(CurrentConVar.RobustAssemblyName)!, engine,
|
||||
out var clientAssembly))
|
||||
throw new Exception("Unable to locate Robust.Client.dll in engine build!");
|
||||
|
||||
if (!assemblyService.TryGetLoader(clientAssembly, out var loader))
|
||||
|
||||
@@ -22,10 +22,6 @@ public static class Helper
|
||||
{
|
||||
Process.Start("open", url);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<T> AsJson<T>(this HttpContent content) where T : notnull
|
||||
|
||||
132
Nebula.SourceGenerators/DependencyAutoGenerator.cs
Normal file
132
Nebula.SourceGenerators/DependencyAutoGenerator.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
namespace Nebula.SourceGenerators;
|
||||
|
||||
[Generator]
|
||||
public class DependencyAutoGenerator : IIncrementalGenerator
|
||||
{
|
||||
private static readonly string ConstructGeneratorAttributeName = "ConstructGeneratorAttribute";
|
||||
private static readonly string GeneratePropertyAttributeName = "GeneratePropertyAttribute";
|
||||
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
GenerateAttribute(ConstructGeneratorAttributeName, "Class", context);
|
||||
GenerateAttribute(GeneratePropertyAttributeName, "Property", context);
|
||||
|
||||
var provider = context.SyntaxProvider
|
||||
.CreateSyntaxProvider(
|
||||
(s, _) => s is ClassDeclarationSyntax,
|
||||
(ctx, _) => GetClassDeclarationForSourceGen(ctx))
|
||||
.Where(t => t.reportAttributeFound)
|
||||
.Select((t, _) => t.Item1);
|
||||
|
||||
context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()),
|
||||
(ctx, t) => GenerateCode(ctx, t.Left, t.Right));
|
||||
}
|
||||
|
||||
private static void GenerateAttribute(string attributeName, string usage,
|
||||
IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
var attributeSourceCode = $@"// <auto-generated/>
|
||||
|
||||
namespace SourceGen
|
||||
{{
|
||||
[System.AttributeUsage(System.AttributeTargets.{usage})]
|
||||
public class {attributeName} : System.Attribute
|
||||
{{
|
||||
}}
|
||||
}}";
|
||||
|
||||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource(
|
||||
$"{attributeName}.g.cs",
|
||||
SourceText.From(attributeSourceCode, Encoding.UTF8)));
|
||||
}
|
||||
|
||||
private static (ClassDeclarationSyntax, bool reportAttributeFound) GetClassDeclarationForSourceGen(
|
||||
GeneratorSyntaxContext context)
|
||||
{
|
||||
var classDeclarationSyntax = (ClassDeclarationSyntax)context.Node;
|
||||
|
||||
foreach (var attributeListSyntax in classDeclarationSyntax.AttributeLists)
|
||||
foreach (var attributeSyntax in attributeListSyntax.Attributes)
|
||||
{
|
||||
if (context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
|
||||
continue;
|
||||
|
||||
var attributeName = attributeSymbol.ContainingType.ToDisplayString();
|
||||
|
||||
if (attributeName == $"SourceGen.{ConstructGeneratorAttributeName}")
|
||||
return (classDeclarationSyntax, true);
|
||||
}
|
||||
|
||||
return (classDeclarationSyntax, false);
|
||||
}
|
||||
|
||||
private void GenerateCode(SourceProductionContext context, Compilation compilation,
|
||||
ImmutableArray<ClassDeclarationSyntax> classDeclarations)
|
||||
{
|
||||
foreach (var classDeclarationSyntax in classDeclarations)
|
||||
{
|
||||
var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree);
|
||||
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
|
||||
continue;
|
||||
|
||||
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
||||
var className = classDeclarationSyntax.Identifier.Text;
|
||||
|
||||
var defaultConstruct = $@"public {className}(){{}}";
|
||||
|
||||
var propertiesGenerated = GetProperties(classSymbol).ToList();
|
||||
|
||||
var constr = propertiesGenerated.Select(a => $"{a.Type.ToDisplayString()} g{a.Name}");
|
||||
var body = propertiesGenerated.Select(a => $"this.{a.Name} = g{a.Name};");
|
||||
|
||||
if (!constr.Any()) defaultConstruct = "";
|
||||
|
||||
var code = $@"// <auto-generated/>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace {namespaceName};
|
||||
|
||||
partial class {className}
|
||||
{{
|
||||
|
||||
{defaultConstruct}
|
||||
public {className}(
|
||||
{string.Join(",\n\t\t", constr)}
|
||||
) : base(){{
|
||||
{string.Join("\n\t\t", body)}
|
||||
if (Avalonia.Controls.Design.IsDesignMode) InitialiseInDesignMode();
|
||||
else Initialise();
|
||||
}}
|
||||
}}
|
||||
";
|
||||
|
||||
// Add the source code to the compilation.
|
||||
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<IPropertySymbol> GetProperties(INamedTypeSymbol classSymbol)
|
||||
{
|
||||
return classSymbol.GetMembers().OfType<IPropertySymbol>().Where(a =>
|
||||
HasAttribute(a, $"SourceGen.{GeneratePropertyAttributeName}"));
|
||||
}
|
||||
|
||||
private static bool HasAttribute(ISymbol type, string attributeName)
|
||||
{
|
||||
foreach (var attribute in type.GetAttributes())
|
||||
if (attribute.AttributeClass?.ToDisplayString() == attributeName)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
26
Nebula.SourceGenerators/Nebula.SourceGenerators.csproj
Normal file
26
Nebula.SourceGenerators/Nebula.SourceGenerators.csproj
Normal file
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
<IsRoslynComponent>true</IsRoslynComponent>
|
||||
|
||||
<RootNamespace>Nebula.SourceGenerators</RootNamespace>
|
||||
<PackageId>Nebula.SourceGenerators</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0"/>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
9
Nebula.SourceGenerators/Properties/launchSettings.json
Normal file
9
Nebula.SourceGenerators/Properties/launchSettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"DebugRoslynSourceGenerator": {
|
||||
"commandName": "DebugRoslynComponent",
|
||||
"targetProject": "../Nebula.Shared/Nebula.Shared.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebula.Shared", "Nebula.Sha
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebula.Runner", "Nebula.Runner\Nebula.Runner.csproj", "{82D96367-44B0-4F25-A094-CBE73B052B73}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebula.SourceGenerators", "Nebula.SourceGenerators\Nebula.SourceGenerators.csproj", "{985A8F36-AFEB-4E85-8EDB-7C9DDEC698DC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -30,5 +32,9 @@ Global
|
||||
{82D96367-44B0-4F25-A094-CBE73B052B73}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{82D96367-44B0-4F25-A094-CBE73B052B73}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{82D96367-44B0-4F25-A094-CBE73B052B73}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{985A8F36-AFEB-4E85-8EDB-7C9DDEC698DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{985A8F36-AFEB-4E85-8EDB-7C9DDEC698DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{985A8F36-AFEB-4E85-8EDB-7C9DDEC698DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{985A8F36-AFEB-4E85-8EDB-7C9DDEC698DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Reference in New Issue
Block a user