using System; using System.ComponentModel; using System.IO; using System.Reflection; using System.Text.RegularExpressions; using Avalonia; using Avalonia.Media; using Avalonia.Styling; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CRD.Downloader; using CRD.Utils.Updater; using Markdig; namespace CRD.ViewModels; public partial class UpdateViewModel : ViewModelBase{ [ObservableProperty] private bool _updateAvailable; [ObservableProperty] private bool _updating; [ObservableProperty] private double _progress; [ObservableProperty] private bool _failed; private AccountPageViewModel accountPageViewModel; [ObservableProperty] private string _changelogText = "
No changelog found.
"; [ObservableProperty] private string _currentVersion; public UpdateViewModel(){ var version = Assembly.GetExecutingAssembly().GetName().Version; _currentVersion = $"{version?.Major}.{version?.Minor}.{version?.Build}"; LoadChangelog(); UpdateAvailable = ProgramManager.Instance.UpdateAvailable; Updater.Instance.PropertyChanged += Progress_PropertyChanged; } [RelayCommand] public void StartUpdate(){ Updating = true; ProgramManager.Instance.NavigationLock = true; // Title = "Updating"; _ = Updater.Instance.DownloadAndUpdateAsync(); } private void Progress_PropertyChanged(object? sender, PropertyChangedEventArgs e){ if (e.PropertyName == nameof(Updater.Instance.progress)){ Progress = Updater.Instance.progress; } else if (e.PropertyName == nameof(Updater.Instance.failed)){ Failed = Updater.Instance.failed; ProgramManager.Instance.NavigationLock = !Failed; } } private void LoadChangelog(){ string changelogPath = "CHANGELOG.md"; if (!File.Exists(changelogPath)){ ChangelogText = "No changelog found.
"; return; } string markdownText = File.ReadAllText(changelogPath); markdownText = PreprocessMarkdown(markdownText); var pipeline = new MarkdownPipelineBuilder() .UseAdvancedExtensions() .UseSoftlineBreakAsHardlineBreak() .Build(); string htmlContent = Markdown.ToHtml(markdownText, pipeline); htmlContent = MakeIssueLinksClickable(htmlContent); htmlContent = ModifyImages(htmlContent); Color themeTextColor = Application.Current?.RequestedThemeVariant == ThemeVariant.Dark ? Colors.White : Color.Parse("#E4000000"); string cssColor = $"#{themeTextColor.R:X2}{themeTextColor.G:X2}{themeTextColor.B:X2}"; string styledHtml = $@" {htmlContent} "; ChangelogText = styledHtml; } private string MakeIssueLinksClickable(string htmlContent){ // Match GitHub issue links string issuePattern = @"]*>[^<]+<\/a>"; // Match GitHub discussion links string discussionPattern = @"]*>[^<]+<\/a>"; htmlContent = Regex.Replace(htmlContent, issuePattern, match => { string fullUrl = match.Groups[1].Value; string issueNumber = match.Groups[2].Value; return $"#{issueNumber}"; }); htmlContent = Regex.Replace(htmlContent, discussionPattern, match => { string fullUrl = match.Groups[1].Value; string discussionNumber = match.Groups[2].Value; return $"#{discussionNumber}"; }); return htmlContent; } private string ModifyImages(string htmlContent){ // Regex to match