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:
commit
55337fe120
@ -24,10 +24,15 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string ExecutablePath = Utilities.GetCurrentLocation();
|
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>
|
/// <summary>
|
||||||
/// The full path to the Artemis data folder
|
/// The full path to the Artemis data folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string DataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Artemis");
|
public static readonly string DataFolder = Path.Combine(BaseFolder, "Artemis");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The full path to the Artemis logs folder
|
/// The full path to the Artemis logs folder
|
||||||
|
|||||||
@ -2,14 +2,19 @@ using Avalonia;
|
|||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using Ninject;
|
||||||
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
|
||||||
namespace Artemis.UI.Linux
|
namespace Artemis.UI.Linux
|
||||||
{
|
{
|
||||||
public class App : Application
|
public class App : Application
|
||||||
{
|
{
|
||||||
|
private StandardKernel? _kernel;
|
||||||
|
private ApplicationStateManager? _applicationStateManager;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
ArtemisBootstrapper.Bootstrap(this);
|
_kernel = ArtemisBootstrapper.Bootstrap(this);
|
||||||
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
|
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
@ -17,6 +22,8 @@ namespace Artemis.UI.Linux
|
|||||||
public override void OnFrameworkInitializationCompleted()
|
public override void OnFrameworkInitializationCompleted()
|
||||||
{
|
{
|
||||||
ArtemisBootstrapper.Initialize();
|
ArtemisBootstrapper.Initialize();
|
||||||
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
|
_applicationStateManager = new ApplicationStateManager(_kernel!, desktop.Args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
141
src/Avalonia/Artemis.UI.Linux/ApplicationStateManager.cs
Normal file
141
src/Avalonia/Artemis.UI.Linux/ApplicationStateManager.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@
|
|||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--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 Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.10" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.10" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.10" />
|
||||||
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.80.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />
|
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />
|
||||||
|
|||||||
@ -53,6 +53,15 @@
|
|||||||
"System.Reactive": "5.0.0"
|
"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": {
|
"Avalonia.Angle.Windows.Natives": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "2.1.0.2020091801",
|
"resolved": "2.1.0.2020091801",
|
||||||
@ -678,14 +687,6 @@
|
|||||||
"SkiaSharp": "2.80.2"
|
"SkiaSharp": "2.80.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SkiaSharp.NativeAssets.Linux": {
|
|
||||||
"type": "Transitive",
|
|
||||||
"resolved": "2.80.2",
|
|
||||||
"contentHash": "uQSxFy5iVTK6tENWrlc+HCKGSCLgJ+d2KGXUlC1OMCXlKOVkzMqdwa0gMukrEA6HYdO+qk6IUq3ya4fk70EB4g==",
|
|
||||||
"dependencies": {
|
|
||||||
"SkiaSharp": "2.80.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Splat": {
|
"Splat": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "13.1.63",
|
"resolved": "13.1.63",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Core.Ninject;
|
using Artemis.Core.Ninject;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Ninject;
|
using Artemis.UI.Ninject;
|
||||||
using Artemis.UI.Screens.Root;
|
using Artemis.UI.Screens.Root;
|
||||||
@ -20,6 +21,8 @@ namespace Artemis.UI
|
|||||||
{
|
{
|
||||||
if (_application != null || _kernel != null)
|
if (_application != null || _kernel != null)
|
||||||
throw new ArtemisUIException("UI already bootstrapped");
|
throw new ArtemisUIException("UI already bootstrapped");
|
||||||
|
|
||||||
|
Utilities.PrepareFirstLaunch();
|
||||||
|
|
||||||
_application = application;
|
_application = application;
|
||||||
_kernel = new StandardKernel();
|
_kernel = new StandardKernel();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user