refacto blogPost
Some checks failed
Dotnet build and test / log-the-inputs (push) Has been cancelled
Dotnet build and test / build (push) Has been cancelled

This commit is contained in:
Paul Schneider 2026-08-03 01:32:59 +01:00
commit b25e0e842e
No known key found for this signature in database
GPG key ID: 1E66C65EE2B46F1B
11 changed files with 85 additions and 52 deletions

View file

@ -1,6 +1,7 @@
using PostIt.Models;
using PostIt.Services;
using PostIt.ViewModels;
using Yavsc.Models;
namespace PostIt.Tests;

View file

@ -24,7 +24,7 @@ public partial class App : Application
/// binding sink with a cross-thread exception inside
/// <c>DataValidationErrors.SetErrors</c>.
/// </summary>
public IServiceProvider? Services { get; private set; }
public IServiceProvider? ServiceProvider { get; private set; }
private MainWindow window;
public App()
{
@ -91,19 +91,17 @@ public partial class App : Application
services.AddSingleton(sessionStatus);
services.AddTransient<SessionStatusBanner>();
var provider = services.BuildServiceProvider();
ServiceProvider = services.BuildServiceProvider();
// Bind the canonical Settings to the static accessor so any
// code path that can't easily take a constructor parameter
// (designer surfaces, Avalonia data templates) still gets
// the same instance the rest of the app is using. Idempotent:
// re-binding from a second App boot (tests) is a no-op.
Settings.BindToServiceProvider(provider);
Services = provider;
Settings.BindToServiceProvider(ServiceProvider);
DataTemplates.Clear();
DataTemplates.Add(new ViewLocator(provider));
DataTemplates.Add(new ViewLocator(ServiceProvider));
// Wire the Settings singleton onto the SettingsPage singleton
// once, at composition time. The page is registered as a
@ -113,7 +111,7 @@ public partial class App : Application
// DataContext, and the TwoWay bindings inside the page keep
// mutating the same in-memory Settings instance that the rest
// of the app reads (OidcClientOptions construction, etc.).
provider.GetRequiredService<SettingsPage>().DataContext = settings;
ServiceProvider.GetRequiredService<SettingsPage>().DataContext = settings;
// Settings.DarkMode was previously a dead field: it round-
// tripped through the settings file and the SettingsPage
@ -134,8 +132,8 @@ public partial class App : Application
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
var homePage = provider.GetRequiredService<HomePage>();
homePage.DataContext = provider.GetRequiredService<HomePageViewModel>();
var homePage = ServiceProvider.GetRequiredService<HomePage>();
homePage.DataContext = ServiceProvider.GetRequiredService<HomePageViewModel>();
window = new MainWindow();
window.SessionBanner.DataContext = sessionStatus;
@ -155,8 +153,8 @@ public partial class App : Application
{
var w = (MainWindow)((IClassicDesktopStyleApplicationLifetime)ApplicationLifetime!).MainWindow!;
var nav = w.NavRoot;
var hp = provider.GetRequiredService<HomePage>();
hp.DataContext = provider.GetRequiredService<HomePageViewModel>();
var hp = ServiceProvider.GetRequiredService<HomePage>();
hp.DataContext = ServiceProvider.GetRequiredService<HomePageViewModel>();
_ = nav.PopToRootAsync();
};
@ -187,7 +185,7 @@ public partial class App : Application
sessionStatus.OpenSettingsRequested += () =>
{
var w = (MainWindow)((IClassicDesktopStyleApplicationLifetime)ApplicationLifetime!).MainWindow!;
var settingsPage = provider.GetRequiredService<SettingsPage>();
var settingsPage = ServiceProvider.GetRequiredService<SettingsPage>();
var stack = w.NavRoot.NavigationStack;
if (stack.Count > 0 && ReferenceEquals(stack[stack.Count - 1], settingsPage))
{
@ -196,13 +194,13 @@ public partial class App : Application
_ = w.NavRoot.PushAsync(settingsPage);
};
window.Opened += async (_, _) => await BootAsync(provider, api);
window.Opened += async (_, _) => await BootAsync(ServiceProvider, api);
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView)
{
singleView.MainView = new MainWindow
{
DataContext = provider.GetRequiredService<HomePageViewModel>()
DataContext = ServiceProvider.GetRequiredService<HomePageViewModel>()
};
}
}
@ -243,8 +241,8 @@ public partial class App : Application
public static async Task PushMainPageAsync()
{
var app = (App)Current;
var mainVm = app.Services.GetRequiredService<MainPageViewModel>();
var mainPage = app.Services.GetRequiredService<MainPage>();
var mainVm = app.ServiceProvider.GetRequiredService<MainPageViewModel>();
var mainPage = app.ServiceProvider.GetRequiredService<MainPage>();
mainPage.DataContext = mainVm;
await app.window.FindControl<NavigationPage>("NavRoot").PushAsync(mainPage).ConfigureAwait(true);
}

View file

