mirror of
https://github.com/ankitects/anki.git
synced 2026-09-10 07:29:19 -04:00
## Linked issue (required)
Closes #5321
## Summary / motivation (required)
In the old Qt-based editor, attaching an audio file (paperclip button or
the mic recording button) played the file immediately, before the card
was saved. This was handled by `Editor.fnameToLink()` in
`qt/aqt/editor.py`, which called `av_player.play_file_with_caller()`
right after building the `[sound:...]` tag.
That method was removed in 4dd402334 ("Remove legacy editor code") once
the editor moved to the Svelte/TS implementation. Its replacement,
`filenameToLink()` in
`ts/routes/editor/rich-text-input/data-transfer.ts`, only builds the
`[sound:...]` string and never carried the playback call forward. So
today, attaching audio inserts the tag silently and you only hear it
after saving and reopening the card (or opening the Cards preview).
This restores the immediate playback, using the same `av_player`
mechanism the rest of the app uses (so it respects the configured audio
backend/volume), by:
- Adding a `PlayFile` RPC to `FrontendService` in `frontend.proto`,
following the same pattern as the existing Python-only
`RecordAudio`/`OpenMedia` RPCs (no Rust implementation needed,
`FrontendService` is filtered out of Rust codegen in
`rslib/rust_interface.rs`).
- Implementing `play_file()` in `qt/aqt/mediasrv.py`. It resolves the
path relative to the media folder the same way
`open_media`/`show_in_media_folder` do, then plays it on the main
thread. When the active window is the editor, it uses
`av_player.play_file_with_caller(path, window.editor.editorMode)`
instead of a plain `play_file()`, the same pattern already used by
`open_cards_dialog`/`open_fields_dialog` in the same file. This ties
playback to `Editor.cleanup()`'s existing
`av_player.stop_and_clear_queue_if_caller(self.editorMode)` call, so the
sound is stopped if the editor closes mid-playback.
- Calling the new `playFile()` binding from `attachPath()` in
`TemplateButtons.svelte` right after the media is inserted, only when
the attached file is audio (added an `isAudio()` helper next to
`filenameToLink()`, reusing the existing `audioSuffixes` list).
## Steps to reproduce (required, use N/A if not applicable)
1. Open the Add or Edit dialog for a note.
2. Click the paperclip (attach) button in the field toolbar.
3. Pick an audio file.
4. Notice nothing plays. The `[sound:...]` tag is inserted silently, and
you only hear the audio after saving/reviewing or opening the Cards
preview.
## How to test (required)
### Checklist (minimum)
- [x] I ran `./ninja check` or an equivalent relevant check locally.
- [x] I added or updated tests when the change is non-trivial or
behavior changed.
### Details
Ran `just check` locally, everything passed, including a new vitest
covering `isAudio()` in `data-transfer.test.ts`. Manually verified in
`just run`: opened Add dialog, attached an audio file via the paperclip
button and it plays as soon as it's inserted into the field, before
saving. Also tested the mic recording button (F5), which goes through
the same `attachPath()` function; recording and playback both work as
expected.
## Before / after behavior (optional)
Before: attaching audio via the paperclip inserts the `[sound:...]` tag
silently.
After: the audio plays immediately after being inserted, matching the
old Qt editor's behavior.
## Risk / compatibility / migration (optional)
Low risk. New RPC is additive (no changes to existing `FrontendService`
methods), and playback only triggers for files already classified as
audio/video by the existing suffix list used elsewhere in the same file.
## UI evidence (required for visual changes; otherwise N/A)
N/A, behavior-only change (audio playback), nothing visual to show.
## Scope
- [x] This PR is focused on one change (no unrelated edits).
Protobuf files defining the interface the frontend and backend components use to talk to each other, and how Anki stores some of the data inside its SQLite database. These files are used to generate Rust, Python and TypeScript bindings.