Commit Graph

226 Commits

Author SHA1 Message Date
Henrik Giesel
de2cc20c59
Change how resizable images work (#1859)
* Add ResizableImage.svelte in ts/editable

* Set image constrained via attributes instead of managed style sheet

* Implement new constrained size method

* Turn WithImageConstrained.svelte into normal ts file

* Introduce removeStyleProperties

Removes "style" attribute if all style properties were cleared

* Avoid --editor-width and use one variable set on container

* Disable shrinking if already smaller than shrunken size

* Add button to restore image to original size

* Don't allow restoring original size if no custom width set

* Bottom-center HandleLabel

* Satisfy svelte-check
2022-05-13 12:57:07 +10:00
Damien Elmes
c8a4e5ea22 Add more progress + abort points to export code
The old `media_files_did_export` hook has been kept around for use with
the legacy apkg exporter (an add-on uses it), and a new 
`legacy_export_progress` hook has been added so we can get progress
from the new colpkg exporter until we move over fully to the new code.
2022-05-06 15:32:23 +10:00
Damien Elmes
72389b97be Show a user-facing message instead of a traceback on invalid file type
While our importing dialog limits the types of files that can be selected,
users can also import by providing a filename on the command line.
2022-05-05 21:24:12 +10:00
Damien Elmes
1297beff63 Minor progress tweaks to apkg importing
- Set progress as soon as possible; previously the extracting and
gathering steps happened prior to the first progress.
- Add "extracting" and "gathering" progress steps, so that large imports
show more feedback in the early stage, and can be more quickly
interrupted.
2022-05-05 12:23:05 +10:00
RumovZ
5f9451f547
Add apkg import/export on backend (#1743)
* Add apkg export on backend

* Filter out missing media-paths at write time

* Make TagMatcher::new() infallible

* Gather export data instead of copying directly

* Revert changes to rslib/src/tags/

* Reuse filename_is_safe/check_filename_safe()

* Accept func to produce MediaIter in export_apkg()

* Only store file folder once in MediaIter

* Use temporary tables for gathering

export_apkg() now accepts a search instead of a deck id. Decks are
gathered according to the matched notes' cards.

* Use schedule_as_new() to reset cards

* ExportData → ExchangeData

* Ignore ascii case when filtering system tags

* search_notes_cards_into_table →

search_cards_of_notes_into_table

* Start on apkg importing on backend

* Fix due dates in days for apkg export

* Refactor import-export/package

- Move media and meta code into appropriate modules.
- Normalize/check for normalization when deserializing media entries.

* Add SafeMediaEntry for deserialized MediaEntries

* Prepare media based on checksums

- Ensure all existing media files are hashed.
- Hash incoming files during preparation to detect conflicts.
- Uniquify names of conflicting files with hash (not notetype id).
- Mark media files as used while importing notes.
- Finally copy used media.

* Handle encoding in `replace_media_refs()`

* Add trait to keep down cow boilerplate

* Add notetypes immediately instaed of preparing

* Move target_col into Context

* Add notes immediately instaed of preparing

* Note id, not guid of conflicting notes

* Add import_decks()

* decks_configs → deck_configs

* Add import_deck_configs()

* Add import_cards(), import_revlog()

* Use dyn instead of generic for media_fn

Otherwise, would have to pass None with type annotation in the default
case.

* Fix signature of import_apkg()

* Fix search_cards_of_notes_into_table()

* Test new functions in text.rs

* Add roundtrip test for apkg (stub)

* Keep source id of imported cards (or skip)

* Keep source ids of imported revlog (or skip)

* Try to keep source ids of imported notes

* Make adding notetype with id undoable

* Wrap apkg import in transaction

* Keep source ids of imported deck configs (or skip)

* Handle card due dates and original due/did

* Fix importing cards/revlog

Card ids are manually uniquified.

* Factor out card importing

* Refactor card and revlog importing

* Factor out card importing

Also handle missing parents .

* Factor out note importing

* Factor out media importing

* Maybe upgrade scheduler of apkg

* Fix parent deck gathering

* Unconditionally import static media

* Fix deck importing edge cases

Test those edge cases, and add some global test helpers.

* Test note importing

* Let import_apkg() take a progress func

* Expand roundtrip apkg test

* Use fat pointer to avoid propogating generics

* Fix progress_fn type

* Expose apkg export/import on backend

* Return note log when importing apkg

* Fix archived collection name on apkg import

* Add CollectionOpWithBackendProgress

* Fix wrong Interrupted Exception being checked

* Add ClosedCollectionOp

* Add note ids to log and strip HTML

* Update progress when checking incoming media too

* Conditionally enable new importing in GUI

* Fix all_checksums() for media import

Entries of deleted files are nulled, not removed.

* Make apkg exporting on backend abortable

* Return number of notes imported from apkg

* Fix exception printing for QueryOp as well

* Add QueryOpWithBackendProgress

Also support backend exporting progress.

* Expose new apkg and colpkg exporting

* Open transaction in insert_data()

Was slowing down exporting by several orders of magnitude.

* Handle zstd-compressed apkg

* Add legacy arg to ExportAnkiPackage

Currently not exposed on the frontend

* Remove unused import in proto file

* Add symlink for typechecking of import_export_pb2

* Avoid kwargs in pb message creation, so typechecking is not lost

Protobuf's behaviour is rather subtle and I had to dig through the docs
to figure it out: set a field on a submessage to automatically assign 
the submessage to the parent, or call SetInParent() to persist a default
version of the field you specified.

* Avoid re-exporting protobuf msgs we only use internally

* Stop after one test failure

mypy often fails much faster than pylint

* Avoid an extra allocation when extracting media checksums

* Update progress after prepare_media() finishes

Otherwise the bulk of the import ends up being shown as "Checked: 0"
in the progress window.

* Show progress of note imports

Note import is the slowest part, so showing progress here makes the UI
feel more responsive.

* Reset filtered decks at import time

Before this change, filtered decks exported with scheduling remained
filtered on import, and maybe_remove_from_filtered_deck() moved cards
into them as their home deck, leading to errors during review.

We may still want to provide a way to preserve filtered decks on import,
but to do that we'll need to ensure we don't rewrite the home decks of
cards, and we'll need to ensure the home decks are included as part of
the import (or give an error if they're not).

https://github.com/ankitects/anki/pull/1743/files#r839346423

* Fix a corner-case where due dates were shifted by a day

This issue existed in the old Python code as well. We need to include
the user's UTC offset in the exported file, or days_elapsed falls back
on the v1 cutoff calculation, which may be a day earlier or later than
the v2 calculation.

* Log conflicting note in remapped nt case

* take_fields() → into_fields()

* Alias `[u8; 20]` with `Sha1Hash`

* Truncate logged fields

* Rework apkg note import tests

- Use macros for more helpful errors.
- Split monolith into unit tests.
- Fix some unknown error with the previous test along the way.
(Was failing after 969484de4388d225c9f17d94534b3ba0094c3568.)

* Fix sorting of imported decks

Also adjust the test, so it fails without the patch. It was only passing
before, because the parent deck happened to come before the
inconsistently capitalised child alphabetically. But we want all parent
decks to be imported before their child decks, so their children can
adopt their capitalisation.

* target[_id]s → existing_card[_id]s

* export_collection_extracting_media() → ...

export_into_collection_file()

* target_already_exists→card_ordinal_already_exists

* Add search_cards_of_notes_into_table.sql

* Imrove type of apkg export selector/limit

* Remove redundant call to mod_schema()

* Parent tooltips to mw

* Fix a crash when truncating note text

String::truncate() is a bit of a footgun, and I've hit this before
too :-)

* Remove ExportLimit in favour of separate classes

* Remove OpWithBackendProgress and ClosedCollectionOp

Backend progress logic is now in ProgressManager. QueryOp can be used
for running on closed collection.

Also fix aborting of colpkg exports, which slipped through in #1817.

* Tidy up import log

* Avoid QDialog.exec()

* Default to excluding scheuling for deck list deck

* Use IncrementalProgress in whole import_export code

* Compare checksums when importing colpkgs

* Avoid registering changes if hashes are not needed

* ImportProgress::Collection → ImportProgress::File

* Make downgrading apkgs depend on meta version

* Generalise IncrementableProgress

And use it in entire import_export code instead.

* Fix type complexity lint

* Take count_map for IncrementableProgress::get_inner

* Replace import/export env with Shift click

* Accept all args from update() for backend progress

* Pass fields of ProgressUpdate explicitly

* Move update_interval into IncrementableProgress

* Outsource incrementing into Incrementor

* Mutate ProgressUpdate in progress_update callback

* Switch import/export legacy toggle to profile setting

Shift would have been nice, but the existing shortcuts complicate things.
If the user triggers an import with ctrl+shift+i, shift is unlikely to
have been released by the time our code runs, meaning the user accidentally
triggers the new code. We could potentially wait a while before bringing
up the dialog, but then we're forced to guess at how long it will take the
user to release the key.

One alternative would be to use alt instead of shift, but then we need to
trigger our shortcut when that key is pressed as well, and it could
potentially cause a conflict with an add-on that already uses that
combination.

* Show extension in export dialog

* Continue to provide separate options for schema 11+18 colpkg export

* Default to colpkg export when using File>Export

* Improve appearance of combo boxes when switching between apkg/colpkg

+ Deal with long deck names

* Convert newlines to spaces when showing fields from import

Ensures each imported note appears on a separate line

* Don't separate total note count from the other summary lines

This may come down to personal preference, but I feel the other counts
are equally as important, and separating them feels like it makes it
a bit easier to ignore them.

* Fix 'deck not normal' error when importing a filtered deck for the 2nd time

* Fix [Identical] being shown on first import

* Revert "Continue to provide separate options for schema 11+18 colpkg export"

This reverts commit 8f0b2c175f4794d642823b60414d142a12768441.

Will use a different approach

* Move legacy support into a separate exporter option; add to apkg export

* Adjust 'too new' message to also apply to .apkg import case

* Show a better message when attempting to import new apkg into old code

Previously the user could end seeing a message like:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 1: invalid start byte

Unfortunately we can't retroactively fix this for older clients.

* Hide legacy support option in older exporting screen

* Reflect change from paths to fnames in type & name

* Make imported decks normal at once

Then skip special casing in update_deck(). Also skip updating
description if new one is empty.

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2022-05-02 21:12:46 +10:00
Abdo
964f0a5763
Add relative overdueness to review order (#1757)
* Add relative overdueness to review order

* Add test for relative overdue
2022-04-09 13:20:09 +10:00
Damien Elmes
0fe2b6f699 Garbage-collect unused FTL strings
Two strings related to scheduler upgrade have been manually excluded,
as we may be able to reuse them for a future V3 update.
2022-04-09 12:39:50 +10:00
RumovZ
84e0acf9b7
Template order (#1769)
* Improve new card sort order tooltip

* Use card type instead of template in deck config

* Card type ordinal → card type number
2022-04-04 09:50:36 +10:00
Damien Elmes
6df63f8643 Tweak cloze deletion labels 2022-03-31 14:47:51 +10:00
Henrik Giesel
5b1fcccf33
Add extra button group for cloze commands (#1756)
* First attempt at adding a directory for icons under //ts

* Fix image import

* Fix import order

* Add cloze button group

* Fix issue with toolbar.toolbar dynamically slottable

* Change tooltip for repeating cloze deletion

* Fix repeat cloze button not working on macOS (dae)
2022-03-31 13:30:00 +10:00
Henrik Giesel
bf20353b53
Add tooltip that you can double-click image for restoring its size (#1738)
* Add tooltip that you can double-click image for restoring its size

* Update ftl/core/editing.ftl

Lower case label
2022-03-24 19:53:57 +10:00
Damien Elmes
4515c41d2c
Backup improvements (#1728)
* Collection needs to be closed prior to backup even when not downgrading

* Backups -> BackupLimits

* Some improvements to backup_task

- backup_inner now returns the error instead of logging it, so that
the frontend can discover the issue when they await a backup (or create
another one)
- start_backup() was acquiring backup_task twice, and if another thread
started a backup between the two locks, the task could have been accidentally
overwritten without awaiting it

* Backups no longer require a collection close

- Instead of closing the collection, we ensure there is no active
transaction, and flush the WAL to disk. This means the undo history
is no longer lost on backup, which will be particularly useful if we
add a periodic backup in the future.
- Because a close is no longer required, backups are now achieved with
a separate command, instead of being included in CloseCollection().
- Full sync no longer requires an extra close+reopen step, and we now
wait for the backup to complete before proceeding.
- Create a backup before 'check db'

* Add File>Create Backup

https://forums.ankiweb.net/t/anki-mac-os-no-backup-on-sync/6157

* Defer checkpoint until we know we need it

When running periodic backups on a timer, we don't want to be fsync()ing
unnecessarily.

* Skip backup if modification time has not changed

We don't want the user leaving Anki open overnight, and coming back
to lots of identical backups.

* Periodic backups

Creates an automatic backup every 30 minutes if the collection has been
modified.

If there's a legacy checkpoint active, tries again 5 minutes later.

* Switch to a user-configurable backup duration

CreateBackup() now uses a simple force argument to determine whether
the user's limits should be respected or not, and only potentially
destructive ops (full download, check DB) override the user's configured
limit.

I considered having a separate limit for collection close and automatic
backups (eg keeping the previous 5 minute limit for collection close),
but that had two downsides:

- When the user closes their collection at the end of the day, they'd
get a recent backup. When they open the collection the next day, it
would get backed up again within 5 minutes, even though not much had
changed.
- Multiple limits are harder to communicate to users in the UI

Some remaining decisions I wasn't 100% sure about:

- If force is true but the collection has not been modified, the backup
will be skipped. If the user manually deleted their backups without
closing Anki, they wouldn't get a new one if the mtime hadn't changed.
- Force takes preference over the configured backup interval - should
we be ignored the user here, or take no backups at all?

Did a sneaky edit of the existing ftl string, as it hasn't been live
long.

* Move maybe_backup() into Collection

* Use a single method for manual and periodic backups

When manually creating a backup via the File menu, we no longer make
the user wait until the backup completes. As we continue waiting for
the backup in the background, if any errors occur, the user will get
notified about it fairly quickly.

* Show message to user if backup was skipped due to no changes

+ Don't incorrectly assert a backup will be created on force

* Add "automatic" to description

* Ensure we backup prior to importing colpkg if collection open

The backup doesn't happen when invoked from 'open backup' in the profile
screen, which matches Anki's previous behaviour. The user could
potentially clobber up to 30 minutes of their work if they exited to
the profile screen and restored a backup, but the alternative is we
create backups every time a backup is restored, which may happen a number
of times if the user is trying various ones. Or we could go back to a
separate throttle amount for this case, at the cost of more complexity.

* Remove the 0 special case on backup interval; minimum of 5 minutes

https://github.com/ankitects/anki/pull/1728#discussion_r830876833
2022-03-21 19:40:42 +10:00
Damien Elmes
4687620f5e Expand normalization checks on import/export
The old Python code was only checking for NFC encoding, but we should
check for other issues like special filenames on windows (eg con.mp3)

- On export, the user is told to use Check Media if their media has
invalid filenames.
- On import, legacy packages will be transparently normalized. Since we're
doing the checks on export as well, any invalid names in a v3 package
are an error.
2022-03-17 17:31:19 +10:00
RumovZ
e759885734
Backend colpkg exporting (#1719)
* Implement colpkg exporting on backend

* Use exporting logic in backup.rs

* Refactor exporting.rs

* Add backend function to export collection

* Refactor backend/collection.rs

* Use backend for colpkg exporting

* Don't use default zip compression for media

* Add exporting progress

* Refactor media file writing

* Write dummy collections

* Localize dummy collection note

* Minimize dummy db size

* Use `NamedTempFile::new()` instead of `new_in`

* Drop redundant v2 dummy collection

* COLLECTION_VERSION -> PACKAGE_VERSION

* Split `lock_collection()` into two to drop flag

* Expose new colpkg in GUI

* Improve dummy collection message

* Please type checker

* importing-colpkg-too-new -> exporting-...

* Compress the media map in the v3 package (dae)

On collections with lots of media, it can grow into megabytes.

Also return an error in extract_media_file_names(), instead of masking
it as an optional.

* Store media map as a vector in the v3 package (dae)

This compresses better (eg 280kb original, 100kb hashmap, 42kb vec)

In the colpkg import case we don't need random access. When importing
an apkg, we will need to be able to fetch file data for a given media
filename, but the existing map doesn't help us there, as we need
filename->index, not index->filename.

* Ensure folders in the media dir don't break the file mapping (dae)
2022-03-15 16:48:02 +10:00
Bruce Harris
d7a101827a
Extend maximum answer time... (#1698)
* Extend maximum answer time...

Previously the time allowed to answer a question was capped at 10 minutes.
While this makes sense for fact recall, it limits the utility of Anki when
used for solving problems that can take more time to work through. This
extends the maximum answer time to 2 hours, which seems to be a reasonable
upper limit for solving a math or algorithm question.

* Add warning when max answer time exceeds 10 minutes

* Move warning below input field
2022-03-15 10:06:45 +10:00
Henrik Giesel
1ec3741934
Fix outstanding tag editor issues (#1717)
* Start using WithFloating for SelectedTagBadge

* Adjust arrow on WithFloating for all directions

* Move TagOptionsBadge to its own sub directory

* Show autocomplete menu via WithFloating

* Have WithFloating return asReference instead of initializing its own reference element

* Add html: overflow: hidden for editor

* Replace ButtonToolbar with generic div

* Move scroll logic into autocomplete item + restrict Popover width to 95vw

* Fix autocomplete menu after pressing enter after selecting

- should not trigger an autocomplete choose

* Overlap TagInput perfectly with Tag

* Satisfy formatter

* Fix autocompletion item scrolling too much

* Remove unused Tag.svelte focusable prop

* Remove console.log

* Fix floating arrow is a diamond in dark mode

* Set autocompletion menu to 80vw
2022-03-11 15:48:49 +10:00
Damien Elmes
f3e81c8a95 Move custom study tag and limit gathering+saving into the backend
Ideally this would have been in beta 6 :-) No add-ons appear to be
using customstudy.py/taglimit.py though, so it should hopefully not be
disruptive.

In the earlier custom study changes, we didn't get around to addressing
issue #1136. Now instead of trying to determine the maximum increase
to allow (which doesn't work correctly with nested decks), we just
present the total available to the user again, and let them decide. There's
plenty of room for improvement here still, but further work here might
be better done once we look into decoupling deck limits from deck presets.

Tags and available cards are fetched prior to showing the dialog now,
and will show a progress dialog if things take a while.

Tags are stored in an aux var now, so they don't inflate the deck
object size.
2022-03-10 16:23:03 +10:00
RumovZ
b9c3b12f71
Optionally restore original position and reset counts when forgetting (#1714)
* Add forget prompt with options

- Restore original position
- Reset reps and lapses

* Restore position when resetting for export

* Add config context to avoid passing keys

* Add routine to fetch defaults; use method-specific enum (dae)

* Keep original position by default (dae)

* Fix code completion for forget dialog (dae)

Needs to be a symbolic link to the generated file
2022-03-09 16:51:41 +10:00
RumovZ
c21e6e2b97
Disable full screen on Windows with OpenGL (#1715) 2022-03-09 14:21:54 +10:00
Damien Elmes
e6028cd9a4 Preserve old translation
7f076ee92a..9f37a0245c (r820447434)
2022-03-07 18:14:12 +10:00
RumovZ
f3c8857421
Backups (#1685)
* Add zstd dep

* Implement backend backup with zstd

* Implement backup thinning

* Write backup meta

* Use new file ending anki21b

* Asynchronously backup on collection close in Rust

* Revert "Add zstd dep"

This reverts commit 3fcb2141d2be15f907269d13275c41971431385c.

* Add zstd again

* Take backup col path from col struct

* Fix formatting

* Implement backup restoring on backend

* Normalize restored media file names

* Refactor `extract_legacy_data()`

A bit cumbersome due to borrowing rules.

* Refactor

* Make thinning calendar-based and gradual

* Consider last kept backups of previous stages

* Import full apkgs and colpkgs with backend

* Expose new backup settings

* Test `BackupThinner` and make it deterministic

* Mark backup_path when closing optional

* Delete leaky timer

* Add progress updates for restoring media

* Write restored collection to tempfile first

* Do collection compression in the background thread

This has us currently storing an uncompressed and compressed copy of
the collection in memory (not ideal), but means the collection can be
closed without waiting for compression to complete. On a large collection,
this takes a close and reopen from about 0.55s to about 0.07s. The old
backup code for comparison: about 0.35s for compression off, about
8.5s for zip compression.

* Use multithreading in zstd compression

On my system, this reduces the compression time of a large collection
from about 0.55s to 0.08s.

* Stream compressed collection data into zip file

* Tweak backup explanation

+ Fix incorrect tab order for ignore accents option

* Decouple restoring backup and full import

In the first case, no profile is opened, unless the new collection
succeeds to load.
In the second case, either the old collection is reloaded or the new one
is loaded.

* Fix number gap in Progress message

* Don't revert backup when media fails but report it

* Tweak error flow

* Remove native BackupLimits enum

* Fix type annotation

* Add thinning test for whole year

* Satisfy linter

* Await async backup to finish

* Move restart disclaimer out of backup tab

Should be visible regardless of the current tab.

* Write restored collection in chunks

* Refactor

* Write media in chunks and refactor

* Log error if removing file fails

* join_backup_task -> await_backup_completion

* Refactor backup.rs

* Refactor backup meta and collection extraction

* Fix wrong error being returned

* Call sync_all() on new collection

* Add ImportError

* Store logger in Backend, instead of creating one on demand

init_backend() accepts a Logger rather than a log file, to allow other
callers to customize the logger if they wish.

In the future we may want to explore using the tracing crate as an
alternative; it's a bit more ergonomic, as a logger doesn't need to be
passed around, and it plays more nicely with async code.

* Sync file contents prior to rename; sync folder after rename.

* Limit backup creation to once per 30 min

* Use zstd::stream::copy_decode

* Make importing abortable

* Don't revert if backup media is aborted

* Set throttle implicitly

* Change force flag to minimum_backup_interval

* Don't attempt to open folders on Windows

* Join last backup thread before starting new one

Also refactor.

* Disable auto sync and backup when restoring again

* Force backup on full download

* Include the reason why a media file import failed, and the file path

- Introduce a FileIoError that contains a string representation of
the underlying I/O error, and an associated path. There are a few
places in the code where we're currently manually including the filename
in a custom error message, and this is a step towards a more consistent
approach (but we may be better served with a more general approach in
the future similar to Anyhow's .context())
- Move the error message into importing.ftl, as it's a bit neater
when error messages live in the same file as the rest of the messages
associated with some functionality.

* Fix importing of media files

* Minor wording tweaks

* Save an allocation

I18n strings with replacements are already strings, so we can skip the
extra allocation. Not that it matters here at all.

* Terminate import if file missing from archive

If a third-party tool is creating invalid archives, the user should know
about it. This should be rare, so I did not attempt to make it
translatable.

* Skip multithreaded compression on small collections

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2022-03-07 15:11:31 +10:00
RumovZ
8504bd67ed
Fix bury count (more) (#1712)
* Fix bury count for negative values

* Enhance bury count tooltip

* Please type checker
2022-03-07 11:03:14 +10:00
Henrik Giesel
8b84368e3a
Move all buttons to our custom inline surrounding (#1682)
* Clarify some comments

* Don't destructure insertion trigger

* Make superscript and subscript use domlib/surround

* Create new {Text,Highlight}ColorButton

* Use domlib/surround for textcolor

- However there's still a crucial bug, when you're breaking existing
  colored span when unsurrounding, their color is not restored

* Add underline format to removeFormats

* Simplify type of ElementMatcher and ElementClearer for end users

* Add some comments for normalize-insertion-ranges

* Split normalize-insertion-ranges into remove-adjacent and remove-within

* Factor out find-remove from unsurround.ts

* Rename merge-mach, simplify remove-within

* Clarify some comments

* Refactor first reduce

* Refactor reduceRight

* Flatten functions in merge-ranges

* Move some functionality to merge-ranges and do not export

* Refactor merge-ranges

* Remove createInitialMergeMatch

* Finish refactoring of merge-ranges

* Refactor merge-ranges to minimal-ranges and add some unit testing

* Move more logic into text-node

* Remove most most of the logic from remove-adjacent

- remove-adjacent is still part of the "merging" logic, as it increases
  the scope of the child node ranges

* Add some tests for edge cases

* Merge remove-adjacent logic into minimal-ranges

* Refactor unnecessary list destructuring

* Add some TODOs

* Put removing nodes and adding new nodes into sequence

* Refactor MatchResult to MatchType and return clear from matcher

* Inline surround/helpers

* Shorten name of param

* Add another edge case test

* Add an example where commonAncestorContainer != normalization level

* Fix bug in find-adjacent when find more than one nested nodes

* Allow comments for Along type

* Simplify find-adjacent by removing intermediate and/or curried functions

* Remove extend-adjacent

* Add more tests when find-adjacent finds by descension

* Fix find-adjacent descending into block-level elements

* Add clarifying comment to refusing to descend into block-level elements

* Move shifting logic into find-adjacent

* Rename file matcher to match-type

* Give a first implemention of TreeVertex

* Remove MatchType.ALONG

- findAdjacent now directly modifies the range

* Rename MatchType.MATCH into MatchType.REMOVE

* Implement a version of find-within that utilizies match-tree

* Turn child node range into a class

* Fix bug in new find-adjacent function

* Make all find-adjacent tests test for ranges

* Surrounding within farthestMatchingAncestor when available

* Fix an issue with negligable elements

- also rename "along" elements to "negligable"

* Add two TODOs to SurroundFormat interface

* Have a messy first implementation of the new tree-node algorithm

* Maintain whether formatting nodes are covered or within user selection

* Move covered and insideRange into TreeNode superclass

* Reimplement findAdjacent logic

* Add extension logic

* Add an evaluate method to nodes

* Introduce BlockNode

* Add a first evaluate implementation

* Add left shift and inner shift logic

* Implement SurroundFormatUser

* Allow pass in formatter, ascender and merger from outside

* Fix insideRange and covered switch-up

* Fix MatchNode.prototype.isAscendable

* Fix another switch-up of covered and insideRange...

* Remove a lot of old code

* Have surround functions only return the range

- I still cannot think of a good reason why we should return addedNodes
  and removedNodes, except for testing.

* Create formatting-tree directory

* Create build-tree directory + Move find-above up to /domlib

* Remove range-anchors

* Move unsurround logic into no-splitting

* Fix extend-merge

* Fix inner shift being eroneusly returned as left shift

* Fix oversight in SplitRange

* Redefine how ranges are recreated

* Rename covered to insideMatch and put as fourth parameter instead of third

* Keep track of match holes and match leaves

* Rename ChildNodeRange to FlatRange

* Change signature of matcher

* Fix bug in extend-merge

* Improve Match class

* Utilize cache in TextColorButton

* Implement getBaseSurrounder for TextColorButton

* Add matchAncestors field to FormattingNode

* Introduce matchAncestors and getCache

* Do clearing during parsing already

- This way, you know whether elements will be removed before getting to
  Formatting nodes

* Make HighlightColorButton use our surround mechanism

* Fix a bug with calling .removeAttribute and .hasAttribute

* Add side button to RemoveFormat button

* Add disabled to remove format side button

* Expose remove formats on RemoveFormat button

* Reinvent editor/surround as Surrounder class

* Fix split-text when working with insert trigger

* Try counteracting the contenteditable's auto surrounding

* Remove matching elements before normalizing

* Rewrite match-type

* Move setting match leaves into build

* Change editing strings

- So that color strings match bold/italic strings better

* Fix border radius of List options menu

* Implement extensions functionality

* Remove some unnecessary code

* Fix split range endOffset

* Type MatchType

* Reformat MatchType + add docs

* Fix domlib/surround/apply

* Satisfy last tests

* Register Surrounder as package

* Clarify some comments

* Correctly implement reformat

* Reformat with inactive eraser formats

* Clear empty spans with RemoveFormatButton

* Fix Super/Subscript button

* Use ftl string for hardcoded tooltip

* Adjust wording
2022-02-22 22:17:22 +10:00
RumovZ
131a94dd85
Config for burying interday learning cards (#1680)
* Add config for burying interday learning cards

* Expose bury interday learning config in GUI
2022-02-22 21:37:59 +10:00
RumovZ
700fc50f7a
View menu (#1668)
* Add main view menu

* Add browser view menu

* Use standard keys for zooming and full screen

* Capitalise menu item names

* Toggle Showing Cards/Notes -> Toggle Cards/Notes

* Explicitly set linux full screen key

on_toggle_fullscreen -> on_toggle_full_screen
2022-02-17 16:31:46 +10:00
Abdo
fd6a78e7cf
Add option to ignore accents in search by default (#1667)
* Add option to ignore accents in unqualified search

* Support ignoring accents in word boundary search

* Update ftl/core/preferences.ftl
2022-02-17 16:30:52 +10:00
Damien Elmes
b6d7ef506e tweak insertion order tip 2022-02-11 23:27:15 +10:00
RumovZ
d55f080733
V3 parent limits (#1638)
* avoid repinning Rust deps by default

* add id_tree dependency

* Respect intermediate child limits in v3

* Test new behaviour of v3 counts

* Rework v3 queue building to respect parent limits

* Add missing did field to SQL query

* Fix `LimitTreeMap::is_exhausted()`

* Rework tree building logic

https://github.com/ankitects/anki/pull/1638#discussion_r798328734

* Add timer for build_queues()

* `is_exhausted()` -> `limit_reached()`

* Move context and limits into `QueueBuilder`

This allows for moving more logic into QueueBuilder, so less passing
around of arguments. Unfortunately, some tests will require additional
work to set up.

* Fix stop condition in new_cards_by_position

* Fix order gather order of new cards by deck

* Add scheduler/queue/builder/burying.rs

* Fix bad tree due to unsorted child decks

* Fix comment

* Fix `cap_new_to_review_rec()`

* Add test for new card gathering

* Always sort `child_decks()`

* Fix deck removal in `cap_new_to_review_rec()`

* Fix sibling ordering in new card gathering

* Remove limits for deck total count with children

* Add random gather order

* Remove bad sibling order handling

All routines ensure ascending order now.
Also do some other minor refactoring.

* Remove queue truncating

All routines stop now as soon as the root limit is reached.

* Move deck fetching into `QueueBuilder::new()`

* Rework new card gather and sort options

https://github.com/ankitects/anki/pull/1638#issuecomment-1032173013

* Disable new sort order choices ...

depending on set gather order.

* Use enum instead of numbers

* Ensure valid sort order setting

* Update new gather and sort order tooltips

* Warn about random insertion order with v3

* Revert "Add timer for build_queues()"

This reverts commit c9f5fc6ebe87953c17a0c842990b009b5596c69c.

* Update rslib/src/storage/card/mod.rs (dae)

* minor wording tweaks to the tooltips (dae)

+ move legacy strings to bottom
+ consistent capitalization (our leech action still needs fixing,
but that will require introducing a new 'suspend card' string as the
existing one is used elsewhere as well)
2022-02-10 09:55:43 +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
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
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
f2173fddb0
Live theme changes (#1497)
* Allow theme change at runtime and add hook

* Save or restore default palette on theme change

* Update aqt widget styles on theme change

* styling fixes

- drop _light_palette, as default_palette serves the same purpose
- save default platform theme, and restore it when switching away
from nightmode
- update macOS light/dark mode on theme switch
- fix unreadable menus on Windows

* update night-mode classes on theme change

This is the easy part - CSS styling that uses standard_css or our
css variables should update automatically. The main remaining issue
is JS code that sets colors based on the theme at the time it's run -
eg the graph code, and the editor.

* switch night mode value on toggle

* expose current theme via a store; switch graphs to use it

https://github.com/ankitects/anki/issues/1471#issuecomment-972402492

* start using currentTheme in editor/components

This fixes basic editing - there are still components that need updating.

* add simple xcodeproj for code completion

* add helper to get currently-active system theme on macOS

* fix setCurrentTheme not being immediately available

* live update tag color

* style().name() doesn't work on Qt5

* automatic theme switching on Windows/Mac

* currentTheme -> pageTheme

* Replace `nightModeKey` with `pageTheme`

Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2021-11-25 07:17:41 +10:00
Damien Elmes
cb8c83a405 run ftl/remove-unused.sh 2021-11-24 14:44:02 +10:00
Damien Elmes
7f40d6d2a5 retire the v1 scheduler 2021-11-24 14:12:56 +10:00
Matthias Metelka
68092082f2
Change Notetype UI Rework (#1499)
* Enable access to old notetype name

* Set minimum height for ChangeNotetypeDialog

* Add bootstrap icons to change-notetype

* Move alert up and make it collapsible

* Tweak some CSS

- Add variables --sticky-bg and --sticky-border to StickyContainer
- Tweak base.css

* Add translatable string "(Nothing)"

* Rework ChangeNotetype screen

* Initially load option at newIndex and remaining options on focus

Optimization for big notetypes:
Should increase efficiency from O(n²) to O(n). Test on notetype with 500 templates shows significant improvement in load time (~10s down to ~1s).

* Try to satisfy rust test

* Change arrow direction depending on reading direction

+ add 0.5em top padding to main

* Create Alert.svelte

* Introduce CSS variable --pane-bg

* Revert "Initially load option at newIndex and remaining options on focus"

This reverts commit f42beee45c27dba9433d76217fb583b117fb5231.

* Final cleanup

* Refine padding/gutter
2021-11-24 12:09:55 +10:00
Damien Elmes
18b7691e2c drop beta tag from v3 scheduler
Will exit beta when 2.1.50 is released as stable
2021-11-23 11:10:04 +10:00
Henrik Giesel
2778b9220c
Mathjax editor improvements (#1502)
* Remove unnecessary stopPropagation of mathjax-overlay events

* Use CodeMirror component for MathjaxHandle

* Refactor ResizeObserver code in MathjaxHandle

* Wrap setRange in CodeMirror in try/catch

* Add Mathjax Editor bottom margin

* Add custom Enter and Shift+Enter shortcuts for the MathjaxHandle

* Format

* Move placeCaretAfter to domlib

* Move focus back to field after editing Mathjax

* Put Cursor after Mathjax after accepting

* Add delete button for Mathjax

* Change border color of mathjax menu

* Refactor into MathjaxMenu

* Put caretKeyword in variable

* Use one ResizeObserver for all Mathjax images

* Add minmimum width for Mathjax editor

* is still smaller than minimal window width

* Add bazel directories to .prettierignore and format from root

* exclude ftl/usage (dae)

the json files that live there are output from our tooling, and
formatting them means an extra step each time we want to update them

also exclude .mypy_cache, which is output by scripts/mypy*

* minor ftl tweak: newline -> new line  (dae)
2021-11-23 10:27:32 +10:00
Matthias Metelka
371f731e30
Editor Field Descriptions (#1476)
* Add description input to fields dialog

QLineEdit seems like the best option, as it saves space and motivates users to keep their descriptions concise.

* Add setDescriptions to note initialization script

Went for the extra function instead of including it in setFields to prevent potential add-on breakages.

* Add tooltip next to field name if description is set

* Refactor code according to suggestions

Set default tooltip placement to right instead of bottom

Use .get() for fld["description"]

Fix tab order in fields dialog

Swap out abbreviation "desc" for full length name to keep consistency

* Update Protobuf and Rust for description

Add description to notetypes.proto and schema11

Co-authored-by: RumovZ <RumovZ@users.noreply.github.com>

* Fix tooltips not updating with description

Remove redundant variable tooltipOptions

Update previousTooltip within reactive function

* Move LabelDescription out of LabelName

Co-authored-by: Henrik Giesel <hgiesel@users.noreply.github.com>

* Decrease icon size and fix alignment

Co-Authored-By: Henrik Giesel <hengiesel@gmail.com>

* the new key needs to be cleared from fields, not the notetype itself

Co-authored-by: RumovZ <RumovZ@users.noreply.github.com>
Co-authored-by: Henrik Giesel <hengiesel@gmail.com>
Co-authored-by: Damien Elmes <gpg@ankiweb.net>
2021-11-06 09:42:48 +10:00
RumovZ
3cdb3d72c1
Do not bury suspended cards (#1447)
* Skip burying for suspended cards

* Inform about number of buried cards
2021-10-23 11:04:26 +10:00
RumovZ
5062024974 Move update logic into CardInfo.svelte 2021-10-18 09:01:24 +02:00
RumovZ
1d63253b4f Make window titles more user-friendly 2021-10-18 09:01:23 +02:00
RumovZ
f0d7e6f4d1 Use updating card infos in browser and reviewer 2021-10-18 09:01:23 +02:00
Damien Elmes
a174c41801
Merge pull request #1397 from RumovZ/column-tooltips
Add tooltips for some browser columns
2021-10-01 19:12:59 +10:00
Damien Elmes
c413a0d9f2
"number of cards a note has" 2021-10-01 19:12:49 +10:00
RumovZ
ee2ecd0700 Add tooltips for some browser columns 2021-09-30 13:15:09 +02:00
RumovZ
b89913a2c0
Apply suggestions from code review
Capitalise "selected"

Co-authored-by: Damien Elmes <dae@users.noreply.github.com>
2021-09-22 16:59:05 +02:00
RumovZ
75f210a66c Enable adding/removing tags from the sidebar ...
... to selected notes.
2021-09-21 11:48:43 +02:00
Damien Elmes
b877026248 don't check state of current card when repositioning
closes #1365
2021-09-13 14:56:53 +10:00
Damien Elmes
bbd7d057d8
Merge pull request #1358 from evandroforks/lastcardinfo
Add option to reveal previous card's info
2021-09-13 12:06:10 +10:00
Damien Elmes
8a0ccee840 tweak sync conflict message 2021-09-08 19:19:23 +10:00