Fix blog save button highlight

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Paul Schneider 2026-10-18 22:04:19 +01:00
commit b68bc7b328
Signed by: notazof
GPG key ID: AD4B9B545FBD7D12
4 changed files with 52 additions and 9 deletions

View file

@ -47,6 +47,9 @@
* [PostIt] Le changement de disposition de la page des blogs est différé * [PostIt] Le changement de disposition de la page des blogs est différé
sur le thread UI, évitant l'exception « Visual was invalidated during sur le thread UI, évitant l'exception « Visual was invalidated during
the render pass » au redimensionnement. the render pass » au redimensionnement.
* [PostIt] Le bouton d'enregistrement des billets reflète les modifications
non sauvegardées et réinitialise son surlignage après sauvegarde, sans
fermer l'éditeur ni perdre la sélection.
## [1.0.8-rc26] - unstable ## [1.0.8-rc26] - unstable

View file

@ -58,6 +58,7 @@ public class PostItViewModelTests
Dispatcher.UIThread.RunJobs(); Dispatcher.UIThread.RunJobs();
Assert.Same(selected, page.PostsListBox.SelectedItem); Assert.Same(selected, page.PostsListBox.SelectedItem);
Assert.Same(selected, vm.SelectedPost); Assert.Same(selected, vm.SelectedPost);
vm.IsEditing = true;
Assert.DoesNotContain("modified", page.SaveButton.Classes); Assert.DoesNotContain("modified", page.SaveButton.Classes);
vm.DraftTitle = "Titre modifié"; vm.DraftTitle = "Titre modifié";
Dispatcher.UIThread.RunJobs(); Dispatcher.UIThread.RunJobs();
@ -67,11 +68,13 @@ public class PostItViewModelTests
await vm.SaveAsync(); await vm.SaveAsync();
Dispatcher.UIThread.RunJobs(); Dispatcher.UIThread.RunJobs();
Assert.Same(page, navigation.NavigationStack.Last()); Assert.Same(page, navigation.NavigationStack.Last());
Assert.True(vm.IsEditing);
Assert.Same(selected, vm.SelectedPost); Assert.Same(selected, vm.SelectedPost);
Assert.Same(selected, page.PostsListBox.SelectedItem); Assert.Same(selected, page.PostsListBox.SelectedItem);
Assert.Equal("Titre modifié", vm.DraftTitle); Assert.Equal("Titre modifié", vm.DraftTitle);
Assert.Equal("Corps", vm.DraftArticle); Assert.Equal("Corps", vm.DraftArticle);
Assert.DoesNotContain("modified", page.SaveButton.Classes); Assert.DoesNotContain("modified", page.SaveButton.Classes);
Assert.Equal(Avalonia.Media.FontWeight.Normal, page.SaveButton.FontWeight);
} }
finally finally
{ {

View file

@ -17,13 +17,6 @@
<Design.DataContext> <Design.DataContext>
<vm:BlogsViewModel /> <vm:BlogsViewModel />
</Design.DataContext> </Design.DataContext>
<ContentPage.Styles>
<Style Selector="CommandBarButton.modified">
<Setter Property="Background" Value="#FFF0C2" />
<Setter Property="Foreground" Value="#663C00" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ContentPage.Styles>
<Grid x:Name="MainGrid" <Grid x:Name="MainGrid"
RowDefinitions="Auto,Auto,*,4,2*,Auto" RowDefinitions="Auto,Auto,*,4,2*,Auto"
Margin="5,5,10,5" Margin="5,5,10,5"

View file

@ -1,11 +1,13 @@
using System.IO; using System.IO;
using System.ComponentModel;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Markdown.Avalonia; using Markdown.Avalonia;
@ -16,6 +18,7 @@ public partial class BlogsPage : ContentPage
private static readonly RelayCommand<string?> DisabledLinkCommand = private static readonly RelayCommand<string?> DisabledLinkCommand =
new(static _ => { }, static _ => false); new(static _ => { }, static _ => false);
private bool? _isWideLayout; private bool? _isWideLayout;
private ViewModels.BlogsViewModel? _observedViewModel;
public BlogsPage() public BlogsPage()
{ {
@ -26,6 +29,13 @@ public partial class BlogsPage : ContentPage
UpdateResponsiveLayout(); UpdateResponsiveLayout();
}); });
DataContextChanged += (_, _) => UpdateHyperlinkCommand(); DataContextChanged += (_, _) => UpdateHyperlinkCommand();
AttachedToVisualTree += (_, _) => UpdateHyperlinkCommand();
DetachedFromVisualTree += (_, _) =>
{
if (_observedViewModel is not null)
_observedViewModel.PropertyChanged -= ViewModel_PropertyChanged;
_observedViewModel = null;
};
UpdateHyperlinkCommand(); UpdateHyperlinkCommand();
} }
@ -68,13 +78,47 @@ public partial class BlogsPage : ContentPage
private void UpdateHyperlinkCommand() private void UpdateHyperlinkCommand()
{ {
if (_observedViewModel is not null)
_observedViewModel.PropertyChanged -= ViewModel_PropertyChanged;
_observedViewModel = DataContext as ViewModels.BlogsViewModel;
if (_observedViewModel is not null)
_observedViewModel.PropertyChanged += ViewModel_PropertyChanged;
if (ArticleReader.Engine is IMarkdownEngine2 engine) if (ArticleReader.Engine is IMarkdownEngine2 engine)
{ {
if (DataContext is ViewModels.BlogsViewModel vm) if (_observedViewModel is not null)
engine.HyperlinkCommand = vm.OpenResourceCommand; engine.HyperlinkCommand = _observedViewModel.OpenResourceCommand;
else else
engine.HyperlinkCommand = DisabledLinkCommand; engine.HyperlinkCommand = DisabledLinkCommand;
} }
UpdateSaveButtonHighlight();
}
private void ViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ViewModels.BlogsViewModel.IsDraftModified))
UpdateSaveButtonHighlight();
}
private void UpdateSaveButtonHighlight()
{
if (SaveButton is null)
return;
if (_observedViewModel?.IsDraftModified == true)
{
SaveButton.FontWeight = FontWeight.Bold;
SaveButton.Background = new SolidColorBrush(Color.Parse("#FFF0C2"));
SaveButton.Foreground = new SolidColorBrush(Color.Parse("#663C00"));
}
else
{
SaveButton.FontWeight = FontWeight.Normal;
SaveButton.ClearValue(TemplatedControl.BackgroundProperty);
SaveButton.ClearValue(TemplatedControl.ForegroundProperty);
}
} }
protected override async void OnApplyTemplate(TemplateAppliedEventArgs e) protected override async void OnApplyTemplate(TemplateAppliedEventArgs e)