Skip to content

Commit 8115351

Browse files
authored
Merge pull request #3 from Virenbar/v2.4
V2.4
2 parents deb32be + 09ef71b commit 8115351

34 files changed

+3006
-2327
lines changed

.github/workflows/build-artifact.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ jobs:
3232
version: ${{steps.version.outputs.version}}
3333
steps:
3434
- name: Checkout
35-
uses: actions/checkout@v3
35+
uses: actions/checkout@v4
3636
with:
3737
fetch-depth: 0
3838

3939
- name: Install .NET
40-
uses: actions/setup-dotnet@v3
40+
uses: actions/setup-dotnet@v4
4141
with:
4242
dotnet-version: 6.x
4343

@@ -46,7 +46,7 @@ jobs:
4646
run: .\.github\scripts\version.ps1
4747

4848
- name: Restore cache
49-
uses: actions/cache@v3
49+
uses: actions/cache@v4
5050
with:
5151
path: ~\.nuget\packages
5252
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
@@ -62,7 +62,7 @@ jobs:
6262
run: dotnet publish -c Release -p:PublishProfile=$env:PROFILE -f $env:FRAMEWORK /property:Version=$env:VERSION
6363

6464
- name: Upload artifact
65-
uses: actions/upload-artifact@v3
65+
uses: actions/upload-artifact@v4
6666
with:
6767
name: GDPIControl(${{ matrix.framework }})
6868
path: |

.github/workflows/publish-artifact.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
run: echo "Version builded ${{ needs.build.outputs.version }}"
1818

1919
- name: Download artifacts
20-
uses: actions/download-artifact@v3
20+
uses: actions/download-artifact@v4
2121

2222
- name: List files
2323
run: ls -R
@@ -28,7 +28,7 @@ jobs:
2828
zip -r "GDPIControl-4.7.2.zip" "GDPIControl(net472)"
2929
3030
- name: Create Release
31-
uses: softprops/action-gh-release@v1
31+
uses: softprops/action-gh-release@v2
3232
with:
3333
files: |
3434
GDPIControl.zip

GDPIControl/Config.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ internal static class Config
99
{
1010
public static ControlSettings Current { get; set; }
1111

12-
private static ControlSettings Default => new() { Modeset = Modeset.M5, GDPISettings = GDPISettings.ModesetSettings(Modeset.M5) };
12+
private static ControlSettings Default => new()
13+
{
14+
Modeset = Modeset.M5,
15+
CustomSettings1 = new GDPISettings(),
16+
CustomSettings2 = new GDPISettings(),
17+
CustomSettings3 = new GDPISettings()
18+
};
1319

1420
public static void Load()
1521
{
@@ -20,6 +26,12 @@ public static void Load()
2026
var XS = new XmlSerializer(typeof(ControlSettings));
2127
using var SR = new StreamReader(Constants.ConfigPath);
2228
Current = (ControlSettings)XS.Deserialize(SR);
29+
30+
var def = Default;
31+
if (Current.Modeset == Modeset.Custom) { Current.Modeset = Modeset.Custom1; }
32+
Current.CustomSettings1 ??= Current.GDPISettings ?? def.CustomSettings1;
33+
Current.CustomSettings2 ??= def.CustomSettings2;
34+
Current.CustomSettings3 ??= def.CustomSettings3;
2335
}
2436
catch (Exception)
2537
{

GDPIControl/Constants.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,21 @@ internal static class Constants
1515
public static string BlacklistPath => Path.Combine(StartupPath, BlacklistName);
1616
public static string BlacklistTempPath => Path.Combine(StartupPath, BlacklistTempName);
1717
public static string ConfigPath => Path.Combine(StartupPath, ConfigName);
18-
19-
/// <summary>
20-
/// .NET 6 uses TEMP directory for GDPI
21-
/// </summary>
2218
public static string GDPIPath => Path.Combine(Application.StartupPath, Environment.Is64BitOperatingSystem ? x86_64 : x86);
19+
public static string UserlistPath => Path.Combine(StartupPath, UserlistName);
20+
21+
#region StartupPath
22+
/*
23+
.NET 6 uses TEMP directory for GDPIControl
24+
Application.StartupPath - Real executable path
25+
Environment.ProcessPath - Packed executable path
26+
*/
2327

2428
#if NET6_0_OR_GREATER
2529
public static string StartupPath => Path.GetDirectoryName(Environment.ProcessPath);
2630
#else
2731
public static string StartupPath => Application.StartupPath;
2832
#endif
29-
public static string UserlistPath => Path.Combine(StartupPath, UserlistName);
33+
#endregion StartupPath
3034
}
3135
}

