Skip to content
This repository has been archived by the owner on Dec 31, 2023. It is now read-only.

Add Edit dialog #306

Merged
merged 17 commits into from
Apr 20, 2022
Merged

Add Edit dialog #306

merged 17 commits into from
Apr 20, 2022

Conversation

oakkitten
Copy link
Contributor

@oakkitten oakkitten commented Mar 8, 2022

As discussed in FooSoft/yomichan#2070, this dialog can be an alternative to opening Browser after adding a card in Yomichan. Some parts of the browser, such as the sidebar and the note list, take a lot of space and cannot be collapsed fully. This dialog looks like Edit Current dialog, except it:

  • has a Preview button to preview the cards for this note in its regular place
  • has a Browse button to open the Browser with them
  • has Previous/Back buttons to navigate the history of the dialog
  • has no Close button bar

image

This is a work in progress. At the time being the code works fine on Anki ⁨2.1.49 (dc80804a) but has not been tested on other Anki versions. ⁩Remains to be done:

  • Add the API
  • [ ] Make code compatible with earlier Anki versions
  • See whether the upcoming Anki version breaks it
  • Add tests
  • Update documentation

I made some decisions that I'm not completely confident in.

  • I used snake case not camel case. This seems to be what Anki is moving to, and the file is isolated.
  • I chose the hotkey Ctrl-F for the Browser, and Alt-Left and Alt-Right for the Previous/Next buttons. Ctrl-F is easy to press and that's one of the hotkeys that focus the input field in the Browser. Alt-Left and Alt-Right are what browsers normally use so I hope these are a good fit.
  • I choose "foosoft.ankiconnect." as a prefix for various identifiers, something else might be more appropriate?
  • Previous/Next buttons navigate between whatever has been opened in the dialog. Alternatively, it could navigate the cards in the order added.
  • If the dialog history is empty and you delete the note in the browser, the Browser fails to reflect the change, keeping the Editor open. It leads to errors if you try to edit the note since it does not exist; however this appears harmless, so I don't suppose this requires much attention? This appears to be a bug in Anki, since the Edit Current dialog is also affected. Not sure what causes it.

Also, what's the minimal version of Anki that the code is supposed to support? This should work on Anki 2.1.45+ without changes. Making it work with earlier versions would lead to significant ugliness.

@oakkitten
Copy link
Contributor Author

I looked into testing a bit. It seems that the best choice would be pytest and pytest-anki, although it's at the time still in beta. Would it be feasible to move the tests to pytest, and perhaps throw in poetry and perhaps CI?

Not sure how to run existing tests, they seem to be failing due to various errors, such as

Exception: rem() takes 2 positional arguments but 3 were given

or

Exception: model was not found: Basic

@FooSoft
Copy link
Owner

FooSoft commented Mar 20, 2022

I used snake case not camel case. This seems to be what Anki is moving to, and the file is isolated.

I think that's fine. I actually prefer snake case myself (as that follows the python coding standard), but the code all used to be camel case, which I have been matching. Agreed that it just makes sense to use snake case going forward.

I chose the hotkey Ctrl-F for the Browser, and Alt-Left and Alt-Right for the Previous/Next buttons. Ctrl-F is easy to press and that's one of the hotkeys that focus the input field in the Browser. Alt-Left and Alt-Right are what browsers normally use so I hope these are a good fit.

Sounds good to me.

I choose "foosoft.ankiconnect." as a prefix for various identifiers, something else might be more appropriate?

I think it's great that there is any sort of identifier at all :) That should work just fine.

Previous/Next buttons navigate between whatever has been opened in the dialog. Alternatively, it could navigate the cards in the order added.

Fine with either approach.

If the dialog history is empty and you delete the note in the browser, the Browser fails to reflect the change, keeping the Editor open. It leads to errors if you try to edit the note since it does not exist; however this appears harmless, so I don't suppose this requires much attention? This appears to be a bug in Anki, since the Edit Current dialog is also affected. Not sure what causes it.

Yeah I wouldn't worry about it. It may be fixed in future releases of AnkiConnect for all we know.

@oakkitten
Copy link
Contributor Author

Aha, great! As for testing;

I've been experimenting with testing a bit and if that's fine with you I can try to fix current tests. Most now fail due to changes in Anki. I want to:

@oakkitten
Copy link
Contributor Author

oakkitten commented Mar 30, 2022

Anyway, here's my attempt, with tests running on GitHub Actions passing. I hope the commit history is ok. This PR is mostly ready, but I'll keep it as a draft for a few days in case I remember anything.

I removed one API method and fixed a few and converted all tests to pytest and made them run with tox against Anki versions 2.1.45 to 2.1.49. The tests might be slightly flaky. I fixed all of the flakiness I could find but I'm not sure what can be done about segfaults. If the tests prove too flaky, we can try run them forked with tox -- --forked. Either way, you should be able to rerun the workflow by pressing a button. Currently the tests run (mostly) in a single process, with the profile being torn down after each test. Actions run so much faster than my computer so if there's any issues due to computer speed I won't be able to deal with those. See tox.ini regarding how to run tests.

As for the Edit dialog, I refactored it slightly and added a guiEditNote method that takes an integer note. I'm not sure if the method should attempt to coerce note to int if it is a str; for now I let it fail.

Note that I added GitHub actions for PRs as well. This should be safe as due to the dangers inherent to automatic processing of PRs, GitHub’s standard pull_request workflow trigger by default prevents write permissions and secrets access to the target repository. Just something to keep in mind.

