fix(plugins): report merged card-mined ids as the kept note

- Resolve note ids merged away by field grouping to the surviving note before emitting card-mined, deduplicating results
- Update plugin docs and setCardsReadyCallback comment to match
This commit is contained in:
sudacode committed 2026-10-27 22:16:24 -07:00
1 parent d2ab808bc3
commit 390cf03e8d
3 files changed
+17 -3

No files matched your search

+1 -1
View File
@@ -130,6 +130,6 @@ A panel's `signal` aborts when the user closes it or another panel replaces it.
mpv events: `connection-change`, `subtitle-change`, `subtitle-timing`, `time-pos-change`, `duration-change`, `pause-change`, `fullscreen-change`, `media-path-change`, `media-title-change`, `subtitle-track-change`, `subtitle-track-list-change`, `secondary-subtitle-change`, `secondary-subtitle-track-change`, `secondary-subtitle-delay-change`, `secondary-subtitle-visibility`, `client-message`, and `end-file`. `end-file` gives `{ reason, playlistEntryId, error }`, where `reason` is `eof`, `stop`, `quit`, `error`, `redirect`, or `unknown`.
Anki events: `card-mined` gives `{ noteIds }` once SubMiner has finished filling in a mined card (sentence, audio, image, and field grouping). For YouTube cards whose media waits on the download, it fires once that media is added or the download fails. With `ankiConnect.behavior.autoUpdateNewCards` off, it fires as soon as SubMiner sees the card. If field grouping merged the card into an older one, the id may no longer exist.
Anki events: `card-mined` gives `{ noteIds }` once SubMiner has finished filling in a mined card (sentence, audio, image, and field grouping). For YouTube cards whose media waits on the download, it fires once that media is added or the download fails. With `ankiConnect.behavior.autoUpdateNewCards` off, it fires as soon as SubMiner sees the card. If field grouping merged the card into an older one, you get the older card's id.
`anki.invoke` takes `{ timeoutMs }` (default 10 seconds), rejects on an Anki error, and never retries, so an action like `sync` or `addNote` runs at most once.
+12
View File
@@ -274,6 +274,18 @@ test('AnkiIntegration resolves merged-away note ids to the kept note id', () =>
assert.equal(integration.resolveCurrentNoteId(444), 444);
});
test('AnkiIntegration reports ready cards under the note that kept them after a merge', () => {
const integration = createIntegration({});
const ready: number[][] = [];
integration.setCardsReadyCallback((noteIds) => ready.push(noteIds));
const internals = internalsOf(integration);
internals.rememberMergedNoteIds(111, 222);
internals.reportCardsReady([111, 222, 444]);
assert.deepEqual(ready, [[222, 444]]);
});
// --- Sentence highlighting --------------------------------------------------
const MPV_SENTENCE = '先日 貴様らが潜入した キールダンジョンから―';
+4 -2
View File
@@ -352,8 +352,10 @@ export class AnkiIntegration {
private emitCardsReady(noteIds: number[]): void {
if (noteIds.length === 0) return;
// Field grouping may have merged a note away; report the note that kept its content.
const currentNoteIds = [...new Set(noteIds.map((noteId) => this.resolveCurrentNoteId(noteId)))];
try {
this.cardsReadyCallback?.(noteIds);
this.cardsReadyCallback?.(currentNoteIds);
} catch (error) {
log.warn('cardsReady callback failed:', (error as Error).message);
}
@@ -1821,7 +1823,7 @@ export class AnkiIntegration {
/**
* Called once SubMiner has finished writing a mined card (fields, media including queued YouTube
* media, and field grouping), or as soon as polling or the proxy sees it when auto-update is off.
* Field grouping may have merged the note away by then.
* Ids merged away by field grouping are reported as the note that kept them.
*/
setCardsReadyCallback(callback: ((noteIds: number[]) => void) | null): void {
this.cardsReadyCallback = callback;