Blur gallery images by default, sync progress UI, and add chat/monitor tests

- Blur NSFW media gallery images until hover/reveal
- Surface chat sync progress in the dashboard header
- Extend chat service, cache, and monitor with delta-media handling
- Add tests for chat cooldown, delta media, and monitor flows

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jjbruntonandClaude Opus 4.7 committed 2026-05-22 10:01:09 +01:00
1 parent 633bb0ec04
commit 2260388dc8
15 files changed
+675 -41

No files matched your search

+64
View File
@@ -156,6 +156,70 @@ describe('MonitorService', () => {
expect(Array.isArray(result)).toBe(true);
});
it('prefers a recent post over an older one when prioritizeRecentPosts is enabled', async () => {
const now = Math.floor(Date.now() / 1000);
const oldPost: RedditPost = {
id: 't3_old', subreddit: 'sub1', author: 'u_old', title: 'Old',
url: 'http://example.com/old.jpg', permalink: '/r/sub1/old', thumbnail: '',
is_self: false, created_utc: now - 7200, over_18: false, spoiler: false,
};
const recentPost: RedditPost = {
id: 't3_new', subreddit: 'sub2', author: 'u_new', title: 'New',
url: 'http://example.com/new.jpg', permalink: '/r/sub2/new', thumbnail: '',
is_self: false, created_utc: now - 600, over_18: false, spoiler: false,
};
const redditApi = {
getNewPosts: vi.fn(async (sub: string) =>
sub === 'sub1' ? [oldPost] : [recentPost],
),
getImageUrl: vi.fn(),
getPostUrl: vi.fn(),
isSellerProfile: vi.fn(async () => false),
} as unknown as RedditApiClient;
const postsRepo = createMockPostsRepo();
const messagesRepo = createMockMessagesRepo();
const config = getTestConfig({
reddit: {
subreddits: [{ name: 'sub1', type: 'image' }, { name: 'sub2', type: 'image' }],
prioritizeRecentPosts: true,
recentWindowMinutes: 60,
},
});
monitor = new MonitorService(redditApi, postsRepo, messagesRepo, config, logger, 0);
const result = await monitor.getUnprocessedPosts();
expect(result.length).toBe(1);
expect(result[0].id).toBe('t3_new');
});
it('falls back to the newest older post when no recent posts exist', async () => {
const now = Math.floor(Date.now() / 1000);
const oldPost: RedditPost = {
id: 't3_old', subreddit: 'sub1', author: 'u_old', title: 'Old',
url: 'http://example.com/old.jpg', permalink: '/r/sub1/old', thumbnail: '',
is_self: false, created_utc: now - 7200, over_18: false, spoiler: false,
};
const redditApi = createMockRedditApi([oldPost]);
const postsRepo = createMockPostsRepo();
const messagesRepo = createMockMessagesRepo();
const config = getTestConfig({
reddit: {
subreddits: [{ name: 'sub1', type: 'image' }],
prioritizeRecentPosts: true,
recentWindowMinutes: 60,
},
});
monitor = new MonitorService(redditApi, postsRepo, messagesRepo, config, logger, 0);
const result = await monitor.getUnprocessedPosts();
expect(result.length).toBe(1);
expect(result[0].id).toBe('t3_old');
});
it('returns empty array when no subreddits have valid posts', async () => {
const redditApi = createMockRedditApi([]);
const postsRepo = createMockPostsRepo();