Commit Graph

2708 Commits

Author SHA1 Message Date
RumovZ
9aca778a93
Backend Custom Study (#1600)
* Implement custom study on backend

* Switch frontend to backend custom study

* Skip typecheck for new pb classes

* Build tag search string on backend

Also fixes escaping of special characters in tag names.

* `cram.cards` -> `cram.card_limit`

* Assign more meaningful names in `TagLimit`

* Broaden rustfmt glob

* Use `invalid_input()` helper

* Assign `FilteredDeckForUpdate` to temp var

* Implement `SearchBuilder`

* Rewrite `custom_study()` with `SearchBuilder`

* Replace match macros with `SearchBuilder`

* Remove `into_nodes_list` & `concatenate_searches`
2022-01-20 14:25:22 +10:00
Felipe Kinoshita
ce966b13ca
Change X-GNOME-SingleWindow key to SingleMainWindow (#1582)
X-GNOME-SingleWindow was upstreamed to be an XDG spec with the name
"SingleMainWindow" in
https://gitlab.freedesktop.org/xdg/xdg-specs/-/merge_requests/53
2022-01-20 11:58:27 +10:00
RumovZ
a51232debe
Fix is_zoom_event() (#1607) 2022-01-20 11:56:12 +10:00
RumovZ
fe7a8db231
Selectively disable zoom (#1602)
* Make webview zoom optional

Also suppress mouse wheel zooming.

* Disable zoom for top and bottom bars in main view

* Factor in macos zoom by scrolling and refactor
2022-01-18 19:12:57 +10:00
qxo
90da6a8885
fix: AttributeError: 'QMouseEvent' object has no attribute 'pos' (#1598)
* fix: AttributeError: 'QMouseEvent' object has no attribute 'pos'

```
Caught exception:
Traceback (most recent call last):
  File "D:\Python\Python39\lib\site-packages\aqt\browser\sidebar\tree.py", line 328, in mouseReleaseEvent
    if (index := self.currentIndex()) == self.indexAt(event.pos()):
d
```

* fix:   AttributeError: 'QMouseEvent' object has no attribute 'pos'
2022-01-16 15:29:04 +10:00
Henrik Giesel
478b3a53f1
Remove individual .html files + other refactorings (#1588)
* Move some AddCards specific code to NoteCreator.svelte

* Add new strings for Toggling the Visual / HTML editor

* Set LabelContainer vertical-align to text-top

- Makes them look more centered

* Remove appendInParentheses helper

* Make all ts/*.html files include only module.js and module.css

* Move any JS from .html to index files

* Remove .html files from ts modules

* Remove Python with Starlark implemenation

* Remove reference to non-existing file

* Remove deck-option.html as well

* fix change-notetype screen (dae)
2022-01-16 15:05:35 +10:00
qxo
492f0a5e32
fix: try catch excepton in get_windows_dark_mode and global cache the check (#1587)
* fix: try catch excepton on get_windows_dark_mode and global cache that check

* add commitor email to CONTRIBUTORS

* remove is_windows_dark_mode cache

* avoid logging the missing key (dae)

The check happens frequently, so this will fill up the user's console if we print it each time.
2022-01-16 14:07:28 +10:00
RumovZ
9936f6f7d1
Only warn once about missing av player (#1592) 2022-01-16 13:46:01 +10:00
RumovZ
0e21c49f58
Use white menubar on Windows in lightmode (#1590) 2022-01-16 13:45:16 +10:00
Damien Elmes
732c33c2b3 update to latest rules_python 2022-01-15 16:16:33 +10:00
Damien Elmes
1315a3a3bb update mypy and mypy-protobuf
- The way mypy gathers site packages has changed slightly, so we had to
update extendsitepkgs.py to work with it.
- Not sure if there's a way to avoid the ignore in
operations/__init__.py. mypy is still ensuring a provided argument has
a .changes attribute, so thankfully we don't seem to have lost much here.
2022-01-15 16:04:04 +10:00
Damien Elmes
404a1a1f6d PEP8 editorMode 2022-01-12 15:01:43 +10:00
Henrik Giesel
3beea5e1e4
Split/Merge editor.py for its three use cases (#1581)
* Forbid inserting object and iframe tags via PlainTextInput

* Add optional browserMode parameter to Editor

* Create new ts modules for three editor instances

- note-creator for AddCards
- browser-editor for the editor in the Browser
- reviewer-editor for the EditCurrent

* Revert "Forbid inserting object and iframe tags via PlainTextInput"

This reverts commit ab90ae8194494d883a1863126496e2d8f332509e.

* Refactor browserMode to editorMode

* Move new editor variants inside /ts/editor directory

* Fix typo
2022-01-12 14:51:43 +10:00
Henrik Giesel
4e4d12a62a
Browser sidebar icon improvements (#1586)
* Fix cardtype icon, add flag-off icon, remove flag.svg

* This removes the old flag.svg, because mdi-icons also has
  one icon called `flag.svg`, and there was undefined behavior
  which flag icon was being picked, when requesting "flag.svg"

* Sort no-flag to beginning of subtree

* to match tags
2022-01-11 16:35:46 +10:00
Fusion future
71e554b1db
Add "X-GNOME-SingleWindow=true" to the desktop file (#1572)
Since this commit (ebd2acd98e),
Plasma Desktop will check "X-GNOME-SingleWindow" property to determine
whether to show "Open New Window" action in the context menu of a task.

Anki cannot launch a new instance or open a new window, so add the
property and set it to true to hide the action.
2022-01-04 08:53:22 +10:00
Damien Elmes
e49496abae temporarily disable importing multiple files
Will follow up on this on https://github.com/ankitects/anki/pull/1562
2022-01-02 09:49:51 +10:00
Damien Elmes
008c62a844 dump traceback to console on importing exception 2022-01-02 09:47:44 +10:00
RumovZ
30dc2cf7ea
Add Create Copy to reviewer and use current card's deck (#1569)
* Use deck of current card when copying note

* Add Create Copy to reviewer menu

* Add ellipsis to Set Due Date
2021-12-31 16:45:30 +10:00
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
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
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
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
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
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
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
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
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
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
RumovZ
cd22485f9b
Add browser action to create note copy (#1535)
* Add browser action to create note copy

* Use new note and copy instead of using source

* Change shortcut due to Qt's Alt-Gr bug

* Add separate routine for suffixing action with ...

* Remove '...' from some translations

The convention is to add an ellipsis if more input is required to
perform the action. Whether or not the action opens a new window is not
decisive.
Sources:
https://developer.apple.com/design/human-interface-guidelines/macos/menus/menu-anatomy/
https://docs.microsoft.com/en-us/windows/win32/uxguide/cmd-toolbars
2021-12-08 08:40:48 +10:00
RumovZ
bcea43dc6a
Disable saving fullscreen geometry (#1538)
Restoring fullscreen windows is buggy.
https://forums.ankiweb.net/t/anki-2-1-50-beta/15608/39
2021-12-08 08:12:10 +10:00
nwwt
9becb4c11f
Allow <audio> to play without user interaction in accordance to autoplay setting v2 (#1539)
Adds back setting Chromium's autoplay policy according to Anki's, this time without globals.
2021-12-08 08:08:56 +10:00
Damien Elmes
0de24122ad implement a basic native macOS audio recorder
This was motivated by the fact that recording was crashing on the native
M1 build. That ended up being mostly a PEBKAC problem - turns out the
Mac Mini has no built-in microphone 🤦.

I still thinks this has some value though - it doesn't crash in such
cases, and probably doesn't suffer from the problem shown in this thread
either:

https://forums.ankiweb.net/t/anki-crashes-when-trying-to-record-on-mac/14764

For now, this is only enabled when running on arm64. If it turns out to
be reliable, it could be offered as an option on amd64 as well.
2021-12-07 18:48:24 +10:00
Damien Elmes
d9c8addbc1 switch AnkiHelper to Swift
More pleasant to work with than ObjectiveC, which will help with the
following commit.

Swift libraries weren't added to macOS until 10.14.4, so theme
autodetection will fail on 10.14.0-10.14.3. The Qt6 build will have its
minimum version bumped to 10.14.4; the Qt5 build will remain on 10.13.4.

Bazel's rules_swift doesn't currently support building Swift dylibs, so
we need to invoke swiftc directly via a genrule().
2021-12-07 18:48:24 +10:00
Matthias Metelka
924e16879f
Update about.py (#1533)
* Update about.py

* Add cqg to list

for his contributions to the community (testing, support, suggestions).

* Add the AnKing to list

for his efforts to keep add-ons compatible with new versions and popularizing Anki in the medical community via YouTube, Reddit and other social media.
2021-12-07 09:01:30 +10:00
Abdo
4571e78016
Fix error on previewer close (#1528)
_on_close was being called twice, causing an error when the destroyed
_web is accessed again.
2021-12-06 19:34:41 +10:00
Abdo
dc4fd95f24
Fix previous card info shortcut label (#1534) 2021-12-06 19:01:37 +10:00