[PostIT] #55 nearly ok, it-s better ...
Some checks failed
Dotnet build and test / build (pull_request) Failing after 33m44s

This commit is contained in:
Paul Schneider 2026-09-26 18:02:53 +01:00
commit c1f447636b
Signed by: notazof
GPG key ID: AD4B9B545FBD7D12
11 changed files with 218 additions and 6 deletions

View file

@ -46,5 +46,9 @@
}
},
"dotnet.defaultSolution": "yavsc.sln",
"axaml.selectedSolution": "/home/paul/Workspace/yavsc/yavsc.sln"
"axaml.selectedSolution": "/home/paul/Workspace/yavsc/yavsc.sln",
"chat.tools.terminal.autoApprove": {
"dotnet build": true,
"dotnet test": true
}
}

View file

@ -2,6 +2,7 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Views;
using AndroidX.Core.Provider;
using AndroidX.Emoji2.Text;
using Avalonia.Android;
@ -15,7 +16,9 @@ namespace PostIt.Android;
Theme = "@style/MyTheme.NoActionBar",
Icon = "@drawable/icon",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
WindowSoftInputMode = SoftInput.AdjustResize,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)
]
public class MainActivity : AvaloniaMainActivity
{
/// <summary>

View file

@ -53,6 +53,7 @@ public static class ServiceCollectionHelpers
// the navigation stack, each bound to a fresh
// SettingsViewModel and missing any in-flight edits.
services.AddSingleton<SettingsPage>();
services.AddSingleton<AboutPage>();
services.AddSingleton<HomePage>();
services.AddSingleton<SignaturePage>();
services.AddSingleton<CirclesPage>();
@ -82,6 +83,7 @@ public static class ServiceCollectionHelpers
services.AddSingleton(userFilesClient);
services.AddSingleton<IReverseGeocodingService>(reverseGeocoding);
services.AddSingleton<IUserDirectory>(userDirectory);
services.AddSingleton<AboutPageViewModel>();
services.AddSingleton<HomePageViewModel>();
services.AddSingleton<SignaturePageViewModel>();
services.AddSingleton<CirclesPageViewModel>();

View file

@ -41,6 +41,7 @@ public class ViewLocator : IDataTemplate
{
BlogsViewModel => services.GetRequiredService<BlogsPage>(),
Settings => services.GetRequiredService<SettingsPage>(),
AboutPageViewModel => services.GetRequiredService<AboutPage>(),
HomePageViewModel => services.GetRequiredService<HomePage>(),
ActivitiesPageViewModel => services.GetRequiredService<ActivitiesPage>(),
CommandFormsPageViewModel => services.GetRequiredService<CommandFormsPage>(),

View file

@ -0,0 +1,77 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace PostIt.ViewModels;
/// <summary>
/// ViewModel de la page « À propos de PostIt ». Page statique :
/// version de l'application, description, licence et liens vers le
/// dépôt Forgejo et son suivi de tickets.
/// </summary>
public partial class AboutPageViewModel : ViewModelBase
{
public const string RepositoryUrl = "https://forgejo.pschneider.fr/notazof/yavsc";
public const string IssuesUrl = RepositoryUrl + "/issues";
public AboutPageViewModel()
{
Version = ReadVersion();
}
public string Version { get; }
public string Description { get; } =
"PostIt est le client de la plateforme Yavsc : blog, devis, " +
"demandes de prestations et fichiers personnels.";
public string License { get; } =
"Licence WTFPL — Do What The Fuck You Want To Public License, version 2";
public override bool CanNavigateNext
{
get => false;
protected set => throw new NotImplementedException();
}
public override bool CanNavigatePrevious
{
get => true;
protected set => throw new NotImplementedException();
}
[RelayCommand]
private Task OpenRepository() => OpenUrlAsync(RepositoryUrl);
[RelayCommand]
private Task OpenIssues() => OpenUrlAsync(IssuesUrl);
private static async Task OpenUrlAsync(string url)
{
var app = (App)App.Current!;
var topLevel = TopLevel.GetTopLevel(app.View);
if (topLevel is not null)
{
await topLevel.Launcher.LaunchUriAsync(new Uri(url)).ConfigureAwait(true);
}
}
private static string ReadVersion()
{
var assembly = typeof(AboutPageViewModel).Assembly;
var info = assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
?.InformationalVersion;
if (!string.IsNullOrEmpty(info))
{
// "1.1.0-estimate.1+364.Branch.x.Sha.y" → "1.1.0-estimate.1"
var plus = info.IndexOf('+');
return plus > 0 ? info[..plus] : info;
}
return assembly.GetName().Version?.ToString() ?? "inconnue";
}
}

View file

@ -143,4 +143,11 @@ public partial class SessionStatusViewModel : ViewModelBase
await app.PushPageAsync(app.ServiceProvider!.GetRequiredService<Settings>()).ConfigureAwait(true);
}
[RelayCommand]
internal async Task OpenAbout()
{
var app = (App)App.Current!;
await app.PushPageAsync(app.ServiceProvider!.GetRequiredService<AboutPageViewModel>()).ConfigureAwait(true);
}
}