@ -1,16 +1,37 @@
using System;
using Yavsc.Abstract.Identity;
using Yavsc.Abstract.Identity.Security;
using Yavsc.Blogspot;
namespace PostIt.Models;
public class BlogPost
public class BlogPost : IBlogPost
{
public string AuthorId { get; set; }
public IApplicationUser Author { get; set; }
public string Article { get; set ; }
public string Photo { get; set ; }
public long Id { get; set ; }
public string Title { get; set; } = string.Empty;
public string? Article { get; set; }
public string? Photo { get; set; }
public string? AuthorId { get; set; }
public DateTime DateCreated { get; set ; }
public string? UserCreated { get; set; }
public string UserCreated { get; set ; }
public DateTime DateModified { get; set ; }
public string? UserModified { get; set; }
public string UserModified { get; set ; }
public string Title { get; set ; }
public bool AuthorizeCircle(long circleId)
{
throw new NotImplementedException();
}
public ICircleAuthorization[] GetACL()
{
throw new NotImplementedException();
}
public string[] GetTags()
{
throw new NotImplementedException();
}
}

View file

@ -1,4 +1,5 @@
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.DependencyInjection;
using PostIt;
using PostIt.Services;
namespace PostIt.ViewModels;
@ -7,6 +8,7 @@ public class HomePageViewModel : ViewModelBase
{
public YavscApiClient Api { get; }
public Settings Settings { get; }
public SessionStatusViewModel SessionStatus { get; }
private string _welcomeText = "Welcome to PostIt!";
public string WelcomeText
@ -18,10 +20,12 @@ public class HomePageViewModel : ViewModelBase
public override bool CanNavigateNext { get => true; protected set => throw new System.NotImplementedException(); }
public override bool CanNavigatePrevious { get => false; protected set => throw new System.NotImplementedException(); }
public HomePageViewModel(YavscApiClient api, Settings settings)
public HomePageViewModel(YavscApiClient api, Settings settings, SessionStatusViewModel sessionStatus)
{
Api = api;
Settings = settings;
SessionStatus = sessionStatus;
}
public RelayCommand OpenBlogs { get; set; } = new RelayCommand(() => App.PushMainPageAsync());
/// <summary>
@ -33,5 +37,8 @@ public class HomePageViewModel : ViewModelBase
/// (thread-safe dispatcher marshalling on PropertyChanged) — a
/// designer-only duplicate instance is therefore harmless.
/// </summary>
public HomePageViewModel() : this(null!, new Settings()) { }
public HomePageViewModel() : this(null!, new Settings(), new SessionStatusViewModel())
{
}
}

View file

@ -28,7 +28,7 @@ public partial class MainPage : ContentPage
// Resolve via the App's DI container so the page gets
// the canonical services (Api client, settings, ...).
var app = Application.Current as App;
var services = app?.Services;
var services = app?.ServiceProvider;
if (services is null) return;
var page = services.GetRequiredService<SignaturePage>();

View file

@ -1,19 +0,0 @@

using Yavsc.Abstract.Identity;
namespace Yavsc
{
public interface IBlogPostPayLoad
{
string Article { get; set; }
string Photo { get; set; }
}
public interface IBlogPost : IBlogPostPayLoad, ITrackedEntity, IIdentified<long>, ITitle
{
string AuthorId { get; set; }
IApplicationUser Author { get; }
}
}

View file

@ -0,0 +1,15 @@
using Yavsc.Abstract.Identity;
using Yavsc.Abstract.Identity.Security;
using Yavsc.Interfaces;
namespace Yavsc.Blogspot
{
public interface IBlogPost : IBlogPostPayLoad, ICircleAuthorized, ITaggable<long>, ITrackedEntity, IIdentified<long>, ITitle
{
string AuthorId { get; set; }
IApplicationUser Author { get; }
}
}

View file

@ -0,0 +1,9 @@
namespace Yavsc.Blogspot
{
public interface IBlogPostPayLoad
{
string Article { get; set; }
string Photo { get; set; }
}
}

View file

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Yavsc.Blogspot;
using Yavsc.Models.Blog;
using Yavsc.Server.Exceptions;
using Yavsc.Server.Helpers;

View file

@ -3,15 +3,14 @@ using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
using Yavsc.Abstract.Identity;
using Yavsc.Abstract.Identity.Security;
using Yavsc.Interfaces;
using Yavsc.Models.Access;
using Yavsc.Models.Relationship;
using Yavsc.Blogspot;
namespace Yavsc.Models.Blog
{
public class BlogPost :
IBlogPost, ICircleAuthorized, ITaggable<long>
public class BlogPost : IBlogPost
{
[Key(), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "Identifiant du post")]

View file

@ -10,6 +10,7 @@ using Yavsc.Server.Helpers;
using Yavsc.Services;
using Yavsc.ViewModels.Auth;
using Microsoft.AspNetCore.Http;
using Yavsc.Blogspot;
public class BlogSpotService
{