Plainva 0.5.2: 27 apps to move in from — and an importer that tells the truth
0.5.0 shipped an importer. 0.5.2 is me finding out what it actually did.
The report that lied
Plainva’s import wrote a report at the end of every run: how many notes came across, what was skipped, what came in degraded. I was rather proud of that report. It was the thing that made the import feel trustworthy.
It was also, for Notion, wrong.
The Notion API importer pulled pages, converted blocks, resolved relations between databases — and quietly dropped every image. Not “logged a warning and moved on”. Dropped. And then the report said everything had come across, because nothing had thrown an error. From where you sat, the import worked. You would find the holes weeks later, in a note you happened to open.
That was the one dishonest place in the system, and it is the thing I most wanted gone in this release.
The unpacker that only read text
Then I went looking for why file-based imports had no attachments either, and found something worse.
Plainva unpacked import archives in JavaScript. That unpacker had a filter on it — it read entries whose extension looked like text. Markdown, HTML, JSON, CSV. Everything else, it skipped.
Which means that for every file-based import Plainva has ever done, attachments could not arrive. Not “sometimes failed”. Could not. Your Evernote images, your Keep photos, the PDFs in a Notion export: the code that would have written them was never reached, because the code that would have read them declined to.
Unpacking now goes through Rust: it streams instead of holding an archive in the renderer’s memory, it has hard limits so a zip bomb cannot take the app down, and it skips symlink entries rather than following them somewhere it should not go. And it reads every entry, because that was the entire point.
”Everything today”
The third thing that was quietly wrong: dates.
Every imported note got the timestamp of the moment it was written to disk. Import a decade of Evernote and you get a decade of notes that all claim to be from this afternoon. Your recents are meaningless, the heatmap is a single block, and sorting by date tells you nothing at all.
Timestamps now come from the export. Your 2017 note says 2017.
There is one honest limitation: notes you imported before this release keep their wrong dates. I decided against writing a migration for it — a migration would have to guess which import a note came from and where the original export went, and a wrong guess would be worse than a wrong date. If it matters to you, importing again into a fresh folder will do it properly.
And, yes: 27 apps
With the mechanics fixed, adding sources became cheap. Plainva now imports from:
Notion (through the API and from a file export), Evernote, Google Keep, Logseq, Simplenote, a plain folder of Markdown, and then the whole Markdown family that exports something close enough to it — Joplin, Bear, Notesnook, Capacities, Amplenote, Supernotes, Heptabase, UpNote, Craft, Anytype. Plus Standard Notes, the OPML outliners (Workflowy, Dynalist), Trilium, Roam, Reflect, TiddlyWiki, Tana, RemNote — and an HTML folder importer that reads a Confluence space export and rewrites the links between its pages so they still work.
Two decisions in there worth naming, because both are “no”:
Evernote’s API was in the plan, on the condition that a developer token was freely available. It is not, so the ENEX file route is what there is.
Confluence was supposed to get a proper adapter. Its storage format is an XHTML dialect built around macros, and a space export needs admin rights — I could not have tested it honestly. The HTML folder importer does the same job through the door that is actually open.
The sync that could not say what it carried
The other half of this release started with a question, not a bug report: what does the settings sync actually transfer? On iOS it arrives, on Android it doesn’t.
I could not answer it. Not “I had to look it up” — there was no place in the code that said what the sync carries. The desktop kept a list of 22 store keys. The phone kept two hand-written strings. They had been written eighteen months apart by me, and neither knew the other existed. A setting one side synced simply never arrived on the other, and because nothing anywhere claimed to be the authoritative list, the gap could not be noticed.
There is now one catalog. Both shells read it. If a shell has no field for an entry, it has to state why — and a test fails if that reason is missing. It is a small thing that makes a whole class of bug impossible.
Both surfaces now also tell you what the last sync run did, and which of the three quiet states a device is in: not switched on, locked, or no provider connected. Those three used to look identical from the outside — which is to say, they all looked like “broken”.
Also in this release
One sign-in for a whole Google account. Files, calendar and tasks used to hold a copy of the token each. Now they share one, through the same broker Microsoft got in 0.5.1 — so renewing a sign-in once brings all three back instead of one.
Tasks on the phone, properly. Both sections, filters, promotion, the status menu, repetition, blocking time. The same list as on the desktop rather than a read-only shadow of it.
Mail works on iPhone again. The socket plugin was the only one of five without a CAPBridgedPlugin declaration, so iOS could not see it at all. One missing contract, one entire feature invisible.
One folder for attachments. Dropped, pasted and photographed files used to land beside the note. That is fine for one note and unbearable for a vault — attachments scattered across every folder that ever received one, left behind whenever you move a note. There is now one folder, set per vault, and the phone and desktop agree on it.
That last one changes where new files land in existing vaults. Deliberately, and without a migration: everything already filed stays exactly where it is and keeps working. If you liked it the old way, empty the setting and you have it back.
What is not fixed
The encrypted workspace is still marked experimental, and it stays that way until someone who is not me has reviewed the cryptography. Windows builds are still unsigned — the certificate is a cost question, not a technical one. And the guide now says plainly that Plainva does not renew Google tokens in the background: under the “Testing” consent status they expire with it, which is a thing I had described wrongly in ten languages.