mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Deck options without bridge (#3571)
* NF: Modify CONTRIBUTORS Just so that I stop getting the warning * NF: Create `deckOptionsReady` * NF: rename _close to require_close The method will have to be used outside of this class, so can't be private * NF: simplify slightly some code * NF: remove bridge command from deck options * Remove unused import * Remove superfluous comment with a typo
This commit is contained in:
parent
769f302ea8
commit
d7fc98d4d8
6 changed files with 54 additions and 51 deletions
|
@ -32,8 +32,8 @@ AMBOSS MD Inc. <https://www.amboss.com/>
|
||||||
Aristotelis P. <https://glutanimate.com/contact>
|
Aristotelis P. <https://glutanimate.com/contact>
|
||||||
Erez Volk <erez.volk@gmail.com>
|
Erez Volk <erez.volk@gmail.com>
|
||||||
zjosua <zjosua@hotmail.com>
|
zjosua <zjosua@hotmail.com>
|
||||||
Arthur Milchior <arthur@milchior.fr>
|
|
||||||
Yngve Hoiseth <yngve@hoiseth.net>
|
Yngve Hoiseth <yngve@hoiseth.net>
|
||||||
|
Arthur Milchior <arthur@milchior.fr>
|
||||||
Ijgnd
|
Ijgnd
|
||||||
Yoonchae Lee <bluegreenmagick@gmail.com>
|
Yoonchae Lee <bluegreenmagick@gmail.com>
|
||||||
Evandro Coan <github.com/evandrocoan>
|
Evandro Coan <github.com/evandrocoan>
|
||||||
|
|
|
@ -22,6 +22,11 @@ service FrontendService {
|
||||||
rpc ImportDone(generic.Empty) returns (generic.Empty);
|
rpc ImportDone(generic.Empty) returns (generic.Empty);
|
||||||
|
|
||||||
rpc SearchInBrowser(search.SearchNode) returns (generic.Empty);
|
rpc SearchInBrowser(search.SearchNode) returns (generic.Empty);
|
||||||
|
|
||||||
|
// Force closing the deck options.
|
||||||
|
rpc deckOptionsRequireClose(generic.Empty) returns (generic.Empty);
|
||||||
|
// Warns python that the deck option web view is ready to receive requests.
|
||||||
|
rpc deckOptionsReady(generic.Empty) returns (generic.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
service BackendFrontendService {}
|
service BackendFrontendService {}
|
||||||
|
|
|
@ -14,7 +14,6 @@ from aqt.qt import *
|
||||||
from aqt.utils import (
|
from aqt.utils import (
|
||||||
KeyboardModifiersPressed,
|
KeyboardModifiersPressed,
|
||||||
addCloseShortcut,
|
addCloseShortcut,
|
||||||
ask_user_dialog,
|
|
||||||
disable_help_button,
|
disable_help_button,
|
||||||
restoreGeom,
|
restoreGeom,
|
||||||
saveGeom,
|
saveGeom,
|
||||||
|
@ -46,7 +45,6 @@ class DeckOptionsDialog(QDialog):
|
||||||
addCloseShortcut(self)
|
addCloseShortcut(self)
|
||||||
|
|
||||||
self.web = AnkiWebView(kind=AnkiWebViewKind.DECK_OPTIONS)
|
self.web = AnkiWebView(kind=AnkiWebViewKind.DECK_OPTIONS)
|
||||||
self.web.set_bridge_command(self._on_bridge_cmd, self)
|
|
||||||
self.web.load_sveltekit_page(f"deck-options/{self._deck['id']}")
|
self.web.load_sveltekit_page(f"deck-options/{self._deck['id']}")
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
@ -58,43 +56,22 @@ class DeckOptionsDialog(QDialog):
|
||||||
without_unicode_isolation(tr.actions_options_for(val=self._deck["name"]))
|
without_unicode_isolation(tr.actions_options_for(val=self._deck["name"]))
|
||||||
)
|
)
|
||||||
|
|
||||||
def _on_bridge_cmd(self, cmd: str) -> None:
|
def set_ready(self):
|
||||||
if cmd == "deckOptionsReady":
|
self._ready = True
|
||||||
self._ready = True
|
gui_hooks.deck_options_did_load(self)
|
||||||
gui_hooks.deck_options_did_load(self)
|
|
||||||
elif cmd == "confirmDiscardChanges":
|
|
||||||
self.confirm_discard_changes()
|
|
||||||
elif cmd == "_close":
|
|
||||||
self._close()
|
|
||||||
|
|
||||||
def closeEvent(self, evt: QCloseEvent | None) -> None:
|
def closeEvent(self, evt: QCloseEvent | None) -> None:
|
||||||
if self._close_event_has_cleaned_up:
|
if self._close_event_has_cleaned_up or not self._ready:
|
||||||
return super().closeEvent(evt)
|
return super().closeEvent(evt)
|
||||||
assert evt is not None
|
assert evt is not None
|
||||||
evt.ignore()
|
evt.ignore()
|
||||||
self.check_pending_changes()
|
self.web.eval("anki.deckOptionsPendingChanges();")
|
||||||
|
|
||||||
def _close(self):
|
def require_close(self):
|
||||||
"""Close. Ensure the closeEvent is not ignored."""
|
"""Close. Ensure the closeEvent is not ignored."""
|
||||||
self._close_event_has_cleaned_up = True
|
self._close_event_has_cleaned_up = True
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def confirm_discard_changes(self) -> None:
|
|
||||||
def callbackWithUserChoice(choice: int) -> None:
|
|
||||||
if choice == 0:
|
|
||||||
# The user accepted to discard current input.
|
|
||||||
self._close()
|
|
||||||
|
|
||||||
ask_user_dialog(
|
|
||||||
tr.card_templates_discard_changes(),
|
|
||||||
callback=callbackWithUserChoice,
|
|
||||||
buttons=[
|
|
||||||
QMessageBox.StandardButton.Discard,
|
|
||||||
(tr.adding_keep_editing(), QMessageBox.ButtonRole.RejectRole),
|
|
||||||
],
|
|
||||||
parent=self,
|
|
||||||
)
|
|
||||||
|
|
||||||
def reject(self) -> None:
|
def reject(self) -> None:
|
||||||
self.mw.col.set_wants_abort()
|
self.mw.col.set_wants_abort()
|
||||||
self.web.cleanup()
|
self.web.cleanup()
|
||||||
|
@ -102,12 +79,6 @@ class DeckOptionsDialog(QDialog):
|
||||||
saveGeom(self, self.TITLE)
|
saveGeom(self, self.TITLE)
|
||||||
QDialog.reject(self)
|
QDialog.reject(self)
|
||||||
|
|
||||||
def check_pending_changes(self):
|
|
||||||
if self._ready:
|
|
||||||
self.web.eval("anki.deckOptionsPendingChanges();")
|
|
||||||
else:
|
|
||||||
self._close()
|
|
||||||
|
|
||||||
|
|
||||||
def confirm_deck_then_display_options(active_card: Card | None = None) -> None:
|
def confirm_deck_then_display_options(active_card: Card | None = None) -> None:
|
||||||
decks = [aqt.mw.col.decks.current()]
|
decks = [aqt.mw.col.decks.current()]
|
||||||
|
|
|
@ -75,6 +75,7 @@ class PageContext(enum.IntEnum):
|
||||||
REVIEWER = enum.auto()
|
REVIEWER = enum.auto()
|
||||||
PREVIEWER = enum.auto()
|
PREVIEWER = enum.auto()
|
||||||
CARD_LAYOUT = enum.auto()
|
CARD_LAYOUT = enum.auto()
|
||||||
|
DECK_OPTIONS = enum.auto()
|
||||||
# something in /_anki/pages/
|
# something in /_anki/pages/
|
||||||
NON_LEGACY_PAGE = enum.auto()
|
NON_LEGACY_PAGE = enum.auto()
|
||||||
# Do not use this if you present user content (e.g. content from cards), as it's a
|
# Do not use this if you present user content (e.g. content from cards), as it's a
|
||||||
|
@ -574,6 +575,26 @@ def change_notetype() -> bytes:
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
|
|
||||||
|
def deck_options_require_close() -> bytes:
|
||||||
|
def handle_on_main() -> None:
|
||||||
|
window = aqt.mw.app.activeWindow()
|
||||||
|
if isinstance(window, DeckOptionsDialog):
|
||||||
|
window.require_close()
|
||||||
|
|
||||||
|
aqt.mw.taskman.run_on_main(handle_on_main)
|
||||||
|
return b""
|
||||||
|
|
||||||
|
|
||||||
|
def deck_options_ready() -> bytes:
|
||||||
|
def handle_on_main() -> None:
|
||||||
|
window = aqt.mw.app.activeWindow()
|
||||||
|
if isinstance(window, DeckOptionsDialog):
|
||||||
|
window.set_ready()
|
||||||
|
|
||||||
|
aqt.mw.taskman.run_on_main(handle_on_main)
|
||||||
|
return b""
|
||||||
|
|
||||||
|
|
||||||
post_handler_list = [
|
post_handler_list = [
|
||||||
congrats_info,
|
congrats_info,
|
||||||
get_deck_configs_for_update,
|
get_deck_configs_for_update,
|
||||||
|
@ -587,6 +608,8 @@ post_handler_list = [
|
||||||
import_json_file,
|
import_json_file,
|
||||||
import_json_string,
|
import_json_string,
|
||||||
search_in_browser,
|
search_in_browser,
|
||||||
|
deck_options_require_close,
|
||||||
|
deck_options_ready,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -685,11 +708,12 @@ def _check_dynamic_request_permissions():
|
||||||
aqt.mw.taskman.run_on_main(warn)
|
aqt.mw.taskman.run_on_main(warn)
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
if (
|
if context in [
|
||||||
context == PageContext.NON_LEGACY_PAGE
|
PageContext.NON_LEGACY_PAGE,
|
||||||
or context == PageContext.EDITOR
|
PageContext.EDITOR,
|
||||||
or context == PageContext.ADDON_PAGE
|
PageContext.ADDON_PAGE,
|
||||||
):
|
PageContext.DECK_OPTIONS,
|
||||||
|
]:
|
||||||
pass
|
pass
|
||||||
elif context == PageContext.REVIEWER and request.path in (
|
elif context == PageContext.REVIEWER and request.path in (
|
||||||
"/_anki/getSchedulingStatesWithContext",
|
"/_anki/getSchedulingStatesWithContext",
|
||||||
|
|
|
@ -611,6 +611,7 @@ html {{ {font} }}
|
||||||
# print(html)
|
# print(html)
|
||||||
import aqt.browser.previewer
|
import aqt.browser.previewer
|
||||||
import aqt.clayout
|
import aqt.clayout
|
||||||
|
import aqt.deckoptions
|
||||||
import aqt.editor
|
import aqt.editor
|
||||||
import aqt.reviewer
|
import aqt.reviewer
|
||||||
from aqt.mediasrv import PageContext
|
from aqt.mediasrv import PageContext
|
||||||
|
@ -623,6 +624,8 @@ html {{ {font} }}
|
||||||
page_context = PageContext.PREVIEWER
|
page_context = PageContext.PREVIEWER
|
||||||
elif isinstance(context, aqt.clayout.CardLayout):
|
elif isinstance(context, aqt.clayout.CardLayout):
|
||||||
page_context = PageContext.CARD_LAYOUT
|
page_context = PageContext.CARD_LAYOUT
|
||||||
|
elif isinstance(context, aqt.deckoptions.DeckOptionsDialog):
|
||||||
|
page_context = PageContext.DECK_OPTIONS
|
||||||
else:
|
else:
|
||||||
page_context = PageContext.UNKNOWN
|
page_context = PageContext.UNKNOWN
|
||||||
self.setHtml(html, page_context)
|
self.setHtml(html, page_context)
|
||||||
|
|
|
@ -3,11 +3,13 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
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 { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import DeckOptionsPage from "../DeckOptionsPage.svelte";
|
import DeckOptionsPage from "../DeckOptionsPage.svelte";
|
||||||
import { commitEditing } from "../lib";
|
import { commitEditing } from "../lib";
|
||||||
import type { PageData } from "./$types";
|
import type { PageData } from "./$types";
|
||||||
import { bridgeCommand, bridgeCommandsAvailable } from "@tslib/bridgecommand";
|
import { deckOptionsRequireClose, deckOptionsReady } from "@generated/backend";
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
let page: DeckOptionsPage;
|
let page: DeckOptionsPage;
|
||||||
|
@ -15,12 +17,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
globalThis.anki ||= {};
|
globalThis.anki ||= {};
|
||||||
globalThis.anki.deckOptionsPendingChanges = async (): Promise<void> => {
|
globalThis.anki.deckOptionsPendingChanges = async (): Promise<void> => {
|
||||||
await commitEditing();
|
await commitEditing();
|
||||||
if (bridgeCommandsAvailable()) {
|
if (
|
||||||
if (await data.state.isModified()) {
|
!(await data.state.isModified()) ||
|
||||||
bridgeCommand("confirmDiscardChanges");
|
confirm(tr.cardTemplatesDiscardChanges())
|
||||||
} else {
|
) {
|
||||||
bridgeCommand("_close");
|
// Either there was no change, or the user accepted to discard the changes.
|
||||||
}
|
deckOptionsRequireClose({});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,9 +31,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
resolve(page);
|
resolve(page);
|
||||||
});
|
});
|
||||||
data.state.resolveOriginalConfigs();
|
data.state.resolveOriginalConfigs();
|
||||||
if (bridgeCommandsAvailable()) {
|
deckOptionsReady({});
|
||||||
bridgeCommand("deckOptionsReady");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue