diff --git a/CHANGELOG.md b/CHANGELOG.md
index 86afc7514..b2219e41b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -47,6 +47,9 @@
* [PostIt] Le changement de disposition de la page des blogs est différé
sur le thread UI, évitant l'exception « Visual was invalidated during
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
diff --git a/src/PostIt/PostIt.Tests/PostItViewModelTests.cs b/src/PostIt/PostIt.Tests/PostItViewModelTests.cs
index 9a1247657..5f23d2a61 100644
--- a/src/PostIt/PostIt.Tests/PostItViewModelTests.cs
+++ b/src/PostIt/PostIt.Tests/PostItViewModelTests.cs
@@ -58,6 +58,7 @@ public class PostItViewModelTests
Dispatcher.UIThread.RunJobs();
Assert.Same(selected, page.PostsListBox.SelectedItem);
Assert.Same(selected, vm.SelectedPost);
+ vm.IsEditing = true;
Assert.DoesNotContain("modified", page.SaveButton.Classes);
vm.DraftTitle = "Titre modifié";
Dispatcher.UIThread.RunJobs();
@@ -67,11 +68,13 @@ public class PostItViewModelTests
await vm.SaveAsync();
Dispatcher.UIThread.RunJobs();
Assert.Same(page, navigation.NavigationStack.Last());
+ Assert.True(vm.IsEditing);
Assert.Same(selected, vm.SelectedPost);
Assert.Same(selected, page.PostsListBox.SelectedItem);
Assert.Equal("Titre modifié", vm.DraftTitle);
Assert.Equal("Corps", vm.DraftArticle);
Assert.DoesNotContain("modified", page.SaveButton.Classes);
+ Assert.Equal(Avalonia.Media.FontWeight.Normal, page.SaveButton.FontWeight);
}
finally
{
diff --git a/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml b/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml
index 1d387ad3a..527eaa1b0 100644
--- a/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml
+++ b/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml
@@ -17,13 +17,6 @@
-
-
-
DisabledLinkCommand =
new(static _ => { }, static _ => false);
private bool? _isWideLayout;
+ private ViewModels.BlogsViewModel? _observedViewModel;
public BlogsPage()
{
@@ -26,6 +29,13 @@ public partial class BlogsPage : ContentPage
UpdateResponsiveLayout();
});
DataContextChanged += (_, _) => UpdateHyperlinkCommand();
+ AttachedToVisualTree += (_, _) => UpdateHyperlinkCommand();
+ DetachedFromVisualTree += (_, _) =>
+ {
+ if (_observedViewModel is not null)
+ _observedViewModel.PropertyChanged -= ViewModel_PropertyChanged;
+ _observedViewModel = null;
+ };
UpdateHyperlinkCommand();
}
@@ -68,13 +78,47 @@ public partial class BlogsPage : ContentPage
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 (DataContext is ViewModels.BlogsViewModel vm)
- engine.HyperlinkCommand = vm.OpenResourceCommand;
+ if (_observedViewModel is not null)
+ engine.HyperlinkCommand = _observedViewModel.OpenResourceCommand;
else
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)