[#8] Add auto update checker
This commit is contained in:
		@@ -31,14 +31,19 @@ namespace Elwig.Helpers {
 | 
			
		||||
 | 
			
		||||
    public class Config {
 | 
			
		||||
 | 
			
		||||
        private static readonly string[] TrueValues = ["1", "true", "yes", "on"];
 | 
			
		||||
 | 
			
		||||
        private readonly string FileName;
 | 
			
		||||
 | 
			
		||||
        public bool Debug;
 | 
			
		||||
        public string DatabaseFile = App.DataPath + "database.sqlite3";
 | 
			
		||||
        public string? DatabaseLog = null;
 | 
			
		||||
        public string? Branch = null;
 | 
			
		||||
        public string? UpdateUrl = null;
 | 
			
		||||
        public bool UpdateAuto = false;
 | 
			
		||||
 | 
			
		||||
        public IList<ScaleConfig> Scales;
 | 
			
		||||
        private readonly List<ScaleConfig> ScaleList = [];
 | 
			
		||||
        private static readonly string[] trueValues = ["1", "true", "yes", "on"];
 | 
			
		||||
 | 
			
		||||
        public Config(string filename) {
 | 
			
		||||
            FileName = filename;
 | 
			
		||||
@@ -53,7 +58,9 @@ namespace Elwig.Helpers {
 | 
			
		||||
            var log = config["database:log"];
 | 
			
		||||
            DatabaseLog = log != null ? Path.Combine(App.DataPath, log) : null;
 | 
			
		||||
            Branch = config["general:branch"];
 | 
			
		||||
            Debug = trueValues.Contains(config["general:debug"]?.ToLower());
 | 
			
		||||
            Debug = TrueValues.Contains(config["general:debug"]?.ToLower());
 | 
			
		||||
            UpdateUrl = config["update:url"];
 | 
			
		||||
            UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
 | 
			
		||||
 | 
			
		||||
            var scales = config.AsEnumerable().Where(i => i.Key.StartsWith("scale.")).GroupBy(i => i.Key.Split(':')[0][6..]).Select(i => i.Key);
 | 
			
		||||
            ScaleList.Clear();
 | 
			
		||||
@@ -73,6 +80,10 @@ namespace Elwig.Helpers {
 | 
			
		||||
            if (Debug) file.Write("debug = true\r\n");
 | 
			
		||||
            file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n");
 | 
			
		||||
            if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n");
 | 
			
		||||
            file.Write($"\r\n[update]\r\n");
 | 
			
		||||
            if (UpdateUrl != null) file.Write($"url = {UpdateUrl}\r\n");
 | 
			
		||||
            if (UpdateAuto) file.Write($"auto = true\r\n");
 | 
			
		||||
 | 
			
		||||
            foreach (var s in ScaleList) {
 | 
			
		||||
                file.Write($"\r\n[scale.{s.Id}]\r\ntype = {s.Type}\r\nmodel = {s.Model}\r\nconnection = {s.Connection}\r\n");
 | 
			
		||||
                if (s.Empty != null) file.Write($"empty = {s.Empty}\r\n");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								Elwig/Helpers/HttpClientExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Elwig/Helpers/HttpClientExtensions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Elwig.Helpers {
 | 
			
		||||
    public static class HttpClientExtensions {
 | 
			
		||||
        public static async Task DownloadAsync(this HttpClient client, string requestUri, Stream destination, IProgress<double>? progress = null, CancellationToken cancellationToken = default) {
 | 
			
		||||
            using var response = await client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
 | 
			
		||||
            var contentLength = response.Content.Headers.ContentLength;
 | 
			
		||||
 | 
			
		||||
            using var download = await response.Content.ReadAsStreamAsync(cancellationToken);
 | 
			
		||||
            if (progress == null || !contentLength.HasValue) {
 | 
			
		||||
                await download.CopyToAsync(destination, cancellationToken);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var relativeProgress = new Progress<long>(totalBytes => progress.Report((double)totalBytes / contentLength.Value));
 | 
			
		||||
            await download.CopyToAsync(destination, 81920, relativeProgress, cancellationToken);
 | 
			
		||||
            progress.Report(100.0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								Elwig/Helpers/StreamExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								Elwig/Helpers/StreamExtensions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Elwig.Helpers {
 | 
			
		||||
    public static class StreamExtensions {
 | 
			
		||||
        public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long>? progress = null, CancellationToken cancellationToken = default) {
 | 
			
		||||
            ArgumentNullException.ThrowIfNull(source);
 | 
			
		||||
            if (!source.CanRead) throw new ArgumentException("Has to be readable", nameof(source));
 | 
			
		||||
            ArgumentNullException.ThrowIfNull(destination);
 | 
			
		||||
            if (!destination.CanWrite) throw new ArgumentException("Has to be writable", nameof(destination));
 | 
			
		||||
            ArgumentOutOfRangeException.ThrowIfNegative(bufferSize);
 | 
			
		||||
 | 
			
		||||
            var buffer = new byte[bufferSize];
 | 
			
		||||
            long totalBytesRead = 0;
 | 
			
		||||
            int bytesRead;
 | 
			
		||||
            while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0) {
 | 
			
		||||
                await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false);
 | 
			
		||||
                totalBytesRead += bytesRead;
 | 
			
		||||
                progress?.Report(totalBytesRead);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,6 +12,10 @@ using System.Text;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using Elwig.Models.Entities;
 | 
			
		||||
using Elwig.Helpers.Billing;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Text.Json.Nodes;
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
namespace Elwig.Helpers {
 | 
			
		||||
    public static partial class Utils {
 | 
			
		||||
@@ -61,6 +65,8 @@ namespace Elwig.Helpers {
 | 
			
		||||
            return PhoneNrTypes.Where(t => t.Key == type).Select(t => t.Value).FirstOrDefault(type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static readonly string[] TempWildcards = ["*.html", "*.pdf", "*.exe"];
 | 
			
		||||
 | 
			
		||||
        private static readonly ushort[] Crc16ModbusTable = [
 | 
			
		||||
            0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
 | 
			
		||||
            0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
 | 
			
		||||
@@ -302,7 +308,7 @@ namespace Elwig.Helpers {
 | 
			
		||||
        public static string GetSign<T>(T number) where T : INumber<T>
 | 
			
		||||
            => T.Sign(number) switch {
 | 
			
		||||
                < 0 => "\u2212",  // minus
 | 
			
		||||
                  0 => "\u00b1",  // plus minus
 | 
			
		||||
                0 => "\u00b1",  // plus minus
 | 
			
		||||
                > 0 => "+",
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -378,5 +384,33 @@ namespace Elwig.Helpers {
 | 
			
		||||
                .Select(s => new Varibute(s, varieties, attributes, cultivations))
 | 
			
		||||
                .ToList();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LibraryImport("wininet.dll")]
 | 
			
		||||
        [return: MarshalAs(UnmanagedType.Bool)]
 | 
			
		||||
        private static partial bool InternetGetConnectedState(out int description, int reservedValue);
 | 
			
		||||
 | 
			
		||||
        public static bool HasInternetConnectivity() {
 | 
			
		||||
            return InternetGetConnectedState(out var _, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<(string Version, string Url, long Size)?> GetLatestInstallerUrl(string url) {
 | 
			
		||||
            try {
 | 
			
		||||
                using var client = new HttpClient() {
 | 
			
		||||
                    Timeout = TimeSpan.FromSeconds(5),
 | 
			
		||||
                };
 | 
			
		||||
                var res = JsonNode.Parse(await client.GetStringAsync(url));
 | 
			
		||||
                var data = res!["data"]![0]!;
 | 
			
		||||
                return ((string)data["version"]!, (string)data["url"]!, (int)data["size"]!);
 | 
			
		||||
            } catch {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void CleanupTempFiles() {
 | 
			
		||||
            var dir = new DirectoryInfo(App.TempPath);
 | 
			
		||||
            foreach (var file in TempWildcards.SelectMany(dir.EnumerateFiles)) {
 | 
			
		||||
                file.Delete();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user