mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 15:02:21 -04:00
Move Record Audio button
This commit is contained in:
parent
e48a2a5b6a
commit
cf099ea508
4 changed files with 32 additions and 32 deletions
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue