Commit graph

1062 commits

Author SHA1 Message Date
Damien Elmes
b9bb9920b5 more reset refactoring
'card modified' covers the common case where we need to rebuild the
study queue, but is also set when changing the card flags. We want to
avoid a queue rebuild in that case, as it causes UI flicker, and may
result in a different card being shown. Note marking doesn't trigger
a queue build, but still causes flicker, and may return the user back
to the front side when they were looking at the answer.

I still think entity-based change tracking is the simplest in the
common case, but to solve the above, I've introduced an enum describing
the last operation that was taken. This currently is not trying to list
out all possible operations, and just describes the ones we want to
special-case.

Other changes:

- Fire the old 'state_did_reset' hook after an operation is performed,
so legacy code can refresh itself after an operation is performed.
- Fire the new `operation_did_execute` hook when mw.reset() is called,
so that as the UI is updated to the use the new hook, it will still
be able to refresh after legacy code calls mw.reset()
- Update the deck browser, overview and review screens to listen to
the new hook, instead of relying on the main window to call moveToState()
- Add a 'set flag' backend action, so we can distinguish it from a
normal card update.
- Drop the separate added/modified entries in the change list in
favour of a single entry per entity.
- Add typing to mw.state
- Tweak perform_op()
- Convert a few more actions to use perform_op()
2021-03-19 19:45:21 +10:00
Damien Elmes
fbcfa48419 experiment with finer-scoped reset in perform_op()
Basic proof of concept, where the 'delete note' operation in the
reviewer has been updated to use mw.perform_op(). Instead of manually
calling .reset() afterwards, a summary of the changes is returned as
part of the undo status query, and various parts of the GUI can listen
to gui_hooks.operation_did_execute and decide whether they want to
redraw based on the scope of the changes. This should allow the sidebar
to selectively redraw just the tags area in the future for example.

Currently we're just listing out all possible areas that might be changed;
in the future we could theoretically inspect the specific changes in the
undo log to provide a more accurate report (avoiding refreshing the tags
list when no tags were added for example).

You can test it out by opening the browse screen while studying, and
then deleting the current card - the browser should update to show (deleted)
on the cards due the earlier change.

If going ahead with this, aside from updating all the screens that currently
listen for resets, some thought will be required on how we can integrate
it with legacy code that expects to called when resets are made, and expects
to call .reset() when it makes changes.

Thoughts?
2021-03-19 19:45:21 +10:00
Damien Elmes
4fa632f335 derive reset scope from last undoable operation 2021-03-19 19:45:21 +10:00
Damien Elmes
c72862af9f move ops.rs out of undo/ 2021-03-19 19:45:21 +10:00
Damien Elmes
b8e56dafda move collection mtime bump into backend
Fixes the following issue:
- some code directly modifies the database, causing modified_in_python
to be set to true
- an undoable operation is run, which calls autosave() at the end
- autosave() notices there's an undoable operation, and commits immediately
- because modified_in_python was true, col.mtime was bumped in Python
- that invalidated the undo queue, preventing the operation from being
undone
2021-03-19 19:45:21 +10:00
Arthur Milchior
d1bf02a709 If a template name contains only quote, show relevant error message
This is for the sake of the consistency with the last commit
2021-03-14 02:10:48 +01:00
Arthur Milchior
574a513fe6 Return meaningful message if a field is empty after normalizing
This correct the probably rare bug as follow:

I got a note type with a field whose name is "\".

