Skip to content
Open
3 changes: 2 additions & 1 deletion source/Reloaded.Mod.Launcher.Lib/Lib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static void Init(IDictionaryResourceProvider provider, SynchronizationCon
Actions.ShowModLoaderUpdateDialogDelegate showModLoaderUpdate, Actions.ShowModUpdateDialogDelegate showModUpdate, Actions.ConfigureNuGetFeedsDialogDelegate configureNuGetFeeds,
Actions.ConfigureModDialogDelegate configureModDialog, Actions.ShowMissingCoreDependencyDialogDelegate showMissingCoreDependency,
Actions.EditModDialogDelegate editModDialog, Actions.PublishModDialogDelegate publishModDialog,
Actions.ShowEditModUserConfigDialogDelegate showEditModUserConfig, Actions.ShowFetchPackageDialogDelegate showFetchPackageDialog,
Actions.ShowEditModUserConfigDialogDelegate showEditModUserConfig, Actions.ShowFetchPackageDialogDelegate showFetchPackageDialog, Actions.ShowInstallPackageDialogDelegate showInstallPackageDialog,
Actions.ShowSelectAddedGameDialogDelegate showSelectAddedGameDialog, Actions.ShowAddAppHashMismatchDialogDelegate showAddAppMismatchDialog,
Actions.ShowApplicationWarningDialogDelegate showApplicationWarningDialog, Actions.ShowRunAppViaWineDialogDelegate showRunAppViaWineDialog,
Actions.ShowEditPackDialogDelegate showEditPackDialog, Actions.ShowInstallModPackDialogDelegate showInstallModPackDialog, Action initControllerSupport)
Expand All @@ -85,6 +85,7 @@ public static void Init(IDictionaryResourceProvider provider, SynchronizationCon
Actions.PublishModDialog = publishModDialog;
Actions.ShowEditModUserConfig = showEditModUserConfig;
Actions.ShowFetchPackageDialog = showFetchPackageDialog;
Actions.ShowInstallPackageDialog = showInstallPackageDialog;
Actions.ShowSelectAddedGameDialog = showSelectAddedGameDialog;
Actions.ShowAddAppHashMismatchDialog = showAddAppMismatchDialog;
Actions.ShowApplicationWarningDialog = showApplicationWarningDialog;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public CreateModViewModel(ModConfigService modConfigService)
ReleaseMetadataFileName = $"{ModId}.ReleaseMetadata.json"
};

config.IgnoreRegexes.Add($"{Regex.Escape($@"{config.ModId}.nuspec")}");
config.IncludeRegexes.Add(Regex.Escape(ModConfig.ConfigFileName));
var modDirectory = Path.Combine(IoC.Get<LoaderConfig>().GetModConfigDirectory(), IOEx.ForceValidFilePath(ModId));
var filePath = Path.Combine(modDirectory, ModConfig.ConfigFileName);
await IConfig<ModConfig>.ToPathAsync(config, filePath);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Reloaded.Mod.Launcher.Lib.Models.ViewModel.Dialog;

/// <summary>
/// ViewModel for downloading an individual package.
/// </summary>
[AddINotifyPropertyChangedInterface]
public class InstallPackageViewModel : INotifyPropertyChanged
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use autogeneration for INotifyPropertyChanged here.
It's been a while since I've worked on R2 but I believe this uses Fody.PropertyChanged.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the way the rest of the project does this IIRC. Have a quick peek around.

