v0.2: All videos folder, shared watched state, release-order sorting, official icon, OAuth plumbing, docs
Some checks failed
release / build-release (push) Has been cancelled
Some checks failed
release / build-release (push) Has been cancelled
- per-creator "All videos" folder (release order across sub-channels); sub-channel copies use cpost: ids and UserDataMirror keeps played/resume state in sync - SortNameUpdater forces release-order sort names so every client lists newest first by default - official Floatplane icon as channel image (Primary only — a channel Thumb hid video thumbnails in Continue Watching) and as 16:9 plugin thumbnail; one-time image replacement on upgrade - OAuth device-flow login (FloatplaneAuthService + settings UI); needs a Floatplane client id; Turnstile verified domain-bound so password login inside Jellyfin is impossible - generic install.sh (linuxserver / official image / native), thumb.png in package + manifest - README rewritten for a general audience, doc/usage.md with screenshots, 60 tests Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,9 @@ public class CatalogService
|
||||
|
||||
public DateTimeOffset LastRefresh => _creatorsFetched;
|
||||
|
||||
/// <summary>"oauth", "cookie" or "none".</summary>
|
||||
public string SessionKind => _api.SessionKind;
|
||||
|
||||
/// <summary>Session state as last observed (null = not checked yet).</summary>
|
||||
public string? SessionState { get; private set; }
|
||||
|
||||
@@ -83,7 +86,16 @@ public class CatalogService
|
||||
var done = 0;
|
||||
foreach (var creator in creators)
|
||||
{
|
||||
var channelIds = creator.Channels.Count > 0 ? creator.Channels.Select(c => c.Id).ToList() : new List<string> { string.Empty };
|
||||
var channelIds = creator.Channels.Select(c => c.Id).ToList();
|
||||
try
|
||||
{
|
||||
await GetAllPostsAsync(creator.Id, ct).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||
{
|
||||
_logger.LogWarning(ex, "Could not warm all-videos list for {Creator}", creator.Urlname);
|
||||
}
|
||||
|
||||
foreach (var channelId in channelIds)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
@@ -240,6 +252,22 @@ public class CatalogService
|
||||
return posts;
|
||||
}
|
||||
|
||||
/// <summary>Newest video posts across all of a creator's channels (the "All videos" folder).</summary>
|
||||
public async Task<IReadOnlyList<PostModel>> GetAllPostsAsync(string creatorId, CancellationToken ct)
|
||||
{
|
||||
var key = creatorId + "|*";
|
||||
var ttl = TimeSpan.FromMinutes(Math.Max(1, _config().CatalogCacheMinutes));
|
||||
if (_posts.TryGetValue(key, out var cached) && DateTimeOffset.UtcNow - cached.Fetched < ttl)
|
||||
{
|
||||
return cached.Posts;
|
||||
}
|
||||
|
||||
var max = Math.Clamp(_config().MaxPostsAllVideos, 20, 5000);
|
||||
var posts = await FetchPostsAsync(creatorId, string.Empty, max, ct).ConfigureAwait(false);
|
||||
_posts[key] = new CachedPosts(posts, DateTimeOffset.UtcNow);
|
||||
return posts;
|
||||
}
|
||||
|
||||
/// <summary>Pages through /content/creator until <paramref name="max"/> posts or the end.</summary>
|
||||
public async Task<IReadOnlyList<PostModel>> FetchPostsAsync(string creatorId, string channelId, int max, CancellationToken ct, string? search = null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user