When I made any change to this note type, even unrelated, I get a message stating that there is an empty field. This is
strange because I can see it to be false. Investigating show that "\" is normalized to empty field. This ensure that
it's shown
2021-03-14 02:10:32 +01:00
Damien Elmes
b5a913c1cf Merge pull request #1067 from RumovZ/regex-err
Fix regex error formatting and search error escaping
2021-03-13 10:16:10 +10:00
RumovZ
9bbe584522 Fix markdown escaping in search errors 2021-03-12 20:32:38 +01:00
RumovZ
456a3b214a Fix formatting of invalid regex error
Preserve whitespace, special characters and use monospace font.
2021-03-12 20:31:23 +01:00
Damien Elmes
ae6cf81d69 add indexes to graves table to speed up undo 2021-03-12 18:59:24 +10:00
Damien Elmes
b9581b94fb 'change deck' now undoable 2021-03-12 16:27:57 +10:00
Damien Elmes
5b52f0e931 consume original card when updating 2021-03-12 16:20:58 +10:00
Damien Elmes
fef8c402e0 make 'forget card' undoable; remove checkpoint() in set_due_date 2021-03-12 16:13:50 +10:00
Damien Elmes
28cd625204 limit initial sort selection to new cards
https://github.com/ankidroid/Anki-Android/issues/8172
2021-03-12 14:58:19 +10:00
Damien Elmes
7f8d675e25 'set due date' now undoable 2021-03-12 14:50:31 +10:00
Damien Elmes
091ea67690 enable deck removal undo again 2021-03-11 22:24:12 +10:00
RumovZ
b093d62f5a Merge branch 'master' into sidebar-tools 2021-03-11 12:08:32 +01:00
Damien Elmes
abf4ef9eac deck drag&drop undo 2021-03-11 20:02:16 +10:00
Damien Elmes
f09c1d027c add a separate 'rename deck' method 2021-03-11 19:24:54 +10:00
RumovZ
193e7cc2aa Remove deck remove prompt but show card count 2021-03-11 09:52:11 +01:00
RumovZ
a5464de688 Show tooltip instead of prompt for removing tags 2021-03-11 09:14:50 +01:00
Damien Elmes
c89fea1174 split out remaining rpc methods
@david-allison-1 note this also changes the method index to start at
0 instead of 1
2021-03-11 17:04:32 +10:00
Damien Elmes
35a2022901 split out stats, media and search 2021-03-11 16:16:40 +10:00
Damien Elmes
ebc5695038 split out tags, deck config and card rendering 2021-03-11 16:05:06 +10:00
Damien Elmes
c30d3ee137 split out sync, notetypes and config code 2021-03-11 15:47:31 +10:00
Damien Elmes
7c09b73b6b rework backend codegen to support multiple services; split out sched
Rust requires all methods of impl Trait to be in a single file, which
means we had a giant backend/mod.rs covering all exposed methods. By
using separate service definitions for the separate areas, and updating
the code generation, we can split it into more manageable chunks -
this commit starts with the scheduling code.

In the long run, we'll probably want to split up the protobuf file into
multiple files as well.

Also dropped want_release_gil() from rsbridge, and the associated method
enum. While it allows us to skip the thread save/restore and mutex unlock/
lock, it looks to only be buying about 2.5% extra performance in the
best case (tested with timeit+format_timespan), and the majority of
the backend methods deal with I/O, and thus were already releasing the
GIL.
2021-03-11 14:51:29 +10:00
RumovZ
d11e9a5d3f Borrow dids in remove_decks_and_child_decks 2021-03-10 15:56:54 +01:00
Damien Elmes
78a37c7935 make sure we invalidate cache when undoing deck add 2021-03-10 23:59:40 +10:00
Damien Elmes
c2280cb776 undo support for deck adding/removing
Work in progress - still to do:
- renames appear as 'Update Deck' - easiest way to solve it would
be to have a separate backend method for renames
- drag&drop of decks not yet undoable
- since the undo status is updated after the backend method ends,
the older checkpoint() calls need to be replaced with an
update_undo_status() at the end of the call - if we just remove the
checkpoint, then the menu doesn't get updated
2021-03-10 23:50:11 +10:00
RumovZ
c018c31985 Merge branch 'master' into sidebar-tools 2021-03-10 10:34:36 +01:00
Damien Elmes
99f825c138 expand backend Preferences and make undoable
- moved 'default to current deck when adding' into prefs
- move some profile options into the collection config, so they're
undoable and will sync. There is (currently) no automatic migration
from the old profile settings, meaning users will need to set the
options again if they've customized them.
- tidy up preferences.py
- drop the deleteMedia option that was not exposed in the UI
2021-03-10 18:51:03 +10:00
Damien Elmes
37b34d5da9 inline scheduling settings into preferences 2021-03-10 14:11:59 +10:00
Damien Elmes
0d4e70fa64 roll back slog-term due to Windows break (2/2)
The cargo.toml update was missing from the previous commit, and term
was included directly when it didn't need to be.
2021-03-10 13:28:32 +10:00
Damien Elmes
a5c2766a71 roll back slog-term due to Windows breakage 2021-03-10 12:22:11 +10:00
Damien Elmes
13b61e081b move sync/err backend code into separate files 2021-03-10 11:53:27 +10:00
Damien Elmes
12cb903427 move progress and search backend code into separate files 2021-03-10 11:53:27 +10:00
Damien Elmes
7e93000e4d undo support for config entries 2021-03-10 11:53:27 +10:00
Damien Elmes
ade12fe2fb Simplify note adding and the deck/notetype choosers
The existing code was really difficult to reason about:

- The default notetype depended on the selected deck, and vice versa,
and this logic was buried in the deck and notetype choosing screens,
and models.py.
- Changes to the notetype were not passed back directly, but were fired
via a hook, which changed any screen in the app that had a notetype
selector.

It also wasn't great for performance, as the most recent deck and tags
were embedded in the notetype, which can be expensive to save and sync
for large notetypes.

To address these points:

- The current deck for a notetype, and notetype for a deck, are now
stored in separate config variables, instead of directly in the deck
or notetype. These are cheap to read and write, and we'll be able to
sync them individually in the future once config syncing is updated in
the future. I seem to recall some users not wanting the tag saving
behaviour, so I've dropped that for now, but if people end up missing
it, it would be simple to add as an extra auxiliary config variable.
- The logic for getting the starting deck and notetype has been moved
into the backend. It should be the same as the older Python code, with
one exception: when "change deck depending on notetype" is enabled in
the preferences, it will start with the current notetype ("curModel"),
instead of first trying to get a deck-specific notetype.
- ModelChooser has been duplicated into notetypechooser.py, and it
has been updated to solely be concerned with keeping track of a selected
notetype - it no longer alters global state.
2021-03-10 11:53:27 +10:00
Damien Elmes
9312ad2a5e split config.rs up 2021-03-10 11:53:27 +10:00
Damien Elmes
9f47b75ac6 native stringkey 2021-03-10 11:53:27 +10:00
Damien Elmes
6469e454f1 use native boolkey instead of separate getters/setters
Makes it easier to add new config settings in the future, especially
if we don't need to export them via protobuf.
2021-03-10 11:53:27 +10:00
Damien Elmes
831f8528d2 use strum for config keys 2021-03-10 11:53:27 +10:00
Damien Elmes
79e6de24ae add strum crate 2021-03-10 11:53:27 +10:00
Damien Elmes
f8e023d56b update Rust deps 2021-03-10 11:53:27 +10:00
Damien Elmes
1ba7f66413 when only sort field changed, we don't need to update ordinals 2021-03-10 11:53:27 +10:00
Damien Elmes
aff8df067d make flag changes in the reviewer undoable
This splits update_card() into separate undoable/non-undoable ops
like the change to notes in b4396b94abdeba3347d30025c5c0240d991006c9

It means that actions get a blanket 'Update Card' description - in the
future we'll probably want to either add specific actions to the backend,
or allow an enum or string to be passed in to describe the op.

Other changes:
- card.flush() can no longer be used to add new cards. Card creation
is only supposed to be done in response to changes in a note's fields,
and this functionality was only exposed because the card generation
hadn't been migrated to the backend at that point. As far as I'm aware,
only Arthur's "copy notes" add-on used this functionality, and that should
be an easy fix - when the new note is added, the associated cards will
be generated, and they can then be retrieved with note.cards()
- tidy ups/PEP8
2021-03-10 11:53:27 +10:00
Damien Elmes
15dc6766f2 coalesce note updates; avoid unnecessary saving due to mtime changes 2021-03-10 11:53:27 +10:00
Damien Elmes
254c9dab69 dispatch undo operations via enum instead of trait
To coalesce successive note edits into a single undo op we'll need to
be able to get the original Undoable type, which is awkward to do with
a trait object.
2021-03-10 11:53:27 +10:00
Damien Elmes
18fed218e4 move remaining undo ops into separate files 2021-03-10 11:53:27 +10:00