matthayes / anki_cloze_anything

Add cloze deletions to any existing Anki notes without any modification to Anki
https://ankiweb.net/shared/info/330680661
Apache License 2.0
52 stars 10 forks source link

Cloze not created, then created for wrong text #26

Closed jsreaves closed 2 years ago

jsreaves commented 2 years ago

Hello Matt,

Since a recent Anki upgrade (not sure if it was 2.1.49 or the one before), the cloze button hasn't worked for me. I understand this was due to changes in the Anki editor that caused Cloze Anything to break. Despite this, I was still able to use Cmd+Shift+C to create clozes with my custom Cloze Anything template. (I have been using the Custom Keyboard Shortcuts addon.) I was accustomed to seeing some weird behavior with the numbered fields but these were easily corrected.

Today, I noticed that the keyboard shortcut is no longer working. Now, when I press Cmd-Shift-C the behavior has reverted to the default Anki "{{c1:blah}}" cloze, and it complains that I'm not using the Anki cloze template. I'm not sure what I did to cause things to break today; I did experiment with Notion 2 Anki, which added a couple of new card templates (which I later deleted), but I can't see why this would have affected Cloze Anything.

In the course of troubleshooting the problem, I'm seeing some strange behavior with Cloze Anything. Here's an example, which I'm seeing when using the Cloze Anything template from the sample deck, and with the Custom Keyboard shortcuts add-on disabled:

  1. Type "first second" into the ExpressionCloze field.
  2. Select "first" and click the cloze button. "((c1::first))" is not created (the ExpressionCloze field appears unchanged), but the ExpressionCloze1 field is populated with 1.
  3. Select "second" and click the cloze button.
  4. "((c2::second))" is not created but instead the cloze for the previous action, "((c1::first))", now appears, and ExpressionCloze2 is populated.

So the first time I click the button, the cloze doesn't seem to be created but the numbered field is populated. The second time I click it, rather that creating the cloze for what I selected, it creates a cloze for my previous action. The only thing that's working as expected is the filing in of the numbered fields.

BTW, I'm using Anki 2.1.49 and the latest version of Cloze Anything on MacOS 12.1.

matthayes commented 2 years ago

Hi there, thanks for the report. Let's see if we can figure out what's going on.

Today, I noticed that the keyboard shortcut is no longer working. Now, when I press Cmd-Shift-C the behavior has reverted to the default Anki "{{c1:blah}}" cloze, and it complains that I'm not using the Anki cloze template.

I had to change the shortcut to Cmd-Shift-W because I couldn't figure out how to hook into Cmd-Shift-C without messing with Anki's cloze functionality. I don't think I clearly documented this in the release but you should see it in the tooltip when you hover of the cloze button at the end.

But, I find it strange that for you using Cmd-Shift-C applies "{{c1:blah}}". The Cloze Anything sample deck isn't a Cloze card type, so in 2.1.49 I don't see Anki's standard cloze button (only the one added at the end by my plugin) and when I try Cmd-Shift-C it does nothing to the field and shows no message. Do you have any other addons enabled?

In the course of troubleshooting the problem, I'm seeing some strange behavior with Cloze Anything.

I tried following these steps with Anki 2.1.49 and latest plugin version and was not able to reproduce the problem either when adding a new card or editing an existing card in the browser. Are there any other details that might help me reproduce it?

I recall seeing this behavior you describe though I believe when I was working on updating the plugin for Anki 2.1.49 before I settled on the current implementation. What seems to be happening is there is an inconsistency between the internal state of the note and the representation of it in the editor. The editor is web-based and communicates with the rest of the app through a JavaScript bridge.

When you hit the cloze button, the sequence in the plugin is:

1) Update internal state of cloze fields (i.e. ExpressionCloze1, etc.) 2) Execute "wrap" command in the editor (JavaScript) to add the ((c1::blah)) markup. This "should" update the note's internal state as well via the bridge. 3) Execute a "setFields" command in the editor (JavaScript) so that all the fields match the note's internal state (so that the ExpressionCloze1, etc. fields are updated).

I suspect what could be happening is this:

Perhaps there is a delay in step 2 where the editor has been changed (i.e. wrap happened) but the internal note state hasn't been updated yet. So c1 in the editor but not in the note. Then when step 3 happens it reads a stale version of the fields and updates the editor, overriding the wrap that just happened. So now there isn't c1 anywhere. Then at some point the internal state of the note is updated based on the"wrap" command's delayed callbacks completing. Now the note has c1 but the editor no longer does. When you hit the cloze button on the second word , steps 1-3 execute again, except now the difference is that in step 3 the internal state of the note has c1, and so it updates the editor to show c1 only. Basically the editor's ExpressionCloze field ends up being one step being the internal state. But the ExpressionCloze1, etc. fields are always correct because the source of the updates are outside of JavaScript land. The problem with wrap is that the source of the update happens in JavaScript, and the rest of the state needs to be made consistent based on that.

