Commit graph

329 commits

Author SHA1 Message Date
Damien Elmes
bb1b289690 Add some helpers to allow add-ons to install packages into the venv
While something we probably don't want to encourage much of, this
may enable some previously-unshared add-ons.

https://forums.ankiweb.net/t/bundling-numpy-in-an-add-on/62669/5

The 'uv add' command is transaction, so if an add-on tries to inject
incompatible dependencies into the environment, the venv will be
left as-is. And each Anki upgrade/downgrade resets the requirements,
so the requested packages shouldn't cause errors down the line.

Sample add-on:

import subprocess
from aqt import mw
from aqt.operations import QueryOp
from aqt.qt import QAction
from aqt.utils import showInfo

def ensure_spacy(col):
    print("trying to import spacy")
    try:
        import spacy
        print("successful import")
        return
    except Exception as e:
        print("error importing:", e)

    print("attempting add")
    try:
        from aqt.package import add_python_requirements as add
    except Exception as e:
        raise Exception(f"package unavailable, can't install: {e}")
    # be explicit about version, or Anki beta users will get
    # a beta wheel that may break
    (success, output) = add(["spacy==3.8.7", "https://github.com/explosion/spacy-models/releases/download/ko_core_news_sm-3.8.0/ko_core_news_sm-3.8.0-py3-none-any.whl"])
    if not success:
        raise Exception(f"adding failed: {output}")

    print("success")

    # alterantively:
    # from aqt.package import venv_binary
    # subprocess.run([venv_binary("spacy"), "download", "ko_core_news_sm"], check=True)
    # print("model added")

    # large packages will freeze for a while on first import on macOS
    import spacy
    print("spacy import successful")

def activate_spacy():
    def on_success(res):
        mw.progress.single_shot(1000, lambda: showInfo("Spacy installed"))

    QueryOp(parent=mw, op=ensure_spacy, success=on_success).with_progress("Installing spacy...").run_in_background()

