0.8.0 came out on 25 october, seven weeks after 0.7.8. the release notes are the short version. this is the long one: what changed on the phone and why, every fix on the desktop and the phone, and the build machinery that took more of those seven weeks than i expected.
the phone has its own app
until 0.8.0, shizumu on a phone was the desktop app made narrow. every phone fix went inside a desktop component as one more branch for small screens. by august the history showed what that cost. about fifty-five of the last eighty commits were mobile fixes, and the editor component alone carried nine phone branches in three and a half thousand lines. the bugs kept coming back in the same shapes: the keyboard and the viewport disagreeing about how much screen was left, controls drawn over the writing, a bar that hid itself and stayed hidden.
so on 22 august i wrote a different plan. the phone gets its own set of screens, and the desktop stays exactly as it was. the phone shell owns everything you see and touch, and borrows everything underneath it: the editor, the database, sync, search. it was built alongside the desktop for two months and merged on 23 october.
the page is home. its header holds the date, the trail and the pages of the day, and folds to one line while you scroll or type. three tabs sit at the bottom: page, memory and settings.
the editing controls live in one place, a single strip above the keyboard, and nothing floats over the text. with the caret in a block, the strip holds six things: turn into, bold, italic, insert, pin and undo. select some words and it changes to what a selection can do. type / or @ and the suggestions show as chips to tap. a control that cannot apply to the block you are in is left out rather than greyed. in a list, indent and outdent join it.
each block has one handle beside it. tap it for the block’s actions. hold it for about a third of a second and the block lifts and follows your finger, with a thin line showing where it will land.
pins, memory, trails and sync each got screens of their own. you can read a pin, edit it in place, or move it to another trail. memory filters by date from a month calendar and narrows to one trail. a living document’s date opens a list of its days. sync can be set up, paired by camera and switched off from the phone. sheets come up from the bottom and fit what they hold: renaming a pin is one field, so it opens halfway, and a note with a body opens full height so its field is not hidden under the keyboard.
the keyboard took longest. android 15 draws every app edge to edge, and for an app built against a recent android it no longer shrinks the window when the keyboard opens. on the galaxy a16 i test with, the page measured 832 pixels tall with the keyboard down, and 832 with a 310 pixel keyboard up. the editing strip was behind the keyboard. the fix was to stop asking the web page. the android side of the app now measures the keyboard itself, and the page shrinks by that much.
one samsung webview taught the hardest lesson. it froze every height reading at the keyboard-up value, so the app believed a keyboard was open for the rest of the session, and the editing strip took the place of the tabs, and with them every way off the page. since then the tabs and the editing strip are two rows, and nothing the keyboard does can take the tabs away.
the layout is chosen by the shape of the screen and the kind of pointer, not the operating system. so the browser demo opens it on a phone, with a few weeks of writing already in it. a linux phone gets it too: under phosh or plasma mobile a touch-only screen counts as a phone, and flathub now builds for arm64. i have not run it on a linux phone myself yet. if you have one, i would like to hear how it goes.
tested on two devices at once
a feature that works on one device and breaks on the second is not done. so most of september and october went into runs with a laptop and a real phone side by side, paired, writing on both, deleting, going offline, starting over, moving to another relay. i test on two phones, a galaxy a16 and a galaxy a06, driven over wifi from the laptop. the runs found most of the sync fixes below, and the a06 found one nobody would have guessed: with out of date time zone data, today’s page would not take typing for an hour around midnight.
everything that was fixed
two of these started as github issues, and i am grateful to the two people who wrote them up so clearly. the rest came from testing and from using it.
writing and the editor
- ctrl+left and ctrl+right now move the caret by a word while you write, instead of turning the page.
- ctrl+page up and ctrl+page down now turn the page from anywhere, and the shortcuts panel says so.
- escape inside a block, such as a list or a recipe, no longer throws the caret to the end of the page.
- closing the find bar now takes its highlights off the page and puts the caret back in the writing.
- @ and / typed inside a code block now stay as typed, instead of opening a menu.
- text copied out of shizumu now arrives in other apps as you typed it, without stray backslashes.
- a screenshot pasted on the linux desktop now makes an image, where before nothing happened.
- a pasted image whose file name has no extension is now inserted, instead of being refused without a word.
- pressing pin on a block that is already pinned now says so, instead of making a second pin.
- the interface labels and every italic line now use the real fonts, with real bold faces, where before each platform drew its own stand-in.
- a day with more than eight pages now shows a count, instead of a row of dots that ran into the header.
- the last welcome slide no longer leaves begin and skip dead when the database is slow to answer.
- a save that fails is now said in one quiet line and tried again, instead of failing without telling you.
sync between devices
- a sentence typed in the second before the other device’s changes arrived no longer disappears.
- a page that sync just updated is no longer saved straight back, which used to let the older copy win over the other device’s newer words.
- leaving a page before its writing had arrived no longer saves it empty over what the other device wrote.
- a page opened from memory, and memory’s list itself, now show what the other device writes without leaving and coming back.
- the trail name in the header now changes when you rename that trail on the other device.
- a page deleted on one device now stays deleted on every device.
- a page deleted on one device while the other was still editing it now ends up kept on both, instead of the two disagreeing for good.
- deleting or folding a trail that has trails inside it now moves those trails to the same place on every device.
- a continuous trail, the one long living document, now syncs like any other page.
- an image that arrives by sync now appears on the page you have open.
- an edit typed into a pinned block now reaches that pin on the other device too.
- an edit to a pin made in memory or in the pins panel is no longer undone by the next save of the page it came from.
- search now finds the writing that arrived from your other device.
- a device that has just paired now shows what it receives without being restarted.
- a device joining an account that already has a lot of writing now catches up from a recent snapshot, instead of replaying every change one by one.
- a device that starts over, or moves to a new relay, now receives again instead of skipping everything as already seen.
- a device moved to a new account can send again, where before every change it made failed.
- a device that starts over now sends its writing as it is, so things you deleted, moved or folded since no longer come back.
- a change held back while its trail had not arrived no longer brings back a page, pin or trail you deleted after it.
- a device wiped with delete all now takes the account’s writing back down, instead of offering an empty copy to every device that joins later.
- a photo sent before a move to a new account now reaches the new one.
sync is still optional and end-to-end encrypted. the relay holds what it cannot read, and neither can i.
the lock, encryption at rest and backups
- with the lock on, you can now change its passphrase or turn it off, where before the row said “on” with nothing behind it.
- the lock after inactivity menu now opens in front of settings, instead of behind it.
- turning the lock off while the app is open no longer brings up a lock screen that no passphrase can open.
- when the app locks itself after a while, an encrypted database is now closed behind the lock screen until the right passphrase opens it again.
- the screen that sets up encryption now shows in full, with its encrypt button in reach and a cancel button beside it.
- the file that holds the database key is now readable by your account only, and an older one is tightened the next time the app starts.
- a backup of an encrypted database now works, and the copy keeps its passphrase.
- a database that will not open now gets a screen that says why and leaves the file untouched, instead of the app closing.
- delete all writing now also removes your attached files from disk, as its row says it does.
memory, pins, trails and search
- search in memory now finds older writing, not only what is in the last hundred pages.
- a word that appears on hundreds of pages now lists every one of them, newest first, instead of a ranked cut that could skip last week.
- a page that holds only its focus line can now be found by searching for that line.
- an @-mention of a pin no longer overwrites the pin with the mention.
- an @-mention of a pin on another trail now opens that pin, instead of an empty panel.
- after deleting or folding a trail, the trails inside it now stay in the trail picker where they went, instead of dropping out.
the phone and installing
- today’s page now stays writable around midnight on a phone whose time zone data is out of date.
- opening an attachment, exporting a page and backing up now work in the android release build, instead of saying the share sheet could not open.
- on a linux phone, gnome software and discover no longer mark shizumu as incompatible with the screen.
five platforms, and no mac
a fair share of the seven weeks was not the app. it was the machinery that turns one version tag into installers for linux, windows, android, iphone and mac, run by one person who does not own a mac.
a tag starts one pipeline, and its first real job is the test suite. at release time that was 3424 unit tests. until the middle of october, the windows and android builds ran beside the tests rather than after them, so a tag could ship whatever it built. now every build waits, and a tag with one failing test produces no installers at all.
windows builds on a machine i own and is signed by a cloud signing service that never hands over the key. the job checks the signature itself before it uploads anything, because an earlier run printed success while the signing had failed. android signs with one upload key. an early version of the job generated a fresh key on every run, and play refused every bundle after the first, because play ties an app to the certificate it saw first.
the public repository at github.com/shizumu-app/shizumu is built on each tag by copying only the paths on an allowlist into a fresh tree, then checking that tree for private paths, credential-shaped text and key files before it is pushed. copying what is allowed, instead of deleting what is not, means a new private folder cannot leak by being forgotten. during this release i found a hole in that check: the container’s small version of find did not understand one option, so the key-file check errored, matched nothing, and passed. it uses the full findutils now. on release day the push itself was refused twice, first by an expired token and then by one that was not allowed to update workflow files, until both were replaced.
flathub builds from that mirror, pinned to the tag and the exact commit behind it. for 0.8.0 the deb, rpm and tarball went away and flathub became the only linux build, on x86_64 and aarch64. flathub builds offline, so every npm package has to be listed ahead of time, and two new packages since 0.7.8 meant regenerating that list. flathub’s bot opens its own update request on a new tag, but it changes only the tag and commit and its build would have failed, so i closed it and opened one with all three files.
the website’s download section is built last. it fetches the installers that actually arrived, names only those, and fails the deploy if a link points at a file that is not there. that rule came from 0.7.1, which went out with no android download because the site deployed before the apk landed.
iphone and mac build on github’s macos runners, from the same allowlisted snapshot. the iphone build took ten runs in september before apple would take it: the project wanted automatic signing the runner cannot do, the large icon carried an alpha channel, the sdk was too old, and the newer xcode failed in the linker until the minimum ios version went to 17. the day before release, app store connect asked for a privacy manifest declaring the system calls the rust code makes, and the build writes one now.
the mac build makes one dmg for apple silicon and one for intel. each is signed, notarized, checked by gatekeeper and launched for twenty seconds before it is uploaded. on release day the mac keychain refused the signing certificate until it was exported again in an older format, and then the upload refused to go because it was waiting for the linux deb that 0.8.0 had just stopped making. it waits for the android bundle now. the mac version ships as a beta, and the people who run it are its testers.
getting it
on linux, flathub updates it for you, on x86_64 and arm64. on windows, get the installer from the download section. on android, the play closed test updates itself: join from the android page in two steps, or install the apk directly. on iphone, open the testflight link on the phone. on a mac, the beta download is signed and notarized for both chips.
if something is still wrong for you, open an issue and say which version you are on. a screenshot helps more than anything.