Wire the client to PrivaPub: one sign-in, real feeds, a globe, nerd stats
One sign-in for both of PrivaPub's APIs: the root logs in on /clientapi, picks a persona, and each persona gets its own Mastodon token in exchange for the JWT (PersonaExchange). HttpService picks credentials and JSON by route (JWT and camelCase for /clientapi, the persona token and snake_case for /api, nothing for /oauth), retries a refused persona token once, and records every request for the nerd stats. The feed page is three columns: navigation with a persona switcher, the feed with a tab per kind (home, local, federated, nearby, communities and circles, direct, notifications, favourites, bookmarks, hashtags), and a 3D globe that looks at the spherical mean of the posts in view and draws a pulse and an arc to a hovered one. Posts sit at their own place, their event's venue, the reader (located posts) or their author's server as PrivaPub publishes it. Cards favourite, boost, bookmark, reply, mute, block and delete; the composer posts with a content warning, visibility, media and alt text, or as a located post. Older pages load as the end nears; newer ones are polled while visible. Nerd stats in tooltips: provenance, author and server, place, media, counts, paging, the globe's camera and frame rate. The mock (Faker, MessagesService, the Message models and store) and the OIDC template leftovers are gone. Strings in English and Italian. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
f41ebf2160
commit
827ecb770e
56 files changed
+5367
-832
No files matched your search
@@ -0,0 +1,109 @@
|
||||
namespace decePubClient.Models.Mastodon;
|
||||
|
||||
/// <summary>
|
||||
/// A post as PrivaPub's Mastodon API sends it (snake_case JSON, MastodonJsonContext). PrivaPub-only details are in
|
||||
/// Privapub; ids are opaque strings.
|
||||
/// </summary>
|
||||
public class Status
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Uri { get; set; }
|
||||
public string Url { get; set; }
|
||||
public Account Account { get; set; }
|
||||
public string InReplyToId { get; set; }
|
||||
public string InReplyToAccountId { get; set; }
|
||||
public Status Reblog { get; set; }
|
||||
public string Content { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? EditedAt { get; set; }
|
||||
public List<CustomEmoji> Emojis { get; set; } = [];
|
||||
public int RepliesCount { get; set; }
|
||||
public int ReblogsCount { get; set; }
|
||||
public int FavouritesCount { get; set; }
|
||||
public bool Reblogged { get; set; }
|
||||
public bool Favourited { get; set; }
|
||||
public bool Muted { get; set; }
|
||||
public bool Bookmarked { get; set; }
|
||||
public bool Pinned { get; set; }
|
||||
public bool Sensitive { get; set; }
|
||||
public string SpoilerText { get; set; }
|
||||
/// <summary>public, unlisted, private (followers and circles) or direct.</summary>
|
||||
public string Visibility { get; set; }
|
||||
public List<MediaAttachment> MediaAttachments { get; set; } = [];
|
||||
public List<StatusMention> Mentions { get; set; } = [];
|
||||
public List<StatusTag> Tags { get; set; } = [];
|
||||
public PreviewCard Card { get; set; }
|
||||
public Poll Poll { get; set; }
|
||||
public StatusApplication Application { get; set; }
|
||||
public string Language { get; set; }
|
||||
/// <summary>The plain text source, only on the author's own deleted or edited post.</summary>
|
||||
public string Text { get; set; }
|
||||
public PrivaPubStatus Privapub { get; set; }
|
||||
public Quote Quote { get; set; }
|
||||
public int QuotesCount { get; set; }
|
||||
}
|
||||
|
||||
public class StatusMention
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string Acct { get; set; }
|
||||
}
|
||||
|
||||
public class StatusTag
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
|
||||
public class StatusApplication
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Website { get; set; }
|
||||
}
|
||||
|
||||
public class Quote
|
||||
{
|
||||
public string State { get; set; }
|
||||
public Status QuotedStatus { get; set; }
|
||||
public string QuotedStatusId { get; set; }
|
||||
}
|
||||
|
||||
public class StatusContext
|
||||
{
|
||||
public List<Status> Ancestors { get; set; } = [];
|
||||
public List<Status> Descendants { get; set; } = [];
|
||||
}
|
||||
|
||||
public class Poll
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTime? ExpiresAt { get; set; }
|
||||
public bool Expired { get; set; }
|
||||
public bool Multiple { get; set; }
|
||||
public int VotesCount { get; set; }
|
||||
public int? VotersCount { get; set; }
|
||||
public bool? Voted { get; set; }
|
||||
public List<PollOption> Options { get; set; } = [];
|
||||
}
|
||||
|
||||
public class PollOption
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public int? VotesCount { get; set; }
|
||||
}
|
||||
|
||||
public class PreviewCard
|
||||
{
|
||||
public string Url { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string ProviderName { get; set; }
|
||||
public string Image { get; set; }
|
||||
public string ImageDescription { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public string Blurhash { get; set; }
|
||||
}
|
||||
Reference in new issue
Block a user