Skip to content

Commit 064877b

Browse files
committed
- added update notification
- update to .net 9
1 parent a910853 commit 064877b

12 files changed

+279
-53
lines changed

Cursor_Installer_Creator.csproj

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<OutputType>WinExe</OutputType>
4-
<TargetFramework>net8.0-windows</TargetFramework>
4+
<TargetFramework>net9.0-windows7.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
77
<ApplicationManifest>app.manifest</ApplicationManifest>
@@ -24,15 +24,15 @@
2424
</ItemGroup>
2525

2626
<ItemGroup>
27-
<PackageReference Include="Avalonia" Version="11.1.0" />
28-
<PackageReference Include="Avalonia.Desktop" Version="11.1.0" />
29-
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.0" />
30-
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.1.0" />
27+
<PackageReference Include="Avalonia" Version="11.2.3" />
28+
<PackageReference Include="Avalonia.Desktop" Version="11.2.3" />
29+
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.3" />
30+
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.3" />
3131
<!--Condition
3232
below is needed to remove Avalonia.Diagnostics package from build output in Release
3333
configuration.-->
34-
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.0" />
34+
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.3" />
3535
<PackageReference Include="CsvHelper" Version="33.0.1" />
36-
<PackageReference Include="System.Drawing.Common" Version="8.0.7" />
36+
<PackageReference Include="System.Drawing.Common" Version="9.0.0" />
3737
</ItemGroup>
3838
</Project>

CCursor.cs renamed to Data/CCursor.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
using System.IO;
1+
using Cursor_Installer_Creator.Utils;
2+
using System.IO;
23

3-
namespace Cursor_Installer_Creator;
4+
namespace Cursor_Installer_Creator.Data;
45

56
public enum CCursorType
67
{
@@ -16,7 +17,7 @@ public sealed class CCursor
1617

1718
public CCursorType GetCursorType()
1819
{
19-
if (string.IsNullOrEmpty(CursorPath))
20+
if (string.IsNullOrWhiteSpace(CursorPath))
2021
return CCursorType.unknown;
2122

2223
if (CursorPath.EndsWith(".ani"))

CursorAssignment.cs renamed to Data/CursorAssignment.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System.IO;
66
using System.Linq;
77

8-
namespace Cursor_Installer_Creator;
8+
namespace Cursor_Installer_Creator.Data;
99

1010
public enum CursorAssignmentType
1111
{
@@ -40,7 +40,7 @@ public static Dictionary<int, CursorAssignment> ReadCsvString(string fileContent
4040
var dictionary = new Dictionary<int, CursorAssignment>();
4141
foreach (var record in records)
4242
{
43-
if (string.IsNullOrEmpty(record.Name))
43+
if (string.IsNullOrWhiteSpace(record.Name))
4444
continue;
4545
dictionary[record.ID] = record;
4646
}

Data/Version.cs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace Cursor_Installer_Creator.Data;
5+
6+
public sealed class Version
7+
{
8+
public int Major { get; set; } = -1;
9+
public int Minor { get; set; } = -1;
10+
public int Patch { get; set; } = -1;
11+
public bool IsPrerelease { get; set; }
12+
13+
public Version() { }
14+
15+
public Version(int major, int minor, int patch, bool isPrerelease = false)
16+
{
17+
Major = major;
18+
Minor = minor;
19+
Patch = patch;
20+
IsPrerelease = isPrerelease;
21+
}
22+
23+
public Version(string? version)
24+
{
25+
if (string.IsNullOrWhiteSpace(version))
26+
return;
27+
28+
version = version.ToLower();
29+
version = version.TrimStart('v');
30+
31+
var parts = version.Split('-');
32+
IsPrerelease = parts.Length > 1;
33+
34+
var versionParts = parts[0].Split('.').Select(int.Parse).ToArray();
35+
Major = versionParts[0];
36+
Minor = versionParts[1];
37+
Patch = versionParts[2];
38+
}
39+
40+
public override string ToString() => IsPrerelease ? $"{Major}.{Minor}.{Patch}-alpha" : $"{Major}.{Minor}.{Patch}";
41+
42+
public override bool Equals(object? obj)
43+
{
44+
if (obj is Version otherVersion)
45+
{
46+
return Major == otherVersion.Major
47+
&& Minor == otherVersion.Minor
48+
&& Patch == otherVersion.Patch
49+
&& IsPrerelease == otherVersion.IsPrerelease;
50+
}
51+
return base.Equals(obj);
52+
}
53+
54+
public override int GetHashCode() => HashCode.Combine(Major, Minor, Patch, IsPrerelease);
55+
56+
public static bool operator >(Version v1, Version v2)
57+
{
58+
if (v1.Major != v2.Major)
59+
return v1.Major > v2.Major;
60+
if (v1.Minor != v2.Minor)
61+
return v1.Minor > v2.Minor;
62+
if (v1.Patch != v2.Patch)
63+
return v1.Patch > v2.Patch;
64+
return !v1.IsPrerelease && v2.IsPrerelease;
65+
}
66+
67+
public static bool operator <(Version v1, Version v2)
68+
{
69+
return !(v1 > v2) && !v1.Equals(v2);
70+
}
71+
72+
public static bool operator >=(Version v1, Version v2)
73+
{
74+
return v1 > v2 || v1.Equals(v2);
75+
}
76+
77+
public static bool operator <=(Version v1, Version v2)
78+
{
79+
return v1 < v2 || v1.Equals(v2);
80+
}
81+
82+
public static Version operator +(Version v1, Version v2)
83+
{
84+
return new Version(
85+
v1.Major + v2.Major,
86+
v1.Minor + v2.Minor,
87+
v1.Patch + v2.Patch,
88+
v1.IsPrerelease || v2.IsPrerelease
89+
);
90+
}
91+
92+
public static Version operator -(Version v1, Version v2)
93+
{
94+
return new Version(
95+
Math.Max(v1.Major - v2.Major, 0),
96+
Math.Max(v1.Minor - v2.Minor, 0),
97+
Math.Max(v1.Patch - v2.Patch, 0),
98+
v1.IsPrerelease
99+
);
100+
}
101+
}

CursorHelper.cs renamed to Utils/CursorHelper.cs

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.Win32;
1+
using Cursor_Installer_Creator.Data;
2+
using Microsoft.Win32;
23
using System;
34
using System.Collections.Generic;
45
using System.Diagnostics;
@@ -11,7 +12,7 @@
1112
using System.Text;
1213
using Cursor = System.Windows.Forms.Cursor;
1314

14-
namespace Cursor_Installer_Creator;
15+
namespace Cursor_Installer_Creator.Utils;
1516

1617
public static class CursorHelper
1718
{
@@ -28,19 +29,17 @@ public static List<CCursor> GetSelectedCursors()
2829
foreach (var valueName in valueNames)
2930
{
3031
var cursorPath = key.GetValue(valueName)?.ToString();
31-
if (string.IsNullOrEmpty(cursorPath) || !File.Exists(cursorPath))
32+
if (string.IsNullOrWhiteSpace(cursorPath) || !File.Exists(cursorPath))
3233
{
3334
var assignment = CursorAssignment.FromName(valueName, CursorAssignmentType.WindowsReg);
34-
cursorPath = $"C:/Windows/Cursors/{assignment?.Windows}.cur";
35+
cursorPath = @$"C:\Windows\Cursors\{assignment?.Windows}.cur";
3536
}
3637

3738
if (File.Exists(cursorPath))
3839
{
3940
var ccursor = ConvertCursorFile(cursorPath, valueName);
4041
if (ccursor is not null)
41-
{
4242
ccursors.Add(ccursor);
43-
}
4443
}
4544
}
4645
}
@@ -58,9 +57,7 @@ public static List<CCursor> GetSelectedCursors()
5857
};
5958
ccursor.CursorPath = ConvertCursorFile(ccursor.CursorPath, ccursor.Assignment)?.CursorPath ?? ccursor.CursorPath;
6059
if (File.Exists(ccursor.CursorPath))
61-
{
6260
ccursors.Add(ccursor);
63-
}
6461
}
6562
}
6663

@@ -74,9 +71,7 @@ public static List<CCursor> GetSelectedCursors()
7471
{
7572
var cursorPath = key.GetValue(assignment.WindowsReg)?.ToString();
7673
if (!File.Exists(cursorPath))
77-
{
7874
cursorPath = @$"C:\Windows\Cursors\{assignment.Windows}.cur";
79-
}
8075

8176
return ConvertCursorFile(cursorPath, assignment.ID);
8277
}
@@ -108,9 +103,7 @@ private static Dictionary<string, string> ParseInstallerInfStrings(string filePa
108103
var value = parts[1].Trim().TrimStart('\"').TrimEnd('\"');
109104
var assignment = CursorAssignment.FromName(key, CursorAssignmentType.WindowsInstall);
110105
if (assignment is not null)
111-
{
112106
stringsDictionary[assignment.WindowsReg] = value;
113-
}
114107
}
115108
}
116109
}
@@ -129,9 +122,7 @@ public static IEnumerable<CCursor> CursorsFromInstallerInf(string filePath)
129122
{
130123
var ccursor = ConvertCursorFile(Path.Combine(Path.GetDirectoryName(filePath)!, kvp.Value), assignment);
131124
if (ccursor is not null)
132-
{
133125
ccursors.Add(ccursor);
134-
}
135126
}
136127
}
137128
return ccursors;
@@ -163,9 +154,7 @@ public static void RemoveCursorDisplayImage(CCursor ccursor)
163154
{
164155
var prevCursorImagePath = Path.ChangeExtension(ccursor.CursorPath, ".png");
165156
if (File.Exists(prevCursorImagePath))
166-
{
167157
File.Delete(prevCursorImagePath);
168-
}
169158
}
170159

171160
public static CCursor? ConvertCursorFile(string cursorPath, int cursorID) => ConvertCursorFile(cursorPath, CursorAssignment.CursorAssignments[cursorID]);
@@ -188,9 +177,7 @@ public static void RemoveCursorDisplayImage(CCursor ccursor)
188177

189178
var prevCursorImagePath = Path.ChangeExtension(destinationFullPath, ".png");
190179
if (File.Exists(prevCursorImagePath))
191-
{
192180
File.Delete(prevCursorImagePath);
193-
}
194181

195182
var ccursor = new CCursor
196183
{
@@ -207,24 +194,24 @@ public static void RemoveCursorDisplayImage(CCursor ccursor)
207194
}
208195

209196
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
210-
private static extern IntPtr LoadCursorFromFile(string str);
197+
private static extern nint LoadCursorFromFile(string str);
211198
private static Cursor GetCursorFromFile(string filename)
212199
{
213200
var hCursor = LoadCursorFromFile(filename);
214-
return !IntPtr.Zero.Equals(hCursor)
201+
return !nint.Zero.Equals(hCursor)
215202
? new Cursor(hCursor)
216203
: throw new ApplicationException("Could not create cursor from file " + filename);
217204
}
218205

219206
public static void CreateInstaller(string packageName, string folderPath, IEnumerable<CCursor> ccursors, bool createZip = true)
220207
{
221-
using (var writer = new StreamWriter($"{Program.TempPath}/installer.inf"))
208+
using (var writer = new StreamWriter(@$"{Program.TempPath}\installer.inf"))
222209
{
223210
writer.Write(CreateInstallerInfString(packageName, ccursors));
224211
}
225212

226213
var files = ccursors.Select(x => x.CursorPath).ToList();
227-
files.Add($"{Program.TempPath}/installer.inf");
214+
files.Add(@$"{Program.TempPath}\installer.inf");
228215

229216
if (createZip)
230217
{
@@ -291,9 +278,7 @@ private static string CreateInstallerInfString(string packageName, IEnumerable<C
291278
private static void CreateZipFile(string zipPath, IEnumerable<string> files)
292279
{
293280
if (File.Exists(zipPath))
294-
{
295281
File.Delete(zipPath);
296-
}
297282
using var archive = ZipFile.Open(zipPath, ZipArchiveMode.Create);
298283
var folder = Path.GetFileNameWithoutExtension(zipPath);
299284
foreach (var file in files)
@@ -331,9 +316,7 @@ public static void InstallCursor(string installerFilePath)
331316
catch (System.ComponentModel.Win32Exception ex)
332317
{
333318
if (ex.NativeErrorCode != 1223)
334-
{
335319
throw new Exception(ex.Message + Environment.NewLine + ex.ErrorCode);
336-
}
337320
}
338321
}
339322
}

Utils/GitHubUpdater.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using Cursor_Installer_Creator.Data;
2+
using System.Net.Http;
3+
using System.Text.Json;
4+
using System.Threading.Tasks;
5+
6+
namespace Cursor_Installer_Creator.Utils;
7+
8+
public sealed class GitHubUpdater
9+
{
10+
public const string RepoOwner = "Der-Floh";
11+
public const string RepoName = "Cursor-Installer-Creator";
12+
13+
public static Version CurrentVersion { get; } = new Version(2, 1, 0);
14+
public static string RepoUrl => $"https://github.com/{RepoOwner}/{RepoName}";
15+
public static string LatestReleaseUrl => $"https://github.com/{RepoOwner}/{RepoName}/releases/latest";
16+
17+
private static readonly HttpClient _client = new HttpClient();
18+
19+
public static async Task<bool> HasUpdateAsync()
20+
{
21+
try
22+
{
23+
// GitHub API endpoint for the latest release
24+
var url = $"https://api.github.com/repos/{RepoOwner}/{RepoName}/releases/latest";
25+
_client.DefaultRequestHeaders.UserAgent.ParseAdd(RepoName.Replace('-', '_'));
26+
27+
// Fetch latest release
28+
var response = await _client.GetAsync(url);
29+
response.EnsureSuccessStatusCode();
30+
31+
// Deserialize response
32+
var jsonString = await response.Content.ReadAsStringAsync();
33+
var jsonDocument = JsonDocument.Parse(jsonString);
34+
var latestVersionString = jsonDocument.RootElement.GetProperty("tag_name").GetString();
35+
var latestVersion = new Version(latestVersionString);
36+
37+
// Compare versions
38+
return latestVersion > CurrentVersion;
39+
}
40+
catch
41+
{
42+
return false;
43+
}
44+
}
45+
}

Views/CursorInstallerMainView.axaml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
</Grid.ColumnDefinitions>
1414
<Grid.RowDefinitions>
1515
<RowDefinition Height="*"/>
16-
<RowDefinition Height="10*"/>
16+
<RowDefinition Height="5*"/>
17+
<RowDefinition Height="5*"/>
1718
<RowDefinition Height="*"/>
1819
</Grid.RowDefinitions>
1920

@@ -23,11 +24,11 @@
2324
<TextBox Name="CursorPackagenameTextBox" Watermark="My Custom Cursor" MinWidth="146" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
2425
</StackPanel>
2526

26-
<views:CursorListView Grid.Row="1" Grid.ColumnSpan="2" Name="CursorListViewElem"/>
27+
<views:CursorListView Grid.Row="1" Grid.RowSpan="2" Grid.ColumnSpan="2" Name="CursorListViewElem"/>
2728

28-
<Button Grid.Row="2" Content="Install Cursor" Cursor="Hand" Click="CursorInstallButton_Click" Margin="8,0,0,0"/>
29+
<Button Grid.Row="3" Content="Install Cursor" Cursor="Hand" Click="CursorInstallButton_Click" Margin="8,0,0,0"/>
2930

30-
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,8,0">
31+
<StackPanel Grid.Column="1" Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,8,0">
3132
<TextBlock Name="OperationSuccessTextBlock" Text="Finished" FontWeight="Bold" Foreground="Green" IsVisible="False" VerticalAlignment="Center" Margin="0,0,16,0"/>
3233
<ComboBox Name="CursorPackageTypeComboBox" SelectedIndex="0" Cursor="Hand" MinWidth="196" VerticalAlignment="Center" Margin="0,0,16,0">
3334
<ComboBoxItem Content="Target Folder"/>
@@ -36,6 +37,8 @@
3637
</ComboBox>
3738
<Button Name="CreateCursorPackageButton" Content="Create Package" Cursor="Hand" Click="CreateCursorPackageButton_Click" VerticalAlignment="Center" HorizontalAlignment="Center"/>
3839
</StackPanel>
40+
41+
<views:UpdateNotifyView Name="UpdateNotifyViewElem" IsVisible="False" Grid.Column="1" Grid.RowSpan="2" VerticalAlignment="Top" HorizontalAlignment="Right"/>
3942
</Grid>
4043

4144
</UserControl>

0 commit comments

Comments
 (0)