{
public string Text { get; set; }
public string Title { get; set; }
public double Progress { get; set; }
public bool IsComplete { get; set; }

public event PropertyChangedEventHandler PropertyChanged;

Check warning on line 14 in source/Reloaded.Mod.Launcher.Lib/Models/ViewModel/Dialog/InstallPackageViewModel.cs

View workflow job for this annotation

GitHub Actions / build

Nullability of reference types in type of 'event PropertyChangedEventHandler InstallPackageViewModel.PropertyChanged' doesn't match implicitly implemented member 'event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged'.
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,47 @@ public PublishModDialogViewModel(PathTuple<ModConfig> modTuple)
_modTuple = modTuple;
PackageName = IOEx.ForceValidFilePath(_modTuple.Config.ModName.Replace(' ', '_'));
OutputFolder = Path.Combine(Path.GetTempPath(), $"{IOEx.ForceValidFilePath(_modTuple.Config.ModId)}.Publish");

// Set default Regexes.
IgnoreRegexes = new ObservableCollection<StringWrapper>()
IgnoreRegexes = new ObservableCollection<StringWrapper>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not overkill?
You can just save it when the menu is closed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might also save you from unnecessarily implementing PropertyChanged in the other place.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this still needs moving.

_modTuple.Config.IgnoreRegexes.Select(x => new StringWrapper { Value = x })
);
foreach (StringWrapper item in IgnoreRegexes)
item.PropertyChanged += (_, __) => UpdateConfig(_modTuple.Config.IgnoreRegexes, IgnoreRegexes);
IgnoreRegexes.CollectionChanged += (s, e) =>
{
@".*\.json", // Config files
$"{Regex.Escape($@"{_modTuple.Config.ModId}.nuspec")}"
if (e.NewItems != null)
foreach (StringWrapper item in e.NewItems)
item.PropertyChanged += (_, __) => UpdateConfig(_modTuple.Config.IgnoreRegexes, IgnoreRegexes);

if (e.OldItems != null)
foreach (StringWrapper item in e.OldItems)
item.PropertyChanged -= (_, __) => UpdateConfig(_modTuple.Config.IgnoreRegexes, IgnoreRegexes);
_modTuple.Config.IgnoreRegexes.Clear();
_modTuple.Config.IgnoreRegexes.AddRange(IgnoreRegexes.Select(x => x.Value));
};

IncludeRegexes = new ObservableCollection<StringWrapper>()
IncludeRegexes = new ObservableCollection<StringWrapper>(
_modTuple.Config.IncludeRegexes.Select(x => new StringWrapper { Value = x })
);
foreach (StringWrapper item in IncludeRegexes)
item.PropertyChanged += (_, __) => UpdateConfig(_modTuple.Config.IncludeRegexes, IncludeRegexes);
IncludeRegexes.CollectionChanged += (s, e) =>
{
Regex.Escape(ModConfig.ConfigFileName),
@"\.deps\.json",
@"\.runtimeconfig\.json",
if (e.NewItems != null)
foreach (StringWrapper item in e.NewItems)
item.PropertyChanged += (_, __) => UpdateConfig(_modTuple.Config.IncludeRegexes, IncludeRegexes);

if (e.OldItems != null)
foreach (StringWrapper item in e.OldItems)
item.PropertyChanged -= (_, __) => UpdateConfig(_modTuple.Config.IncludeRegexes, IncludeRegexes);
_modTuple.Config.IncludeRegexes.Clear();
_modTuple.Config.IncludeRegexes.AddRange(IncludeRegexes.Select(x => x.Value));
};
}

// Set notifications
PropertyChanged += ChangeUiVisbilityOnPropertyChanged;
void UpdateConfig(List<string> list, ObservableCollection<StringWrapper> collection)
{
list.Clear();
list.AddRange(collection.Select(x => x.Value));
_modTuple.SaveAsync();
}