action = QAction("Activate Spacy", mw)
action.triggered.connect(activate_spacy)
mw.form.menuTools.addAction(action)
2025-07-04 14:23:04 +07:00
Damien Elmes
469fd763c7 Fix taskbar pinning on Windows
Closes #4107
2025-06-29 20:53:43 +07:00
Abdo
f94d05bcbe
Switch to Ruff (#4119)
* Add check:ruff build action

* Add fix:ruff action

* Add Ruff config

Mostly generated by Cursor

* Handle rest of lints

* Fix formatting

* Replace black and isort with ruff-format

* Run ruff-format

* Fix lint errors

* Remove pylint disables

* Remove .pylintrc

* Update docs

* Fix check:format not just checking

* Fix isort rule being ignored

* Sort imports

* Ensure ./ninja format also handles import sorting

* Remove unused isort cfg

* Enable unsafe fixes in fix:ruff, and enable unused var warning

* Re-run on config change; enable unnecessary ARG ignores

* Use all pycodestyle errors, and add some more commented-out ones

Latter logged on https://github.com/ankitects/anki/issues/4135
2025-06-29 14:38:35 +07:00
Damien Elmes
de7de82f76 Refactor launcher + various tweaks
- Launcher can now be accessed via Tools>Upgrade/Downgrade
- Anki closes automatically on update
- When launcher not available, show update link like in the past
- It appears that access to the modern console host requires an app
to be built with the windows console subsystem, so we introduce an
extra anki-console.exe binary to relaunch ourselves with. Solves
https://forums.ankiweb.net/t/new-online-installer-launcher/62745/50
- Windows now requires you to close the terminal like on a Mac,
as I couldn't figure out how to have it automatically close. Suggestions
welcome!
- Reduce the amount of duplicate/near-duplicate code in the various
platform files, and improve readability
- Add a helper to install the current code into the launcher env
- Fix cargo test failing to build on ARM64 Windows
2025-06-27 16:10:12 +07:00
Damien Elmes
7edd9221ac Avoid Qt's automatic About labeling
It gets confused by our launcher process, and provides no way to
alter the default assigned text while keeping the About role on a Mac.
2025-06-27 16:10:12 +07:00
Abdo
80618cad85
Clear notetypes cache on import (#3969)
* Clear notetypes cache on import

* Clear cache in AnkiQt.on_operation_did_execute() instead
2025-05-08 23:11:47 +10:00
Jake Probst
5552fc6e97
add hook for day rollover (#3817)
* add hook for day rollover

* rollover -> day_did_change
2025-02-18 13:46:15 +07:00
Yuki
db30685b9a
Refactoring and comments (#3721) 2025-01-12 15:46:20 +11:00
Yuki
9460911d90
Fix menubar in fullscreen (#3710)
* Fix/menubar in fullscreen

* CONTRIBUTORS file

* Fix/menubar in fullscreen

* CONTRIBUTORS file

* Fix and add Type hints
2025-01-10 20:18:32 +11:00
Abdo
763712c696
Remove outdated TODO (#3567) 2024-11-09 18:42:49 +03:00
Damien Elmes
7fb261c90b Backup warning needs a new string
We need a new key, as we've introduced a variable. Missed this in
the PR review.
2024-09-27 19:36:58 +10:00
Taylor Obyen
df127b1af7
Add revert to backup option to file menu (#3434)
* Add revert to backup context item

* Fix contributors a new way

* Change relative time to filename

* Update ftl/qt/qt-accel.ftl (dae)
2024-09-25 20:21:59 +10:00
Abdo
5bd66db3c6
Call the profile_did_open() hook earlier (#3421) 2024-09-20 21:22:27 +10:00
David Culley
a6d5c94997
python: add missing type annotations for None values (#3364)
* refactor: explicitly add NoneType to type hints

If variable can be `None`, don't be implicit. Be explicit.
2024-08-22 16:03:44 +07:00
Voczi
1065941767
Add option for toggling update checks (#3346) 2024-08-10 17:46:49 +07:00
David Culley
bab83ffce0
fix: add proper imports (#3296)
Co-authored-by: Damien Elmes <dae@users.noreply.github.com>
2024-08-05 11:34:46 +07:00
David Culley
c0349ea9da
Improve exception handling (#3290)
* fix: except only non-system-exiting exceptions

see https://youtu.be/zrVfY9SuO64

* chore: add myself to CONTRIBUTORS file

* refactor: explicitly specify possible exceptions

If an exception is not an Exception, there are only three options left.
see https://docs.python.org/3/library/exceptions.html#exception-hierarchy

* refactor: use BaseException for fallback

Co-authored-by: Damien Elmes <dae@users.noreply.github.com>

* chore: add myself to contributors
2024-08-04 20:51:13 +07:00
David Culley
63afb0f8c6
Update type annotation syntax (#3283)
* chore: add myself to CONTRIBUTORS file

* refactor: use newer type hints for Union/Optional

* refactor: fix deprecated type annotations

use collections.abc rather than typing

* refactor: use lower letter type annotations

* style: reformat with black

* refactor: remove unused imports

* refactor: add missing imports for type hints

* fixup! refactor: use newer type hints for Union/Optional

* fix: add missing imports for type annotations

* fixup! refactor: use newer type hints for Union/Optional

* fixup! style: reformat with black

* refactor: fix remaining imports re: type hints
2024-07-21 14:00:52 +07:00
Abdo
a9bf702317
Call profile_did_open hook at the end of loadProfile (#3202) 2024-05-24 09:23:29 +01:00
Abdo
ef49e3f741
Do not show media auto sync errors (#3197)
* Do not show media auto sync errors

* is_autosync -> is_periodic_sync

* More wording improvements; fix periodic sync depending on auto sync setting (dae)
2024-05-17 06:25:10 +01:00
Abdo
e6c7d89443
Fix auto sync not working on Windows shutdown (#3153)
* Fix auto sync not working on Windows shutdown

* Fix mypy error

* Use translated string
2024-04-23 00:32:00 +10:00
Damien Elmes
9f55cf26fc
Switch to SvelteKit (#3077)
* Update to latest Node LTS

* Add sveltekit

* Split tslib into separate @generated and @tslib components

SvelteKit's path aliases don't support multiple locations, so our old
approach of using @tslib to refer to both ts/lib and out/ts/lib will no
longer work. Instead, all generated sources and their includes are
placed in a separate out/ts/generated folder, and imported via @generated
instead. This also allows us to generate .ts files, instead of needing
to output separate .d.ts and .js files.

* Switch package.json to module type

* Avoid usage of baseUrl

Incompatible with SvelteKit

* Move sass into ts; use relative links

SvelteKit's default sass support doesn't allow overriding loadPaths

* jest->vitest, graphs example working with yarn dev

* most pages working in dev mode

* Some fixes after rebasing

* Fix/silence some svelte-check errors

* Get image-occlusion working with Fabric types

* Post-rebase lock changes

* Editor is now checked

* SvelteKit build integrated into ninja

* Use the new SvelteKit entrypoint for pages like congrats/deck options/etc

* Run eslint once for ts/**; fix some tests

* Fix a bunch of issues introduced when rebasing over latest main

* Run eslint fix

* Fix remaining eslint+pylint issues; tests now all pass

* Fix some issues with a clean build

* Latest bufbuild no longer requires @__PURE__ hack

* Add a few missed dependencies

* Add yarn.bat to fix Windows build

* Fix pages failing to show when ANKI_API_PORT not defined

* Fix svelte-check and vitest on Windows

* Set node path in ./yarn

* Move svelte-kit output to ts/.svelte-kit

Sadly, I couldn't figure out a way to store it in out/ if out/ is
a symlink, as it breaks module resolution when SvelteKit is run.

* Allow HMR inside Anki

* Skip SvelteKit build when HMR is defined

* Fix some post-rebase issues

I should have done a normal merge instead.
2024-03-31 09:16:31 +01:00
Abdo
aa71313d12
More fixes for auto advance state (#2879)
* Disable auto advance on review cleanup

* Fix auto advance state resetting on card flip when bottom bar is focused

* Move focus handling to reviewer

* Simplify destruction of previous timers

* Fix auto advance firing early

* Fix handling of 'wait for audio'

* Remove unused import

* When focus is lost, disable auto advance (dae)

Otherwise it will resume when the user answers a card, which is
surprising.
2023-12-13 09:23:11 +10:00
Damien Elmes
5f0a74e01f Show tooltip when auto-advance enabled/disabled 2023-12-11 14:43:12 +10:00
Damien Elmes
c09a46f857 Rework rollover check
- Avoid waking up frequently
- Ensure collection access happens before sync begins, as otherwise
it may block the UI
2023-12-10 12:37:01 +10:00
Abdo
843c0417b0
Fix auto advance state not being restored after focus change in some (#2860)
cases
2023-12-04 14:54:25 +10:00
Abdo
ae7b14bf40
Add auto-advance options to deck preset (#2765)
* Move stop-timer-on-answer strings to correct section

* Add auto-advance options to deck preset

* Implement answer actions

* Fix error when last card is answered before timeout

* Fix deserialization of answerAction

* Add answerAction to reserved key list

* Fix inverted boolean

* Add option to wait for audio to finish

* Add auto-advance toggle

* Add shortcut

* Disable auto-advance when main window state changes

* Start auto-advance timer after option is toggled

* Disable auto-advance when main window loses focus

* Use existing translations

* Add Answer Hard and Show Reminder
2023-11-13 10:41:51 +10:00
Damien Elmes
ab3a37ff71 Fix 'creating backup' showing for longer than necessary 2023-11-03 22:18:30 +10:00
Damien Elmes
865296254a Tweaks to add-on startup failure screen / update checks
- Add a Check for Updates button to the screen
- Make the update list screen non-modal, so that other modal pop-ups
at startup don't leave the user stuck
- When manually checking for updates, update Anki's last check time
2023-10-26 11:23:24 +10:00
Abdo
0ce9b3f0a1
Refresh reviewer as the day rolls over (#2756) 2023-10-21 12:18:01 +10:00
Abdo
b23f17df27
Drop support for checkpoints (#2742)
* Drop support for checkpoints

* Deprecate .flush()

* Remove .begin/.commit

* Remove rollback() and deprecate save/autosave/reset()

There's no need to commit anymore, as the Rust code is handling
transactions for us.

* Add safer transact() method

This will ensure add-on authors can't accidentally leave a transaction
open, leading to data loss.

---------

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2023-10-17 12:43:34 +10:00
chandraiyengar
b35a11ffd6
Add profile name in profile deletion confirmation message (#2722)
* Add profile name in profile deletion confirmation message

* Update contributors

* leave old translation and add new one
2023-10-12 13:34:52 +10:00
Abdo
8b0d663fd0
Allow full screen mode on new Qt6 drivers (#2660)
* Allow full screen mode on new Qt6 drivers

* Update fulscreen warning message
2023-09-16 11:28:20 +10:00
Damien Elmes
bfef908c6c
Refactor media sync handling (#2647)
* Refactor media sync handling

- The media USN is now returned in sync/meta, which avoids an extra
round-trip.
- Media syncing is now automatically started by the syncing code at
the end of a normal or full sync, which avoids it competing for bandwidth
and resources, and avoids duplicate invalid login messages when the auth
token is invalid.
- Added a new media_sync_progress() method to both check if media is
syncing, and get access to the latest progress.
- Updated the sync log screen to only show the latest line, like AnkiMobile.
- Show media sync errors in a pop-up, so they don't get missed. Use a non-modal
pop-up to avoid potential conflicts with other modals.

* Remove print statement
2023-09-10 13:22:20 +10:00
Damien Elmes
a3d38bdad3 Fix syncStatus being called twice when auto sync disabled 2023-09-07 15:11:36 +10:00
Damien Elmes
ffd392de21
Change Anki's version scheme; bump to 23.09 (#2640)
* Accept iterables as inputs to backend methods

* Shift add-on check to backend; use new endpoint

The new endpoint will return info on a suitable branch if found,
instead of returning all branches. This simplifies the frontend code,
and means that you can now drop support for certain versions without
it also remotely disabling the add-on for people who are running one of
the excluded versions, like in

https://forums.ankiweb.net/t/prevent-add-ons-from-being-disabled-remote-stealthily-surreptitiously/33427

* Bump version to 23.09

This changes Anki's version numbering system to year.month.patch, as
previously mentioned on https://forums.ankiweb.net/t/use-a-different-versioning-system-semver-perhaps/20046/5

This is shaping up to be a big release, with the introduction of FSRS and
image occlusion, and it seems like a good time to be finally updating the
version scheme as well. AnkiWeb has been updated to understand the new
format, and add-on authors will now specify version compatibility using
the full version number, as can be seen here:

https://ankiweb.net/shared/info/3918629684

* Shift update check to backend, and tidy up update.py

* Use the shared client for sync connections too
2023-09-07 12:37:15 +10:00
Damien Elmes
4691560522 Work around CI failure on Windows with PyQt 6.5.2 2023-07-26 21:10:19 +10:00
Luc Mcgrady
bceffd96c6
Add keyboard shortcut for legacy stats (#2583)
* Added: Shortcut for legacy stats

* Added: Name to contributors

* Capitalize S
2023-07-24 11:31:41 +10:00
RumovZ
9430e3ddf2
Fix addon update dialog showing twice (#2580)
* Gitignore .ninja_deps

* Don't check for addon updates on profile unload

This fixes two update dialogs showing up when switching profiles.

* Only show addon update dialog once

... instead of once every time the profile is changed, when the version
doesn't match.
This is analogous to when the dialog is triggered by elapsed time.

* Manage last_run_version update in ProfileManager
2023-07-18 22:26:59 +10:00
Abdo
0100ae7431
Fix main window geometry/state not being restored in some cases (#2558)
Introduced by 19b08eb280

Report: https://forums.ankiweb.net/t/65-the-size-of-the-main-window-is-reset-every-time-it-is-closed-again/31364
2023-06-27 16:52:34 +10:00
Ren Tatsumoto
9c5edfa88c
Ensure there's no duplicate shortcuts after running state_shortcuts_will_change (#2509)
* remove duplicate shortucts after running hook

* normalize shortcuts by converting them to QKeySequence

* no need to copy here

* extract method
2023-05-22 14:07:15 +10:00
Damien Elmes
e6f970e969 Tolerate missing keys in profile DB
https://forums.ankiweb.net/t/crash-with-error-keyerror-mainwindowstate/29689
2023-04-26 19:07:59 +10:00
RumovZ
b55161cd39
Improve debug console (#2435)
* List actions and locals in debug console

* Ignore whitespace when wrapping line with pp

* Scroll down after printing in debug console

Was previously preserving relative vertical position.

* Add feature to open and save debug scripts

* Refactor debug console into own module

* Add buffers to switch scripts

* Add action to delete script
2023-03-15 15:29:05 +10:00
Damien Elmes
d1abfbc6a1 Passing an invalid profile name on the commandline will now show picker
https://forums.ankiweb.net/t/open-with-profiles-to-start/27612
2023-03-02 17:13:04 +10:00
evandrocoan
d9f1e22648
Create the hook will_show_web to control html5 media elements with Javascript (#2340)
* Replaced ankimedia object directly call by addon specific hook

# Conflicts:
#	qt/aqt/browser/previewer.py
#	qt/aqt/clayout.py
#	qt/aqt/reviewer.py

* Replaced ankimedia.js by addon specific hook

# Conflicts:
#	qt/aqt/browser/previewer.py
#	qt/aqt/clayout.py
#	qt/aqt/main.py

* Create specific location name for each hook to reuse control

* Created the card_review_webview_did_init hook

* Extended the hook card_will_show to replace will_show_web

The new hook card_will_show_state takes three new arguments

* Created the hook audio_did_pause_or_unpause to replace will_show_web

The new hook is called when audio toggle pause is called

* Created the hook audio_will_replay to replace will_show_web

The new hook is called when the audio is replayed by the user.

* Created the hook previewer_will_redraw_after_show_both_sides_toggled

to replace will_show_web.
The new hook fully replaces the last uses of will_show_web.

* Replaced card_will_show_state hook with reviewer_did_init and

equivalents. Instead of receiving the required state, it access it
by caching the object values with hooks as reviewer_did_init.
2023-02-13 14:50:26 +10:00
Aristotelis
0f86c9fd11
Rework & unify webview identification and title setting (#2366)
* Create common web view registry and unify title setting

* Consistently use space-separated naming for webview titles

None of the modified titles seem to be in use by add-ons, so we are not bound to the current naming.

The old naming was likely following camelCase as the name was also acting as a key for saveGeom, which is no longer the case.

* Update webview_did_inject_style_into_page example

* Add docstring to addon-targeted method

* Change AnkiWebView.origin to property

* Fix dupe enum value

* Tweak method name

* Add semicolon

* Rename `AnkiWebViewOrigin` to `AnkiWebViewKind`
2023-02-10 14:53:11 +10:00
evandrocoan
13d557589f
Improve info message (#2343) 2023-01-29 12:55:01 +10:00
Damien Elmes
4c98a1a318 Fix error shown after toggling full screen
https://forums.ankiweb.net/t/anki-2-1-57-beta/26494/62
2023-01-29 12:41:28 +10:00
Aristotelis
476e3af759
Bump Linux theme refresh timer back up to 5 minutes (#2331)
On Linux distributions that do not yet support org.freedesktop.appearance.color-scheme (most distros released prior to 2022), querying DBus for the missing property produces verbose journal entries over Anki's entire runtime.
2023-01-18 22:24:59 +10:00
Matthias Metelka
f169ee0933
Revamp Preferences, implement Minimalist Mode and Qt widget gallery to test GUI changes (#2289)
* Create widget gallery dialog

* Add WidgetGallery to debug dialog

* Use enum for its intended purpose

* Rename "reduced-motion" to "reduce-motion"

* Add another border-radius value

and make former large radius a bit smaller.

* Revamp preferences, add minimalist mode

Also:
- create additional and missing widget styles and tweak existing ones
- use single profile entry to set widget styles and reduce choices to Anki and Native

* Indent QTabBar style definitions

* Add missing styles for QPushButton states

* Fix QTableView background

* Remove unused layout from Preferences

* Fix QTabView focused tab style

* Highlight QCheckBox and QRadioButton when focused

* Fix toolbar styles

* Reorder preferences

* Add setting to hide bottom toolbar

* Move toolbar settings above minimalist modes

* Remove unused lines

* Implement proper full-screen mode

* Sort imports

* Tweak deck overview appearance in minimalist mode

* Undo TitledContainer changes

since nobody asked for that

* Remove dynamic toolbar background from minimalist mode

* Tweak buttons in minimalist mode

* Fix some issues

* Reduce theme check interval to 5s on Linux

* Increase hide timer interval to 2s

* Collapse toolbars with slight delay when moving to review state

This should ensure the bottom toolbar collapses too.

* Allow users to make hiding exclusive to full screen

* Rename full screen option

* Fix hide mode dropdown ignoring checkbox state on startup

* Fix typing issue

* Refine background image handling

Giving the toolbar body the main webview height ensures background-size: cover behaves exactly the same.

To prevent an override of other background properties, users are advised to only set background-images via the background-image property, not the background shorthand.

* Fix top toolbar getting huge when switching modes

The issue was caused by the min-height hack to align the background images. A call to web.adjustHeightToFit would set the toolbar to the same height as the main webview, as the function makes use of document.offsetHeight.

* Prevent scrollbar from appearing on bottom toolbar resize

* Cleanup

* Put review tab before editing; fix some tab orders

* Rename 'network' to 'syncing'

* Fix bottom toolbar disappearing on UI > 100

* Improve Preferences layout by adding vertical spacers to the bottom

also make the hiding of video_driver and its label more obvious in preferences.py.

* Fix bottom toolbar animating on startup

Also fix bottom toolbar not appearing when unchecking hide mode in reviewer.

* Hide/Show menubar in fullscreen mode along with toolbar

* Attempt to fix broken native theme on macOS

* Format

* Improve native theme on other systems by not forcing palette

with the caveat that theme switching can get weird.

* Fix theme switching in native style

* Remove redundant condition

* Add back check for Qt5 to prevent theme issues

* Add check for macOS before setting fusion theme

* Do not force scrollbar styles on macOS

* Remove all of that crazy theme logic

* Use canvas instead of button-bg for ColorRole.Button

* Make sure Anki style is always based on Fusion

otherwise we can't guarantee the same look on all systems.

* Explicitly apply default style when Anki style is not selected

This should fix the style not switching back after it was selected.

* Remove reduncant default_palette

* Revert 8af4c1cc2

On Mac with native theme, both Qt5 and Qt6 look correct already. On
the Anki theme, without this change, we get the fusion-style scrollbars
instead of the rounded ones.

* Rename AnkiStyles enum to WidgetStyle

* Fix theme switching shades on same theme

* Format

* Remove unused placeholderText

that caused an error when opening the widget gallery on Qt5.

* Check for full screen windowState using bitwise operator

to prevent error in Qt5.

Credit: https://stackoverflow.com/a/65425151

* Hide style option on Windows

also exclude native option from dropdown just in case.

* Format

* Minor naming tweak
2023-01-18 21:24:16 +10:00