- fix: remove cloning server entry in list
This commit is contained in:
@@ -7,6 +7,7 @@ using Avalonia.Controls.ApplicationLifetimes;
|
|||||||
using Avalonia.Data.Core.Plugins;
|
using Avalonia.Data.Core.Plugins;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Nebula.Launcher.ViewModels.ContentView;
|
||||||
using Nebula.Launcher.Views;
|
using Nebula.Launcher.Views;
|
||||||
using Nebula.Shared;
|
using Nebula.Shared;
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ public class App : Application
|
|||||||
services.AddAvaloniaServices();
|
services.AddAvaloniaServices();
|
||||||
services.AddServices();
|
services.AddServices();
|
||||||
services.AddViews();
|
services.AddViews();
|
||||||
|
services.AddTransient<DecompilerContentView>();
|
||||||
|
|
||||||
var serviceProvider = services.BuildServiceProvider();
|
var serviceProvider = services.BuildServiceProvider();
|
||||||
|
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ public static class LauncherConVar
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
public static readonly ConVar<string> CurrentLang = ConVarBuilder.Build<string>("launcher.language", "en-US");
|
public static readonly ConVar<string> CurrentLang = ConVarBuilder.Build<string>("launcher.language", "en-US");
|
||||||
|
public static readonly ConVar<string> ILSpyUrl = ConVarBuilder.Build<string>("decompiler.url",
|
||||||
|
"https://github.com/icsharpcode/ILSpy/releases/download/v9.0/ILSpy_binaries_9.0.0.7889-x64.zip");
|
||||||
}
|
}
|
||||||
54
Nebula.Launcher/Services/DecompilerService.cs
Normal file
54
Nebula.Launcher/Services/DecompilerService.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Nebula.Launcher.ViewModels.Popup;
|
||||||
|
using Nebula.Shared;
|
||||||
|
using Nebula.Shared.FileApis;
|
||||||
|
using Nebula.Shared.FileApis.Interfaces;
|
||||||
|
using Nebula.Shared.Services;
|
||||||
|
|
||||||
|
namespace Nebula.Launcher.Services;
|
||||||
|
|
||||||
|
[ConstructGenerator, ServiceRegister]
|
||||||
|
public sealed partial class DecompilerService
|
||||||
|
{
|
||||||
|
[GenerateProperty] private ConfigurationService ConfigurationService { get; }
|
||||||
|
[GenerateProperty] private PopupMessageService PopupMessageService {get;}
|
||||||
|
[GenerateProperty] private ViewHelperService ViewHelperService {get;}
|
||||||
|
|
||||||
|
private HttpClient _httpClient = new HttpClient();
|
||||||
|
|
||||||
|
private static string fullPath = Path.Join(FileService.RootPath,"ILSpy");
|
||||||
|
private static string executePath = Path.Join(fullPath, "ILSpy.exe");
|
||||||
|
|
||||||
|
public async void OpenDecompiler(string path){
|
||||||
|
await EnsureILSpy();
|
||||||
|
var startInfo = new ProcessStartInfo(){
|
||||||
|
FileName = executePath,
|
||||||
|
Arguments = path
|
||||||
|
};
|
||||||
|
Process.Start(startInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Initialise(){}
|
||||||
|
private void InitialiseInDesignMode(){}
|
||||||
|
|
||||||
|
private async Task EnsureILSpy(){
|
||||||
|
if(!Directory.Exists(fullPath))
|
||||||
|
await Download();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Download(){
|
||||||
|
using var loading = ViewHelperService.GetViewModel<LoadingContextViewModel>();
|
||||||
|
loading.LoadingName = "Download ILSpy";
|
||||||
|
loading.SetJobsCount(1);
|
||||||
|
PopupMessageService.Popup(loading);
|
||||||
|
using var response = await _httpClient.GetAsync(ConfigurationService.GetConfigValue(LauncherConVar.ILSpyUrl));
|
||||||
|
using var zipArchive = new ZipArchive(await response.Content.ReadAsStreamAsync());
|
||||||
|
Directory.CreateDirectory(fullPath);
|
||||||
|
zipArchive.ExtractToDirectory(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System.IO;
|
||||||
|
using Nebula.Launcher.Services;
|
||||||
|
using Nebula.Launcher.ViewModels.Pages;
|
||||||
|
|
||||||
|
namespace Nebula.Launcher.ViewModels.ContentView;
|
||||||
|
|
||||||
|
[ConstructGenerator]
|
||||||
|
public sealed partial class DecompilerContentView: ContentViewBase
|
||||||
|
{
|
||||||
|
[GenerateProperty] private DecompilerService decompilerService {get;}
|
||||||
|
|
||||||
|
public override void InitialiseWithData(ContentPath path, Stream stream)
|
||||||
|
{
|
||||||
|
base.InitialiseWithData(path, stream);
|
||||||
|
var myTempFile = Path.Combine(Path.GetTempPath(), "tempie.dll");
|
||||||
|
|
||||||
|
var sw = new FileStream(myTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||||
|
stream.CopyTo(sw);
|
||||||
|
sw.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
decompilerService.OpenDecompiler(myTempFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InitialiseInDesignMode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,14 +7,12 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Media;
|
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Avalonia.Platform;
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Nebula.Launcher.Services;
|
using Nebula.Launcher.Services;
|
||||||
using Nebula.Launcher.ViewModels.ContentView;
|
using Nebula.Launcher.ViewModels.ContentView;
|
||||||
using Nebula.Launcher.ViewModels.Popup;
|
using Nebula.Launcher.ViewModels.Popup;
|
||||||
using Nebula.Launcher.Views.Pages;
|
using Nebula.Launcher.Views.Pages;
|
||||||
|
using Nebula.Shared.FileApis;
|
||||||
using Nebula.Shared.Models;
|
using Nebula.Shared.Models;
|
||||||
using Nebula.Shared.Services;
|
using Nebula.Shared.Services;
|
||||||
using Nebula.Shared.Utils;
|
using Nebula.Shared.Utils;
|
||||||
@@ -44,6 +42,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
[GenerateProperty] private DebugService DebugService { get; } = default!;
|
[GenerateProperty] private DebugService DebugService { get; } = default!;
|
||||||
[GenerateProperty] private PopupMessageService PopupService { get; } = default!;
|
[GenerateProperty] private PopupMessageService PopupService { get; } = default!;
|
||||||
[GenerateProperty] private HubService HubService { get; } = default!;
|
[GenerateProperty] private HubService HubService { get; } = default!;
|
||||||
|
[GenerateProperty] private IServiceProvider ServiceProvider {get;}
|
||||||
[GenerateProperty, DesignConstruct] private ViewHelperService ViewHelperService { get; } = default!;
|
[GenerateProperty, DesignConstruct] private ViewHelperService ViewHelperService { get; } = default!;
|
||||||
|
|
||||||
public ObservableCollection<ContentEntry> Entries { get; } = new();
|
public ObservableCollection<ContentEntry> Entries { get; } = new();
|
||||||
@@ -55,45 +54,48 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
get => _selectedEntry;
|
get => _selectedEntry;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
var oldSearchText = SearchText;
|
||||||
SearchText = value?.GetPath().ToString() ?? "";
|
SearchText = value?.GetPath().ToString() ?? "";
|
||||||
|
|
||||||
ContentView = null;
|
ContentView = null;
|
||||||
|
|
||||||
if (value is { Item: not null })
|
|
||||||
{
|
|
||||||
if (FileService.ContentFileApi.TryOpen(value.Item.Value.Hash, out var stream))
|
|
||||||
{
|
|
||||||
var ext = Path.GetExtension(value.Item.Value.Path);
|
|
||||||
if(TryGetContentViewer(ext, out var contentViewBase)){
|
|
||||||
contentViewBase.InitialiseWithData(value.GetPath(), stream);
|
|
||||||
ContentView = contentViewBase;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var myTempFile = Path.Combine(Path.GetTempPath(), "tempie" + ext);
|
|
||||||
|
|
||||||
using (var sw = new FileStream(myTempFile, FileMode.Create, FileAccess.Write, FileShare.None))
|
|
||||||
{
|
|
||||||
stream.CopyTo(sw);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.Dispose();
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo(myTempFile)
|
|
||||||
{
|
|
||||||
UseShellExecute = true
|
|
||||||
};
|
|
||||||
|
|
||||||
Process.Start(startInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entries.Clear();
|
Entries.Clear();
|
||||||
_selectedEntry = value;
|
_selectedEntry = value;
|
||||||
|
|
||||||
if (value == null) return;
|
if (value == null) return;
|
||||||
|
|
||||||
|
if(value.TryOpen(out var stream, out var item)){
|
||||||
|
|
||||||
|
var ext = Path.GetExtension(item.Value.Path);
|
||||||
|
var myTempFile = Path.Combine(Path.GetTempPath(), "tempie" + ext);
|
||||||
|
|
||||||
|
if(TryGetContentViewer(ext, out var contentViewBase)){
|
||||||
|
DebugService.Debug($"Opening custom context:{item.Value.Path}");
|
||||||
|
contentViewBase.InitialiseWithData(value.GetPath(), stream);
|
||||||
|
ContentView = contentViewBase;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sw = new FileStream(myTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||||
|
stream.CopyTo(sw);
|
||||||
|
|
||||||
|
sw.Dispose();
|
||||||
|
stream.Dispose();
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo(myTempFile)
|
||||||
|
{
|
||||||
|
UseShellExecute = true
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DebugService.Log("Opening " + myTempFile);
|
||||||
|
Process.Start(startInfo);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SearchText.Length > oldSearchText.Length)
|
||||||
|
AppendHistory(oldSearchText);
|
||||||
|
|
||||||
foreach (var (_, entryCh) in value.Childs) Entries.Add(entryCh);
|
foreach (var (_, entryCh) in value.Childs) Entries.Add(entryCh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,17 +105,16 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
if(!_contentContainers.TryGetValue(type, out var contentViewType) ||
|
if(!_contentContainers.TryGetValue(type, out var contentViewType) ||
|
||||||
!contentViewType.IsAssignableTo(typeof(ContentViewBase)))
|
!contentViewType.IsAssignableTo(typeof(ContentViewBase)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
contentViewBase = (ContentViewBase)Activator.CreateInstance(contentViewType)!;
|
contentViewBase = (ContentViewBase)ServiceProvider.GetService(contentViewType)!;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void InitialiseInDesignMode()
|
protected override void InitialiseInDesignMode()
|
||||||
{
|
{
|
||||||
var a = new ContentEntry(this, "A:", "A", "");
|
var a = new ContentEntry(this, "A:", "A", "", default!);
|
||||||
var b = new ContentEntry(this, "B", "B", "");
|
var b = new ContentEntry(this, "B", "B", "", default!);
|
||||||
a.TryAddChild(b);
|
a.TryAddChild(b);
|
||||||
Entries.Add(a);
|
Entries.Add(a);
|
||||||
}
|
}
|
||||||
@@ -126,6 +127,8 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
HubService.HubServerLoaded += GoHome;
|
HubService.HubServerLoaded += GoHome;
|
||||||
|
|
||||||
if (!HubService.IsUpdating) GoHome();
|
if (!HubService.IsUpdating) GoHome();
|
||||||
|
|
||||||
|
_contentContainers.Add(".dll",typeof(DecompilerContentView));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GoHome()
|
private void GoHome()
|
||||||
@@ -142,10 +145,10 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
|
|
||||||
private void FillRoot(IEnumerable<ServerHubInfo> infos)
|
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, default!));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Go(ContentPath path, bool appendHistory = true)
|
public async void Go(ContentPath path)
|
||||||
{
|
{
|
||||||
if (path.Pathes.Count > 0 && (path.Pathes[0].StartsWith("ss14://") || path.Pathes[0].StartsWith("ss14s://")))
|
if (path.Pathes.Count > 0 && (path.Pathes[0].StartsWith("ss14://") || path.Pathes[0].StartsWith("ss14s://")))
|
||||||
{
|
{
|
||||||
@@ -181,7 +184,7 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
|
|
||||||
public void OnBackEnter()
|
public void OnBackEnter()
|
||||||
{
|
{
|
||||||
Go(new ContentPath(GetHistory()), false);
|
Go(new ContentPath(GetHistory()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnGoEnter()
|
public void OnGoEnter()
|
||||||
@@ -200,12 +203,12 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase , IViewModel
|
|||||||
var hashApi = await ContentService.EnsureItems(info.RobustManifestInfo, loading,
|
var hashApi = await ContentService.EnsureItems(info.RobustManifestInfo, loading,
|
||||||
CancellationService.Token);
|
CancellationService.Token);
|
||||||
|
|
||||||
var rootEntry = new ContentEntry(this, "", "", serverUrl);
|
var rootEntry = new ContentEntry(this, "", "", serverUrl, default!);
|
||||||
|
|
||||||
foreach (var item in hashApi.Manifest.Values)
|
foreach (var item in hashApi.Manifest.Values)
|
||||||
{
|
{
|
||||||
var path = new ContentPath(item.Path);
|
var path = new ContentPath(item.Path);
|
||||||
rootEntry.CreateItem(path, item);
|
rootEntry.CreateItem(path, item, hashApi);
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.Dispose();
|
loading.Dispose();
|
||||||
@@ -236,15 +239,17 @@ public class ContentEntry
|
|||||||
{
|
{
|
||||||
private readonly Dictionary<string, ContentEntry> _childs = new();
|
private readonly Dictionary<string, ContentEntry> _childs = new();
|
||||||
private readonly ContentBrowserViewModel _viewModel;
|
private readonly ContentBrowserViewModel _viewModel;
|
||||||
|
private HashApi _fileApi;
|
||||||
|
|
||||||
public RobustManifestItem? Item;
|
public RobustManifestItem? Item { get; private set; }
|
||||||
|
|
||||||
internal ContentEntry(ContentBrowserViewModel viewModel, string name, string pathName, string serverName)
|
internal ContentEntry(ContentBrowserViewModel viewModel, string name, string pathName, string serverName, HashApi fileApi)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
ServerName = serverName;
|
ServerName = serverName;
|
||||||
PathName = pathName;
|
PathName = pathName;
|
||||||
_viewModel = viewModel;
|
_viewModel = viewModel;
|
||||||
|
_fileApi = fileApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDirectory => Item == null;
|
public bool IsDirectory => Item == null;
|
||||||
@@ -259,6 +264,22 @@ public class ContentEntry
|
|||||||
|
|
||||||
public IReadOnlyDictionary<string, ContentEntry> Childs => _childs.ToFrozenDictionary();
|
public IReadOnlyDictionary<string, ContentEntry> Childs => _childs.ToFrozenDictionary();
|
||||||
|
|
||||||
|
public Stream Open()
|
||||||
|
{
|
||||||
|
_fileApi.TryOpen(Item!.Value, out var stream);
|
||||||
|
return stream!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryOpen([NotNullWhen(true)] out Stream? stream,[NotNullWhen(true)] out RobustManifestItem? item){
|
||||||
|
stream = null;
|
||||||
|
item = null;
|
||||||
|
if(Item is null || !_fileApi.TryOpen(Item.Value, out stream))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
item = Item;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGetChild(string name, [NotNullWhen(true)] out ContentEntry? child)
|
public bool TryGetChild(string name, [NotNullWhen(true)] out ContentEntry? child)
|
||||||
{
|
{
|
||||||
return _childs.TryGetValue(name, out child);
|
return _childs.TryGetValue(name, out child);
|
||||||
@@ -295,7 +316,7 @@ public class ContentEntry
|
|||||||
|
|
||||||
if (!TryGetChild(fName, out var child))
|
if (!TryGetChild(fName, out var child))
|
||||||
{
|
{
|
||||||
child = new ContentEntry(_viewModel, fName, fName, ServerName);
|
child = new ContentEntry(_viewModel, fName, fName, ServerName, _fileApi);
|
||||||
TryAddChild(child);
|
TryAddChild(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,13 +329,13 @@ public class ContentEntry
|
|||||||
return Parent.GetRoot();
|
return Parent.GetRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentEntry CreateItem(ContentPath path, RobustManifestItem item)
|
public ContentEntry CreateItem(ContentPath path, RobustManifestItem item, HashApi fileApi)
|
||||||
{
|
{
|
||||||
var dir = path.GetDirectory();
|
var dir = path.GetDirectory();
|
||||||
var dirEntry = GetOrCreateDirectory(dir);
|
var dirEntry = GetOrCreateDirectory(dir);
|
||||||
|
|
||||||
var name = path.GetName();
|
var name = path.GetName();
|
||||||
var entry = new ContentEntry(_viewModel, name, name, ServerName)
|
var entry = new ContentEntry(_viewModel, name, name, ServerName, fileApi)
|
||||||
{
|
{
|
||||||
Item = item
|
Item = item
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using Nebula.Shared;
|
|
||||||
using Nebula.Shared.Models;
|
using Nebula.Shared.Models;
|
||||||
using Nebula.Shared.Services;
|
using Nebula.Shared.Services;
|
||||||
using Nebula.Shared.Utils;
|
using Nebula.Shared.Utils;
|
||||||
@@ -16,11 +11,13 @@ public partial class ServerListViewModel
|
|||||||
[GenerateProperty] private ConfigurationService ConfigurationService { get; }
|
[GenerateProperty] private ConfigurationService ConfigurationService { get; }
|
||||||
[GenerateProperty] private RestService RestService { get; }
|
[GenerateProperty] private RestService RestService { get; }
|
||||||
|
|
||||||
public ObservableCollection<ServerEntryModelView> FavoriteServers { get; } = new();
|
public ObservableCollection<ServerEntryModelView> FavoriteServers { get; } = [];
|
||||||
|
|
||||||
private void UpdateFavoriteEntries()
|
private void UpdateFavoriteEntries()
|
||||||
{
|
{
|
||||||
FavoriteServers.Clear();
|
foreach(var fav in FavoriteServers.ToList()){
|
||||||
|
FavoriteServers.Remove(fav);
|
||||||
|
}
|
||||||
|
|
||||||
var servers = ConfigurationService.GetConfigValue(LauncherConVar.Favorites);
|
var servers = ConfigurationService.GetConfigValue(LauncherConVar.Favorites);
|
||||||
if (servers is null || servers.Length == 0)
|
if (servers is null || servers.Length == 0)
|
||||||
|
|||||||
@@ -67,7 +67,10 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage
|
|||||||
|
|
||||||
private void UpdateServerEntries()
|
private void UpdateServerEntries()
|
||||||
{
|
{
|
||||||
Servers.Clear();
|
foreach(var fav in Servers.ToList()){
|
||||||
|
Servers.Remove(fav);
|
||||||
|
}
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
UnsortedServers.Sort(new ServerComparer());
|
UnsortedServers.Sort(new ServerComparer());
|
||||||
@@ -105,7 +108,6 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage
|
|||||||
{
|
{
|
||||||
UnsortedServers.Clear();
|
UnsortedServers.Clear();
|
||||||
ServerViewContainer.Clear();
|
ServerViewContainer.Clear();
|
||||||
Servers.Clear();
|
|
||||||
UpdateFavoriteEntries();
|
UpdateFavoriteEntries();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ public class FileService
|
|||||||
|
|
||||||
var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Read);
|
var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Read);
|
||||||
|
|
||||||
var prefix = "";
|
return new ZipFileApi(zipArchive, "");
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) prefix = "Space Station 14.app/Contents/Resources/";
|
|
||||||
return new ZipFileApi(zipArchive, prefix);
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user