feat: ship 1.0.8.0 release automation and runtime overhaul

- reduce ASAR IO overhead with streamed archive reads, buffered copies, faster relative-path handling and placeholder integrity records
- fix in-place app.asar.unpacked packing/extraction self-copy cases that caused locked-file failures
- tighten JS patch discovery with candidate bundle filters and search hints
- require prebuilt remote-panel dist artifacts and clean up embedded bridge/script packaging
- add unified build entrypoints for PowerShell, cmd and bash and move native CMake output under .tmp
- add release metadata validation, changelog section extraction, pre-commit hook and GitHub Actions validation/release pipelines
- make CHANGELOG the source of truth for release notes and document the tag-driven release flow
- add updater release notes UI with latest/full changelog loading and localize the new update strings
- modularize bridge renderer scripts, add installed apps and game status sync, and support remote launch/stop commands
- centralize bridge protocol, IPC and WebSocket constants and improve LAN IP selection for QR pairing
- refactor remote panel controls/state enums, persist accent color, polish library/session UI and refresh assets
This commit is contained in:
kitbyte
2026-05-06 13:07:09 +03:00
parent 3b2f373946
commit 13759b1db6
125 changed files with 8933 additions and 2838 deletions
+17 -4
View File
@@ -185,10 +185,19 @@ namespace WandEnhancer.View.MainWindow
});
}
private void OnUpdate(object param)
private async void OnUpdate(object param)
{
MainWindow.Instance.OpenPopup(new UpdatePopup(() =>
var updateInfo = await _updater.GetUpdateInfoAsync();
if (updateInfo == null)
{
Log("No update details are available right now.", ELogType.Warn);
return;
}
MainWindow.Instance.OpenPopup(new UpdatePopup(Constants.Version.ToString(), updateInfo.Version,
updateInfo.LatestNotes, () =>
{
MainWindow.Instance.ClosePopup();
Task.Run(async () =>
{
try
@@ -203,7 +212,7 @@ namespace WandEnhancer.View.MainWindow
Log("WandEnhancer updated successfully. Restarting...", ELogType.Success);
});
}), Application.Current.FindResource("up_popup_title") as string);
}, () => _updater.GetFullChangelogAsync()), Application.Current.FindResource("up_popup_title") as string);
}
private void OnOpenSettings(object param)
@@ -271,7 +280,11 @@ namespace WandEnhancer.View.MainWindow
public MainWindowVm(MainWindow view)
{
Task.Run(async () => IsUpdateAvailable = await _updater.CheckForUpdates());
Task.Run(async () =>
{
var isUpdateAvailable = await _updater.CheckForUpdates();
Application.Current.Dispatcher.Invoke(() => IsUpdateAvailable = isUpdateAvailable);
});
_view = view;
SetFolderPathCommand = new RelayCommand(OnFolderPathSelection);
ApplyPatchCommand = new RelayCommand(OnPatching);
+92 -8
View File
@@ -3,18 +3,102 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WandEnhancer.View.Popups"
mc:Ignorable="d"
d:DesignHeight="Auto" d:DesignWidth="Auto"
Background="{DynamicResource Background}"
Foreground="{DynamicResource MutedForeground}"
FontWeight="Medium"
FontSize="13">
<StackPanel>
<TextBlock Foreground="Red" MaxWidth="320" TextAlignment="Center" Text="{DynamicResource up_warning}" TextWrapping="Wrap" />
<Button Padding="0 5 0 5" Margin="0 15 0 0" Content="{DynamicResource up_update_now}"
Click="OnUpdateClick" />
</StackPanel>
<Grid MinWidth="500" MaxWidth="620">
<Grid.Resources>
<Style x:Key="UpdateActionButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="{DynamicResource Primary}" />
<Setter Property="BorderBrush" Value="{DynamicResource Primary}" />
<Setter Property="Foreground" Value="{DynamicResource PrimaryForeground}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Primary}" />
<Setter Property="BorderBrush" Value="{DynamicResource Primary}" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Grid.Row="0" HorizontalAlignment="Left" MaxWidth="560"
Padding="9 4" CornerRadius="4"
Background="{DynamicResource Muted}">
<DockPanel LastChildFill="True">
<Ellipse Width="7" Height="7" Fill="{DynamicResource Destructive}"
Margin="0 0 8 0" VerticalAlignment="Center" />
<TextBlock Foreground="{DynamicResource Foreground}" FontSize="11.5"
Text="{DynamicResource up_warning}" TextWrapping="Wrap" />
</DockPanel>
</Border>
<WrapPanel Grid.Row="1" Margin="0 10 0 0" Orientation="Horizontal">
<Border Padding="8 4" Margin="0 0 8 0" CornerRadius="4"
Background="{DynamicResource Muted}" BorderBrush="{DynamicResource Border}" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 7 0" VerticalAlignment="Center"
Foreground="{DynamicResource MutedForeground}" FontSize="10.5"
Text="{DynamicResource up_current_version}" />
<TextBlock x:Name="CurrentVersionValue" VerticalAlignment="Center"
Foreground="{DynamicResource Foreground}" FontSize="12.5" FontWeight="Bold" />
</StackPanel>
</Border>
<Border Padding="8 4" CornerRadius="4"
Background="{DynamicResource Primary}" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0 0 7 0" VerticalAlignment="Center"
Foreground="{DynamicResource PrimaryForeground}" FontSize="10.5"
Text="{DynamicResource up_latest_version}" />
<TextBlock x:Name="LatestVersionValue" VerticalAlignment="Center"
Foreground="{DynamicResource PrimaryForeground}" FontSize="12.5" FontWeight="Bold" />
</StackPanel>
</Border>
</WrapPanel>
<TextBlock Grid.Row="2" Margin="0 12 0 6" Foreground="{DynamicResource Foreground}"
FontSize="14" FontWeight="Bold" Text="{DynamicResource up_release_notes}" />
<Border Grid.Row="3"
Background="{DynamicResource Muted}" BorderBrush="{DynamicResource Border}" BorderThickness="1" CornerRadius="4">
<ScrollViewer x:Name="NotesScrollViewer"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Disabled"
CanContentScroll="False">
<TextBox x:Name="NotesTextBlock" Background="Transparent"
BorderBrush="Transparent"
Padding="12"
BorderThickness="0" IsReadOnly="True"
Foreground="{DynamicResource Foreground}"
TextWrapping="Wrap" />
</ScrollViewer>
</Border>
<Grid Grid.Row="4" Margin="0 12 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="ShowMoreButton" Grid.Column="1" Margin="0 0 10 0"
Padding="12 5" Content="{DynamicResource up_show_more}"
Click="OnShowMoreClick" />
<Button Grid.Column="2" Padding="18 5" Style="{StaticResource UpdateActionButton}"
Content="{DynamicResource up_update_now}"
Click="OnUpdateClick" />
</Grid>
</Grid>
</UserControl>
+74 -1
View File
@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@@ -7,16 +8,88 @@ namespace WandEnhancer.View.Popups
public partial class UpdatePopup : UserControl
{
private readonly Action _onUpdate;
private readonly Func<Task<string>> _loadFullChangelog;
private readonly string _latestNotes;
private string _fullChangelog;
private bool _showingFullChangelog;
public UpdatePopup(Action onUpdate)
public UpdatePopup(string currentVersion, string latestVersion, string latestNotes, Action onUpdate,
Func<Task<string>> loadFullChangelog)
{
_onUpdate = onUpdate;
_loadFullChangelog = loadFullChangelog;
InitializeComponent();
CurrentVersionValue.Text = currentVersion;
LatestVersionValue.Text = latestVersion;
_latestNotes = string.IsNullOrWhiteSpace(latestNotes)
? GetResourceText("up_release_notes_unavailable")
: latestNotes;
SetNotesText(_latestNotes);
ShowMoreButton.Visibility = loadFullChangelog == null ? Visibility.Collapsed : Visibility.Visible;
}
private void OnUpdateClick(object sender, RoutedEventArgs e)
{
_onUpdate();
}
private async void OnShowMoreClick(object sender, RoutedEventArgs e)
{
if (_loadFullChangelog == null)
{
return;
}
if (_showingFullChangelog)
{
SetNotesText(_latestNotes);
ShowMoreButton.Content = GetResourceText("up_show_more");
_showingFullChangelog = false;
return;
}
if (string.IsNullOrWhiteSpace(_fullChangelog))
{
ShowMoreButton.IsEnabled = false;
ShowMoreButton.Content = GetResourceText("up_loading_changelog");
try
{
_fullChangelog = await _loadFullChangelog();
}
finally
{
ShowMoreButton.IsEnabled = true;
}
}
if (string.IsNullOrWhiteSpace(_fullChangelog))
{
ShowMoreButton.Content = GetResourceText("up_show_more");
SetNotesText(string.Concat(
_latestNotes,
Environment.NewLine,
Environment.NewLine,
GetResourceText("up_changelog_failed")));
return;
}
SetNotesText(_fullChangelog);
ShowMoreButton.Content = GetResourceText("up_show_less");
_showingFullChangelog = true;
}
private void SetNotesText(string text)
{
NotesTextBlock.Text = text ?? string.Empty;
NotesScrollViewer.ScrollToTop();
}
private static string GetResourceText(string key)
{
return Application.Current.TryFindResource(key) as string ?? string.Empty;
}
}
}