diff --git a/src/PostIt/PostIt.Tests/MD/le-chant-1.md b/src/PostIt/PostIt.Tests/MD/le-chant-1.md new file mode 100644 index 000000000..f4a7506fe --- /dev/null +++ b/src/PostIt/PostIt.Tests/MD/le-chant-1.md @@ -0,0 +1,34 @@ + + Loin vers l'infini s'étendent + Les grands prés marécageux . + Pas un seul oiseau ne chante + Sur les arbres secs et creux ! + +*(Refrain)* + + Ô terre de détresse, + Où nous devons sans cesse, + Piocher, piocher . + + Dans ce camp morne et sauvage + Entouré de murs de fer, + Il nous semble vivre en cage + Au milieu d'un grand désert . + + Bruit des pas et bruit des armes, + Sentinelles jours et nuits, + Et du sang, et des cris, des larmes, + La mort pour celui qui fuit . + + Mais un jour dans notre vie, + Le printemps refleurira . + Liberté, liberté chérie + Je dirai : « Tu es à moi ! » + +*(Dernier refrain)* + + Ô terre d'allégresse, + Où nous pourrons sans cesse, + Aimer, aimer ! + +[audio : Mario Hacquard - Youtube](https://www.youtube.com/watch?v=ogw_mgk1pFs) diff --git a/src/PostIt/PostIt/Controls/MarkdownEditorControl.axaml b/src/PostIt/PostIt/Controls/MarkdownEditorControl.axaml new file mode 100644 index 000000000..9e8df6dd1 --- /dev/null +++ b/src/PostIt/PostIt/Controls/MarkdownEditorControl.axaml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + diff --git a/src/PostIt/PostIt/Controls/MarkdownEditorControl.axaml.cs b/src/PostIt/PostIt/Controls/MarkdownEditorControl.axaml.cs new file mode 100644 index 000000000..0431b726e --- /dev/null +++ b/src/PostIt/PostIt/Controls/MarkdownEditorControl.axaml.cs @@ -0,0 +1,88 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using AvaloniaEdit.Document; + +namespace PostIt.Controls; + +public partial class MarkdownEditorControl : UserControl +{ + public static readonly StyledProperty MarkdownTextProperty = + AvaloniaProperty.Register(nameof(MarkdownText)); + + public static readonly StyledProperty DocumentProperty = + AvaloniaProperty.Register(nameof(Document)); + + public static readonly StyledProperty IsPreviewVisibleProperty = + AvaloniaProperty.Register(nameof(IsPreviewVisible), false); + + public string? MarkdownText + { + get => GetValue(MarkdownTextProperty); + set => SetValue(MarkdownTextProperty, value); + } + + public TextDocument? Document + { + get => GetValue(DocumentProperty); + set => SetValue(DocumentProperty, value); + } + + public bool IsPreviewVisible + { + get => GetValue(IsPreviewVisibleProperty); + set => SetValue(IsPreviewVisibleProperty, value); + } + + public MarkdownEditorControl() + { + InitializeComponent(); + PropertyChanged += OnPropertyChanged; + SizeChanged += OnSizeChanged; + UpdateEditorLimits(); + } + + private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) + { + if (e.Property == MarkdownTextProperty) + { + var text = e.NewValue as string ?? string.Empty; + if (Document is null || !string.Equals(Document.Text, text, StringComparison.Ordinal)) + { + Document = new TextDocument(text); + } + } + else if (e.Property == DocumentProperty) + { + var newDocument = e.NewValue as TextDocument; + var text = newDocument?.Text ?? string.Empty; + if (!string.Equals(MarkdownText, text, StringComparison.Ordinal)) + { + MarkdownText = text; + } + } + } + + private void OnSizeChanged(object? sender, SizeChangedEventArgs e) + { + UpdateEditorLimits(); + } + + private void UpdateEditorLimits() + { + var visibleHeight = Bounds.Height > 0 ? Bounds.Height - 24 : 260; + visibleHeight = Math.Max(visibleHeight, 80); + + if (SourceEditor is not null) + { + SourceEditor.MaxHeight = visibleHeight; + SourceEditor.Height = double.NaN; + } + + if (PreviewViewer is not null) + { + PreviewViewer.MaxHeight = visibleHeight; + PreviewViewer.Height = double.NaN; + } + } +} diff --git a/src/PostIt/PostIt/ViewModels/Blogs/BlogsViewModel.cs b/src/PostIt/PostIt/ViewModels/Blogs/BlogsViewModel.cs index 6fe6eccc9..9de63c24c 100644 --- a/src/PostIt/PostIt/ViewModels/Blogs/BlogsViewModel.cs +++ b/src/PostIt/PostIt/ViewModels/Blogs/BlogsViewModel.cs @@ -39,18 +39,56 @@ public partial class BlogsViewModel : ViewModelBase, IActionStatusViewModel /// Editor buffer for the post body. Same pattern as /// . - public string DraftArticle + public string? DraftArticle { - get => DraftArticleDocument.Text; - set { + get => DraftArticleDocument?.Text ?? null; + set + { + var currentText = DraftArticleDocument?.Text; + if (string.Equals(currentText, value, StringComparison.Ordinal)) + { + OnPropertyChanged(nameof(DraftArticle)); + return; + } + OnPropertyChanging(nameof(DraftArticle)); - DraftArticleDocument = new TextDocument(value); - this.OnPropertyChanged(nameof(DraftArticle)); + DraftArticleDocument = value is not null ? new TextDocument(value) : null; + OnPropertyChanged(nameof(DraftArticle)); } } - [ObservableProperty] - public partial TextDocument DraftArticleDocument {get; set;} + private TextDocument? _draftArticleDocument; + + public TextDocument? DraftArticleDocument + { + get => _draftArticleDocument; + set + { + if (ReferenceEquals(_draftArticleDocument, value)) + { + return; + } + + if (_draftArticleDocument is not null) + { + _draftArticleDocument.TextChanged -= DraftArticleDocument_TextChanged; + } + + _draftArticleDocument = value; + + if (_draftArticleDocument is not null) + { + _draftArticleDocument.TextChanged += DraftArticleDocument_TextChanged; + } + + OnPropertyChanged(nameof(DraftArticleDocument)); + } + } + + private void DraftArticleDocument_TextChanged(object? sender, EventArgs e) + { + OnPropertyChanged(nameof(DraftArticle)); + } /// Editor buffer for the post's publication state. /// Reflects the server-side IsPublished flag (the diff --git a/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml b/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml index 90397f09d..5c926bdee 100644 --- a/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml +++ b/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml @@ -17,10 +17,14 @@ - - + + - + @@ -103,7 +107,7 @@ - + @@ -137,90 +141,61 @@ - + + + + + + + + + + + + + + - - + IsPreviewVisible="{Binding IsMarkdownViewerVisible, Mode=TwoWay}" + MarkdownText="{Binding DraftArticle, Mode=TwoWay}" + Document="{Binding DraftArticleDocument, Mode=TwoWay}" /> - - - - - - - - - - - + VerticalAlignment="Stretch"> + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - + diff --git a/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml.cs b/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml.cs index 629727870..b40021276 100644 --- a/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml.cs +++ b/src/PostIt/PostIt/Views/Blogs/BlogsPage.axaml.cs @@ -4,69 +4,16 @@ using Avalonia.Controls; using Avalonia.Platform.Storage; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; -using Avalonia.Controls.Platform; namespace PostIt.Views.Blogs; public partial class BlogsPage : ContentPage { - private IInputPane? _inputPane; - public BlogsPage() { InitializeComponent(); } - protected override void OnLoaded(RoutedEventArgs e) - { - base.OnLoaded(e); - - // Récupère l'accès au TopLevel de la fenêtre/application - var topLevel = TopLevel.GetTopLevel(this); - if (topLevel != null) - { - _inputPane = topLevel!.InputPane; - if (_inputPane != null) - { - // S'abonne aux changements d'état du clavier virtuel - _inputPane.StateChanged += OnInputPaneStateChanged; - - // Applique la configuration initiale si le clavier est déjà présent - UpdateLayoutForKeyboard(_inputPane.OccludedRect.Height); - } - } - } - - protected override void OnUnloaded(RoutedEventArgs e) - { - if (_inputPane != null) - { - _inputPane.StateChanged -= OnInputPaneStateChanged; - } - base.OnUnloaded(e); - } - - - private void UpdateLayoutForKeyboard(double keyboardHeight) - { - double visibleHeight = this.Bounds.Height - keyboardHeight; - if (keyboardHeight > 0) - { - DraftArticleTextEditor.MaxHeight = visibleHeight; - } - else - { - DraftArticleTextEditor.MaxHeight = double.PositiveInfinity; - } - } - - private void OnInputPaneStateChanged(object? sender, InputPaneStateEventArgs e) - { - // e.EndRect contient le rectangle final du clavier virtuel - // e.EndRect.Height vous donne sa hauteur exacte en pixels indépendants du périphérique (pixels logiques) - UpdateLayoutForKeyboard(e.EndRect.Height); - } - protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); diff --git a/src/Yavsc.Org/wwwroot/css/site.css b/src/Yavsc.Org/wwwroot/css/site.css index bafc2d571..2e4720ff3 100644 --- a/src/Yavsc.Org/wwwroot/css/site.css +++ b/src/Yavsc.Org/wwwroot/css/site.css @@ -1,4 +1 @@ -.user-icon { - max-width: 1.5em; - max-height: 1.5em; -} +.user-icon{max-width:1.5em;max-height:1.5em}.card{padding:.5em} diff --git a/src/Yavsc.Org/wwwroot/css/site.scss b/src/Yavsc.Org/wwwroot/css/site.scss index 1bf7a4d34..546aac220 100644 --- a/src/Yavsc.Org/wwwroot/css/site.scss +++ b/src/Yavsc.Org/wwwroot/css/site.scss @@ -1,4 +1,7 @@ -user-icon { +.user-icon { max-width: 1.5em; max-height: 1.5em; } +.card { + padding: .5em; +}