It used to be that the plugin would set only the ExpressionCloze1, etc. fields, and not the ExpressionCloze (because there's not need to do this). However, the old method stopped working, and the only alternative I could find was using setFields. I'm working on an update to the plugin for the next release of Anki, 2.1.50, which doesn't use setFields and instead uses another method to selectively update only ExpressionCloze1, etc. Therefore it doesn't suffer from this race condition. I would have released this new version for 2.1.49 but I think I ran into some problems using it for that version so I'm holding out.

I think we may be able to figure out a workaround until then. If you're comfortable editing the plugin code (probably under ~/Library/Application\ Support/Anki2/addons21/330680661/), I would try replacing this entire line having the editor.web.eval call with just pass. The impact of this is that after the "wrap" command is executed it will not update the UI fields ExpressionCloze1, etc.. But the note's internal state should still be updated. Once you hit tab in the editor or change the focus you should see the ExpressionCloze1, etc. fields filled in.

https://github.com/matthayes/anki_cloze_anything/blob/master/cloze_anything/__init__.py#L145

                def callback(arg):
                    # editor.web.eval(get_set_fields_command(editor))
                    pass
matthayes commented 2 years ago

By the way, that addons directory is sometimes not easy to navigate to in an editor. I use a symbolic link like this to get direct access:

ln -s ~/Library/Application\ Support/Anki2/addons21/ ~/AnkiAddons
jsreaves commented 2 years ago

Matt,

Bingo! I disabled all add-ons except Close Anything, and it’s working beautifully. I’m going to re-enable my add-ons one by one, and when I find out which one is the culprit, I’ll let you know.

Jason On Dec 26, 2021, 2:10 AM -0500, Matthew Hayes @.***>, wrote:

Hi there, thanks for the report. Let's see if we can figure out what's going on.

Today, I noticed that the keyboard shortcut is no longer working. Now, when I press Cmd-Shift-C the behavior has reverted to the default Anki "{{c1:blah}}" cloze, and it complains that I'm not using the Anki cloze template. I had to change the shortcut to Cmd-Shift-W because I couldn't figure out how to hook into Cmd-Shift-C without messing with Anki's cloze functionality. I don't think I clearly documented this in the release but you should see it in the tooltip when you hover of the cloze button at the end. But, I find it strange that for you using Cmd-Shift-C applies "{{c1:blah}}". The Cloze Anything sample deck isn't a Cloze card type, so in 2.1.49 I don't see Anki's standard cloze button (only the one added at the end by my plugin) and when I try Cmd-Shift-C it does nothing to the field and shows no message. Do you have any other addons enabled? In the course of troubleshooting the problem, I'm seeing some strange behavior with Cloze Anything. I tried following these steps with Anki 2.1.49 and latest plugin version and was not able to reproduce the problem either when adding a new card or editing an existing card in the browser. Are there any other details that might help me reproduce it? I recall seeing this behavior you describe though I believe when I was working on updating the plugin for Anki 2.1.49 before I settled on the current implementation. What seems to be happening is there is an inconsistency between the internal state of the note and the representation of it in the editor. The editor is web-based and communicates with the rest of the app through a JavaScript bridge. When you hit the cloze button, the sequence in the plugin is:

  1. Update internal state of cloze fields (i.e. ExpressionCloze1, etc.)
  2. Execute "wrap" command in the editor (JavaScript) to add the ((c1::blah)) markup. This "should" update the note's internal state as well via the bridge.
  3. Execute a "setFields" command in the editor (JavaScript) so that all the fields match the note's internal state.

I suspect what could be happening is this: Perhaps there is a delay in step 2 where the editor has been changed (i.e. wrap happened) but the internal note state hasn't been updated yet. So c1 in the editor but not in the note. Then when step 3 happens it reads a stale version of the fields and updates the editor, overriding the wrap that just happened. So now there isn't c1 anywhere. Then at some point the internal state of the note is updated based on the"wrap" command's delayed callbacks completing. Now the note has c1 but the editor no longer does. When you hit the cloze button on the second word , steps 1-3 execute again, except now the difference is that in step 3 the internal state of the note has c1, and so it updates the editor to show c1 only. Basically the editor ends up being one step being the internal state. It used to be that the plugin would set only the ExpressionCloze1, etc. fields, and not the ExpressionCloze (because there's not need to do this). However, the old method stopped working, and the only alternative I could find was using setFields. I'm working on an update to the plugin for the next release of Anki, 2.1.50, which doesn't use setFields and instead uses another method to selectively update only ExpressionCloze1, etc. Therefore it doesn't suffer from this race condition. I would have released this new version for 2.1.49 but I think I ran into some problems using it for that version so I'm holding out. I think we may be able to figure out a workaround until then. If you're comfortable editing the plugin code (probably under ~/Library/Application\ Support/Anki2/addons21/330680661/ ), I would try replacing this entire line having the editor.web.eval call with just pass. The impact of this is that after the "wrap" command is executed it will not update the UI fields ExpressionCloze1, etc.. But the note's internal state should still be updated. Once you hit tab in the editor or change the focus you should see the ExpressionCloze1, etc. fields filled in. https://github.com/matthayes/anki_cloze_anything/blob/master/cloze_anything/__init__.py#L145 def callback(arg): editor.web.eval(get_set_fields_command(editor)) — Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you authored the thread.Message ID: @.***>

jsreaves commented 2 years ago

I found the culprit: Resize Images in Editor. This is an addon I can easily live without, so I'll just leave it off. Thanks for your help!

matthayes commented 2 years ago

Great! I added this to the compat problems list.