/// <summary>
Expand Down Expand Up @@ -148,8 +172,8 @@ await PublishAsync(new PublishArgs()
PublishTarget = PublishTarget,
OutputFolder = OutputFolder,
ModTuple = _modTuple,
IgnoreRegexes = IgnoreRegexes.Select(x => x.Value).ToList(),
IncludeRegexes = IncludeRegexes.Select(x => x.Value).ToList(),
IgnoreRegexes = _modTuple.Config.IgnoreRegexes,
IncludeRegexes = _modTuple.Config.IncludeRegexes,
Progress = new Progress<double>(d => BuildProgress = d * 100),
AutomaticDelta = AutomaticDelta,
CompressionLevel = CompressionLevel,
Expand Down Expand Up @@ -286,6 +310,11 @@ public void SetOutputFolder()
/// </summary>
public void SetReadmePath() => ReadmePath = FileSelectors.SelectMarkdownFile();

/// <summary>
/// Lets the user save all changes to the mod config.
/// </summary>
public Task SaveAsync() => _modTuple.SaveAsync();

private string GetModFolder() => Path.GetDirectoryName(_modTuple.Path)!;


Expand Down
9 changes: 9 additions & 0 deletions source/Reloaded.Mod.Launcher.Lib/Static/Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public static class Actions
/// </summary>
public static ShowFetchPackageDialogDelegate ShowFetchPackageDialog { get; set; } = null!;

public static ShowInstallPackageDialogDelegate ShowInstallPackageDialog { get; set; } = null!;


/// <summary>
/// Shows a dialog that can be used to select the added game.
/// </summary>
Expand Down Expand Up @@ -254,6 +257,12 @@ public enum MessageBoxType
/// <param name="viewModel">The ViewModel used for downloading the individual package.</param>
public delegate bool ShowFetchPackageDialogDelegate(DownloadPackageViewModel viewModel);

/// <summary>
/// Shows a dialog that can be used to download an individual package.
/// </summary>
/// <param name="viewModel">The ViewModel used for downloading the individual package.</param>
public delegate bool ShowInstallPackageDialogDelegate(InstallPackageViewModel viewModel);

/// <summary>
/// Shows a dialog that can be used to select the added game.
/// </summary>
Expand Down
8 changes: 7 additions & 1 deletion source/Reloaded.Mod.Launcher.Lib/Static/Resources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public static void Init(IDictionaryResourceProvider provider)
// Update 1.21.0: Mod Packs Install
public static IDictionaryResource<string> InstallModPackDownloading { get; set; }
public static IDictionaryResource<string> InstallModPackErrorDownloadFail { get; set; }

// Update 1.21.6: Mod Packs Install
public static IDictionaryResource<string> ErrorAddApplicationGeneral { get; set; }
public static IDictionaryResource<string> ErrorAddApplicationCantReadSymlink { get; set; }
Expand Down Expand Up @@ -219,4 +219,10 @@ public static void Init(IDictionaryResourceProvider provider)
public static IDictionaryResource<string> ErrorViewDetails { get; set; }
public static IDictionaryResource<string> ErrorStacktraceTitle { get; set; }
public static IDictionaryResource<string> ErrorStacktraceSubtitle { get; set; }

// Update 1.X.X: New Progress Window for Local Mod Installation (UPDATE LAUNCHER VER BEFORE RELEASE)
public static IDictionaryResource<string> InstallModArchiveTitle { get; set; }
public static IDictionaryResource<string> InstalledModName { get; set; }
public static IDictionaryResource<string> InstallingModWait { get; set; }
public static IDictionaryResource<string> ExtractingLocalModArchive { get; set; }
}
6 changes: 6 additions & 0 deletions source/Reloaded.Mod.Launcher/Assets/Languages/en-GB.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@
<!-- Download Mod Archive -->
<sys:String x:Key="DownloadModArchiveTitle">Download Mod Archive</sys:String>
<sys:String x:Key="DownloadModArchiveName">File Name</sys:String>

<!-- Install Mod Archive -->
<sys:String x:Key="InstallModArchiveTitle">Installing Mod Archive</sys:String>
<sys:String x:Key="InstalledModName">Mod Name</sys:String>
<sys:String x:Key="InstallingModWait">Please wait while we install the mod!</sys:String>
<sys:String x:Key="ExtractingLocalModArchive">Extracting a local mod, please wait!</sys:String>

