yuleicul / obsidian-ketcher

View or draw chemical structures and reactions using Ketcher.
https://obsidian.md/plugins?search=yulei%20chen
Apache License 2.0
32 stars 2 forks source link

Feature: Auto save #10

Closed Acylation closed 1 year ago

Acylation commented 1 year ago

Closes #2

Changes

Boundary case

If we have multiple tabs holding the same file, on proposed, these tabs will each have an interval, and they will run together, calling save() more frequently then expected.

Notice that, the setViewData() function would only be called by save() if there's any change on file data, and the user may probably can't operate multiple editors at the same time, so here's what we'll get:

Tab A (changed) | Tab Bsave() by Tab A → setViewData() called → Tab A (changed) | Tab B (changed) Tab A (changed) | Tab Bsave() by Tab B → setViewData() won't be called → Tab A (changed) | Tab B -> save() by Tab A ...

And that's a pseudo-sync maybe.

Acylation commented 1 year ago

Sorry for the delay upon my declaration, the API is confusing. Here's the explanation of the second change.

This is also related to the boundary case, that multiple tabs sharing the same file. In this case, when one tab calls save(), the _check flag in setViewData() of other tabs will be false. So through wrapping render KetcherReact, we can retain the editor, and just refresh the data.

With this specific case I found another problem. If we assign the view data through ketcher.setMolecule(), and the undo operation would just revert what the funcion did.

When we have two tabs, drawing on Tab A and updating Tab B automatically, the undo stack of Tab B behaves weird. For obsidian-ketcher v0.1.2, after refreshing the editor, undo will leave a blank canvas on Tab B, because we re-render the editor, and then assign the data value to the tab. For the proposed change, undo will revert save() operation, and we will get the previous state since we retained the editor and pervious data.

If there's a way to interact with the undo stack of ketcher editor, we can even keep it on the page (init in the constructor of KetView), and just update the data. (Update: code here https://github.com/Acylation/obsidian-ketcher/tree/single-editor-instance)

Acylation commented 1 year ago

Update: code in #11

An alter would be, call this.requestSave() when editor change, could be achieved through https://github.com/epam/ketcher/issues/645

requestSave() triggers a debounced save in 2 seconds from now https://docs.obsidian.md/Reference/TypeScript+API/TextFileView/requestSave

image https://github.com/marcusolsson/obsidian-plugin-docs/blob/2b61554e995560036b1789648f46379b76664e3b/docs/tutorials/text-based-file-formats.md#L237-L253

Acylation commented 1 year ago

In latest updates, I migrated to requestSave() method, and unsubscribe onChange() listener when refreshing or removing the editor.