Move Record Audio button

This commit is contained in:
Abdo 2025-06-18 23:30:39 +03:00
parent e48a2a5b6a
commit cf099ea508
4 changed files with 32 additions and 32 deletions

View file

@ -37,6 +37,7 @@ service FrontendService {
rpc openFilePicker(openFilePickerRequest) returns (generic.String); rpc openFilePicker(openFilePickerRequest) returns (generic.String);
rpc openMedia(generic.String) returns (generic.Empty); rpc openMedia(generic.String) returns (generic.Empty);
rpc showInMediaFolder(generic.String) returns (generic.Empty); rpc showInMediaFolder(generic.String) returns (generic.Empty);
rpc recordAudio(generic.Empty) returns (generic.String);
// Profile config // Profile config
rpc GetProfileConfigJson(generic.String) returns (generic.Json); rpc GetProfileConfigJson(generic.String) returns (generic.Json);

View file

@ -23,8 +23,6 @@ import bs4
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import aqt
import aqt.sound
from anki._legacy import deprecated from anki._legacy import deprecated
from anki.cards import Card from anki.cards import Card
from anki.collection import Config 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)});") 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: def _addMedia(self, path: str, canDelete: bool = False) -> str:
"""Add to media folder and return local img or sound tag.""" """Add to media folder and return local img or sound tag."""
# copy to media folder # 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: def _addMediaFromData(self, fname: str, data: bytes) -> str:
return self.mw.col.media._legacy_write_data(fname, data) 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 # Media downloads
###################################################################### ######################################################################
@ -883,7 +860,6 @@ require("anki/ui").loaded.then(() => require("anki/NoteEditor").instances[0].too
self._links: dict[str, Callable] = dict( self._links: dict[str, Callable] = dict(
fields=Editor.onFields, fields=Editor.onFields,
cards=Editor.onCardLayout, cards=Editor.onCardLayout,
record=Editor.onRecSound,
paste=Editor.onPaste, paste=Editor.onPaste,
cut=Editor.onCut, cut=Editor.onCut,
copy=Editor.onCopy, copy=Editor.onCopy,

View file

@ -745,6 +745,25 @@ def show_in_media_folder() -> bytes:
return b"" 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 = [ post_handler_list = [
congrats_info, congrats_info,
@ -772,6 +791,7 @@ post_handler_list = [
open_file_picker, open_file_picker,
open_media, open_media,
show_in_media_folder, show_in_media_folder,
record_audio,
] ]

View file

@ -4,7 +4,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl"; import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand";
import { promiseWithResolver } from "@tslib/promise"; import { promiseWithResolver } from "@tslib/promise";
import { registerPackage } from "@tslib/runtime-require"; import { registerPackage } from "@tslib/runtime-require";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
@ -27,7 +26,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { editingInputIsRichText } from "../rich-text-input"; import { editingInputIsRichText } from "../rich-text-input";
import LatexButton from "./LatexButton.svelte"; import LatexButton from "./LatexButton.svelte";
import { filenameToLink, openFilePickerForMedia } from "../rich-text-input/data-transfer"; import { filenameToLink, openFilePickerForMedia } from "../rich-text-input/data-transfer";
import { addMediaFromPath } from "@generated/backend"; import { addMediaFromPath, recordAudio } from "@generated/backend";
const { focusedInput } = context.get(); const { focusedInput } = context.get();
@ -40,6 +39,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
resolve?.(media); resolve?.(media);
} }
async function attachPath(path: string): Promise<void> {
const filename = (await addMediaFromPath({ path })).val;
resolveMedia(filenameToLink(filename));
}
async function attachMediaOnFocus(): Promise<void> { async function attachMediaOnFocus(): Promise<void> {
if (disabled) { if (disabled) {
return; return;
@ -50,9 +54,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
async () => setFormat("inserthtml", await mediaPromise), async () => setFormat("inserthtml", await mediaPromise),
{ once: true }, { once: true },
); );
let file = await openFilePickerForMedia(); const path = await openFilePickerForMedia();
file = (await addMediaFromPath({ path: file })).val; await attachPath(path);
resolveMedia(filenameToLink(file));
} }
registerPackage("anki/TemplateButtons", { registerPackage("anki/TemplateButtons", {
@ -61,7 +64,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const recordCombination = "F5"; const recordCombination = "F5";
function attachRecordingOnFocus(): void { async function attachRecordingOnFocus(): Promise<void> {
if (disabled) { if (disabled) {
return; return;
} }
@ -71,8 +74,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
async () => setFormat("inserthtml", await mediaPromise), async () => setFormat("inserthtml", await mediaPromise),
{ once: true }, { once: true },
); );
const path = (await recordAudio({})).val;
bridgeCommand("record"); await attachPath(path);
} }
$: disabled = !$focusedInput || !editingInputIsRichText($focusedInput); $: disabled = !$focusedInput || !editingInputIsRichText($focusedInput);