@FooSoft
Copy link
Owner

FooSoft commented Apr 2, 2022

This is all looking good so far 👍
Set the PR is ready when you feel it is in a good spot for merge.

@oakkitten
Copy link
Contributor Author

Thanks! Of course right after pushing I discovered a major problem, that should be fixed now. A few issues should be adressed before this is ready to merge though.

  • There's one skipped test. I want to remove it and disallow calling guiAddCards with the argument closeAfterAdding=True. While the code does not outright break, the resulting dialog does not do what it is supposed to do anyway.

  • The tests run against Anki 2.1.45-2.1.49 but the plugin might be broken in earlier Anki versions. Is it ok to drop support for Anki < 2.1.45? I think you have multiple versions of an addon (“branches”) on AnkiWeb with different versions supported. I guess targetting 2.1.45+ only will make it easier to support 2.1.50 as well.

Oh and I guess the documentation needs to get updated.

P.S. I set the tests to run with --forked and they seem to be very stable in the CI

@FooSoft
Copy link
Owner

FooSoft commented Apr 6, 2022

I wouldn't worry too much about older versions; they can always use older releases if necessary (or just upgrade to a newer version of AnkiConnect).

oakkitten added 15 commits April 7, 2022 09:48
Like Edit Current, but:
  * has a Preview button to preview all cards for this note
  * has a Browse button to open the browser with these
  * has Previous/Back buttons to navigate the history of the dialog
  * has no Close button bar
The method was failing due to Anki API changes.

Also, make it mandatory to call the method with `cardsToo=True`,
since deleting decks on Anki >= 2.1.28 without cards is
no longer supported, and the deprecated `decks.rem()` method
on Anki >= 2.1.45 ignores keyword arguments.
I think this was a typo?
This method was broken and there are no issues regarding it on GitHub.
Don't start the web server if imported not from inside Anki

Make sure Anki Connect instance is not garbage collected.
This kills the timer that's responsible for the web server.
* make previewer use a more generic Adapter to flip through cards;
* return Previewer from `show_preview()` for testing,
* as well as Edit dialog from `open_dialog_and_show_note_with_id`;
* disable/enable `Edit` editor buttons more reliably;
* a few minor changes
So that it is importable by tests
Previously, tests were run against Anki launched by user.

Now,
 * most tests run against isolated Anki in current process;
 * tests in `test_server.py` launch another Anki in a separate process
   and run a few commands to test the server;
 * nearly all tests were preserved in the sense that
   what was being tested is tested still.
   A few tests in `test_graphical.py` are skipped due to
   a problem with the method tests, see the comments;
 * tests can be run:
   * In a single profile, using --no-tear-down-profile-after-each-test;
   * In a single app instance, but with the profile being torn down
     after each test--default;
   * In separate processes, using --forked.
The tests can be run now using `tox` against multiple Anki versions;
see instructions in `tox.ini`.

The tests depend on `pytest-anki` that had to be slightly modified
to remove the upper constraint on Anki version, as well as
to remove a few dependencies that are not essential to using it.
The functionality was broken, creating a dialog that was not,
in fact, closing after adding a card.

See the deleted comment in `test_graphical.py`
It turns out that `pytest-anki` does what we are trying to do already.

Note that `empty_anki_session_started` creates a temporary user too.
We are “overwriting“ it in `profile_created_and_loaded`
by calling `temporary_user`. It seems that doing this is safe.
Before, pressing the Browse button would only show browser
with the cards or notes corresponding to the currently edited note.

Now, it shows all cards or notes from the dialog history,
in reverse order (last seen on top),
with the currently edited note or its cards selected.
Waitress is a WSGI server that Anki starts to serve css etc to
its web views. It seems to have a race condition issue;
the main loop thread is trying to `select.select` the sockets
which a worker thread is closing because of a dead connection.

This makes waitress skip actually closing the sockets.
@oakkitten
Copy link
Contributor Author

Okay I think this is nearly there (again). I also:

  • Made guiAddCards ignore the option closeAfterAdding I mentioned above;
  • Made browser show all the history of the Edit dialog, not just the current note. The table of cards/notes is shown with the most recently opened note on top. The currently opened note, or all cards corresponding to it, are selected. Also, the sorting column indicator is removed to signal that no browser sorting has been performed, but if the user does click on any columns, the sorting works as expected. I guess this worked out pretty awesomely if I do say so myself, and the code isn't even too hacky;
  • Figured out a major source of test flakiness and removed it. This actually like a bug in a library used by Anki and might be leading to other issues with Anki, I'll report it there once I get the reply from the library authors.

I'll give it a couple of days and then mark as ready. A few days ago Anki 2.1.50 was released and I want to fix the test to also pass for Anki 2.1.50. Shouldn't be too hard, although since they changed all things JavaScript, adding buttons will require some work.

@oakkitten oakkitten marked this pull request as ready for review April 18, 2022 13:35
@FooSoft
Copy link
Owner

FooSoft commented Apr 20, 2022

Awesome work! I'll put this on AnkiWeb this week.

@FooSoft FooSoft merged commit 41d5904 into FooSoft:master Apr 20, 2022
@oakkitten
Copy link
Contributor Author

Thanks! Although it might have been better not to squash the commits. I specifically tried making the commits in such a way that they are useful for anyone who later looks at git history.

Anyway, I think I will have a few more fixes for Anki 2.1.50 shortly 😛

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants