mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 06:52:21 -04:00
Merge remote-tracking branch 'upstream/HEAD' into apkg
This commit is contained in:
commit
bf5254e882
29 changed files with 144 additions and 93 deletions
4
.bazelrc
4
.bazelrc
|
@ -10,6 +10,10 @@ build:windows --build_python_zip=false
|
|||
# record version/build hash
|
||||
build --workspace_status_command='bash ./tools/status.sh'
|
||||
|
||||
# support macOS 10.13+
|
||||
build:macos --action_env="MACOSX_DEPLOYMENT_TARGET=10.13"
|
||||
build:macos --macos_minimum_os=10.13
|
||||
|
||||
# run clippy when compiling rust in test mode
|
||||
test --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect --output_groups=+clippy_checks
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.0.0
|
||||
5.1.1
|
||||
|
|
|
@ -99,6 +99,7 @@ Sachin Govind <sachin.govind.too@gmail.com>
|
|||
Bruce Harris <github.com/bruceharris>
|
||||
Patric Cunha <patricc@agap2.pt>
|
||||
Brayan Oliveira <github.com/BrayanDSO>
|
||||
Luka Warren <github.com/lukawarren>
|
||||
|
||||
********************
|
||||
|
||||
|
|
2
defs.bzl
2
defs.bzl
|
@ -10,7 +10,7 @@ load("@io_bazel_rules_sass//:defs.bzl", "sass_repositories")
|
|||
load("//python/pyqt:defs.bzl", "install_pyqt")
|
||||
load("@rules_python//python:pip.bzl", "pip_parse")
|
||||
|
||||
anki_version = "2.1.51"
|
||||
anki_version = "2.1.52"
|
||||
|
||||
def setup_deps():
|
||||
bazel_skylib_workspace()
|
||||
|
|
|
@ -8,6 +8,7 @@ cargo_build_script(
|
|||
srcs = ["build.rs"],
|
||||
build_script_env = {
|
||||
"PYO3_PYTHON": "$(location @python)",
|
||||
"MACOSX_DEPLOYMENT_TARGET": "10.13",
|
||||
},
|
||||
data = [
|
||||
"@python",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pyqt6==6.2.2
|
||||
pyqt6-qt6==6.2.2
|
||||
pyqt6-webengine==6.2.1
|
||||
pyqt6-webengine-qt6==6.2.2
|
||||
pyqt6_sip==13.2.1
|
||||
pyqt6==6.3.0
|
||||
pyqt6-qt6==6.3.0
|
||||
pyqt6-webengine==6.3.0
|
||||
pyqt6-webengine-qt6==6.3.0
|
||||
pyqt6_sip==13.3.1
|
||||
|
|
|
@ -1,51 +1,48 @@
|
|||
pyqt6==6.2.2 \
|
||||
--hash=sha256:6f983a42239a6b7829ceff718ea943b8034f8d9e5d796a0fcfda0bc53fbaf8e9 \
|
||||
--hash=sha256:9325a0f51c08e37340d916d2723daf9a25c844dac99d71d6c5aacb4f6ee00171 \
|
||||
--hash=sha256:e9d56e25d307c50a8f21c2f210ddada661fac6ffd882deea82b50127919823fd \
|
||||
--hash=sha256:eda7a54f47d70377f95d0aafccfca83a7f5a6895f020d38986dfa96aa8b0883c
|
||||
pyqt6==6.3.0 \
|
||||
--hash=sha256:20dec18471d3e574e37411618725dc2901443a781f5c6d974b041413141f33e4 \
|
||||
--hash=sha256:4fd85dcb15ea4e734b6e4e216fe9a6246779761edaf2cf7c0cce1a2303a8d31b \
|
||||
--hash=sha256:e193f8714ff21cb13fe4a6148b963893ff9ff738676fc9c853333259b9b64425 \
|
||||
--hash=sha256:ff4244507d1ff54fffa27cdaf4d4df90e4252fd1843ba28d2f32a4c79c3ece4e
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pyqt6-webengine
|
||||
pyqt6-qt6==6.2.2 \
|
||||
--hash=sha256:47515bf682748a42f41b9df8cc3854d29802199357ea76d39ece55679f390fe6 \
|
||||
--hash=sha256:8cac87d50a8afd0f3af1a3dd7b32e508bb5fd2a7149a272a84f922c63f5af6f3 \
|
||||
--hash=sha256:b3a3113f3a89d16ea204b99868adc33688559746260e8a2396b2edc9779eb37c \
|
||||
--hash=sha256:c26076c16eb1743f10179a62567d47c1cbda43ac45a1759d2e96563c52d8e41c
|
||||
pyqt6-qt6==6.3.0 \
|
||||
--hash=sha256:0782dc4da4933755182724290b43f52441b1b90c377ee7e6a1b625bb91c09a10 \
|
||||
--hash=sha256:7f94dcf6f60e3e395083d87e49f14ccc194cd45d73f301ade39bc6adfdfc765f \
|
||||
--hash=sha256:bef30ad651fa5fbc4a5d157862108c6ea270e636cc98b1eafdb93f5c7fef7eff \
|
||||
--hash=sha256:e87d192d20c5789aa1271025831881dde071a357a1956c808fb5e1b4603ec832
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pyqt6
|
||||
pyqt6-sip==13.2.0 \
|
||||
--hash=sha256:0baa53e464667b289ee157024e244fd9fa190101ec74eae30d17f0692f6af8cd \
|
||||
--hash=sha256:10e6c5d0004308efcbe8826ff0b8faf6e6f60c9e906cffeb26834e18e6340ed4 \
|
||||
--hash=sha256:121b887e40daac64f139ce3d7fc7b1d549ce75d423c6c174abbdf6ec7ab5d636 \
|
||||
--hash=sha256:12d43e55ec5ce70260097c19ff95942d2d329ba8c81fe140e5e9af08cbcfcb9c \
|
||||
--hash=sha256:149e91b372037765b18e728e68facdb2f072fbf043f76a5a424d2fa78af13163 \
|
||||
--hash=sha256:5f4b4ce20ff851fbf19cc7777485ac531171308705b1b36305cd71680686941f \
|
||||
--hash=sha256:66f3bf78d6bb084d10261111c3a7aa7c4125d73006b763544c81278468e9aa9d \
|
||||
--hash=sha256:6a12210e8547a8d8f9926fc3773e2c83db4511f9ac8bdec0b11b08a751262474 \
|
||||
--hash=sha256:9b79ca8554e40d70783ab7f7f6e16043ffd6c1d6cc14da5eba6ba474a7002233 \
|
||||
--hash=sha256:a0dcd554d00e025c844427860336fab8179173e181717a895af234f0279236f9 \
|
||||
--hash=sha256:abb26230a444f3b65396c3612af5db4f96a6765a56026078b7b45c8fb8bc1693 \
|
||||
--hash=sha256:cc92d5fc57a9192f269a622c340551ad9cde6d7a282273ccb3c64cd742f73760 \
|
||||
--hash=sha256:cda533d545414576e2d88d106c03eaf340bf8897388277838f9f2ffa6e2a7492 \
|
||||
--hash=sha256:d44e69ed4dc208c6cd791be8c54d8d656e1d395fe537bd1320f01b8ab3edec0f \
|
||||
--hash=sha256:e7c8093a6ef36395353a32df026745254b1ebdfcd490f746307d84ba67bcd93a \
|
||||
--hash=sha256:f8a65a876b70fc1c4eb95de74e133c81c146f08ad0e04877e16af8e3798b9d50
|
||||
pyqt6-sip==13.3.1 \
|
||||
--hash=sha256:0f4d7a0dd9c610ab0b2e7b46cfa45eeecd72a50f9d2a82a883d4fc2a0eabe216 \
|
||||
--hash=sha256:10e54200c619276f4e79c615b0d2f1f612a8b4fe443c119869de62546e0f9f2f \
|
||||
--hash=sha256:33c4a39e9fce8448d0abb79f80ecf35b8420ec76fa90b056173ce69a8a2ae769 \
|
||||
--hash=sha256:3bffad016f115a003f290bf8e92d2fd38d6b3c832946e7ee98aa9ecc20c431ba \
|
||||
--hash=sha256:45f23a3de6290ab311d827a371e82c09cd3203d57c74e8aa739280feb0960f80 \
|
||||
--hash=sha256:77edc790f8bae29729103b378ccd29beba402bcdde5c584bd4aebbf8c8a75caa \
|
||||
--hash=sha256:7c26dcba7deebb3d001079eda84be911bac55520b5e7b7113fac1859d850b566 \
|
||||
--hash=sha256:98c53675a4fb2507126ff2ea3ec03872d6e59624d45e6ad95053f74002be121f \
|
||||
--hash=sha256:b94dc4ecda4b6a011cdb5fdff0eae27567d30c30bc884c78394b76e02eb3df7a \
|
||||
--hash=sha256:b9506e2ddb126541457db939311432a63d0affc83bf86ff902d1664c7c167db6 \
|
||||
--hash=sha256:d629c0e39d5ccfdae567b92ba74d92f9180b7c55535f82251f1a12a9076a9e01 \
|
||||
--hash=sha256:ef89555ad34ca8b8f6d2e3ccacd4edacebef781404254c2cb17ba1c60cdc57c2 \
|
||||
--hash=sha256:f17c15665a4007cdf167eaeb133408b8e3409203303199a00068da63ea4c41a3
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pyqt6
|
||||
# pyqt6-webengine
|
||||
pyqt6-webengine==6.2.1 \
|
||||
--hash=sha256:52c65c70050f19e4d38bd9e91667a2d87c595c854b3ba162d863e3c05f696957 \
|
||||
--hash=sha256:6f6d7cb612f20d1f1f8ea1bbe7ebb8bbaa3f7fcd56f0e9c41582851998be20c3 \
|
||||
--hash=sha256:97d4b43f0959458adc119511d22a12814416a3bf8bc78f246068fdd54a6fd2b3 \
|
||||
--hash=sha256:aa2c8e93f99756f1ec5a703d3131605294c6603869e50204ae5a5f52ea15ec2f
|
||||
pyqt6-webengine==6.3.0 \
|
||||
--hash=sha256:1309c518eb159dcb4a9635a5f42e6d11c141ebb3baaee442cc8edf3893f55361 \
|
||||
--hash=sha256:147e6dab0184071f5febf020e29fde6a8dcced6b56f40bbc2a056fac59e76a98 \
|
||||
--hash=sha256:ab2aedbeec54f1bcff872f7dfc236aa0fce4b55cd30f608ca89b408ee9e8147b \
|
||||
--hash=sha256:bb37a7b2a9c0b2856a16066869389053901c20163ef9637344f0279f9597c57d
|
||||
# via -r requirements.in
|
||||
pyqt6-webengine-qt6==6.2.2 \
|
||||
--hash=sha256:8449cec1492085bf0e6168c02e9c0255f66c67cdbdbb4c06d9f0c398f44d4b0d \
|
||||
--hash=sha256:8f83d93b58ea4f13f03ba2c82820a3ade2942f59240191f8153ee4d1e8221e6b \
|
||||
--hash=sha256:b88b913a4bff6246cf57ed5b2067d4dd16502502c2c97b9c63257156beeaa39c \
|
||||
--hash=sha256:f7d42669c484dc65dac7b4833d7638b888603fdd127b7adc2e5c3b0eaa43ff9b
|
||||
pyqt6-webengine-qt6==6.3.0 \
|
||||
--hash=sha256:27bd08f6a0eb5508c444e95aa45b1574239faf03d6d45d5fcd6c2c8d2fd21c69 \
|
||||
--hash=sha256:5401e2a6fa6b13f271af946433f95af06e102613c90344aceb8424514a3f8784 \
|
||||
--hash=sha256:c075ed6c73f9d3e14e7ab5a9d1501590104dab7ecb3d57ad41b2d35760237ec5 \
|
||||
--hash=sha256:d9d3f1ad908e8f65088db65f27958904104275c6b32c77fec34f319d98eec9b2
|
||||
# via
|
||||
# -r requirements.in
|
||||
# pyqt6-webengine
|
||||
|
|
|
@ -495,7 +495,7 @@ def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiAp
|
|||
|
||||
if (
|
||||
getattr(sys, "frozen", False)
|
||||
and os.getenv("QT_QPA_PLATFORM") == "wayland"
|
||||
and (os.getenv("QT_QPA_PLATFORM") == "wayland" or os.getenv("WAYLAND_DISPLAY"))
|
||||
and not os.getenv("ANKI_WAYLAND")
|
||||
):
|
||||
# users need to opt in to wayland support, given the issues it has
|
||||
|
|
|
@ -225,6 +225,7 @@ def show(mw: aqt.AnkiQt) -> QDialog:
|
|||
"Sergio Quintero",
|
||||
"Nicholas Flint",
|
||||
"Daniel Vieira Memoria10X",
|
||||
"Luka Warren",
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -897,6 +897,7 @@ class Browser(QMainWindow):
|
|||
gui_hooks.operation_did_execute.append(self.on_operation_did_execute)
|
||||
gui_hooks.focus_did_change.append(self.on_focus_change)
|
||||
gui_hooks.flag_label_did_change.append(self._update_flag_labels)
|
||||
gui_hooks.collection_will_temporarily_close.append(self._on_temporary_close)
|
||||
|
||||
def teardownHooks(self) -> None:
|
||||
gui_hooks.undo_state_did_change.remove(self.on_undo_state_change)
|
||||
|
@ -905,6 +906,11 @@ class Browser(QMainWindow):
|
|||
gui_hooks.operation_did_execute.remove(self.on_operation_did_execute)
|
||||
gui_hooks.focus_did_change.remove(self.on_focus_change)
|
||||
gui_hooks.flag_label_did_change.remove(self._update_flag_labels)
|
||||
gui_hooks.collection_will_temporarily_close.remove(self._on_temporary_close)
|
||||
|
||||
def _on_temporary_close(self, col: Collection) -> None:
|
||||
# we could reload browser columns in the future; for now we just close
|
||||
self.close()
|
||||
|
||||
# Undo
|
||||
######################################################################
|
||||
|
|
|
@ -1331,6 +1331,10 @@ class EditorWebView(AnkiWebView):
|
|||
def flagAnkiText(self) -> None:
|
||||
# be ready to adjust when clipboard event fires
|
||||
self._markInternal = True
|
||||
# workaround broken QClipboard.dataChanged() on recent Qt6 versions
|
||||
# https://github.com/ankitects/anki/issues/1793
|
||||
if is_win and qtmajor == 6:
|
||||
self.editor.mw.progress.single_shot(300, self._flagAnkiText, True)
|
||||
|
||||
def _flagAnkiText(self) -> None:
|
||||
# add a comment in the clipboard html so we can tell text is copied
|
||||
|
@ -1342,6 +1346,10 @@ class EditorWebView(AnkiWebView):
|
|||
if not mime.hasHtml():
|
||||
return
|
||||
html = mime.html()
|
||||
if is_win and qtmajor == 6:
|
||||
# workaround Qt including CF_HTML header in clipboard
|
||||
# FIXME: remove after we switch to Qt 6.2.5/6.3.1+.
|
||||
html = re.sub(r"^Version:0.9(.|\r|\n)+?SourceURL:.*?\r\n", "", html)
|
||||
mime.setHtml(f"<!--anki-->{html}")
|
||||
aqt.mw.progress.timer(10, lambda: clip.setMimeData(mime), False, parent=self)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ from anki import hooks
|
|||
from anki.cards import CardId
|
||||
from anki.decks import DeckId
|
||||
from anki.exporting import Exporter, exporters
|
||||
from aqt import gui_hooks
|
||||
from aqt.errors import show_exception
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
|
@ -181,6 +182,8 @@ class ExportDialog(QDialog):
|
|||
else:
|
||||
self.on_export_finished()
|
||||
|
||||
if self.isVerbatim:
|
||||
gui_hooks.collection_will_temporarily_close(self.mw.col)
|
||||
self.mw.progress.start()
|
||||
hooks.media_files_did_export.append(exported_media)
|
||||
|
||||
|
|
|
@ -575,8 +575,9 @@ class AnkiQt(QMainWindow):
|
|||
self.col = Collection(cpath, backend=self.backend)
|
||||
self.setEnabled(True)
|
||||
|
||||
def reopen(self) -> None:
|
||||
self.col.reopen()
|
||||
def reopen(self, after_full_sync: bool = False) -> None:
|
||||
self.col.reopen(after_full_sync=after_full_sync)
|
||||
gui_hooks.collection_did_temporarily_close(self.col)
|
||||
|
||||
def unloadCollection(self, onsuccess: Callable) -> None:
|
||||
def after_media_sync() -> None:
|
||||
|
@ -629,11 +630,6 @@ class AnkiQt(QMainWindow):
|
|||
if corrupt:
|
||||
showWarning(tr.qt_misc_your_collection_file_appears_to_be())
|
||||
|
||||
def _close_for_full_download(self) -> None:
|
||||
"Backup and prepare collection to be overwritten."
|
||||
self.create_backup_now()
|
||||
self.col.close_for_full_sync()
|
||||
|
||||
def apply_collection_options(self) -> None:
|
||||
"Setup audio after collection loaded."
|
||||
aqt.sound.av_player.interrupt_current_audio = self.col.get_config_bool(
|
||||
|
|
|
@ -83,8 +83,15 @@ class NewDeckStats(QDialog):
|
|||
path = self._imagePath()
|
||||
if not path:
|
||||
return
|
||||
self.form.web.page().printToPdf(path)
|
||||
tooltip(tr.statistics_saved())
|
||||
# When scrolled down in dark mode, the top of the page in the
|
||||
# final PDF will have a white background, making the text and graphs
|
||||
# unreadable. A simple fix for now is to scroll to the top of the
|
||||
# page first.
|
||||
def after_scroll(arg: Any) -> None:
|
||||
self.form.web.page().printToPdf(path)
|
||||
tooltip(tr.statistics_saved())
|
||||
|
||||
self.form.web.evalWithCallback("window.scrollTo(0, 0);", after_scroll)
|
||||
|
||||
# legacy add-ons
|
||||
def changePeriod(self, n: Any) -> None:
|
||||
|
|
|
@ -14,6 +14,7 @@ from anki.errors import Interrupted, SyncError, SyncErrorKind
|
|||
from anki.lang import without_unicode_isolation
|
||||
from anki.sync import SyncOutput, SyncStatus
|
||||
from anki.utils import plat_desc
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import (
|
||||
QDialog,
|
||||
QDialogButtonBox,
|
||||
|
@ -181,13 +182,17 @@ def full_download(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
|||
qconnect(timer.timeout, on_timer)
|
||||
timer.start(150)
|
||||
|
||||
# hook needs to be called early, on the main thread
|
||||
gui_hooks.collection_will_temporarily_close(mw.col)
|
||||
|
||||
def download() -> None:
|
||||
mw._close_for_full_download()
|
||||
mw.create_backup_now()
|
||||
mw.col.close_for_full_sync()
|
||||
mw.col.full_download(mw.pm.sync_auth())
|
||||
|
||||
def on_future_done(fut: Future) -> None:
|
||||
timer.stop()
|
||||
mw.col.reopen(after_full_sync=True)
|
||||
mw.reopen(after_full_sync=True)
|
||||
mw.reset()
|
||||
try:
|
||||
fut.result()
|
||||
|
@ -204,6 +209,7 @@ def full_download(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
|||
|
||||
|
||||
def full_upload(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||
gui_hooks.collection_will_temporarily_close(mw.col)
|
||||
mw.col.close_for_full_sync()
|
||||
|
||||
def on_timer() -> None:
|
||||
|
@ -215,7 +221,7 @@ def full_upload(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
|||
|
||||
def on_future_done(fut: Future) -> None:
|
||||
timer.stop()
|
||||
mw.col.reopen(after_full_sync=True)
|
||||
mw.reopen(after_full_sync=True)
|
||||
mw.reset()
|
||||
try:
|
||||
fut.result()
|
||||
|
|
|
@ -499,7 +499,7 @@ html {{ {font} }}
|
|||
|
||||
from aqt import mw
|
||||
|
||||
head = mw.baseHTML() + csstxt + jstxt + web_content.head
|
||||
head = mw.baseHTML() + csstxt + web_content.head
|
||||
body_class = theme_manager.body_class()
|
||||
|
||||
if theme_manager.night_mode:
|
||||
|
@ -520,7 +520,9 @@ html {{ {font} }}
|
|||
{head}
|
||||
</head>
|
||||
|
||||
<body class="{body_class}">{web_content.body}</body>
|
||||
<body class="{body_class}">
|
||||
{jstxt}
|
||||
{web_content.body}</body>
|
||||
</html>"""
|
||||
# print(html)
|
||||
self.setHtml(html)
|
||||
|
|
|
@ -389,7 +389,7 @@ if is_win:
|
|||
build_windows_installers()
|
||||
|
||||
if is_mac:
|
||||
print("outputs are in .bazel/out/build/{std,alt}")
|
||||
print("outputs are in .bazel/out/build/app")
|
||||
print("dmg can be created with mac/finalize.py dmg")
|
||||
else:
|
||||
print("outputs are in .bazel/out/dist/")
|
||||
|
|
|
@ -56,8 +56,8 @@ impl Variant {
|
|||
|
||||
fn qt_repo(&self) -> &str {
|
||||
match self {
|
||||
Variant::StandardX86 => "pyqt6.2_mac_bundle_amd64",
|
||||
Variant::StandardArm => "pyqt6.2_mac_bundle_arm64",
|
||||
Variant::StandardX86 => "pyqt6.3_mac_bundle_amd64",
|
||||
Variant::StandardArm => "pyqt6.3_mac_bundle_arm64",
|
||||
Variant::AlternateX86 => "pyqt5.14_mac_bundle_amd64",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -688,6 +688,16 @@ gui_hooks.webview_did_inject_style_into_page.append(mytest)
|
|||
""",
|
||||
),
|
||||
Hook(name="profile_will_close", legacy_hook="unloadProfile"),
|
||||
Hook(
|
||||
name="collection_will_temporarily_close",
|
||||
args=["col: anki.collection.Collection"],
|
||||
doc="""Called before one-way syncs and colpkg imports/exports.""",
|
||||
),
|
||||
Hook(
|
||||
name="collection_did_temporarily_close",
|
||||
args=["col: anki.collection.Collection"],
|
||||
doc="""Called after one-way syncs and colpkg imports/exports.""",
|
||||
),
|
||||
Hook(
|
||||
name="collection_did_load",
|
||||
args=["col: anki.collection.Collection"],
|
||||
|
|
20
repos.bzl
20
repos.bzl
|
@ -115,12 +115,12 @@ def register_repos():
|
|||
################
|
||||
|
||||
core_i18n_repo = "anki-core-i18n"
|
||||
core_i18n_commit = "d6f01a26657ae78371813c8f54e415dc62032a90"
|
||||
core_i18n_zip_csum = "cd74a8f40a6080a144b6f80ad88bd37309ea4f17d4dd3995d154482eafc86f98"
|
||||
core_i18n_commit = "3fbbbd277adf6a307aad1f1389105740fb14bb52"
|
||||
core_i18n_zip_csum = "18db75ca57b5068c0c9cb926f19b451185cf04a086004a96fcf8f6e734f51b29"
|
||||
|
||||
qtftl_i18n_repo = "anki-desktop-ftl"
|
||||
qtftl_i18n_commit = "76751e5dcb8bce78cd54b052f1b444531934ca45"
|
||||
qtftl_i18n_zip_csum = "ad37c33d3d03a05b1094d6692300401a304da9ba48fb2dcf7ad01242ecc97997"
|
||||
qtftl_i18n_commit = "a6811a12eaf86ff02d5ce168ac65022f3e442993"
|
||||
qtftl_i18n_zip_csum = "03b62eb593e4929e502e6ee6d7fd81492d6fe9164aec50573e30028edbc9bf2e"
|
||||
|
||||
i18n_build_content = """
|
||||
filegroup(
|
||||
|
@ -226,22 +226,22 @@ exports_files(["l10n.toml"])
|
|||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "pyqt6.2_mac_bundle_amd64",
|
||||
name = "pyqt6.3_mac_bundle_amd64",
|
||||
build_file_content = " ",
|
||||
urls = [
|
||||
"https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-02-09/pyqt6.2-mac-amd64.tar.gz",
|
||||
"https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-04-20/pyqt6.3-mac-amd64.tar.gz",
|
||||
],
|
||||
sha256 = "c7bf899eee33fcb3b5848f5d3e5fc390012efc05c2308e4349b7bbd5939c85f0",
|
||||
sha256 = "949d403c26036cd13a4a0c86c9416f32ac6d2aa58c6946be93ab949ee6cf9b11",
|
||||
)
|
||||
|
||||
maybe(
|
||||
http_archive,
|
||||
name = "pyqt6.2_mac_bundle_arm64",
|
||||
name = "pyqt6.3_mac_bundle_arm64",
|
||||
build_file_content = " ",
|
||||
urls = [
|
||||
"https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-02-09/pyqt6.2-mac-arm64.tar.gz",
|
||||
"https://github.com/ankitects/anki-bundle-extras/releases/download/anki-2022-04-20/pyqt6.3-mac-arm64.tar.gz",
|
||||
],
|
||||
sha256 = "7a4b7d5bd65c83fd16cf7e56929183ef0d1d7bb67f9deea8f2482d7378e0ea02",
|
||||
sha256 = "c7df555623cdbd8f6981c15b4bfc58665b8e92d91fb43a7082bcfa1852ede10d",
|
||||
)
|
||||
|
||||
maybe(
|
||||
|
|
|
@ -22,11 +22,11 @@ bazel query @pyoxidizer//:*
|
|||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if [ $(uname -m) != "arm64" ]; then
|
||||
bazel query @audio_mac_amd64//:* > /dev/null
|
||||
bazel query @pyqt6.2_mac_bundle_amd64//:* > /dev/null
|
||||
bazel query @pyqt6.3_mac_bundle_amd64//:* > /dev/null
|
||||
bazel query @pyqt5.14_mac_bundle_amd64//:* > /dev/null
|
||||
else
|
||||
bazel query @audio_mac_arm64//:* > /dev/null
|
||||
bazel query @pyqt6.2_mac_bundle_arm64//:* > /dev/null
|
||||
bazel query @pyqt6.3_mac_bundle_arm64//:* > /dev/null
|
||||
bazel query @protobuf_wheel_mac_arm64//:* > /dev/null
|
||||
|
||||
fi
|
||||
|
|
|
@ -18,6 +18,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
</script>
|
||||
|
||||
<!--
|
||||
@component
|
||||
Allows "focusing" an EditingArea, even though it has no open editing inputs.
|
||||
-->
|
||||
<input bind:this={input} class="focus-trap" readonly tabindex="-1" on:focus />
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
@ -273,6 +273,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
setupLifecycleHooks(api);
|
||||
</script>
|
||||
|
||||
<!--
|
||||
@component
|
||||
Serves as a pre-slotted convenience component which combines all the common
|
||||
components and functionality for general note editing.
|
||||
|
||||
Functionality exclusive to specifc note-editing views (e.g. in the browser or
|
||||
the AddCards dialog) should be implemented in the user of this component.
|
||||
-->
|
||||
<div class="note-editor">
|
||||
<FieldsEditor>
|
||||
<EditorToolbar {size} {wrap} api={toolbar}>
|
||||
|
|
|
@ -15,7 +15,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import { context as editorToolbarContext } from "./EditorToolbar.svelte";
|
||||
import { boldIcon } from "./icons";
|
||||
|
||||
const surroundElement = document.createElement("strong");
|
||||
const surroundElement = document.createElement("b");
|
||||
|
||||
function matcher(element: HTMLElement | SVGElement, match: MatchType): void {
|
||||
if (element.tagName === "B" || element.tagName === "STRONG") {
|
||||
|
|
|
@ -15,7 +15,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
import { context as editorToolbarContext } from "./EditorToolbar.svelte";
|
||||
import { italicIcon } from "./icons";
|
||||
|
||||
const surroundElement = document.createElement("em");
|
||||
const surroundElement = document.createElement("i");
|
||||
|
||||
function matcher(element: HTMLElement | SVGElement, match: MatchType): void {
|
||||
if (element.tagName === "I" || element.tagName === "EM") {
|
||||
|
|
|
@ -16,11 +16,16 @@ function translateModifierToPlatform(modifier: Modifier): string {
|
|||
return platformModifiers[allModifiers.indexOf(modifier)];
|
||||
}
|
||||
|
||||
const GENERAL_KEY = 0;
|
||||
const NUMPAD_KEY = 3;
|
||||
export function checkIfModifierKey(event: KeyboardEvent): boolean {
|
||||
// At least the web view on Desktop Anki gives out the wrong values for
|
||||
// `event.location`, which is why we do it like this.
|
||||
let isInputKey = false;
|
||||
|
||||
export function checkIfInputKey(event: KeyboardEvent): boolean {
|
||||
return event.location === GENERAL_KEY || event.location === NUMPAD_KEY;
|
||||
for (const modifier of allModifiers) {
|
||||
isInputKey ||= event.code.startsWith(modifier);
|
||||
}
|
||||
|
||||
return isInputKey;
|
||||
}
|
||||
|
||||
export function keyboardEventIsPrintableKey(event: KeyboardEvent): boolean {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import { on } from "./events";
|
||||
import type { Modifier } from "./keys";
|
||||
import {
|
||||
checkIfInputKey,
|
||||
checkIfModifierKey,
|
||||
checkModifiers,
|
||||
keyToPlatformString,
|
||||
modifiersToPlatformString,
|
||||
|
@ -135,7 +135,7 @@ function innerShortcut(
|
|||
function handler(event: KeyboardEvent): void {
|
||||
if (nextCheck(event)) {
|
||||
innerShortcut(target, event, callback, ...restChecks);
|
||||
} else if (checkIfInputKey(event)) {
|
||||
} else if (!checkIfModifierKey(event)) {
|
||||
// Any non-modifier key will cancel the shortcut sequence
|
||||
remove();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" id="viewport" content="width=device-width" />
|
||||
<link href="{PAGE}.css" rel="stylesheet" />
|
||||
<script src="{PAGE}.js"></script>
|
||||
<script src="{PAGE}.js" defer></script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import { getRange, getSelection } from "../lib/cross-browser";
|
||||
import { on } from "../lib/events";
|
||||
import { keyboardEventIsPrintableKey } from "../lib/keys";
|
||||
import { HandlerList } from "./handler-list";
|
||||
|
||||
const nbsp = "\xa0";
|
||||
|
@ -62,13 +61,6 @@ function useInputHandler(): [InputHandlerAPI, SetupInputHandlerAction] {
|
|||
insertText.clear();
|
||||
}
|
||||
|
||||
function onKeydown(event: KeyboardEvent): void {
|
||||
/* using arrow keys should cancel */
|
||||
if (!keyboardEventIsPrintableKey(event)) {
|
||||
clearInsertText();
|
||||
}
|
||||
}
|
||||
|
||||
function onInput(this: HTMLElement, event: InputEvent): void {
|
||||
// prevent unwanted <div> from being left behind when clearing field contents
|
||||
if (
|
||||
|
@ -87,7 +79,7 @@ function useInputHandler(): [InputHandlerAPI, SetupInputHandlerAction] {
|
|||
|
||||
const blurOff = on(element, "blur", clearInsertText);
|
||||
const pointerDownOff = on(element, "pointerdown", clearInsertText);
|
||||
const keyDownOff = on(element, "keydown", onKeydown);
|
||||
const selectionChangeOff = on(document, "selectionchange", clearInsertText);
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
|
@ -95,7 +87,7 @@ function useInputHandler(): [InputHandlerAPI, SetupInputHandlerAction] {
|
|||
inputOff();
|
||||
blurOff();
|
||||
pointerDownOff();
|
||||
keyDownOff();
|
||||
selectionChangeOff();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue