v0.7.0 — Touch reading, paged flip, safer data writes
This release is mostly touch. A finger now scrolls the page with momentum and a rubber band at either end, a stylus marks it, and which one does what is a setting rather than a guess. The reader's chrome was rebuilt around that: a three-section top bar with the low-frequency controls behind a More menu, the side panel as an overlay drawer, and the first button in the tool rack turned into a navigation lock. Paged horizontal flip is a new opt-in layout and the two-page spread is gone. Underneath, data files are written atomically and a token-refresh race that signed you out mid-session is fixed.
New
- Finger scrolling with momentum. A drag follows the finger, a flick coasts and settles, pushing past either end stretches and springs back, and a finger landing on moving content picks it up where it is. A thin indicator fades in while the page moves and out when it stops, so a long book gives some sense of position.
- Draw with your finger, in Settings under Reader input. Off by default: the finger only moves the page and the stylus does the marking, whatever tool is selected. Turn it on for a device with no stylus.
- Navigate only, in the tool rack: a latch rather than a tool. While it is down every pointer, stylus included, only moves the page, and nothing draws or selects. Press it again for the ordinary mode where the stylus marks and the finger scrolls.
- Paged flip, an opt-in layout in the More menu: one whole page per screen, in either orientation. A horizontal swipe turns the page and follows the finger; a vertical swipe, or a swipe past the first or last page, bands and springs back. A pinch magnifies to read detail and pans; the next turn comes back to fit-page. The choice persists per book.
- Sign in with a code, on the Claude and ChatGPT cards. ChatGPT runs the device-code flow (user code, verification link, polling, cancel, with a paste-the-URL fallback), Claude the paste-the-code flow. Neither needs a local callback listener; the usual browser sign-in stays the primary button on desktop.
- Touch sizing throughout: 44px hit areas under a coarse pointer, hover-only controls that stay visible where there is no hover, safe-area insets, and a chat composer that rises above the soft keyboard. The home, briefing and reading call surfaces have narrow-screen layouts. All of it inert on desktop.
- An iPad build, not on this page: CI now produces a sideloadable .ipa with an install manual, and the TestFlight workflow was brought up to match it. This release page carries the Linux, macOS and Windows builds.
Changed
- The reader top bar is three sections: drawer and library on the left, the annotation tools and page indicator in the middle, the AI thread entry and a More overflow on the right. Zoom, fit width, paged flip and settings moved into More, every icon shares one neutral line style, and the open book's title is no longer repeated in the bar.
- The reader's side panel is a left overlay drawer, closed by default, opened from the top bar and dismissed by a backdrop tap or Esc. Its toggle carries a status dot while prep or note generation runs, so background progress is visible with the drawer shut. The five tabs moved into a row along the drawer's top.
- The two-page spread is gone; the reader lays out one page per row. Reading positions saved with it still open.
Fixes
- Data files are written atomically — a temp file in the same directory, fsynced, renamed over the target — so a process killed mid-write can no longer leave a half file that the next save makes permanent. An unreadable library or settings file is quarantined and reported instead of being silently replaced by an empty shelf or default settings.
- An expired AI token is refreshed once rather than once per running pipeline. Both providers rotate the refresh token, so the losing refreshes came back invalid_grant and signed you out mid-session. Credential writes are serialized as well: a refresh no longer writes back a snapshot taken before you saved an API key.
- Marks pulled from another device survive. A sync pull now drops the book's cached annotations; before, the next mark made here wrote the stale cache back over them.
- A book opens with no tool selected, so the previous book's pen no longer marks the page the moment a finger lands on it.
- Signing in to Claude by pasting a code opens the page that actually displays the code.
- The reader top bar no longer pushes the page wider than a phone viewport, and the reading call bubble fits a narrow screen.
- On an iPad the app asks the system what platform it is on instead of trusting a user-agent string that claims to be a Mac.
Internal
- src/ is regrouped by layer — platform, ai, memory, fulltext, reading, info, ui — and a test walks every import to enforce the dependency direction. Five directory cycles that had accumulated under convention alone are gone.
- The touch logic is pure and unit-tested apart from the DOM: the table that decides draw versus scroll, the vertical scroll and fling machine, the rubber band, and the paged flip machine.
- Duplicated code merged: model resolution across five wirings, the PKCE helpers, the pipeline observable shell, the streaming tool-trace reducer, the shared button classes. App.tsx handed off the library screen, the info home, the reader top bar and reading-turn assembly.