Skip to content

Commit f798fe3

Browse files
Merge pull request #28 from nullinside-development-group/bug/update
bug: fixing updating logic
2 parents c26a07e + 628fe7d commit f798fe3

File tree

9 files changed

+187
-42
lines changed

9 files changed

+187
-42
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<UserControl xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
mc:Ignorable="d" Width="200" Height="200"
6+
x:Class="SiteMonitor.Controls.Loading">
7+
<UserControl.Styles>
8+
<Style Selector="Rectangle.textColor">
9+
<Setter Property="Fill" Value="rgb(204, 200, 175)" />
10+
<Style.Animations>
11+
<Animation Duration="0:0:1" IterationCount="INFINITE">
12+
<KeyFrame Cue="0%">
13+
<Setter Property="Opacity" Value="0.0" />
14+
<Setter Property="RotateTransform.Angle" Value="0.0" />
15+
</KeyFrame>
16+
<KeyFrame Cue="50%">
17+
<Setter Property="Opacity" Value="1.0" />
18+
<Setter Property="RotateTransform.Angle" Value="90.0" />
19+
</KeyFrame>
20+
<KeyFrame Cue="100%">
21+
<Setter Property="Opacity" Value="0.0" />
22+
<Setter Property="RotateTransform.Angle" Value="180.0" />
23+
</KeyFrame>
24+
</Animation>
25+
</Style.Animations>
26+
</Style>
27+
</UserControl.Styles>
28+
29+
<Rectangle Classes="textColor" Width="50" Height="50" />
30+
</UserControl>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Avalonia.Controls;
2+
3+
namespace SiteMonitor.Controls;
4+
5+
/// <summary>
6+
/// A loading icon.
7+
/// </summary>
8+
public partial class Loading : UserControl {
9+
/// <summary>
10+
/// Initializes a new instance of the <see cref="Loading" /> class.
11+
/// </summary>
12+
public Loading() {
13+
InitializeComponent();
14+
}
15+
}

src/SiteMonitor/Models/Configuration.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ public class Configuration {
2020
/// </summary>
2121
public string? ServerAddress { get; set; }
2222

23+
/// <summary>
24+
/// The server username.
25+
/// </summary>
26+
public string? ServerUsername { get; set; }
27+
28+
/// <summary>
29+
/// The server username's password.
30+
/// </summary>
31+
public string? ServerPassword { get; set; }
32+
2333
/// <summary>
2434
/// The singleton instance of the class.
2535
/// </summary>
@@ -35,6 +45,10 @@ public static Configuration Instance {
3545

3646
private static Configuration? ReadConfiguration() {
3747
try {
48+
if (!Directory.Exists(Path.GetDirectoryName(S_CONFIG_LOCATION))) {
49+
Directory.CreateDirectory(Path.GetDirectoryName(S_CONFIG_LOCATION)!);
50+
}
51+
3852
string json = File.ReadAllText(S_CONFIG_LOCATION);
3953
return JsonConvert.DeserializeObject<Configuration>(json);
4054
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
using SiteMonitor.ViewModels;
4+
5+
namespace SiteMonitor;
6+
7+
/// <summary>
8+
/// A wrapper that contains the registered services.
9+
/// </summary>
10+
public static class ServiceCollectionExtensions {
11+
/// <summary>
12+
/// Adds the services used throughout the application.
13+
/// </summary>
14+
/// <param name="collection">The services collection to initialize.</param>
15+
public static void AddCommonServices(this IServiceCollection collection) {
16+
// View models
17+
collection.AddTransient<MainWindowViewModel>();
18+
collection.AddTransient<NewVersionWindowViewModel>();
19+
}
20+
}

src/SiteMonitor/SiteMonitor.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@
2626
</ItemGroup>
2727

2828
<ItemGroup>
29-
<PackageReference Include="Avalonia" Version="11.3.1"/>
30-
<PackageReference Include="Avalonia.Desktop" Version="11.3.1"/>
31-
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.1"/>
32-
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.1"/>
29+
<PackageReference Include="Avalonia" Version="11.3.2"/>
30+
<PackageReference Include="Avalonia.Desktop" Version="11.3.2"/>
31+
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.2"/>
32+
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.2"/>
3333
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
3434
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.3.1"/>
35-
<PackageReference Include="Avalonia.ReactiveUI" Version="11.3.1"/>
35+
<PackageReference Include="Avalonia.ReactiveUI" Version="11.3.2"/>
3636
</ItemGroup>
3737

3838
<ItemGroup>

src/SiteMonitor/ViewModels/MainWindowViewModel.cs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public MainWindowViewModel() {
4242
Task.Factory.StartNew(PingServer);
4343
Task.Factory.StartNew(PingSite);
4444
ServerAddress = Configuration.Instance.ServerAddress;
45+
SshUsername = Configuration.Instance.ServerUsername;
46+
SshPassword = Configuration.Instance.ServerPassword;
4547
}
4648

4749
/// <summary>
@@ -137,15 +139,29 @@ public bool IsDisplayingAdvancedCommands {
137139
/// </summary>
138140
public string? SshUsername {
139141
get => _sshUsername;
140-
set => this.RaiseAndSetIfChanged(ref _sshUsername, value);
142+
set {
143+
Configuration.Instance.ServerUsername = value;
144+
this.RaiseAndSetIfChanged(ref _sshUsername, value);
145+
try {
146+
Configuration.WriteConfiguration();
147+
}
148+
catch { }
149+
}
141150
}
142151

143152
/// <summary>
144153
/// The password to use for the SSH session for commands.
145154
/// </summary>
146155
public string? SshPassword {
147156
get => _sshPassword;
148-
set => this.RaiseAndSetIfChanged(ref _sshPassword, value);
157+
set {
158+
Configuration.Instance.ServerPassword = value;
159+
this.RaiseAndSetIfChanged(ref _sshPassword, value);
160+
try {
161+
Configuration.WriteConfiguration();
162+
}
163+
catch { }
164+
}
149165
}
150166

151167
/// <summary>
@@ -178,9 +194,10 @@ private async Task PingSite() {
178194
WebsiteUp = await SendHeadRequest("https://nullinside.com");
179195
ApiUp = await SendHeadRequest("https://nullinside.com/api/v1/featureToggle");
180196
NullUp = await SendHeadRequest("https://nullinside.com/null/v1/database/migration");
181-
ChatTimestamp = await SendGetRequest("https://nullinside.com/twitch-bot/v1/bot/chat/timestamp");
197+
(HttpStatusCode, string?) chat = await SendGetRequest("https://nullinside.com/twitch-bot/v1/bot/chat/timestamp");
182198
bool chatNotUpdating = false;
183-
if (null != ChatTimestamp) {
199+
if (HttpStatusCode.OK == chat.Item1 && null != chat.Item2) {
200+
ChatTimestamp = chat.Item2;
184201
string parsed = ChatTimestamp.Trim('"');
185202
if (DateTime.TryParse(parsed, out DateTime time)) {
186203
string timestamp = time.ToLocalTime().ToString(CultureInfo.InvariantCulture);
@@ -190,6 +207,10 @@ private async Task PingSite() {
190207
chatNotUpdating = diff > TimeSpan.FromMinutes(5);
191208
}
192209
}
210+
else {
211+
ChatTimestamp = null;
212+
chatNotUpdating = true;
213+
}
193214

194215
if ((!WebsiteUp || !ApiUp || !NullUp || chatNotUpdating) && IsMinimized) {
195216
WindowState = WindowState.Normal;
@@ -224,18 +245,18 @@ private async Task<bool> SendHeadRequest(string address) {
224245
/// </summary>
225246
/// <param name="address">The address to send the request to.</param>
226247
/// <returns>The content of the response.</returns>
227-
private async Task<string?> SendGetRequest(string address) {
248+
private async Task<(HttpStatusCode, string?)> SendGetRequest(string address) {
228249
try {
229250
var handler = new HttpClientHandler();
230251
handler.AutomaticDecompression = ~DecompressionMethods.None;
231252
using var httpClient = new HttpClient(handler);
232253
using var request = new HttpRequestMessage(HttpMethod.Get, address);
233254
request.Headers.TryAddWithoutValidation("user-agent", Nullinside.Api.Common.Constants.FAKE_USER_AGENT);
234255
HttpResponseMessage response = await httpClient.SendAsync(request);
235-
return await response.Content.ReadAsStringAsync();
256+
return (response.StatusCode, await response.Content.ReadAsStringAsync());
236257
}
237258
catch {
238-
return null;
259+
return (HttpStatusCode.InternalServerError, null);
239260
}
240261
}
241262

src/SiteMonitor/ViewModels/NewVersionWindowViewModel.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ namespace SiteMonitor.ViewModels;
1717
/// The view model for the <seealso cref="NewVersionWindow" /> class.
1818
/// </summary>
1919
public class NewVersionWindowViewModel : ViewModelBase {
20+
/// <summary>
21+
/// True if updating the application currently, false otherwise.
22+
/// </summary>
23+
private bool _isUpdating;
24+
2025
/// <summary>
2126
/// The local version of the software.
2227
/// </summary>
@@ -36,9 +41,10 @@ public class NewVersionWindowViewModel : ViewModelBase {
3641
/// Initializes a new instance of the <see cref="NewVersionWindowViewModel" /> class.
3742
/// </summary>
3843
public NewVersionWindowViewModel() {
39-
OpenBrowser = ReactiveCommand.Create(LaunchBrowser);
44+
UpdateSoftware = ReactiveCommand.Create(StartUpdateSoftware);
4045
CloseWindow = ReactiveCommand.Create<Window>(CloseWindowCommand);
4146

47+
// asynchronously determine the current version number.
4248
Task.Factory.StartNew(async () => {
4349
GithubLatestReleaseJson? version =
4450
await GitHubUpdateManager.GetLatestVersion("nullinside-development-group", "nullinside-site-monitor");
@@ -69,9 +75,17 @@ public string? ServerVersion {
6975
}
7076

7177
/// <summary>
72-
/// A command to open the browser window at the current update's location.
78+
/// True if updating the application currently, false otherwise.
79+
/// </summary>
80+
public bool IsUpdating {
81+
get => _isUpdating;
82+
set => this.RaiseAndSetIfChanged(ref _isUpdating, value);
83+
}
84+
85+
/// <summary>
86+
/// A command to update the software.
7387
/// </summary>
74-
public ICommand OpenBrowser { get; }
88+
public ICommand UpdateSoftware { get; }
7589

7690
/// <summary>
7791
/// A command to close the current window.
@@ -89,11 +103,16 @@ private void CloseWindowCommand(Window self) {
89103
/// <summary>
90104
/// Launches the web browser at the new release page.
91105
/// </summary>
92-
private void LaunchBrowser() {
93-
if (string.IsNullOrWhiteSpace(_newVersionUrl)) {
94-
return;
95-
}
96-
97-
Process.Start("explorer", _newVersionUrl);
106+
private void StartUpdateSoftware() {
107+
IsUpdating = true;
108+
GitHubUpdateManager.PrepareUpdate()
109+
.ContinueWith(_ => {
110+
if (string.IsNullOrWhiteSpace(_newVersionUrl)) {
111+
return;
112+
}
113+
114+
Process.Start("explorer", _newVersionUrl);
115+
GitHubUpdateManager.ExitApplicationToUpdate();
116+
}).ConfigureAwait(false);
98117
}
99118
}

src/SiteMonitor/Views/MainWindow.axaml.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
using Avalonia.Controls;
66
using Avalonia.Interactivity;
77

8-
using Nullinside.Api.Common.Desktop;
9-
#if !DEBUG
108
using Microsoft.Extensions.DependencyInjection;
119

10+
using Nullinside.Api.Common.Desktop;
11+
#if !DEBUG
1212
using Avalonia.Threading;
1313

1414
using SiteMonitor.ViewModels;
@@ -44,10 +44,15 @@ public MainWindow() {
4444
protected override void OnInitialized() {
4545
base.OnInitialized();
4646

47+
// Register all the services needed for the application to run
48+
var collection = new ServiceCollection();
49+
collection.AddCommonServices();
50+
ServiceProvider = collection.BuildServiceProvider();
51+
4752
// handle the command line arguments for updating the application if applicable.
4853
string[] args = Environment.GetCommandLineArgs();
4954
if (args.Contains("--update")) {
50-
_ = GitHubUpdateManager.PerformUpdateAndRestart("nullinside-development-group", "twitch-streaming-tools", args[2], "windows-x64.zip");
55+
_ = GitHubUpdateManager.PerformUpdateAndRestart("nullinside-development-group", "nullinside-site-monitor", args[2], "windows-x64.zip");
5156
return;
5257
}
5358

src/SiteMonitor/Views/NewVersionWindow.axaml

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,55 @@
33
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
55
xmlns:viewModels="clr-namespace:SiteMonitor.ViewModels"
6+
xmlns:controls="clr-namespace:SiteMonitor.Controls"
67
x:Name="Window"
78
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
89
x:Class="SiteMonitor.Views.NewVersionWindow"
910
x:DataType="viewModels:NewVersionWindowViewModel"
1011
WindowStartupLocation="CenterOwner"
11-
Topmost="True"
1212
SizeToContent="WidthAndHeight"
1313
Icon="/Assets/update.png"
14-
Title="New Version Available">
14+
Title="New Version Available"
15+
Background="rgb(26, 24, 23)">
1516
<Design.DataContext>
16-
<!-- This only sets the DataContext for the previewer in an IDE,
17-
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
1817
<viewModels:NewVersionWindowViewModel />
1918
</Design.DataContext>
2019

21-
<StackPanel Margin="10">
22-
<TextBlock TextWrapping="Wrap" Margin="0 0 0 10">There is a new version of the software available, would you like to download it?</TextBlock>
23-
<StackPanel Orientation="Horizontal">
24-
<Label>App Version: </Label>
25-
<TextBlock Text="{Binding LocalVersion}" HorizontalAlignment="Center" VerticalAlignment="Center" />
26-
</StackPanel>
27-
<StackPanel Orientation="Horizontal">
28-
<Label>Server Version: </Label>
29-
<TextBlock Text="{Binding ServerVersion}" HorizontalAlignment="Center" VerticalAlignment="Center" />
30-
</StackPanel>
31-
<StackPanel Orientation="Horizontal">
32-
<Button Command="{Binding OpenBrowser}" Margin="0 10 0 0">Open Browser...</Button>
33-
<Button Command="{Binding CloseWindow}" CommandParameter="{Binding ElementName=Window}" Margin="10 10 0 0">Close</Button>
20+
<DockPanel HorizontalAlignment="Stretch"
21+
VerticalAlignment="Stretch"
22+
Name="ContentWrapper">
23+
<StackPanel>
24+
<!-- The normal panel -->
25+
<StackPanel Margin="10" IsVisible="{Binding !IsUpdating}">
26+
<TextBlock TextWrapping="Wrap" Margin="0 0 0 10">There is a new version of the software available, would you like to download it?</TextBlock>
27+
<StackPanel Orientation="Horizontal">
28+
<Label>App Version: </Label>
29+
<TextBlock Text="{Binding LocalVersion}" HorizontalAlignment="Center" VerticalAlignment="Center" />
30+
</StackPanel>
31+
<StackPanel Orientation="Horizontal">
32+
<Label>Server Version: </Label>
33+
<TextBlock Text="{Binding ServerVersion}" HorizontalAlignment="Center" VerticalAlignment="Center" />
34+
</StackPanel>
35+
<StackPanel Orientation="Horizontal">
36+
<Button Command="{Binding UpdateSoftware}" Margin="0 10 0 0">Install New Version</Button>
37+
<Button Command="{Binding CloseWindow}" CommandParameter="{Binding ElementName=Window}"
38+
Margin="10 10 0 0">
39+
Close
40+
</Button>
41+
</StackPanel>
42+
</StackPanel>
43+
44+
<!-- The waiting to update display -->
45+
<StackPanel IsVisible="{Binding IsUpdating}">
46+
<Label HorizontalAlignment="Center"
47+
VerticalAlignment="Center"
48+
FontSize="32"
49+
FontWeight="Bold"
50+
Foreground="rgb(204, 200, 175)">
51+
Updating
52+
</Label>
53+
<controls:Loading Width="100" Height="100" />
54+
</StackPanel>
3455
</StackPanel>
35-
</StackPanel>
56+
</DockPanel>
3657
</Window>

0 commit comments

Comments
 (0)