View file

@ -175,6 +175,7 @@
PlaceholderText="Title"
Text="{Binding DraftTitle, Mode=TwoWay}" />
<AvaloniaEdit:TextEditor
Grid.Row="2"
VerticalAlignment="Stretch"
@ -186,10 +187,12 @@
BorderBrush="LightGray"
CornerRadius="5"
Padding="5,5,5,15"
HorizontalScrollBarVisibility="Disabled"
TextInputOptions.Multiline="True"
TextInputOptions.ReturnKeyType="Default"
ClipToBounds="True"
/>
<Border
Grid.Row="3"
Padding="8"

View file

@ -1,19 +1,82 @@
using System;
using System.IO;
using System.Linq;
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)
{
var app = App.Current as App;
app.View.Margin = new Avalonia.Thickness(0, 0, 0, keyboardHeight);
// OPTION B : Si vous devez explicitement appliquer un masque de découpage (Clip) basé sur la hauteur :
/*
if (keyboardHeight > 0)
{
double visibleHeight = this.Bounds.Height - keyboardHeight;
if (visibleHeight > 0)
{
MainContainer.Clip = new Avalonia.Media.RectangleGeometry(
new Avalonia.Rect(0, 0, this.Bounds.Width, visibleHeight));
}
}
else
{
MainContainer.Clip = null; // Réinitialise le clip quand le clavier se ferme
}
*/
}
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);

View file

@ -0,0 +1,38 @@
<ContentPage xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:PostIt.ViewModels"
x:Class="PostIt.Views.AboutPage"
x:DataType="vm:AboutPageViewModel"
Header="À propos">
<Design.DataContext>
<vm:AboutPageViewModel />
</Design.DataContext>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="12"
Margin="16">
<TextBlock Text="PostIt"
FontSize="28"
FontWeight="Bold"
HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Version, StringFormat='Version {0}'}"
HorizontalAlignment="Center"
Opacity="0.8"/>
<TextBlock Text="{Binding Description}"
TextWrapping="Wrap"
TextAlignment="Center"
MaxWidth="420"/>
<TextBlock Text="{Binding License}"
TextWrapping="Wrap"
TextAlignment="Center"
MaxWidth="420"
Opacity="0.8"
FontStyle="Italic"/>
<Button Content="Dépôt du projet"
Command="{Binding OpenRepositoryCommand}"
HorizontalAlignment="Center"/>
<Button Content="Signaler un problème"
Command="{Binding OpenIssuesCommand}"
HorizontalAlignment="Center"/>
</StackPanel>
</ContentPage>

View file

@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace PostIt.Views;
public partial class AboutPage : ContentPage
{
public AboutPage()
{
InitializeComponent();
}
}

View file

@ -28,6 +28,9 @@
<Button Content="Paramètres"
Command="{Binding OpenSettingsCommand}"
DockPanel.Dock="Right"/>
<Button Content="À propos"
Command="{Binding OpenAboutCommand}"
DockPanel.Dock="Right"/>
</DockPanel>
</Border>
</UserControl>