Commit Graph

9111 Commits

Author SHA1 Message Date
Damien Elmes
972c9da12e don't cache js files
https://forums.ankiweb.net/t/anki-2-1-50-beta/15608/101
2021-12-28 13:50:11 +10:00
Damien Elmes
c3b5902da0 add color-scheme: dark in night mode
https://forums.ankiweb.net/t/anki-2-1-50-beta/15608/97
2021-12-28 13:35:19 +10:00
Damien Elmes
4c49337700 tweaks to development.md 2021-12-24 14:12:36 +10:00
Damien Elmes
693672d7a3 remove extraneous to_vec() call 2021-12-24 13:09:19 +10:00
Damien Elmes
b7907741ec fix SQL formatting issue 2021-12-24 12:42:42 +10:00
Damien Elmes
8ed1fa7e99 fix interday learning cards not being buried
https://forums.ankiweb.net/t/2-1-49-mac-automatic-unbury-still-not-working/14799/43
2021-12-24 12:25:16 +10:00
Hikaru Y
df0ad4be4b
Prevent unwanted <div> from being left behind when clearing field (#1565)
* Prevent unwanted <div> from being left behind when clearing field

* Use event.currentTarget instead of 'this'

* Check if event.data is empty for better performance

* Change order of conditions for better performance
2021-12-24 09:12:04 +10:00
Abdo
21fde1b59e
Allow customization of add-on config help path (#1564)
* Allow customization of add-on config help path

This is useful for loading translated versions of the help file if available

* dir -> module

* Allow setting a callback instead to produce config docs
2021-12-22 12:51:18 +10:00
Hikaru Y
12ccdee25b
Fix some issues with closing previewer (#1563)
* Fix media playback not terminating when previewer is closed

https://forums.ankiweb.net/t/anki-2-1-50-beta/15608/78

* Fix _on_preview_closed being called twice unnecessarily

The function was being called twice when the preview button is clicked
while the previewer is open.

* Fix console error caused by leftover code

The following error was shown in the console when closing previewer:
`Uncaught TypeError: Cannot read property 'classList' of null`

* Toggle state of preview button via 'active' prop
2021-12-20 20:23:50 +10:00
Abdo
1120939648
Support drag & drop in main window to import files (#1562)
* Support drag & drop in main window to import files

* Pass drag & drop events to super when not in deck browser

Seems this is required so that JS in the reviewer receives dragover

* Remove unused allowDrops
2021-12-20 20:22:21 +10:00
Damien Elmes
0c7a9be359 fix Windows build with latest rules_rust
the extra .lib file that is being output for .dll files was tripping
up the copy; we need to select only the .dll file
2021-12-20 18:59:55 +10:00
Damien Elmes
4f64494573 fix linkchecker invocation in CI 2021-12-20 17:41:13 +10:00
Damien Elmes
a3b09b0c81 update rules_rust 2021-12-20 17:28:52 +10:00
Damien Elmes
4d431fb7af move linkchecker into separate crate
The feature-based approach didn't work with cargo-raze, leading
to ./update.py in cargo/ breaking.
2021-12-20 17:27:43 +10:00
Damien Elmes
cf4c555169 update translations 2021-12-20 12:57:35 +10:00
Damien Elmes
e175c068af fix inverted SchedBuried and UserBuried in cards.ts
This wasn't causing any problems, as we only ever checked for both at
once.
2021-12-20 12:57:35 +10:00
RumovZ
3e0c9dc866
New TTS/AV tag handling (#1559)
* Add new `card_rendering` mod

Parses a text with av/tts tags and strips or extracts tags.

* Replace old `extract_av_tags` and `strip_av_tags`

... with new `card_rendering` mod

* ressource -> resource

* Add AV prettifier for use in browser table

* Accept String in av tag routines

... and avoid redundant writes if no changes need to be made.

* add benchmarking with criterion; make links test optional (dae)

cargo install cargo-criterion, then run ./bench.sh

* performance comparison: creating HashMap up front (dae)

the previous solution:

anki_tag_parse          time:   [1.8401 us 1.8437 us 1.8476 us]

this solution:

anki_tag_parse          time:   [2.2420 us 2.2447 us 2.2477 us]
                        change: [+21.477% +21.770% +22.066%] (p = 0.00 < 0.05)
                        Performance has regressed.

* Revert "performance comparison: creating HashMap up front" (dae)

This reverts commit f19126a2f15b729b825825a49283f63ab13474d0.

* add missing header

* Write error message if tts lang is missing

* `Tag` -> `Directive`
2021-12-17 19:04:42 +10:00
RumovZ
2221d0a520
Make Hard use current step's interval if it's not the first one (#1561)
* Make hard repeat the current step's interval in v3

Unless for the first step to avoid identical interval with Again.

* Make Hard repeat the current step's interval in v2

* Adjust test to new Hard behaviour
2021-12-16 22:02:13 +10:00
Abdo
f213c3ee8d
Rework field copying when switching notetypes (#1556)
- Copy identical fields as before, but maintain a list of copied fields
  and only add non-empty ones to it.
- Instead of setting remaining fields by their indices, assign remaining non-empty old fields to new fields sequentially

This results in less fields being lost when switching notetypes.
2021-12-16 21:49:42 +10:00
Hikaru Y
e92d7f13e3
Preload external css files to prevent flash of unstyled content (#1558)
* Preload external css files to prevent flash of unstyled content

This is an implementation of the approach mentioned in the commit
message of 46b85d5.

* Tweak max_age value for css files

Ensure that css preloading works even on a slow PC.
2021-12-16 21:47:10 +10:00
RumovZ
80ed94ed08
Cap steps (#1548)
* Fix steps being mistaken for seconds

* Cap steps at `u32::max` seconds

* Fix overflow of steps in Rust

* Prevent overflow of `IntervalKind`

* Prevent overflow in `revlod/mod.rs`

Also replace some `as` with `from` and `try_from` as is recommended to
highlight potential issues.

* Ensure v2 doesn't store overflowing revlog ivls

* Lower steps cap in deck options

Whereas large card intervals are converted to days, revlog intervals use
i32s to store large numbers of seconds.

* Format
2021-12-15 18:46:26 +10:00
Damien Elmes
0d51b4db1f ensure multiple answer buttons don't get accepted when mashed in v3
We want to preserve the backend checks, because they may also detect
bugs. So we do the debouncing on the frontend instead, transitioning
into a temporary state until the background op completes.

https://forums.ankiweb.net/t/anki-2-1-50-beta/15608/74
2021-12-14 15:48:02 +10:00
Damien Elmes
46b85d508a fix flicker when external CSS used
When we updated to flask 2.0, the default caching time changed to
0. When setting the HTML of a new card side in the DOM, the browser
first removes the existing content (including styling), then sends a
HTTP request to us to check whether the file has changed or not. By the
time the answer has arrived, the browser has repainted without the
styling, and thus we get a flicker.

A side-effect of reverting to flask 1.x behaviour is that external changes
to media files will not be reflected in Anki for an hour, unless Anki
is restarted, or the caches are cleared manually with an add-on. An
alternative approach would be to pre-fetch the css files like we do with
images, but there are other things like fonts to think about as well.

Closes #1455
2021-12-14 12:06:16 +10:00
Damien Elmes
8d90b6b061 run buildifier/buildozer to tidy up BUILD files 2021-12-14 09:18:24 +10:00
Damien Elmes
0c821859c5 check for missed dbg!() statements
This works in our main code, but doesn't catch dbg!() statements in
our build scripts.
2021-12-14 09:05:14 +10:00
Abdo
eb839f0ba2
Parse Markdown inside HTML tags in config.md (#1552) 2021-12-13 14:18:12 +10:00
RumovZ
5b2a389454
Use save utils in main window (#1549)
Ensure additional logic like the fullscreen workaround is considered.
2021-12-13 14:10:24 +10:00
Matthias Metelka
cc5ba4ed84
Reimplement "Show Duplicates" button in editor (#1550)
* Add "Show duplicates" to LabelContainer

* Avoid bubbling down the duplicate logic into EditorField

* Move duplicate link into its own slot

to center it between name/description and field-state.

* Revert "Move duplicate link into its own slot"

This reverts commit 3a4511042da7083a52d67b58550b13d873dcbea5.

* Justify dupes within FieldState

to achieve the same result as before while avoiding additional logic within EditorField.

Co-Authored-By: Henrik Giesel <hengiesel@gmail.com>
2021-12-13 14:06:12 +10:00
Henrik Giesel
4966f3cc44
Add back wrap function (#1551)
* Remove surround from RichText and PlainText

* Export wrap
2021-12-13 14:00:35 +10:00
Damien Elmes
b714974464 tweak mac CI state folder 2021-12-13 13:12:59 +10:00
Damien Elmes
afff4fc437 order by template after note id in filtered decks
This brings the behaviour a bit closer to the default ordering of new
cards when they are reset, and is better than an undefined template
order. But it's a stopgap solution, and in the long run, filtered decks
need a bit of a rethink with the improved ordering than v3 has brought.
2021-12-10 18:53:50 +10:00
RumovZ
e336f5a239
Add shortcuts for list and indentation (#1546) 2021-12-10 17:54:31 +10:00
RumovZ
65f6728454
Fix Alt-Gr and add shortcut to create copy again (#1544)
* Set QT_QPA_PLATFORM for Win on recent Qt versions

Erroneously dropped for Qt 5.15.1+.

* Enable original shortcut to create copy

* minor tweaks to comment to make it clearer (dae)
2021-12-10 17:52:08 +10:00
Damien Elmes
1fb026cce9 remove superfluous label in Windows CI 2021-12-10 10:50:57 +10:00
Damien Elmes
1b60f07e51 fix incorrect folder name in pylib mypy invocation 2021-12-10 10:50:57 +10:00
Damien Elmes
366d5ca9e3 experiment with mypy cache
Speeds things up in the small change case; remains to be seen whether
this will be robust or will introduce caching issues or other problems.
2021-12-10 10:46:38 +10:00
Damien Elmes
c51b1c7180 skip superfluous build step in CI; it should be moderately faster 2021-12-09 18:55:19 +10:00
Damien Elmes
db804d9544 macOS audio tools no longer reside in audio/ subfolder
+ fix error message broken by automated .tr() syntax change
2021-12-09 17:33:46 +10:00
Damien Elmes
1b72cd65ea check for syncserver early in startup, so Qt doesn't get imported 2021-12-09 16:06:28 +10:00
Damien Elmes
e11cad9bf7 don't bundle Qt into ARM Linux package
While it worked, it was not portable to other distros, so we'll rely
on the user to provide their own (Py)Qt.
2021-12-09 15:56:00 +10:00
Arthur Milchior
08ad9f33b9
The importer list have a Hook (#1543)
* The importer list have a Hook

Previously, add-on 175027074 simply edited the list once. It became impossible
since the list became a function. Hence I need a filter to add the list here.

@kelciour (nice to meet you by the way), you may be interested by it too (at
least if I believe efb1ce46d4 )

I would have preferred to use `anki.importing.base.Importer` instead of
`Any`. However, this leads to
> Name "anki.importing.base.Importer" is not defined  [name-defined]
when I run test.

Helps to solve this would be welcomed

* mention the hook may not last too long (dae)
2021-12-09 11:20:29 +10:00
Damien Elmes
7ef40cb850 disable 'create copy' shortcut for now
In preparation for a new beta; we can add a new shortcut once one is
decided on https://github.com/ankitects/anki/pull/1541
2021-12-09 10:24:21 +10:00
Arthur Milchior
69469c6428
Add py3.9 to hooks (#1542)
* Add py3.9 to hooks

This follows examples from efb1ce46d4 I assume the
hooks were missed because those were not considered types but strings.

I did not even try to run pyupgrade and did the change manually, then used bazel format

* remove wildcard import in find.py, and change Any to object (dae)
2021-12-09 09:11:22 +10:00
TheFeelTrain
8306bc1e25
Add .aac files to editor (#1540)
.aac files work as expected, but Anki doesn't pick them up by default.
2021-12-08 21:25:47 +10:00
Damien Elmes
52f17c12e0 Partially revert "Fix issue 1362 and add a default favicon.ico (#1369)"
Kept the favicon, but have reverted the rest, as it unfortunately did
not seem to prevent the issue from occurring.

Original discussion: https://github.com/ankitects/anki/pull/1369

This reverts commit 6d0f7e7f05.
2021-12-08 21:20:39 +10:00
Damien Elmes
db5117ce1a fix webviews sometimes failing to load, by enabling cache
Fixes #983

This has been a long-standing issue that was infrequent enough on
developer machines that we weren't able to get to the bottom of it before
now. As luck would have it, the new ARM build had just the right timing
for this to occur every few invocations, and I was able to narrow it down
to the call that turns off the cache.

We don't really want the cache, so this is not a great solution. But I
ran into trouble when trying to figure out a better solution:

- Calling setHttpCacheType() earlier (eg immediately after creating the
page) fails.
- It even fails if you attempt to change the setting in the shared
default profile before any webviews are loaded:

```
    def setupMainWindow(self) -> None:
        QWebEngineProfile.defaultProfile().setHttpCacheType(QWebEngineProfile.HttpCacheType.NoCache)
```

- Creating a profile separately, and passing it into QWebEnginePage()
does work. But it introduces a warning each time a webview is deallocated,
and I fear it may lead to crashes:

```
Release of profile requested but WebEnginePage still not deleted. Expect troubles !
```

I tried various combinations of parents for the profile and page, and
turning web._page into an unretained property, but could not figure it out.
Some Googling pulls up a bunch of other people who seem to have hit similar
issues with PyQt. If anyone has any ideas, they'd be welcome; in the mean
time, I guess we're better off using up some of the user's disk
space than sometimes failing to load.

The profile-in-advance code I tried is below:

```
diff --git a/qt/aqt/webview.py b/qt/aqt/webview.py
index 1c96112d8..4f3e91284 100644
--- a/qt/aqt/webview.py
+++ b/qt/aqt/webview.py
@@ -23,9 +23,49 @@ serverbaseurl = re.compile(r"^.+:\/\/[^\/]+")
 BridgeCommandHandler = Callable[[str], Any]

+def _create_profile(parent: QObject) -> QWebEngineProfile:
+    qwebchannel = ":/qtwebchannel/qwebchannel.js"
+    jsfile = QFile(qwebchannel)
+    if not jsfile.open(QIODevice.OpenModeFlag.ReadOnly):
+        print(f"Error opening '{qwebchannel}': {jsfile.error()}", file=sys.stderr)
+    jstext = bytes(cast(bytes, jsfile.readAll())).decode("utf-8")
+    jsfile.close()
+
+    script = QWebEngineScript()
+    script.setSourceCode(
+        jstext
+        + """
+            var pycmd, bridgeCommand;
+            new QWebChannel(qt.webChannelTransport, function(channel) {
+                bridgeCommand = pycmd = function (arg, cb) {
+                    var resultCB = function (res) {
+                        // pass result back to user-provided callback
+                        if (cb) {
+                            cb(JSON.parse(res));
+                        }
+                    }
+
+                    channel.objects.py.cmd(arg, resultCB);
+                    return false;
+                }
+                pycmd("domDone");
+            });
+        """
+    )
+    script.setWorldId(QWebEngineScript.ScriptWorldId.MainWorld)
+    script.setInjectionPoint(QWebEngineScript.InjectionPoint.DocumentReady)
+    script.setRunsOnSubFrames(False)
+
+    profile = QWebEngineProfile(parent)
+    profile.setHttpCacheType(QWebEngineProfile.HttpCacheType.NoCache)
+    profile.scripts().insert(script)
+    return profile
+
+
 class AnkiWebPage(QWebEnginePage):
-    def __init__(self, onBridgeCmd: BridgeCommandHandler) -> None:
-        QWebEnginePage.__init__(self)
+    def __init__(self, onBridgeCmd: BridgeCommandHandler, parent: QObject) -> None:
+        profile = _create_profile(parent)
+        QWebEnginePage.__init__(self, profile, parent)
         self._onBridgeCmd = onBridgeCmd
         self._setupBridge()
         self.open_links_externally = True
@@ -46,39 +86,6 @@ class AnkiWebPage(QWebEnginePage):
         self._channel.registerObject("py", self._bridge)
         self.setWebChannel(self._channel)

-        qwebchannel = ":/qtwebchannel/qwebchannel.js"
-        jsfile = QFile(qwebchannel)
-        if not jsfile.open(QIODevice.OpenModeFlag.ReadOnly):
-            print(f"Error opening '{qwebchannel}': {jsfile.error()}", file=sys.stderr)
-        jstext = bytes(cast(bytes, jsfile.readAll())).decode("utf-8")
-        jsfile.close()
-
-        script = QWebEngineScript()
-        script.setSourceCode(
-            jstext
-            + """
-            var pycmd, bridgeCommand;
-            new QWebChannel(qt.webChannelTransport, function(channel) {
-                bridgeCommand = pycmd = function (arg, cb) {
-                    var resultCB = function (res) {
-                        // pass result back to user-provided callback
-                        if (cb) {
-                            cb(JSON.parse(res));
-                        }
-                    }
-
-                    channel.objects.py.cmd(arg, resultCB);
-                    return false;
-                }
-                pycmd("domDone");
-            });
-        """
-        )
-        script.setWorldId(QWebEngineScript.ScriptWorldId.MainWorld)
-        script.setInjectionPoint(QWebEngineScript.InjectionPoint.DocumentReady)
-        script.setRunsOnSubFrames(False)
-        self.profile().scripts().insert(script)
-
     def javaScriptConsoleMessage(
         self,
         level: QWebEnginePage.JavaScriptConsoleMessageLevel,
@@ -228,7 +235,7 @@ class AnkiWebView(QWebEngineView):
     ) -> None:
         QWebEngineView.__init__(self, parent=parent)
         self.set_title(title)
-        self._page = AnkiWebPage(self._onBridgeCmd)
+        self._page = AnkiWebPage(self._onBridgeCmd, self)
         self._page.setBackgroundColor(
             self.get_window_bg_color(theme_manager.night_mode)
@@ -242,7 +249,6 @@ class AnkiWebView(QWebEngineView):
         self.requiresCol = True
         self.setPage(self._page)

-        self._page.profile().setHttpCacheType(QWebEngineProfile.HttpCacheType.NoCache)
         self.resetHandlers()
         self.allowDrops = False
         self._filterSet = False
```
2021-12-08 21:20:39 +10:00
Damien Elmes
d87383a2d5 experimental ARM Linux packaged build 2021-12-08 20:53:46 +10:00
Damien Elmes
ed5273fae7 unpin regex & update Python deps
regex was failing to build correctly on the latest Xcode/macOS 12, and
black have dropped it as a dependency due to the build difficulties it
creates.
2021-12-08 15:11:47 +10:00
Damien Elmes
fa71b40df9 update translations 2021-12-08 10:23:27 +10:00
Damien Elmes
cad0c64105 add unbury_cards() op
https://forums.ankiweb.net/t/add-a-collection-operation-to-unbury-cards/15720
2021-12-08 09:44:47 +10:00