Skip to content

Commit

Permalink
Implement auto update logic
Browse files Browse the repository at this point in the history
  • Loading branch information
iodes committed Aug 14, 2022
1 parent 5f64cc1 commit e6d0948
Show file tree
Hide file tree
Showing 15 changed files with 455 additions and 11 deletions.
3 changes: 2 additions & 1 deletion GestureWheel/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Startup="App_OnStartup" Exit="App_OnExit">
Exit="App_OnExit"
Startup="App_OnStartup">

<Application.Resources>
<ResourceDictionary>
Expand Down
18 changes: 15 additions & 3 deletions GestureWheel/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Windows.Controls;
using GestureWheel.Managers;
using GestureWheel.Supports;
using GestureWheel.Utilities;
using Hardcodet.Wpf.TaskbarNotification;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
Expand Down Expand Up @@ -38,7 +39,6 @@ private void InitializeUserInterface()
_taskbarIcon = new TaskbarIcon
{
IsEnabled = true,
ToolTipText = "GestureWheel",
ContextMenu = new ContextMenu(),
Icon = Icon.ExtractAssociatedIcon(EnvironmentSupport.Executable)
};
Expand All @@ -48,8 +48,8 @@ private void InitializeUserInterface()
_taskbarIcon.ContextMenu.Items.Add(CreateMenuItem("프로그램 설정",
ShowWithActivate, SymbolRegular.Wrench20));

_taskbarIcon.ContextMenu.Items.Add(CreateMenuItem("업데이트 확인",
() => Process.Start("https://github.com/iodes/GestureWheel"), SymbolRegular.Earth20));
_taskbarIcon.ContextMenu.Items.Add(CreateMenuItem("홈페이지 방문",
() => UrlUtility.Open("https://github.com/iodes/GestureWheel"), SymbolRegular.Open20));

_taskbarIcon.ContextMenu.Items.Add(new Separator());

Expand Down Expand Up @@ -96,6 +96,18 @@ private void App_OnStartup(object sender, StartupEventArgs e)

if (Environment.GetCommandLineArgs().Contains("/Activate", StringComparer.OrdinalIgnoreCase))
ShowWithActivate();

if (SettingsManager.Current.UseAutoUpdate)
{
try
{
_ = UpdateSupport.CheckUpdateAsync();
}
catch
{
// ignored
}
}
}

private void App_OnExit(object sender, ExitEventArgs e)
Expand Down
73 changes: 73 additions & 0 deletions GestureWheel/Dialogs/UpdateDialog.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<ui:UiWindow
x:Class="GestureWheel.Dialogs.UpdateDialog"
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:ui="http://schemas.lepo.co/wpfui/2022/xaml"
Title="자동 업데이트"
Width="400"
Height="200"
MinHeight="200"
ExtendsContentIntoTitleBar="True"
WindowBackdropType="Mica"
WindowCornerPreference="Round"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Grid x:Name="RootMainGrid" Grid.Row="1">
<Border Background="{ui:ThemeResource ControlFillColorDefaultBrush}" CornerRadius="8,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>

<StackPanel Grid.Row="0" Margin="20,15,20,0">
<TextBlock x:Name="TextVersion" />
<ProgressBar
x:Name="ProgressUpdate"
Margin="0,20,0,0"
Maximum="100" />
</StackPanel>

<StackPanel
Grid.Row="1"
Margin="0,0,20,20"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Orientation="Horizontal">

<ui:Button
x:Name="BtnCancel"
Margin="0,0,10,0"
Appearance="Secondary"
Click="BtnCancel_Click"
Content="취소"
DockPanel.Dock="Right"
Icon="Dismiss24" />

<ui:Button
x:Name="BtnUpdate"
Appearance="Primary"
Click="BtnUpdate_Click"
Content="업데이트"
DockPanel.Dock="Right"
Icon="ArrowDownload24" />
</StackPanel>
</Grid>
</Border>
</Grid>

<ui:TitleBar
Title="자동 업데이트"
Grid.Row="0"
ShowMaximize="False"
ShowMinimize="False" />
</Grid>
</ui:UiWindow>
69 changes: 69 additions & 0 deletions GestureWheel/Dialogs/UpdateDialog.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Windows;
using GestureWheel.Extensions;
using GestureWheel.Windows.Models;

namespace GestureWheel.Dialogs
{
public partial class UpdateDialog
{
#region Properties
private UpdateInfo Info { get; }
#endregion

public UpdateDialog(UpdateInfo info)
{
Info = info;
InitializeComponent();

TextVersion.Text = $"새로운 버전이 출시되었습니다.\n{nameof(GestureWheel)}{info.Version} 버전으로 업데이트 하시겠습니까?";
}

private async void BtnUpdate_Click(object sender, RoutedEventArgs e)
{
BtnCancel.IsEnabled = false;
BtnUpdate.IsEnabled = false;

var fileName = Path.Combine(Path.GetTempPath(), Info.FileName);

using (var client = new HttpClient())
await using (var file = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
var progress = new Progress<double>();

progress.ProgressChanged += (_, value) =>
{
Dispatcher.Invoke(() => ProgressUpdate.Value = value);
};

await client.DownloadAsync(Info.Url, file, progress);
}

try
{
Process.Start(new ProcessStartInfo(fileName)
{
UseShellExecute = true
});

Application.Current.Shutdown();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "오류", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
Close();
}
}

private void BtnCancel_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}
30 changes: 30 additions & 0 deletions GestureWheel/Extensions/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace GestureWheel.Extensions
{
internal 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;
await using var download = await response.Content.ReadAsStreamAsync(cancellationToken);

if (progress is null || !contentLength.HasValue)
{
await download.CopyToAsync(destination, cancellationToken);
return;
}

var relativeProgress = new Progress<long>(totalBytes => progress.Report((double)totalBytes / contentLength.Value * 100));
await download.CopyToAsync(destination, 81920, relativeProgress, cancellationToken);

progress.Report(100);
}
}
}
39 changes: 39 additions & 0 deletions GestureWheel/Extensions/StreamExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace GestureWheel.Extensions
{
internal static class StreamExtensions
{
public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default)
{
if (source == null)
throw new ArgumentNullException(nameof(source));

if (!source.CanRead)
throw new ArgumentException("Has to be readable", nameof(source));

if (destination == null)
throw new ArgumentNullException(nameof(destination));

if (!destination.CanWrite)
throw new ArgumentException("Has to be writable", nameof(destination));

if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));

var buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;

while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
}
}
}
8 changes: 4 additions & 4 deletions GestureWheel/Managers/SettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ namespace GestureWheel.Managers
internal static class SettingsManager
{
#region Fields
private static SettingsModel _current;
private static Settings _current;
#endregion

#region Properties
public static SettingsModel Current
public static Settings Current
{
get
{
Expand All @@ -30,12 +30,12 @@ public static void Load()
{
if (!File.Exists(EnvironmentSupport.Settings))
{
_current = new SettingsModel();
_current = new Settings();
Save();
}

var settingsText = File.ReadAllText(EnvironmentSupport.Settings);
_current = JsonConvert.DeserializeObject<SettingsModel>(settingsText);
_current = JsonConvert.DeserializeObject<Settings>(settingsText);
}

public static void UpdateAutoStartup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

namespace GestureWheel.Models
{
internal class SettingsModel
internal class Settings
{
[JsonProperty]
public bool UseAutoUpdate { get; set; } = true;

[JsonProperty]
public bool UseAutoStartup { get; set; } = true;

Expand Down
17 changes: 17 additions & 0 deletions GestureWheel/Models/UpdateInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace GestureWheel.Windows.Models
{
public class UpdateInfo
{
public string Version { get; set; }

public DateTime Timestamp { get; set; }

public string ReleaseNote { get; set; }

public string FileName { get; set; }

public string Url { get; set; }
}
}
32 changes: 31 additions & 1 deletion GestureWheel/Pages/AboutPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,37 @@
FontSize="13"
FontWeight="Medium"
Text="프로그램 버전" />
<TextBlock FontSize="12" Text="1.0.0.0" />
<TextBlock
x:Name="TextVersion"
FontSize="12"
Text="1.0.0.0" />
</StackPanel>
</ui:CardControl.Header>
</ui:CardControl>

<ui:CardControl
x:Name="BtnCheckUpdate"
Click="BtnCheckUpdate_OnClick"
Icon="ArrowUpload20">
<ui:CardControl.Header>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock
FontSize="13"
FontWeight="Medium"
Text="최신 업데이트 확인" />
<TextBlock FontSize="12" Text="프로그램의 최신 업데이트를 확인 및 설치합니다." />
</StackPanel>
</ui:CardControl.Header>
</ui:CardControl>

<ui:CardControl x:Name="BtnOpenHomepage" Click="BtnOpenHomepage_OnClick" Icon="Open24">
<ui:CardControl.Header>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock
FontSize="13"
FontWeight="Medium"
Text="공식 홈페이지" />
<TextBlock FontSize="12" Text="프로그램의 공식 홈페이지를 방문합니다." />
</StackPanel>
</ui:CardControl.Header>
</ui:CardControl>
Expand Down
Loading

0 comments on commit e6d0948

Please sign in to comment.