From cf099ea508e020c52f64a007c4a69f2e498679ea Mon Sep 17 00:00:00 2001 From: Abdo Date: Wed, 18 Jun 2025 23:30:39 +0300 Subject: [PATCH] Move Record Audio button --- proto/anki/frontend.proto | 1 + qt/aqt/editor.py | 24 ------------------- qt/aqt/mediasrv.py | 20 ++++++++++++++++ .../editor-toolbar/TemplateButtons.svelte | 19 ++++++++------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/proto/anki/frontend.proto b/proto/anki/frontend.proto index 9e4d2de13..73effc4d6 100644 --- a/proto/anki/frontend.proto +++ b/proto/anki/frontend.proto @@ -37,6 +37,7 @@ service FrontendService { rpc openFilePicker(openFilePickerRequest) returns (generic.String); rpc openMedia(generic.String) returns (generic.Empty); rpc showInMediaFolder(generic.String) returns (generic.Empty); + rpc recordAudio(generic.Empty) returns (generic.String); // Profile config rpc GetProfileConfigJson(generic.String) returns (generic.Json); diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 99f648686..38429953f 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -23,8 +23,6 @@ import bs4 import requests from bs4 import BeautifulSoup -import aqt -import aqt.sound from anki._legacy import deprecated from anki.cards import Card from anki.collection import Config @@ -578,19 +576,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too self.web.eval(f"setFormat('inserthtml', {json.dumps(html)});") - def resolve_media(self, path: str) -> None: - """Finish inserting media into a field. - This expects initial setup to have been done by TemplateButtons.svelte.""" - try: - html = self._addMedia(path) - except Exception as e: - showWarning(str(e)) - return - - self.web.eval( - f'require("anki/TemplateButtons").resolveMedia({json.dumps(html)})' - ) - def _addMedia(self, path: str, canDelete: bool = False) -> str: """Add to media folder and return local img or sound tag.""" # copy to media folder @@ -601,14 +586,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too def _addMediaFromData(self, fname: str, data: bytes) -> str: return self.mw.col.media._legacy_write_data(fname, data) - def onRecSound(self) -> None: - aqt.sound.record_audio( - self.parentWindow, - self.mw, - True, - self.resolve_media, - ) - # Media downloads ###################################################################### @@ -883,7 +860,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too self._links: dict[str, Callable] = dict( fields=Editor.onFields, cards=Editor.onCardLayout, - record=Editor.onRecSound, paste=Editor.onPaste, cut=Editor.onCut, copy=Editor.onCopy, diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index 4cda76eab..ddd8ac335 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -745,6 +745,25 @@ def show_in_media_folder() -> bytes: return b"" +async def record_audio() -> bytes: + loop = asyncio.get_event_loop() + future = loop.create_future() + + def on_main() -> None: + from aqt.sound import record_audio + + def cb(path: str | None) -> None: + loop.call_soon_threadsafe(future.set_result, path) + + window = aqt.mw.app.activeWindow() + assert window is not None + record_audio(window, aqt.mw, True, cb) + + aqt.mw.taskman.run_on_main(on_main) + + path = await future + + return generic_pb2.String(val=path if path else "").SerializeToString() post_handler_list = [ congrats_info, @@ -772,6 +791,7 @@ post_handler_list = [ open_file_picker, open_media, show_in_media_folder, + record_audio, ] diff --git a/ts/routes/editor/editor-toolbar/TemplateButtons.svelte b/ts/routes/editor/editor-toolbar/TemplateButtons.svelte index 8102a7f1f..9c19dc79a 100644 --- a/ts/routes/editor/editor-toolbar/TemplateButtons.svelte +++ b/ts/routes/editor/editor-toolbar/TemplateButtons.svelte @@ -4,7 +4,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -->