Hello, I am mainly curious if custom data can be attached to notes, or if there is support for saving custom local data for a plugin. Is this functionality feasible, or even allowed?
For example, attaching a custom time to a note so I can track it and calculate how many minutes I have been typing in that note in total.
This would be separate from the existing note edited time, and persistent across app instances.
That’s a good question.
Storing custom fields is interesting.
It’s technically possible to store fields like x-customField so the app can distinguish if they are custom fields.
For example:
It’s not currently designed for custom fields, so it’s not possible to remove them via editingNote.update action at the moment.
yep, good point. Cleaning up is important.
The field prefix “x-” is not sufficient for cleaning up.
The plugin name should be able to be inferred by the field names like “x-plugin-name-fieldName”.
But I guess scanning all the notes to clean them up may take a while if the user has a lot of notes.
Another way to store custom data is to create separate docs something like:
In this way, the app can support removing them anytime.
But I need further discussion on this because that makes the app complicated.
The database and sync could be broken.
I have also been looking at storing custom fields for notes to support some extra functionality.
Note that you basically should avoid directly calling db.notes.put() to update a lot of times because that makes a revision each time.
While using db.notes.put() might not be a good idea for the revisions sake, it does not even seem to work. I have tried saving some custom fields using it and they never seemed to get applied, the example you provided works but as I’m trying to use custom fields on notes you aren’t currently editing this solution doesn’t seem to be a good idea. Would it be possible to apply the fields some other way or would I have to go with the separate docs?
You also mention that using the separate docs could break the database and sync, is there an actual risk of this even if I just use db.put and db.remove specifically on my custom docs, or is this just a warning you mention to be on the safe side?
Weird. Do you get a new revision in the returned value? It doesn’t filter custom fields.
Yea, you are right.
The separate docs would be better in this case.
Because updating a note will make another copy of the whole document. That’s why you can roll back from the old revisions. That’s kind of redundant for storing custom fields. Also, that would cause unexpected conflicts between devices.
So, plugin:PLUGIN_NAME docs would solve those issues.
Yes. The app should provide custom data APIs for the plugins so that you can avoid directly call db.put, which is dangerous. I don’t want to get reports from users screaming like “my data gone!”
I did some more testing and it seems like a new revision is created but the custom field is not stored.
What I tested
const id = "note:<a note id>"
const db = inkdrop.main.dataStore.getLocalDB()
const notes = db.notes
let note = await notes.get(id)
note["x-test"] = "test-val"
await notes.put(note)
The object returned by the promise of notes.put(note) contains a different rev than what is returned by the notes.get(id)
I then tried both await notes.get(id) and await inkdrop.main.dataStore.localPouch.get(id) and both of the returned objects are identical, also meaning that neither of them contained the custom field (I assumed that maybe notes.get() was filtering some fields when fetching).
Just for the sake of it I also tried updating one of the regular fields of the note alongside setting the custom field, the regular field was updated when calling notes.put(note) but the custom field was still note stored.
It might be worth putting this as a note in the docs info about working with the DB. I’m probably not the only one that haven’t worked with Electron before, and this kind of info can be a bit hard to find if you don’t know what you are looking for.
Edit: I see now that there is some info about Remote Objects under the Accessing the PouchDB instance (Advanced) section but unfortunately the link with more information does not work anymore.
You are right, and that’s one of the reasons why it’s not recommended to use low-level database APIs.
Please hold on storing custom fields to the note documents directly until the app officially supports plugin documents.
Hello @craftzdog,
Any updates of this? For development I am using the first approach discussed but before I release anything I would like to get a stable/non-invasive method that won’t break functionality.
Is this on the roadmap?
Best,
Nick
Another idea I recently came up with is to use YAML frontmatter.
Because it’s visible and clear to users.
It doesn’t solve every use case but is simple and viable. No need to use dangerous store APIs.
Update: v5.6.0-beta.0 is out with its Markdown renderer update:
Now, it allows you to read the YAML frontmatter easily via the preview redux state. So, you don’t parse frontmatters yourself. Check out the new documentation for more detail here:
Note that it currently does not support updating the values.