mirror of
https://github.com/ankitects/anki.git
synced 2026-01-13 22:13:58 -05:00
Merge branch 'main' into Feat/90%-dr-message
This commit is contained in:
commit
3e1d95b24c
29 changed files with 223 additions and 53 deletions
2
.cursor/rules/building.md
Normal file
2
.cursor/rules/building.md
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
- To build and check the project, use ./check in the root folder (or check.bat on Windows)
|
||||
- This will format files, then run lints and unit tests.
|
||||
7
.cursor/rules/i18n.md
Normal file
7
.cursor/rules/i18n.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
- We use the fluent system+code generation for translation.
|
||||
- New strings should be added to rslib/core/. Ask for the appropriate file if you're not sure.
|
||||
- Assuming a string addons-you-have-count has been added to addons.ftl, that string is accessible in our different languages as follows:
|
||||
- Python: from aqt.utils import tr; msg = tr.addons_you_have_count(count=3)
|
||||
- TypeScript: import * as tr from "@generated/ftl"; tr.addonsYouHaveCount({count: 3})
|
||||
- Rust: collection.tr.addons_you_have_count(3)
|
||||
- In Qt .ui files, strings that are marked as translatable will automatically use the registered ftl strings. So a QLabel with a title 'addons_you_have_count' that is marked as translatable will automatically use the translation defined in our addons.ftl file.
|
||||
|
|
@ -226,6 +226,8 @@ Jonathan Schoreels <https://github.com/JSchoreels>
|
|||
JL710
|
||||
Matt Brubeck <mbrubeck@limpet.net>
|
||||
Yaoliang Chen <yaoliang.ch@gmail.com>
|
||||
KolbyML <https://github.com/KolbyML>
|
||||
Adnane Taghi <dev@soleuniverse.me>
|
||||
|
||||
********************
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM rust:1.83.0-alpine3.20 AS builder
|
||||
FROM rust:1.85.0-alpine3.20 AS builder
|
||||
|
||||
ARG ANKI_VERSION
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM rust:1.83.0 AS builder
|
||||
FROM rust:1.85.0 AS builder
|
||||
|
||||
ARG ANKI_VERSION
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 376ae99eb47eae3c5e6298150162715423bc2e4e
|
||||
Subproject commit d2e9201d62b906b029570931e9567fe8cf1889b6
|
||||
|
|
@ -15,6 +15,7 @@ importing-colon = Colon
|
|||
importing-comma = Comma
|
||||
importing-empty-first-field = Empty first field: { $val }
|
||||
importing-field-separator = Field separator
|
||||
importing-field-separator-guessed = Field separator (guessed)
|
||||
importing-field-mapping = Field mapping
|
||||
importing-field-of-file-is = Field <b>{ $val }</b> of file is:
|
||||
importing-fields-separated-by = Fields separated by: { $val }
|
||||
|
|
@ -217,6 +218,9 @@ importing-field-separator-help =
|
|||
Please note that if this character appears in any field itself, the field has to be
|
||||
quoted accordingly to the CSV standard. Spreadsheet programs like LibreOffice will
|
||||
do this automatically.
|
||||
|
||||
It cannot be changed if the text file forces use of a specific separator via a file header.
|
||||
If a file header is not present, Anki will try to guess what the separator is.
|
||||
importing-allow-html-in-fields-help =
|
||||
Enable this if the file contains HTML formatting. E.g. if the file contains the string
|
||||
'<br>', it will appear as a line break on your card. On the other hand, with this
|
||||
|
|
|
|||
|
|
@ -83,6 +83,15 @@ preferences-ankiweb-intro = AnkiWeb is a free service that lets you keep your fl
|
|||
preferences-ankihub-intro = AnkiHub provides collaborative deck editing and additional study tools. A paid subscription is required to access certain features.
|
||||
preferences-third-party-description = Third-party services are unaffiliated with and not endorsed by Anki. Use of these services may require payment.
|
||||
|
||||
## URL scheme related
|
||||
preferences-url-schemes = URL Schemes
|
||||
preferences-url-scheme-prompt = Allowed { preferences-url-schemes } (space-separated):
|
||||
preferences-url-scheme-warning = Blocked attempt to open `{ $link }`, which may be a security issue.
|
||||
|
||||
If you trust the deck author and wish to proceed, you can add `{ $scheme }` to your allowed { preferences-url-schemes }.
|
||||
preferences-url-scheme-allow-once = Allow Once
|
||||
preferences-url-scheme-always-allow = Always Allow
|
||||
|
||||
## NO NEED TO TRANSLATE. This text is no longer used by Anki, and will be removed in the future.
|
||||
|
||||
preferences-basic = Basic
|
||||
|
|
|
|||
|
|
@ -229,6 +229,7 @@ statistics-stability-day-single =
|
|||
# hour range, eg "From 14:00-15:00"
|
||||
statistics-hours-range = From { $hourStart }:00~{ $hourEnd }:00
|
||||
statistics-hours-correct = { $correct }/{ $total } correct ({ $percent }%)
|
||||
statistics-hours-correct-info = → (not 'Again')
|
||||
# the emoji depicts the graph displaying this number
|
||||
statistics-hours-reviews = 📊 { $reviews } reviews
|
||||
# the emoji depicts the graph displaying this number
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ sync-account-required =
|
|||
sync-sanity-check-failed = Please use the Check Database function, then sync again. If problems persist, please force a one-way sync in the preferences screen.
|
||||
sync-clock-off = Unable to sync - your clock is not set to the correct time.
|
||||
sync-upload-too-large =
|
||||
Your collection file is too large to send to AnkiWeb. You can reduce its
|
||||
size by removing any unwanted decks (optionally exporting them first), and
|
||||
then using Check Database to shrink the file size down. ({ $details })
|
||||
Your collection file is too large to send to AnkiWeb. You can reduce its size by removing any unwanted decks (optionally exporting them first), and then using Check Database to shrink the file size down.
|
||||
|
||||
{ $details } (uncompressed)
|
||||
sync-sign-in = Sign in
|
||||
sync-ankihub-dialog-heading = AnkiHub Login
|
||||
sync-ankihub-username-label = Username or Email:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 393bacec35703f91520e4d2feec37ed6953114f4
|
||||
Subproject commit 5b855702dfe191e06cc3fbef4b684acc094500ec
|
||||
|
|
@ -221,6 +221,7 @@ def show(mw: aqt.AnkiQt) -> QDialog:
|
|||
"Yuki",
|
||||
"🦙 (siid)",
|
||||
"Mukunda Madhav Dey",
|
||||
"Adnane Taghi",
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1244,11 +1244,13 @@ class Browser(QMainWindow):
|
|||
self._line_edit().selectAll()
|
||||
|
||||
def onNote(self) -> None:
|
||||
assert self.editor is not None
|
||||
assert self.editor.web is not None
|
||||
def cb():
|
||||
assert self.editor is not None and self.editor.web is not None
|
||||
self.editor.web.setFocus()
|
||||
self.editor.loadNote(focusTo=0)
|
||||
|
||||
self.editor.web.setFocus()
|
||||
self.editor.loadNote(focusTo=0)
|
||||
assert self.editor is not None
|
||||
self.editor.call_after_note_saved(cb)
|
||||
|
||||
def onCardList(self) -> None:
|
||||
self.form.tableView.setFocus()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||
<enum>QComboBox::SizeAdjustPolicy::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -260,7 +260,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -451,6 +451,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="url_schemes">
|
||||
<property name="text">
|
||||
<string>preferences_url_schemes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -466,7 +473,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -518,10 +525,10 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -614,10 +621,10 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -739,7 +746,7 @@
|
|||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -827,7 +834,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -840,7 +847,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -918,10 +925,10 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -953,7 +960,7 @@
|
|||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1020,7 +1027,7 @@
|
|||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1035,10 +1042,10 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1080,7 +1087,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1128,10 +1135,10 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
<enum>QSizePolicy::Policy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1207,7 +1214,7 @@
|
|||
<item>
|
||||
<spacer name="verticalspacer_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1227,17 +1234,17 @@
|
|||
<string>preferences_some_settings_will_take_effect_after</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
|
||||
<set>QDialogButtonBox::StandardButton::Close|QDialogButtonBox::StandardButton::Help</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -1266,6 +1273,7 @@
|
|||
<tabstop>showEstimates</tabstop>
|
||||
<tabstop>spacebar_rates_card</tabstop>
|
||||
<tabstop>render_latex</tabstop>
|
||||
<tabstop>url_schemes</tabstop>
|
||||
<tabstop>pastePNG</tabstop>
|
||||
<tabstop>paste_strips_formatting</tabstop>
|
||||
<tabstop>useCurrent</tabstop>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ from __future__ import annotations
|
|||
import inspect
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import select
|
||||
import socket
|
||||
import subprocess
|
||||
|
|
@ -40,7 +41,7 @@ import time
|
|||
from queue import Empty, Full, Queue
|
||||
from shutil import which
|
||||
|
||||
from anki.utils import is_win
|
||||
from anki.utils import is_mac, is_win
|
||||
|
||||
|
||||
class MPVError(Exception):
|
||||
|
|
@ -88,11 +89,13 @@ class MPVBase:
|
|||
"--keep-open=no",
|
||||
"--autoload-files=no",
|
||||
"--gapless-audio=no",
|
||||
"--no-ytdl",
|
||||
]
|
||||
|
||||
if is_win:
|
||||
default_argv += ["--af-add=lavfi=[apad=pad_dur=0.150]"]
|
||||
if not is_mac or platform.machine() != "arm64":
|
||||
# our arm64 mpv build doesn't support this option (compiled out)
|
||||
default_argv += ["--no-ytdl"]
|
||||
|
||||
def __init__(self, window_id=None, debug=False):
|
||||
self.window_id = window_id
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ from aqt.profiles import VideoDriver
|
|||
from aqt.qt import *
|
||||
from aqt.sync import sync_login
|
||||
from aqt.theme import Theme
|
||||
from aqt.url_schemes import show_url_schemes_dialog
|
||||
from aqt.utils import (
|
||||
HelpPage,
|
||||
add_close_shortcut,
|
||||
add_ellipsis_to_action_label,
|
||||
askUser,
|
||||
disable_help_button,
|
||||
is_win,
|
||||
|
|
@ -152,6 +154,9 @@ class Preferences(QDialog):
|
|||
form.monthly_backups.setValue(self.prefs.backups.monthly)
|
||||
form.minutes_between_backups.setValue(self.prefs.backups.minimum_interval_mins)
|
||||
|
||||
add_ellipsis_to_action_label(self.form.url_schemes)
|
||||
qconnect(self.form.url_schemes.clicked, show_url_schemes_dialog)
|
||||
|
||||
def update_collection(self, on_done: Callable[[], None]) -> None:
|
||||
form = self.form
|
||||
|
||||
|
|
|
|||
|
|
@ -744,3 +744,17 @@ create table if not exists profiles
|
|||
|
||||
def ankihub_username(self) -> str | None:
|
||||
return self.profile.get("thirdPartyAnkiHubUsername")
|
||||
|
||||
def allowed_url_schemes(self) -> list[str]:
|
||||
return self.profile.get("allowedUrlSchemes", [])
|
||||
|
||||
def set_allowed_url_schemes(self, schemes: list[str]) -> None:
|
||||
self.profile["allowedUrlSchemes"] = schemes
|
||||
|
||||
def always_allow_scheme(self, scheme: str) -> None:
|
||||
schemes = self.allowed_url_schemes()
|
||||
|
||||
if scheme not in schemes:
|
||||
schemes.append(scheme)
|
||||
|
||||
self.set_allowed_url_schemes(schemes)
|
||||
|
|
|
|||
|
|
@ -551,9 +551,11 @@ class Reviewer:
|
|||
def after_answer(changes: OpChanges) -> None:
|
||||
if gui_hooks.reviewer_did_answer_card.count() > 0:
|
||||
self.card.load()
|
||||
# v3 scheduler doesn't report this
|
||||
suspended = self.card is not None and self.card.queue < 0
|
||||
self._after_answering(ease)
|
||||
if sched.state_is_leech(answer.new_state):
|
||||
self.onLeech()
|
||||
self.onLeech(suspended)
|
||||
|
||||
self.state = "transition"
|
||||
answer_card(parent=self.mw, answer=answer).success(
|
||||
|
|
@ -949,11 +951,10 @@ timerStopped = false;
|
|||
# Leeches
|
||||
##########################################################################
|
||||
|
||||
def onLeech(self, card: Card | None = None) -> None:
|
||||
def onLeech(self, suspended: bool = False) -> None:
|
||||
# for now
|
||||
s = tr.studying_card_was_a_leech()
|
||||
# v3 scheduler doesn't report this
|
||||
if card and card.queue < 0:
|
||||
if suspended:
|
||||
s += f" {tr.studying_it_has_been_suspended()}"
|
||||
tooltip(s)
|
||||
|
||||
|
|
|
|||
71
qt/aqt/url_schemes.py
Normal file
71
qt/aqt/url_schemes.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from markdown import markdown
|
||||
|
||||
from aqt.qt import QMessageBox, Qt, QUrl
|
||||
from aqt.utils import MessageBox, getText, openLink, tr
|
||||
|
||||
|
||||
def show_url_schemes_dialog() -> None:
|
||||
from aqt import mw
|
||||
|
||||
default = " ".join(mw.pm.allowed_url_schemes())
|
||||
schemes, ok = getText(
|
||||
prompt=tr.preferences_url_scheme_prompt(),
|
||||
title=tr.preferences_url_schemes(),
|
||||
default=default,
|
||||
)
|
||||
if ok:
|
||||
mw.pm.set_allowed_url_schemes(schemes.split(" "))
|
||||
mw.pm.save()
|
||||
|
||||
|
||||
def is_supported_scheme(url: QUrl) -> bool:
|
||||
from aqt import mw
|
||||
|
||||
scheme = url.scheme().lower()
|
||||
allowed_schemes = mw.pm.allowed_url_schemes()
|
||||
|
||||
return scheme in allowed_schemes or scheme in ["http", "https"]
|
||||
|
||||
|
||||
def always_allow_scheme(url: QUrl) -> None:
|
||||
from aqt import mw
|
||||
|
||||
scheme = url.scheme().lower()
|
||||
mw.pm.always_allow_scheme(scheme)
|
||||
|
||||
|
||||
def open_url_if_supported_scheme(url: QUrl) -> None:
|
||||
from aqt import mw
|
||||
|
||||
if is_supported_scheme(url):
|
||||
openLink(url)
|
||||
else:
|
||||
|
||||
def on_button(idx: int) -> None:
|
||||
if idx == 0:
|
||||
openLink(url)
|
||||
elif idx == 1:
|
||||
always_allow_scheme(url)
|
||||
openLink(url)
|
||||
|
||||
msg = markdown(
|
||||
tr.preferences_url_scheme_warning(link=url.toString(), scheme=url.scheme())
|
||||
)
|
||||
MessageBox(
|
||||
msg,
|
||||
buttons=[
|
||||
tr.preferences_url_scheme_allow_once(),
|
||||
tr.preferences_url_scheme_always_allow(),
|
||||
(tr.actions_cancel(), QMessageBox.ButtonRole.RejectRole),
|
||||
],
|
||||
parent=mw,
|
||||
callback=on_button,
|
||||
textFormat=Qt.TextFormat.RichText,
|
||||
default_button=2,
|
||||
icon=QMessageBox.Icon.Warning,
|
||||
)
|
||||
|
|
@ -1188,7 +1188,7 @@ def disallow_full_screen() -> bool:
|
|||
)
|
||||
|
||||
|
||||
def add_ellipsis_to_action_label(*actions: QAction) -> None:
|
||||
def add_ellipsis_to_action_label(*actions: QAction | QPushButton) -> None:
|
||||
"""Pass actions to add '...' to their labels, indicating that more input is
|
||||
required before they can be performed.
|
||||
|
||||
|
|
|
|||
|
|
@ -266,7 +266,9 @@ class AnkiWebPage(QWebEnginePage):
|
|||
print("onclick handler needs to return false")
|
||||
return False
|
||||
# load all other links in browser
|
||||
openLink(url)
|
||||
from aqt.url_schemes import open_url_if_supported_scheme
|
||||
|
||||
open_url_if_supported_scheme(url)
|
||||
return False
|
||||
|
||||
def _onCmd(self, str: str) -> Any:
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ impl SqliteStorage {
|
|||
self.db
|
||||
.prepare_cached(concat!(
|
||||
include_str!("get.sql"),
|
||||
" where ease between 1 and 4",
|
||||
" where (ease between 1 and 4) or (ease = 0 and factor = 0)",
|
||||
" order by cid, id"
|
||||
))?
|
||||
.query_and_then([], row_to_revlog_entry)?
|
||||
|
|
|
|||
|
|
@ -119,9 +119,13 @@ pub enum UploadResponse {
|
|||
}
|
||||
|
||||
pub fn check_upload_limit(size: usize, limit: usize) -> Result<()> {
|
||||
let size_of_one_mb: f64 = 1024.0 * 1024.0;
|
||||
let collection_size_in_mb: f64 = size as f64 / size_of_one_mb;
|
||||
let limit_size_in_mb: f64 = limit as f64 / size_of_one_mb;
|
||||
|
||||
if size >= limit {
|
||||
Err(AnkiError::sync_error(
|
||||
format!("{size} > {limit}"),
|
||||
format!("{collection_size_in_mb:.2} MB > {limit_size_in_mb:.2} MB"),
|
||||
SyncErrorKind::UploadTooLarge,
|
||||
))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ input[type="radio"],
|
|||
input[type="checkbox"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
textarea,
|
||||
input[type="date"],
|
||||
input[type="text"] {
|
||||
border-radius: prop(border-radius);
|
||||
outline: none;
|
||||
|
|
|
|||
|
|
@ -29,10 +29,5 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
width: 100%;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: var(--canvas-inset);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 1px 0.5em;
|
||||
outline: none !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,25 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { tick } from "svelte";
|
||||
|
||||
export let value: number[];
|
||||
export let defaults: number[];
|
||||
|
||||
let stringValue: string;
|
||||
$: stringValue = render(value);
|
||||
let taRef: HTMLTextAreaElement;
|
||||
|
||||
function updateHeight() {
|
||||
if (taRef) {
|
||||
taRef.style.height = "auto";
|
||||
taRef.style.height = `${taRef.scrollHeight}px`;
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
stringValue = render(value);
|
||||
tick().then(updateHeight);
|
||||
}
|
||||
|
||||
function render(params: number[]): string {
|
||||
return params.map((v) => v.toFixed(4)).join(", ");
|
||||
|
|
@ -22,7 +36,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
}
|
||||
</script>
|
||||
|
||||
<svelte:window onresize={updateHeight} />
|
||||
|
||||
<textarea
|
||||
bind:this={taRef}
|
||||
value={stringValue}
|
||||
on:blur={update}
|
||||
class="w-100"
|
||||
|
|
|
|||
|
|
@ -222,8 +222,23 @@ export function renderButtons(
|
|||
const button = tr.statisticsAnswerButtonsButtonNumber();
|
||||
const timesPressed = tr.statisticsAnswerButtonsButtonPressed();
|
||||
const correctStr = tr.statisticsHoursCorrect(totalCorrect(d.group));
|
||||
const correctStrInfo = tr.statisticsHoursCorrectInfo();
|
||||
const pressedStr = `${timesPressed}: ${totalPressedStr(d)}`;
|
||||
return `${button}: ${d.buttonNum}<br>${pressedStr}<br>${correctStr}`;
|
||||
|
||||
let buttonText: string;
|
||||
if (d.buttonNum === 1) {
|
||||
buttonText = tr.studyingAgain();
|
||||
} else if (d.buttonNum === 2) {
|
||||
buttonText = tr.studyingHard();
|
||||
} else if (d.buttonNum === 3) {
|
||||
buttonText = tr.studyingGood();
|
||||
} else if (d.buttonNum === 4) {
|
||||
buttonText = tr.studyingEasy();
|
||||
} else {
|
||||
buttonText = "";
|
||||
}
|
||||
|
||||
return `${button}: ${d.buttonNum} (${buttonText})<br>${pressedStr}<br>${correctStr} ${correctStrInfo}`;
|
||||
}
|
||||
|
||||
svg.select("g.hover-columns")
|
||||
|
|
|
|||
|
|
@ -263,6 +263,8 @@ export function enableUniformScaling(canvas: fabric.Canvas, obj: fabric.Object):
|
|||
|
||||
export function addBorder(obj: fabric.Object): void {
|
||||
obj.stroke = BORDER_COLOR;
|
||||
obj.strokeWidth = 1;
|
||||
obj.strokeUniform = true;
|
||||
}
|
||||
|
||||
export const redraw = (canvas: fabric.Canvas): void => {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
<SettingTitle
|
||||
on:click={() => openHelpModal(Object.keys(settings).indexOf("delimiter"))}
|
||||
>
|
||||
{settings.delimiter.title}
|
||||
{$metadata.forceDelimiter
|
||||
? settings.delimiter.title
|
||||
: tr.importingFieldSeparatorGuessed()}
|
||||
</SettingTitle>
|
||||
</EnumSelectorRow>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue