mirror of
https://github.com/Stone-Red-Code/DesktopMagic.git
synced 2026-09-04 00:46:12 +02:00
Add update dialog showing latest release info after app update
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
<Application x:Class="DesktopMagic.App"
|
<Application x:Class="DesktopMagic.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:md="http://schemas.lepo.co/wpfui/2022/xaml/markdown"
|
||||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||||
xmlns:helpers="clr-namespace:DesktopMagic.Helpers"
|
xmlns:helpers="clr-namespace:DesktopMagic.Helpers"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
@@ -10,6 +11,8 @@
|
|||||||
<ResourceDictionary Source="Resources\Strings\StringResources.en.xaml" />
|
<ResourceDictionary Source="Resources\Strings\StringResources.en.xaml" />
|
||||||
<ui:ThemesDictionary Theme="Light" />
|
<ui:ThemesDictionary Theme="Light" />
|
||||||
<ui:ControlsDictionary />
|
<ui:ControlsDictionary />
|
||||||
|
<md:ThemesDictionary Theme="Light" />
|
||||||
|
<md:ControlsDictionary />
|
||||||
<ResourceDictionary Source="pack://application:,,,/BusyIndicator;component/Theme/Default.xaml" />
|
<ResourceDictionary Source="pack://application:,,,/BusyIndicator;component/Theme/Default.xaml" />
|
||||||
<ResourceDictionary Source="Resources\Images\ImageResources.xaml" />
|
<ResourceDictionary Source="Resources\Images\ImageResources.xaml" />
|
||||||
<ResourceDictionary Source="Resources\Styles\ToggleSwitchContentLeftStyle.xaml" />
|
<ResourceDictionary Source="Resources\Styles\ToggleSwitchContentLeftStyle.xaml" />
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
<PackageReference Include="NAudio" Version="2.2.1" />
|
<PackageReference Include="NAudio" Version="2.2.1" />
|
||||||
<PackageReference Include="System.Management" Version="8.0.0" />
|
<PackageReference Include="System.Management" Version="8.0.0" />
|
||||||
<PackageReference Include="WPF-UI" Version="4.2.0" />
|
<PackageReference Include="WPF-UI" Version="4.2.0" />
|
||||||
|
<PackageReference Include="WPF-UI.Markdown" Version="4.0.2" />
|
||||||
<PackageReference Include="WPF-UI.Tray" Version="4.2.0" />
|
<PackageReference Include="WPF-UI.Tray" Version="4.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<ui:FluentWindow x:Class="DesktopMagic.Dialogs.ReleaseInfoDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:md="http://schemas.lepo.co/wpfui/2022/xaml/markdown"
|
||||||
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
|
||||||
|
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||||
|
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||||
|
WindowCornerPreference="Round"
|
||||||
|
WindowBackdropType="Tabbed"
|
||||||
|
Height="700"
|
||||||
|
Width="900"
|
||||||
|
MinHeight="500"
|
||||||
|
MinWidth="700"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
ExtendsContentIntoTitleBar="True">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<ui:TitleBar x:Name="titleBar" ShowMinimize="False" ShowMaximize="False">
|
||||||
|
<ui:TitleBar.Icon>
|
||||||
|
<ui:ImageIcon Source="{StaticResource Icon}" />
|
||||||
|
</ui:TitleBar.Icon>
|
||||||
|
</ui:TitleBar>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="1" Margin="14,10,14,0">
|
||||||
|
<TextBlock x:Name="releaseNameTextBlock" FontSize="20" FontWeight="SemiBold" />
|
||||||
|
<TextBlock x:Name="publishedAtTextBlock" Foreground="{DynamicResource TextFillColorSecondaryBrush}" Margin="0,4,0,0" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Border Grid.Row="2" Margin="14,12,14,12" BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}" BorderThickness="1" CornerRadius="8">
|
||||||
|
<md:MarkdownViewer x:Name="releaseMarkdownViewer" Margin="8" />
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="14,0,14,12">
|
||||||
|
<Button x:Name="openButton" Width="150" Margin="0,0,8,0" Click="OpenButton_Click" />
|
||||||
|
<Button x:Name="okButton" Width="100" Click="OkButton_Click" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</ui:FluentWindow>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace DesktopMagic.Dialogs;
|
||||||
|
|
||||||
|
public partial class ReleaseInfoDialog : Wpf.Ui.Controls.FluentWindow
|
||||||
|
{
|
||||||
|
public bool OpenReleaseRequested { get; private set; }
|
||||||
|
|
||||||
|
public ReleaseInfoDialog(
|
||||||
|
string title,
|
||||||
|
string releaseName,
|
||||||
|
string publishedAt,
|
||||||
|
string markdown,
|
||||||
|
string openButtonText,
|
||||||
|
string okButtonText)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Resources.MergedDictionaries.Add(App.LanguageDictionary);
|
||||||
|
|
||||||
|
titleBar.Title = title;
|
||||||
|
Title = title;
|
||||||
|
releaseNameTextBlock.Text = releaseName;
|
||||||
|
publishedAtTextBlock.Text = publishedAt;
|
||||||
|
releaseMarkdownViewer.Markdown = string.IsNullOrWhiteSpace(markdown) ? "-" : markdown;
|
||||||
|
openButton.Content = openButtonText;
|
||||||
|
okButton.Content = okButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
OpenReleaseRequested = true;
|
||||||
|
DialogResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
DialogResult = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DesktopMagic.Helpers;
|
||||||
|
|
||||||
|
public sealed class GitHubLatestRelease
|
||||||
|
{
|
||||||
|
[JsonPropertyName("tag_name")]
|
||||||
|
public string TagName { get; init; } = "Unknown";
|
||||||
|
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; init; } = "Unknown";
|
||||||
|
|
||||||
|
[JsonPropertyName("body")]
|
||||||
|
public string Body { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
[JsonPropertyName("published_at")]
|
||||||
|
public DateTimeOffset? PublishedAt { get; init; }
|
||||||
|
|
||||||
|
[JsonPropertyName("html_url")]
|
||||||
|
public string HtmlUrl { get; init; } = "https://github.com/Stone-Red-Code/DesktopMagic/releases/latest";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GitHubReleaseService
|
||||||
|
{
|
||||||
|
private const string LatestReleaseApiUrl = "https://api.github.com/repos/Stone-Red-Code/DesktopMagic/releases/latest";
|
||||||
|
private static readonly HttpClient _httpClient = CreateReleaseHttpClient();
|
||||||
|
|
||||||
|
private static HttpClient CreateReleaseHttpClient()
|
||||||
|
{
|
||||||
|
HttpClient client = new()
|
||||||
|
{
|
||||||
|
Timeout = TimeSpan.FromSeconds(10)
|
||||||
|
};
|
||||||
|
|
||||||
|
client.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github+json");
|
||||||
|
client.DefaultRequestHeaders.UserAgent.ParseAdd("DesktopMagic");
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<GitHubLatestRelease?> GetLatestReleaseInfoAsync()
|
||||||
|
{
|
||||||
|
using HttpResponseMessage response = await _httpClient.GetAsync(LatestReleaseApiUrl);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
await using var responseStream = await response.Content.ReadAsStreamAsync();
|
||||||
|
return await JsonSerializer.DeserializeAsync<GitHubLatestRelease>(responseStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
using DesktopMagic.DataContexts;
|
using DesktopMagic.DataContexts;
|
||||||
|
using DesktopMagic.Dialogs;
|
||||||
|
using DesktopMagic.Helpers;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
using Wpf.Ui.Appearance;
|
using Wpf.Ui.Appearance;
|
||||||
@@ -43,6 +49,7 @@ public partial class MainWindow : FluentWindow
|
|||||||
|
|
||||||
_manager.IsLoaded = true;
|
_manager.IsLoaded = true;
|
||||||
_mainWindowDataContext.IsLoading = false;
|
_mainWindowDataContext.IsLoading = false;
|
||||||
|
await ShowLatestReleaseInfoAfterUpdateAsync();
|
||||||
|
|
||||||
App.Logger.LogInfo("Application loaded", source: "MainWindow");
|
App.Logger.LogInfo("Application loaded", source: "MainWindow");
|
||||||
}
|
}
|
||||||
@@ -190,4 +197,75 @@ public partial class MainWindow : FluentWindow
|
|||||||
{
|
{
|
||||||
Quit();
|
Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ShowLatestReleaseInfoAfterUpdateAsync()
|
||||||
|
{
|
||||||
|
string currentVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "0.0.0.0";
|
||||||
|
string? lastShownVersion = _manager.Settings.ReleaseInfoLastAppVersion;
|
||||||
|
|
||||||
|
if (string.Equals(lastShownVersion, currentVersion, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GitHubLatestRelease? latestRelease = await GetLatestReleaseInfoAsync();
|
||||||
|
if (latestRelease is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string releaseName = !string.IsNullOrWhiteSpace(latestRelease.Name) ? latestRelease.Name : latestRelease.TagName;
|
||||||
|
string publishedAt = latestRelease.PublishedAt?.ToLocalTime().ToString("g") ?? (string)FindResource("unknown");
|
||||||
|
string publishedAtText = string.Format((string)FindResource("releaseInfoPublishedFormat"), publishedAt);
|
||||||
|
string releaseNotesMarkdown = string.IsNullOrWhiteSpace(latestRelease.Body) ? "-" : latestRelease.Body.Trim();
|
||||||
|
|
||||||
|
ReleaseInfoDialog releaseInfoDialog = new(
|
||||||
|
(string)FindResource("releaseInfoTitle"),
|
||||||
|
releaseName,
|
||||||
|
publishedAtText,
|
||||||
|
releaseNotesMarkdown,
|
||||||
|
(string)FindResource("openReleasePage"),
|
||||||
|
(string)FindResource("ok"))
|
||||||
|
{
|
||||||
|
Owner = this,
|
||||||
|
Topmost = true
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = releaseInfoDialog.ShowDialog();
|
||||||
|
|
||||||
|
if (releaseInfoDialog.OpenReleaseRequested)
|
||||||
|
{
|
||||||
|
ProcessStartInfo processStartInfo = new()
|
||||||
|
{
|
||||||
|
UseShellExecute = true,
|
||||||
|
FileName = latestRelease.HtmlUrl
|
||||||
|
};
|
||||||
|
_ = Process.Start(processStartInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
_manager.Settings.ReleaseInfoLastAppVersion = currentVersion;
|
||||||
|
_manager.SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<GitHubLatestRelease?> GetLatestReleaseInfoAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await GitHubReleaseService.GetLatestReleaseInfoAsync();
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
App.Logger.LogError($"Failed to retrieve latest release information: {ex.Message}", source: "MainWindow");
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException ex)
|
||||||
|
{
|
||||||
|
App.Logger.LogWarn($"Timed out while retrieving latest release information: {ex.Message}", source: "MainWindow");
|
||||||
|
}
|
||||||
|
catch (JsonException ex)
|
||||||
|
{
|
||||||
|
App.Logger.LogError($"Failed to parse latest release information: {ex.Message}", source: "MainWindow");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -60,6 +60,11 @@
|
|||||||
<system:String x:Key="addedFormat">Erstellt: {0}</system:String>
|
<system:String x:Key="addedFormat">Erstellt: {0}</system:String>
|
||||||
<system:String x:Key="updatedFormat">Aktualisiert: {0}</system:String>
|
<system:String x:Key="updatedFormat">Aktualisiert: {0}</system:String>
|
||||||
<system:String x:Key="versionFormat">Version: {0}</system:String>
|
<system:String x:Key="versionFormat">Version: {0}</system:String>
|
||||||
|
<system:String x:Key="releaseInfoTitle">DesktopMagic wurde aktualisiert!</system:String>
|
||||||
|
<system:String x:Key="releaseInfoHeaderFormat">Neueste Version: {0}</system:String>
|
||||||
|
<system:String x:Key="releaseInfoPublishedFormat">Veröffentlicht: {0}</system:String>
|
||||||
|
<system:String x:Key="releaseInfoBodyLabel">Release Notes:</system:String>
|
||||||
|
<system:String x:Key="openReleasePage">Release-Seite öffnen</system:String>
|
||||||
<col:ArrayList x:Key="musicVisualizerOptionsComboboxItems">
|
<col:ArrayList x:Key="musicVisualizerOptionsComboboxItems">
|
||||||
<system:String>Unten</system:String>
|
<system:String>Unten</system:String>
|
||||||
<system:String>Mitte</system:String>
|
<system:String>Mitte</system:String>
|
||||||
|
|||||||
@@ -62,6 +62,11 @@
|
|||||||
<system:String x:Key="addedFormat">Added: {0}</system:String>
|
<system:String x:Key="addedFormat">Added: {0}</system:String>
|
||||||
<system:String x:Key="updatedFormat">Updated: {0}</system:String>
|
<system:String x:Key="updatedFormat">Updated: {0}</system:String>
|
||||||
<system:String x:Key="versionFormat">Version: {0}</system:String>
|
<system:String x:Key="versionFormat">Version: {0}</system:String>
|
||||||
|
<system:String x:Key="releaseInfoTitle">DesktopMagic has been updated!</system:String>
|
||||||
|
<system:String x:Key="releaseInfoHeaderFormat">Latest release: {0}</system:String>
|
||||||
|
<system:String x:Key="releaseInfoPublishedFormat">Published: {0}</system:String>
|
||||||
|
<system:String x:Key="releaseInfoBodyLabel">Release notes:</system:String>
|
||||||
|
<system:String x:Key="openReleasePage">Open release page</system:String>
|
||||||
<col:ArrayList x:Key="musicVisualizerOptionsComboboxItems">
|
<col:ArrayList x:Key="musicVisualizerOptionsComboboxItems">
|
||||||
<system:String>Bottom</system:String>
|
<system:String>Bottom</system:String>
|
||||||
<system:String>Middle</system:String>
|
<system:String>Middle</system:String>
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ public class DesktopMagicSettings : INotifyPropertyChanged
|
|||||||
|
|
||||||
public string? ModIoAccessToken { get; set; }
|
public string? ModIoAccessToken { get; set; }
|
||||||
|
|
||||||
|
public string? ReleaseInfoLastAppVersion { get; set; }
|
||||||
|
|
||||||
public DesktopMagicSettings()
|
public DesktopMagicSettings()
|
||||||
{
|
{
|
||||||
themes.CollectionChanged += (s, e) => CurrentLayout.UpdateTheme();
|
themes.CollectionChanged += (s, e) => CurrentLayout.UpdateTheme();
|
||||||
|
|||||||
Reference in New Issue
Block a user