mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-10 03:13:32 -07:00
fix(notifications): show thumbnail image in overlay mined-card notificat
- Share generated notification icon between overlay and system notification paths - Add `image` field to OverlayNotificationPayload; render as IMG with has-image layout - Widen overlay stack to 420px; enlarge card padding and min-height for image variant - Show OSD message after successful anilist retry when attempt key already handled
This commit is contained in:
@@ -3,10 +3,18 @@ import assert from 'node:assert/strict';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { pathToFileURL } from 'url';
|
||||
import { AnkiIntegration } from './anki-integration';
|
||||
import { FieldGroupingMergeCollaborator } from './anki-integration/field-grouping-merge';
|
||||
import { AnkiConnectConfig } from './types';
|
||||
|
||||
type TestOverlayNotificationPayload = {
|
||||
title: string;
|
||||
body?: string;
|
||||
image?: string;
|
||||
variant?: string;
|
||||
};
|
||||
|
||||
interface IntegrationTestContext {
|
||||
integration: AnkiIntegration;
|
||||
calls: {
|
||||
@@ -406,6 +414,81 @@ test('AnkiIntegration marks partial update notifications as failures in OSD mode
|
||||
assert.deepEqual(osdMessages, ['x Updated card: taberu (image failed)']);
|
||||
});
|
||||
|
||||
test('AnkiIntegration includes generated notification image on overlay mined-card notifications', async () => {
|
||||
const desktopNotifications: Array<{ title: string; body?: string; icon?: string }> = [];
|
||||
const overlayNotifications: TestOverlayNotificationPayload[] = [];
|
||||
const generatedFrom: Array<{ videoPath: string; timestamp: number }> = [];
|
||||
const cleanupPaths: string[] = [];
|
||||
const notificationIconPath = path.join(os.tmpdir(), 'subminer-notification-icon.png');
|
||||
|
||||
const integration = new AnkiIntegration(
|
||||
{
|
||||
behavior: {
|
||||
notificationType: 'both',
|
||||
},
|
||||
},
|
||||
{} as never,
|
||||
{
|
||||
currentVideoPath: '/tmp/show.mkv',
|
||||
currentTimePos: 123.45,
|
||||
} as never,
|
||||
undefined,
|
||||
(title, options) => {
|
||||
desktopNotifications.push({ title, body: options.body, icon: options.icon });
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
{},
|
||||
undefined,
|
||||
(payload) => {
|
||||
overlayNotifications.push(payload as TestOverlayNotificationPayload);
|
||||
},
|
||||
);
|
||||
|
||||
(
|
||||
integration as unknown as {
|
||||
mediaGenerator: {
|
||||
generateNotificationIcon: (videoPath: string, timestamp: number) => Promise<Buffer>;
|
||||
writeNotificationIconToFile: (iconBuffer: Buffer, noteId: number) => string;
|
||||
scheduleNotificationIconCleanup: (filePath: string) => void;
|
||||
};
|
||||
}
|
||||
).mediaGenerator = {
|
||||
generateNotificationIcon: async (videoPath, timestamp) => {
|
||||
generatedFrom.push({ videoPath, timestamp });
|
||||
return Buffer.from('png');
|
||||
},
|
||||
writeNotificationIconToFile: (iconBuffer, noteId) => {
|
||||
assert.equal(iconBuffer.toString(), 'png');
|
||||
assert.equal(noteId, 42);
|
||||
return notificationIconPath;
|
||||
},
|
||||
scheduleNotificationIconCleanup: (filePath) => {
|
||||
cleanupPaths.push(filePath);
|
||||
},
|
||||
};
|
||||
|
||||
await (
|
||||
integration as unknown as {
|
||||
showNotification: (noteId: number, label: string | number) => Promise<void>;
|
||||
}
|
||||
).showNotification(42, '食べる');
|
||||
|
||||
assert.deepEqual(generatedFrom, [{ videoPath: '/tmp/show.mkv', timestamp: 123.45 }]);
|
||||
assert.equal(overlayNotifications.length, 1);
|
||||
assert.equal(overlayNotifications[0]?.title, 'Anki Card Updated');
|
||||
assert.equal(overlayNotifications[0]?.body, 'Updated card: 食べる');
|
||||
assert.equal(overlayNotifications[0]?.image, pathToFileURL(notificationIconPath).toString());
|
||||
assert.deepEqual(desktopNotifications, [
|
||||
{
|
||||
title: 'Anki Card Updated',
|
||||
body: 'Updated card: 食べる',
|
||||
icon: notificationIconPath,
|
||||
},
|
||||
]);
|
||||
assert.deepEqual(cleanupPaths, [notificationIconPath]);
|
||||
});
|
||||
|
||||
test('AnkiIntegration routes workflow status notifications through configured surfaces', async () => {
|
||||
const osdMessages: string[] = [];
|
||||
const desktopMessages: string[] = [];
|
||||
|
||||
Reference in New Issue
Block a user