feat(anki): import modern .apkg exports directly (native zstd decode) #764

Merged
raisondetredev merged 1 commit from refs/pull/764/head into main 2026-07-14 09:20:05 +02:00
raisondetredev commented 2026-07-14 09:19:35 +02:00 (Migrated from codeberg.org)

A modern Anki export stores the real deck in a zstd-compressed
collection.anki21b; Phase 1 could only tell the user to re-export with
"Support older Anki versions". Now the collection is decoded in-app on
native platforms (Android/iOS/desktop) via libzstd — compiled from
source by zstd_dart's Dart build hook — so a modern .apkg imports
directly, with the subdeck chooser and all.

  • anki_zstd_facade.dart (+io/web): native decodes via zstd_dart; the web
    has no zstd decoder and throws, so the caller falls back to the
    re-export prompt (web behaviour unchanged).
  • ankiCollectionBytes: when collection.anki21b is present, decode it
    (preferring it over the sibling stub collection.anki2), then downgrade
    the WAL header (bytes 18/19: 02 -> 01) so the checkpointed database
    opens in the in-memory VFS. On a decode failure or on the web, fall
    back to re-export guidance.

Verified end-to-end on a real 2386-card modern export: decodes, flips,
and reads 2338 notes across 121 subdecks.

Requires flutter config --enable-native-assets (experimental, global
Flutter flag) on every build machine and in CI. Known limitation: a
collection compressing better than ~8x overflows zstd_dart's heuristic
output buffer and falls back to re-export guidance; full coverage would
need a streaming decode (follow-up).

A modern Anki export stores the real deck in a zstd-compressed collection.anki21b; Phase 1 could only tell the user to re-export with "Support older Anki versions". Now the collection is decoded in-app on native platforms (Android/iOS/desktop) via libzstd — compiled from source by zstd_dart's Dart build hook — so a modern .apkg imports directly, with the subdeck chooser and all. - anki_zstd_facade.dart (+io/web): native decodes via zstd_dart; the web has no zstd decoder and throws, so the caller falls back to the re-export prompt (web behaviour unchanged). - ankiCollectionBytes: when collection.anki21b is present, decode it (preferring it over the sibling stub collection.anki2), then downgrade the WAL header (bytes 18/19: 02 -> 01) so the checkpointed database opens in the in-memory VFS. On a decode failure or on the web, fall back to re-export guidance. Verified end-to-end on a real 2386-card modern export: decodes, flips, and reads 2338 notes across 121 subdecks. Requires `flutter config --enable-native-assets` (experimental, global Flutter flag) on every build machine and in CI. Known limitation: a collection compressing better than ~8x overflows zstd_dart's heuristic output buffer and falls back to re-export guidance; full coverage would need a streaming decode (follow-up).
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
project-halkyon/halkyon-learn!764
No description provided.