<!-- WMI Administrator Message -->
<sys:String x:Key="RunAsAdminMessage">You need to run this application as administrator.&#x0a;Administrative privileges are needed to receive application launch/exit events from Windows Management Instrumentation (WMI).&#x0a;Developers: Run your favourite IDE e.g. Visual Studio as Admin.</sys:String>
Expand Down
2 changes: 2 additions & 0 deletions source/Reloaded.Mod.Launcher/LibraryBindings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static void Init(IResourceFileSelector? languageSelector, IResourceFileSe
publishModDialog: PublishModDialog,
showEditModUserConfig: ShowEditModUserConfig,
showFetchPackageDialog: ShowFetchPackageDialog,
showInstallPackageDialog: ShowInstallPackageDialog,
showSelectAddedGameDialog: ShowSelectAddedGameDialog,
showAddAppMismatchDialog: ShowAddAppMismatchDialog,
showApplicationWarningDialog: ShowApplicationWarningDialog,
Expand Down Expand Up @@ -106,6 +107,7 @@ private static bool EditModDialog(EditModDialogViewModel viewmodel, object? owne
private static bool ShowEditModUserConfig(EditModUserConfigDialogViewModel viewmodel) => ShowDialogAndGetResult(new EditModUserConfigDialog(viewmodel));
private static bool PublishModDialog(PublishModDialogViewModel viewmodel) => ShowDialogAndGetResult(new PublishModDialog(viewmodel));
private static bool ShowFetchPackageDialog(DownloadPackageViewModel viewmodel) => ShowDialogAndGetResult(new DownloadPackageDialog(viewmodel));
private static bool ShowInstallPackageDialog(InstallPackageViewModel viewmodel) => ShowDialogAndGetResult(new InstallPackageDialog(viewmodel));
private static bool ShowAddAppMismatchDialog(AddAppHashMismatchDialogViewModel viewmodel) => ShowDialogAndGetResult(new AddAppHashMismatchDialog(viewmodel));
private static bool ShowApplicationWarningDialog(AddApplicationWarningDialogViewModel viewmodel) => ShowDialogAndGetResult(new ShowApplicationWarningDialog(viewmodel));
private static bool ShowInstallModPackDialog(InstallModPackDialogViewModel viewmodel) => ShowDialogAndGetResult(new InstallModPackDialog(viewmodel));
Expand Down
40 changes: 36 additions & 4 deletions source/Reloaded.Mod.Launcher/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Text;
using NuGet.Common;
using Reloaded.Mod.Loader.Update.Providers.Web;
using Sewer56.DeltaPatchGenerator.Lib.Utility;
using Sewer56.Update.Extractors.SevenZipSharp;
using System.Text;
using System.Windows.Threading;
using static Reloaded.Mod.Launcher.Lib.Static.Resources;

namespace Reloaded.Mod.Launcher;
Expand Down Expand Up @@ -88,10 +90,40 @@ private async void InstallMod_Drop(object sender, DragEventArgs e)
/* Extract to Temp Directory */
using var tempFolder = new TemporaryFolderAllocation();
var archiveExtractor = new SevenZipSharpExtractor();
await archiveExtractor.ExtractPackageAsync(file, tempFolder.FolderPath, new Progress<double>(), default);

/* Get name of package. */
WebDownloadablePackage.CopyPackagesFromExtractFolderToTargetDir(modsFolder!, tempFolder.FolderPath, default);
var installVM = new InstallPackageViewModel
{
Title = InstallModArchiveTitle.Get(),
Text = ExtractingLocalModArchive.Get(),
Progress = 0
};

var progress = new Progress<double>(value =>
{
installVM.Progress = value * 100;
});

//Waits for 3 seconds before showing the install dialog, if the installation is not complete by then.
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(3)
};

timer.Tick += (s, e) =>
{
timer.Stop();
if (installVM.Progress != 100)
{
Actions.ShowInstallPackageDialog.Invoke(installVM);
}
};
timer.Start();

await archiveExtractor.ExtractPackageAsync(file, tempFolder.FolderPath, progress, default);

installVM.Text = InstallingModWait.Get();
await WebDownloadablePackage.CopyPackagesFromExtractFolderToTargetDir(modsFolder!, tempFolder.FolderPath, default);
installVM.IsComplete = true;
}

// Find the new mods
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<default:ReloadedWindow x:Class="Reloaded.Mod.Launcher.Pages.Dialogs.InstallPackageDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:local="clr-namespace:Reloaded.Mod.Launcher.Pages.Dialogs"
xmlns:converters="clr-namespace:Reloaded.Mod.Launcher.Converters"
xmlns:default="clr-namespace:Reloaded.WPF.Theme.Default;assembly=Reloaded.WPF.Theme.Default"
mc:Ignorable="d"
SizeToContent="Height"
Width="500"
Title="{Binding Title}"
Style="{DynamicResource ReloadedWindow}">
<Grid Margin="{DynamicResource PageMarginSmall}" DataContext="{Binding Path=ViewModel, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}">

<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<TextBlock HorizontalAlignment="Center"
Grid.Row="0"
Text="{Binding Text}"
Visibility="{Binding Text, Converter={x:Static converters:StringToVisibilityConverter.Instance}}"
Style="{DynamicResource DefaultTextBlock}" />

<Grid Margin="{DynamicResource PanelMargin}"
Grid.Row="1"/>

<Grid Margin="{DynamicResource PanelMargin}" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="{DynamicResource GridInterPanelMargin}" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>

<ProgressBar Grid.Column="0"
Height="25"
Value="{Binding Progress, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Maximum="100" />
</Grid>
</Grid>
</default:ReloadedWindow>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Button = System.Windows.Controls.Button;

namespace Reloaded.Mod.Launcher.Pages.Dialogs;