GDPIControl/Extensions.cs renamed to GDPIControl/Extensions/FormExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using System;
22
using System.Windows.Forms;
33

4-
namespace GDPIControl
4+
namespace GDPIControl.Extensions
55
{
6-
internal static class Extensions
6+
internal static class FormExtensions
77
{
88
public static DialogResult ShowError(this Form form, Exception exception)
99
{
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.IO;
3+
using System.Net.Http;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
namespace GDPIControl.Extensions
8+
{
9+
internal static class IOExtensions
10+
{
11+
public static Task CopyToAsync(this Stream source, Stream destination, int bufferSize) => CopyToAsync(source, destination, bufferSize, default, default);
12+
13+
public static Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress) => CopyToAsync(source, destination, bufferSize, progress, default);
14+
15+
/// <summary>
16+
/// https://stackoverflow.com/a/46497896
17+
/// </summary>
18+
public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress, CancellationToken cancellationToken)
19+
{
20+
if (source is null) { throw new ArgumentNullException(nameof(source)); }
21+
if (!source.CanRead) { throw new ArgumentException("Has to be readable", nameof(source)); }
22+
if (destination is null) { throw new ArgumentNullException(nameof(destination)); }
23+
if (!destination.CanWrite) { throw new ArgumentException("Has to be writable", nameof(destination)); }
24+
if (bufferSize < 0) { throw new ArgumentOutOfRangeException(nameof(bufferSize)); }
25+
26+
var buffer = new byte[bufferSize];
27+
long totalBytesRead = 0;
28+
int bytesRead;
29+
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
30+
{
31+
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
32+
totalBytesRead += bytesRead;
33+
progress?.Report(totalBytesRead);
34+
}
35+
}
36+
37+
/// <summary>
38+
/// Асинхронно скачать файл
39+
/// </summary>
40+
public static Task DownloadAsync(this HttpClient client, string requestUri, Stream destination) => DownloadAsync(client, requestUri, destination, default(CancellationToken));
41+
42+
/// <summary>
43+
/// Асинхронно скачать файл
44+
/// </summary>
45+
public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, CancellationToken cancellationToken)
46+
{
47+
// Считать только заголовок
48+
using var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
49+
response.EnsureSuccessStatusCode();
50+
// А содержимое записать прямо в файл
51+
using var download = await response.Content.ReadAsStreamAsync();
52+
await download.CopyToAsync(destination);
53+
}
54+
55+
/// <summary>
56+
/// Асинхронно скачать файл с отчётом о прогрессе
57+
/// </summary>
58+
public static Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, IProgress<float> progress) => DownloadAsync(client, requestUri, destination, progress, default);
59+
60+
/// <summary>
61+
/// Асинхронно скачать файл с отчётом о прогрессе
62+
/// </summary>
63+
public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, IProgress<float> progress, CancellationToken cancellationToken)
64+
{
65+
// Get the http headers first to examine the content length
66+
using var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
67+
response.EnsureSuccessStatusCode();
68+
var contentLength = response.Content.Headers.ContentLength;
69+
using var download = await response.Content.ReadAsStreamAsync();
70+
// Ignore progress reporting when no progress reporter was
71+
// passed or when the content length is unknown
72+
if (!contentLength.HasValue)
73+
{
74+
await download.CopyToAsync(destination);
75+
progress.Report(1);
76+
return;
77+
}
78+
79+
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
80+
var relativeProgress = new Progress<long>(totalBytes => progress.Report((float)totalBytes / contentLength.Value));
81+
// Use extension method to report progress while downloading
82+
await download.CopyToAsync(destination, 81920, relativeProgress, cancellationToken);
83+
progress.Report(1);
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)