Strip HTML from note type and template names in the Empty Cards screen.
## How to test
```
cargo test -p anki --lib notetype::emptycards
```
---------
Co-authored-by: Fernando Lins <1887601+fernandolins@users.noreply.github.com>
<!--
Title (for the Pull Request title field at the top):
Use a short prefix so the change type is obvious. You do not need to
repeat it in the body below.
Examples:
- fix: — bugfix
- feat: — feature
- refactor: — internal change without user-facing feature
- docs: — documentation only
- chore: — tooling, CI, deps, build housekeeping
- test: — tests only
-->
## Linked issue (required)
- #4433
- #4716
## Summary / motivation (required)
This PR modifies `Check Media` to dedupe filenames case-insensitively so
as to avoid files that were added on case-sensitive filesystems
potentially being overwritten on case-insensitive ones
## Steps to reproduce (required, use N/A if not applicable)
N/A
## How to test (required)
Given a.jpg (hash 1), A.JPG (hash 2) and a.JPG (hash 1) as existing
media files on a case-sensitive fs, see that `Check Media` renames A.JPG
to a-2.jpg and a.JPG to a.jpg
### Checklist (minimum)
- [x] I ran `./ninja check` or an equivalent relevant check locally.
- [ ] I added or updated tests when the change is non-trivial or
behavior changed.
## Scope
- [x] This PR is focused on one change (no unrelated edits).
<!--
Title (for the Pull Request title field at the top):
Use a short prefix so the change type is obvious. You do not need to
repeat it in the body below.
Examples:
- fix: — bugfix
- feat: — feature
- refactor: — internal change without user-facing feature
- docs: — documentation only
- chore: — tooling, CI, deps, build housekeeping
- test: — tests only
-->
## Linked issue (required)
- #4716
## Summary / motivation (required)
Currently, on filesystems where the media folder is treated as
case-insensitive, `[sound:BLAH.mp3]` and `[sound:blah.mp3]` point to the
same file on disk (if any), but one of the two would be considered as a
ref pointing to a missing file by the media checker which assumes
case-sensitivity
## Steps to reproduce (required, use N/A if not applicable)
See linked pr
## How to test (required)
On windows/macos, add `blah.mp3`, rename `blah.mp3` to `Blah.mp3` in the
ref, run `Check Media` and see that `Blah.mp3` isn't considered missing
### Checklist (minimum)
- [x] I ran `./ninja check` or an equivalent relevant check locally.
- [ ] I added or updated tests when the change is non-trivial or
behavior changed.
## Scope
- [x] This PR is focused on one change (no unrelated edits).
<!--
Title (for the Pull Request title field at the top):
Use a short prefix so the change type is obvious. You do not need to
repeat it in the body below.
Examples:
- fix: — bugfix
- feat: — feature
- refactor: — internal change without user-facing feature
- docs: — documentation only
- chore: — tooling, CI, deps, build housekeeping
- test: — tests only
-->
## Linked issue (required)
- #4851
## Summary / motivation (required)
I made a mistake in #4851 by not lowercasing in the case where a file
with the same name but different contents already exists, leading to
inconsistent behaviour across platforms
## Steps to reproduce (required, use N/A if not applicable)
See linked pr
## How to test (required)
Run ./check on linux and windows and see that the same lowercasing
behaviour occurs on both
### Checklist (minimum)
- [x] I ran `./ninja check` or an equivalent relevant check locally.
- [ ] I added or updated tests when the change is non-trivial or
behavior changed.
## Scope
- [x] This PR is focused on one change (no unrelated edits).
<!--
Title (for the Pull Request title field at the top):
Use a short prefix so the change type is obvious. You do not need to
repeat it in the body below.
Examples:
- fix: — bugfix
- feat: — feature
- refactor: — internal change without user-facing feature
- docs: — documentation only
- chore: — tooling, CI, deps, build housekeeping
- test: — tests only
-->
## Linked issue (required)
Fixes#4716
## Summary / motivation (required)
#4435 made it so that all new added media would have lowercased names,
but this was bugged and led to media refs pointing to inexistent files
on case-insensitive filesystems
The fix proposed is to try adding new files with lowercased names only
if they don't already exist, using the existing file otherwise
## Steps to reproduce (required, use N/A if not applicable)
See linked issue
## How to test (required)
Try copy-pasting a media file from the Edit window of an existing note
to the Add window and see that the filename in the resulting media ref
isn't forced to be lowercased
When pasting a new file, see that the filename is now lowercased
### Checklist (minimum)
- [x] I ran `./ninja check` or an equivalent relevant check locally.
- [ ] I added or updated tests when the change is non-trivial or
behavior changed.
## Scope
- [x] This PR is focused on one change (no unrelated edits).
## Linked issue
#4678
## Summary
This enables native Windows ARM64 builds for Briefcase. Depends on #4797
## How to test
- Run `./tools/ninja installer` in a Windows ARM64 machine.
- Check the architecture of the installer under `./out/installer/dist`
by going to Properties > Compatibility and confirming emulation settings
are disabled.
- Install the package and confirm Anki.exe is a native binary.
- Open Anki, go to the [debug
console](https://docs.ankiweb.net/misc.html#debug-console) and run the
following code to check the architecture of the Python build:
```python
import platform
print(platform.machine(), platform.python_compiler())
```
migrates Anki Desktop packaging from the legacy
NSIS/uv-based installer to [BeeWare
Briefcase](https://briefcase.readthedocs.io/). This branch integrates
work from many related issues and PRs to deliver cross-platform native
installers (MSI on Windows, .app on macOS, PyInstaller on Linux) with
code signing, notarization, and file association support.
## Integrated PRs
- #4585 — Set up Briefcase
- #4596 — Add Briefcase icons
- #4598 — Handle Briefcase file associations
- #4601 — Add Briefcase app permissions
- #4609 — Customize Briefcase's MSI installer
- #4616 — Set up Briefcase code signing and notarization
- #4618 — Fix Briefcase packaging for x86 Macs
- #4623 — Customize Briefcase's Linux template
- #4627 — List required Debian packages for Briefcase installer
- #4630 — Update Briefcase's Windows template
- #4631 — Rewrite Linux install/uninstall scripts for PyInstaller
- #4638 — Use PyInstaller on Linux
- #4645 — Update installer docs
- #4654 — Disable Briefcase's universal builds for macOS
- #4672 — Deal with existing NSIS installations in MSI installer
- #4676 — Remove duplicate Briefcase icons
- #4677 — Tweak Linux scripts for new installer
- #4709 — Add anki-console.bat to Briefcase's Windows package
## Related Issues
- #4557 — Evaluate BeeWare Briefcase for Anki packaging and distribution
- #4678 — Support native Windows ARM64 builds for Briefcase
- #4688 — Linux installer: migrate to PyInstaller and rewrite install
scripts
- #4689 — Investigate startup performance with Briefcase
- #4690 — Specify required Linux system packages for Briefcase
- #4691 — Investigate Windows ARM64 support with Briefcase
- #4692 — Test on Linux ARM with Briefcase
- #4693 — Separate ARM and Intel macOS releases
- #4694 — Update developer documentation for Briefcase installer
- #4695 — Support upgrade/downgrade with the Briefcase installer
- #4696 — Update user documentation for new installer
- #4702 — Update Briefcase's Windows template with upstream security fix
and OS version check
- #4703 — Follow-up tweaks to Linux install/uninstall scripts
## Related PRs
- #4619 — Enable Windows ARM64 support
- #4632 — Release action
---------
Co-authored-by: Abdo <abdo@abdnh.net>
Co-authored-by: Andrew Sanchez <andrewsanchez@users.noreply.github.com>
Co-authored-by: Fernando Lins <1887601+fernandolins@users.noreply.github.com>
The Problem
The "learn now" add-on can bulk-add many new cards to the learn queue
with due == now. When a user answers some of those and fails them, the
failed cards are scheduled for a few minutes later, but the current
queue-building behavior requires the user to finish the remaining "learn
now" cards (due == now) before the failed cards are shown again. This
increases the chance of repeated failures and reduces learning
efficiency.
The Change
The queue builder now partitions intraday learning cards into two
groups: previously-attempted (reps > 0) and never-attempted (reps == 0).
Within each group cards remain ordered by due time. The builder
concatenates the groups with previously-attempted cards first.
Why this fixes the problem
Failed learning cards (which now have reps > 0 and a later due
timestamp) will be prioritized ahead of never-attempted cards added by
"learn now". This ensures the user sees the failed cards as soon as they
are due, reducing repeated failures.
Why changes to Anki rather than the add-on
As far as I know, there is nothing that the add-on can do to improve
this situation. Secondly, I think that Anki should, at some point,
natively include the "Learn now" feature as it is quite useful when the
user wants to introduce specific cards (for e.g., for an upcoming exam)
without creating a temporary deck for that purpose. "Learn now" is also
a good way to solve one aspect of the Set Due Date misuse problem (see
https://github.com/open-spaced-repetition/fsrs4anki/issues/675#issuecomment-2548839346).
Fixes#4581
`contains_cloze_replacement()` was doing a shallow check, missing cloze
fields nested inside conditionals. Delegating to
`all_referenced_cloze_field_names()` fixes the inconsistency with
`contains_field_replacement()`
the load balancer only looks at cards in the same preset when balancing
cards. which means that if a sibling is in a different preset, it
doesn't get avoided. this is not ideal. so heres a fix.
and while I was here I added some extra weighting so it tries to spread
siblings out a bit.
The AV_TAGS regex matches an old format of the `anki:tts` tag
(`[anki:tts][lang=en_US]` rather than `[anki:tts lang=en_US]`). It was
originally updated when the feature got introduced in
0942ffbff6
but then was never adjusted to reflect later changes to the syntax.
I removed it from the pattern rather than updating it to match, because
AV_TAGS is only used for matching filenames nowadays (stripping is
handled by a different module).
* Add regression test for #1909 (long filename rename not reported as unused)
* Add Brett Schwartz to CONTRIBUTORS
* Use MAX_MEDIA_FILENAME_LENGTH constant and 'a'
* Update to Rust 1.90
* Fix clippy errors
* Update to 1.92
* Update cargo-deny again
Deno crate was using a CVSS version 4.0, which wasn't supported
---------
Co-authored-by: Damien Elmes <gpg@ankiweb.net>
* add wrapper struct with case-folding get impl
* use wrapper struct
* restrict case-folding to windows
* Revert "restrict case-folding to windows"
This reverts commit aad01d904f.
* case-fold filenames for newly added media
* add test
* fix incorrect comment
* Show text on occlusion cards regardless of `occludeInactive`.
Before this change, on an image occlusion card, a text box was visible
during editing but not visible during review. This change makes text
visible even if other shapes would be hidden.
* Move fix to render_image_occlusion()
---------
Co-authored-by: jariji <jariji>
Co-authored-by: Abdo <abdo@abdnh.net>
Use OriginalStockKind instead of StockKind when setting
original_stock_kind for basic notetype variants. The two enums
have different numeric values, causing 'Restore to Default' to
restore the wrong template.
For example, StockKind::BasicTyping has value 3, but when read
back as OriginalStockKind, value 3 corresponds to
BasicOptionalReversed instead of BasicTyping (which is 4).
This fixes the off-by-one behavior where:
- Basic (type in the answer) → Basic (optional reversed card)
- Basic (and reversed card) → Basic (optional reversed card)
- Basic (optional reversed card) → Basic (and reversed card)
Fixes#4353
* Fix/Ensure fuzz doesn't go backward during rescheduling
Fixes https://github.com/ankitects/anki/issues/2694
* Fix
* Get previous_interval from LastRevlogInfo
* Fix
* Format
* Format
* Exclude lapses
* Force reconfigure in CI
The cached build.ninja may reference files that don't exist in the PR.
On a local build this tends to auto-fix itself as the build scripts detect
a quick failure and re-run the configure, but CI tends to be too slow.
https://github.com/ankitects/anki/pull/4364#issuecomment-3338026129
* Rename min/max to make it clear they restrict interval, not fuzz
* Wording tweaks/comments for clarity
---------
Co-authored-by: Damien Elmes <gpg@ankiweb.net>
* Export last_interval to Python
* Add last_interval field to StatsRevlogEntry
* Implement last_interval_secs function
* Update last_interval field type in stats.proto
* Update last_interval to use last_interval_secs
* Refactor reviews_for_fsrs function for improved performance
Replaced the previous implementation with a more efficient approach using a single loop and pre-allocated vectors. This change reduces the complexity of creating FSRSItems and enhances overall performance, especially for larger datasets.
* collapse `if` statement
* When not training, only create the final FSRS item
* add GetCustomColours rpc method
* save colours as rgb instead of argb
* show saved custom colours as possible options in colour picker
this is primarily for mobile clients, as qt currently ignores this
* save custom colours on colour picker change (for desktop)
* Enable nc: to only search in a specific field
* Add FieldSearchMode enum to replace boolean fields
* Avoid magic numbers in enum
* Use standard naming so Prost can remove redundant text
---------
Co-authored-by: Damien Elmes <gpg@ankiweb.net>
* Increase randomness in random sorting of new cards
Currently, the new cards appear roughly in the same order on consecutive days (if they are skipped by burying). This change aims to increase randomness by spreading out the salt across the hash space.
* Fix errors
* Make simulator fill missing values of DR and decay too
If a card has missing memory states, it will likely have missing DR and decay too. So, it makes sense to simultaneously update them as well.
* Fix error
* Avoid causing sync conflicts when filling in missing memory in sim
https://github.com/ankitects/anki/pull/4269#issuecomment-3201450124
---------
Co-authored-by: Damien Elmes <gpg@ankiweb.net>