/// <summary>
/// Interaction logic for DownloadPackageDialog.xaml
/// </summary>
public partial class InstallPackageDialog : ReloadedWindow
{
public new InstallPackageViewModel ViewModel { get; set; }

/// <inheritdoc />
public InstallPackageDialog(InstallPackageViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
DataContext = viewModel;
viewModel.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(InstallPackageViewModel.IsComplete) && viewModel.IsComplete)
{
ActionWrappers.ExecuteWithApplicationDispatcher(this.Close);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ public PublishModDialog(PublishModDialogViewModel viewModel)
this.Closing += OnClosing;
}

private void OnClosing(object? sender, CancelEventArgs e) => _cancellationTokenSource.Cancel();
private async void OnClosing(object? sender, CancelEventArgs e) {
await ViewModel.SaveAsync();
_cancellationTokenSource.Cancel();
}

private async void Publish_Click(object sender, System.Windows.RoutedEventArgs e)
{
Expand Down
5 changes: 5 additions & 0 deletions source/Reloaded.Mod.Loader.IO/Config/ModConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Reloaded.Memory.Extensions;
using System.Text.RegularExpressions;

namespace Reloaded.Mod.Loader.IO.Config;

Expand Down Expand Up @@ -36,6 +37,10 @@ public class ModConfig : ObservableObject, IConfig<ModConfig>, IModConfig
public bool IsLibrary { get; set; } = false;
public string ReleaseMetadataFileName { get; set; } = "Sewer56.Update.ReleaseMetadata.json";

/// Publishing
public List<string> IgnoreRegexes { get; set; } = [@".*\.json"];
public List<string> IncludeRegexes { get; set; } = [@"\.deps\.json", @"\.runtimeconfig\.json"];

[JsonIgnore]
public string ModSubDirs { get; set; } = string.Empty;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ await retryPolicy.ExecuteAsync(async () =>
await archiveExtractor.ExtractPackageAsync(tempDownloadPath, tempExtractDir.FolderPath, extractSlice, token);

// Copy all packages from download.
return WebDownloadablePackage.CopyPackagesFromExtractFolderToTargetDir(packageFolder, tempExtractDir.FolderPath, token);
return await WebDownloadablePackage.CopyPackagesFromExtractFolderToTargetDir(packageFolder, tempExtractDir.FolderPath, token);
}

#pragma warning disable CS0067 // Event never used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
await archiveExtractor.ExtractPackageAsync(tempFilePath, tempExtractDirectory.FolderPath, extractProgress, token);

/* Get name of package. */
return CopyPackagesFromExtractFolderToTargetDir(packageFolder, tempExtractDirectory.FolderPath, token);
return await CopyPackagesFromExtractFolderToTargetDir(packageFolder, tempExtractDirectory.FolderPath, token);
}

/// <inheritdoc />
Expand All @@ -139,7 +139,7 @@
/// Finds all mods in <paramref name="tempExtractDir"/> and copies them to appropriate subfolders in <paramref name="packageFolder"/>.
/// </summary>
/// <returns>Path to last folder copied.</returns>
public static string CopyPackagesFromExtractFolderToTargetDir(string packageFolder, string tempExtractDir, CancellationToken token)
public async static Task<string> CopyPackagesFromExtractFolderToTargetDir(string packageFolder, string tempExtractDir, CancellationToken token)

Check warning on line 142 in source/Reloaded.Mod.Loader.Update/Providers/Web/WebDownloadablePackage.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 142 in source/Reloaded.Mod.Loader.Update/Providers/Web/WebDownloadablePackage.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
var configs = ConfigReader<ModConfig>.ReadConfigurations(tempExtractDir, ModConfig.ConfigFileName, token, int.MaxValue, 0);
var returnResult = "";
Expand All @@ -162,7 +162,7 @@
// Obtain the name of the file.
try
{
var fileReq = WebRequest.CreateHttp(url);

Check warning on line 165 in source/Reloaded.Mod.Loader.Update/Providers/Web/WebDownloadablePackage.cs

View workflow job for this annotation

GitHub Actions / build

'WebRequest.CreateHttp(Uri)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 165 in source/Reloaded.Mod.Loader.Update/Providers/Web/WebDownloadablePackage.cs

View workflow job for this annotation

GitHub Actions / build

'WebRequest.CreateHttp(Uri)' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)
using var fileResp = await fileReq.GetResponseAsync();

try
Expand Down
Loading
Loading