1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Merge remote-tracking branch 'origin/feature/avalonia' into feature/avalonia

This commit is contained in:
Robert 2021-12-04 12:02:24 +01:00
commit 55337fe120
6 changed files with 168 additions and 10 deletions

View File

@ -24,10 +24,15 @@ namespace Artemis.Core
/// </summary>
public static readonly string ExecutablePath = Utilities.GetCurrentLocation();
/// <summary>
/// The base path for Artemis application data folder
/// </summary>
public static readonly string BaseFolder = Environment.GetFolderPath(OperatingSystem.IsWindows() ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.LocalApplicationData);
/// <summary>
/// The full path to the Artemis data folder
/// </summary>
public static readonly string DataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Artemis");
public static readonly string DataFolder = Path.Combine(BaseFolder, "Artemis");
/// <summary>
/// The full path to the Artemis logs folder

View File

@ -2,14 +2,19 @@ using Avalonia;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using ReactiveUI;
using Ninject;
using Avalonia.Controls.ApplicationLifetimes;
namespace Artemis.UI.Linux
{
public class App : Application
{
private StandardKernel? _kernel;
private ApplicationStateManager? _applicationStateManager;
public override void Initialize()
{
ArtemisBootstrapper.Bootstrap(this);
_kernel = ArtemisBootstrapper.Bootstrap(this);
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this);
}
@ -17,6 +22,8 @@ namespace Artemis.UI.Linux
public override void OnFrameworkInitializationCompleted()
{
ArtemisBootstrapper.Initialize();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
_applicationStateManager = new ApplicationStateManager(_kernel!, desktop.Args);
}
}
}

View File

@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Principal;
using System.Threading;
using Artemis.Core;
using Artemis.UI.Shared.Services.Interfaces;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Threading;
using Ninject;
namespace Artemis.UI.Linux
{
public class ApplicationStateManager
{
private readonly IWindowService _windowService;
// ReSharper disable once NotAccessedField.Local - Kept in scope to ensure it does not get released
private Mutex? _artemisMutex;
public ApplicationStateManager(IKernel kernel, string[] startupArguments)
{
_windowService = kernel.Get<IWindowService>();
StartupArguments = startupArguments;
Core.Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
Core.Utilities.RestartRequested += UtilitiesOnRestartRequested;
// On OS shutdown dispose the kernel just so device providers get a chance to clean up
if (Application.Current.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
{
controlledApplicationLifetime.Exit += (_, _) =>
{
RunForcedShutdownIfEnabled();
kernel.Dispose();
};
}
}
public string[] StartupArguments { get; }
public bool FocusExistingInstance()
{
_artemisMutex = new Mutex(true, "Artemis-3c24b502-64e6-4587-84bf-9072970e535d", out bool createdNew);
if (createdNew)
return false;
return RemoteFocus();
}
public void DisplayException(Exception e)
{
try
{
_windowService.ShowExceptionDialog("An unhandled exception occured", e);
}
catch
{
// ignored, we tried
}
}
private bool RemoteFocus()
{
// At this point we cannot read the database yet to retrieve the web server port.
// Instead use the method external applications should use as well.
if (!File.Exists(Path.Combine(Constants.DataFolder, "webserver.txt")))
{
KillOtherInstances();
return false;
}
string url = File.ReadAllText(Path.Combine(Constants.DataFolder, "webserver.txt"));
using HttpClient client = new();
try
{
CancellationTokenSource cts = new();
cts.CancelAfter(2000);
HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground"), cts.Token);
httpResponseMessage.EnsureSuccessStatusCode();
return true;
}
catch (Exception)
{
KillOtherInstances();
return false;
}
}
private void KillOtherInstances()
{
// Kill everything else heh
List<Process> processes = Process.GetProcessesByName("Artemis.UI").Where(p => p.Id != Process.GetCurrentProcess().Id).ToList();
foreach (Process process in processes)
{
try
{
process.Kill(true);
}
catch (Exception)
{
// ignored
}
}
}
private void UtilitiesOnRestartRequested(object? sender, RestartEventArgs e)
{
List<string> argsList = new();
argsList.AddRange(StartupArguments);
if (e.ExtraArgs != null)
argsList.AddRange(e.ExtraArgs.Except(argsList));
//TODO: start new instance with correct arguments
if (Application.Current.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
Dispatcher.UIThread.Post(() => controlledApplicationLifetime.Shutdown());
}
private void UtilitiesOnShutdownRequested(object? sender, EventArgs e)
{
RunForcedShutdownIfEnabled();
if (Application.Current.ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime)
Dispatcher.UIThread.Post(() => controlledApplicationLifetime.Shutdown());
}
private void RunForcedShutdownIfEnabled()
{
if (StartupArguments.Contains("--disable-forced-shutdown"))
return;
//todo
}
}
}

View File

@ -14,6 +14,7 @@
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.10" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.10" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.80.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />

View File

@ -53,6 +53,15 @@
"System.Reactive": "5.0.0"
}
},
"SkiaSharp.NativeAssets.Linux": {
"type": "Direct",
"requested": "[2.80.3, )",
"resolved": "2.80.3",
"contentHash": "LYl/mvEXrsKMdDNPVjA4ul8JDDGZI8DIkFE0a5GdhaC/aooxgwjuaXZ9NfPg4cJsRf8tb6VhGHvjSNUngNOcJw==",
"dependencies": {
"SkiaSharp": "2.80.3"
}
},
"Avalonia.Angle.Windows.Natives": {
"type": "Transitive",
"resolved": "2.1.0.2020091801",
@ -678,14 +687,6 @@
"SkiaSharp": "2.80.2"
}
},
"SkiaSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "2.80.2",
"contentHash": "uQSxFy5iVTK6tENWrlc+HCKGSCLgJ+d2KGXUlC1OMCXlKOVkzMqdwa0gMukrEA6HYdO+qk6IUq3ya4fk70EB4g==",
"dependencies": {
"SkiaSharp": "2.80.2"
}
},
"Splat": {
"type": "Transitive",
"resolved": "13.1.63",

View File

@ -1,4 +1,5 @@
using Artemis.Core.Ninject;
using Artemis.Core;
using Artemis.UI.Exceptions;
using Artemis.UI.Ninject;
using Artemis.UI.Screens.Root;
@ -20,6 +21,8 @@ namespace Artemis.UI
{
if (_application != null || _kernel != null)
throw new ArtemisUIException("UI already bootstrapped");
Utilities.PrepareFirstLaunch();
_application = application;
_kernel = new StandardKernel();