A filed note stays filed, and the handles are asked for
Three things that all came from chapters being thought through too late. A note put into a chapter came back out of it a few seconds later. The server had it right the whole time; every sync rebuilds the local copy from the server's answer, and the function doing that never carried chapter_id — so each sync handed back a note belonging to no chapter and the notebook took it in again. The bin's query left the column out too, which would have unfiled anything restored from it. A separator drawn in a notebook vanished when a chapter was opened. "Which chapter is open" and "which list is on screen" were one value. Opened beside or below, the list still shows the notebook — but everything around it had switched to the chapter, so the notebook's own separators were filtered away and a drag among its rows was measured against the chapter's notes, found nothing, and did nothing. And where a new note lands is now visible and yours to choose: pressing in either place makes it the one being worked in, marked with a line along its top and the word "here", and the + button names it. Rearranging becomes a mode, switched on beside the sort menu — until then no row wears a grip and none can be dragged. Filing a note is back in the row's own menu, where starring and exporting already are; the button that had appeared in every row is gone with its dialog. The account panel closes with Escape. Thirteen suites green: 335 browser checks, 241 unit tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4bb86bc5ac
commit
b2a5f051fe
12 files changed
+406
-291
No files matched your search
@@ -332,6 +332,14 @@ devices get different starts, because they want different things:
|
||||
The row under the finger is found with `elementFromPoint`, not with enter/leave
|
||||
handlers — a finger generates no `pointerover` on anything it did not press.
|
||||
|
||||
**Rearranging is a mode**, switched on by the handle button beside the sort menu
|
||||
and off again by itself when the list is left or the order stops being a
|
||||
hand-made one. Only while it is on does a row wear its grip or move at all. Rows
|
||||
are read constantly and dragged rarely, so six dots beside every title was
|
||||
clutter that also made an ordinary press able to carry a row off. Filing a note
|
||||
somewhere else is not part of it: that is one of the things done to a row from
|
||||
the row's own menu, like starring, exporting and discarding.
|
||||
|
||||
**The context menu** was placed with `innerWidth - 220`, a stand-in for a width
|
||||
nobody had measured, and its submenu was pinned to `left: 100%` and opened only
|
||||
on hover. On a phone the parent already sits against the right edge, so the list
|
||||
@@ -431,8 +439,8 @@ docker compose -f docker-compose.dev.yml up -d --build # must be running
|
||||
| `attachments-lifecycle` | 10 | a picture is kept while any version shows it, and freed once none does |
|
||||
| `conflict` | 10 | a late write wins but the state it buries survives as a version |
|
||||
| `export` | 21 | the downloaded bytes are real Markdown, ZIP and PNG, unpacked and read back |
|
||||
| `organise` | 52 | a hand-made order survives a search; separators hold their place; a note exported and imported comes back whole |
|
||||
| `chapters` | 21 | a note filed into a chapter leaves the notebook's list, and removing the chapter gives every note back |
|
||||
| `organise` | 53 | a hand-made order survives a search; separators hold their place; a note exported and imported comes back whole |
|
||||
| `chapters` | 31 | a filed note stays filed across a sync; the notebook's separators survive a chapter being opened; handles appear only while rearranging |
|
||||
| `offline` | 17 | a cold page load with the network off still opens notes and searches them — and a note made, written and drawn on offline arrives whole once there is a connection |
|
||||
| `sync` | 7 | a PDF written on one device — document, drawing and pinned notes — reaches a second one, which can find it by its contents without opening it |
|
||||
|
||||
@@ -881,9 +889,28 @@ on every keystroke. They are now separate blobs; the body only keeps an id.
|
||||
| POST | `/api/attachments` | Upload a base64 data URL |
|
||||
| GET | `/api/attachments/:id` | Fetch the bytes (owner only) |
|
||||
|
||||
> Removing an image from a note does not yet delete its blob: the body is
|
||||
> encrypted, so the server cannot tell what is still referenced. Unused blobs
|
||||
> cost disk space, nothing else.
|
||||
### Where it all actually sits
|
||||
|
||||
Two directories, both bind-mounted from the host so that whatever backs up the
|
||||
host backs up InkNote:
|
||||
|
||||
```
|
||||
/srv/inknote/db/inknote.db every note, encrypted body and all
|
||||
/srv/inknote/uploads/attachments/<sha> one file per distinct upload, encrypted
|
||||
/srv/inknote/uploads/drawing_<id>.png legacy raster drawings
|
||||
```
|
||||
|
||||
**There is no folder per user, and there is deliberately nothing on disk to read.**
|
||||
Who owns what is a column in the database (`attachments.user_id`), not a path.
|
||||
The file name is the SHA-256 of the *plaintext* — encryption uses a fresh IV each
|
||||
time, so hashing the ciphertext would store the same photo twice — and the bytes
|
||||
beside it are AES-256-GCM. So a file name tells you that two people uploaded the
|
||||
same document, and nothing else: not who, not what, not which note.
|
||||
|
||||
Sorting uploads into per-user folders would name the owner in the clear on a disk
|
||||
where nothing else is readable, and it would break the sharing that keeps one copy
|
||||
of a file two accounts happen to have. Deleting stays safe without it: a blob goes
|
||||
only when **no** row in `attachments` points at it any more, whoever owned them.
|
||||
|
||||
---
|
||||
|
||||
@@ -990,6 +1017,20 @@ should follow you to the phone.
|
||||
A phone has room for neither. There the chapter fills the list and the header
|
||||
button becomes a way back out, which is what it did before there was a choice.
|
||||
|
||||
**Which list is on screen is not the same as which chapter is open.** Beside and
|
||||
below, the middle column still shows the notebook; only the phone's fallback
|
||||
replaces it. The two were one value for a while, and a separator drawn in a
|
||||
notebook vanished the moment a chapter was opened — the list still showed the
|
||||
notebook, but everything around it had switched to the chapter, so the notebook's
|
||||
own separators were filtered out and a drag in that list wrote nothing at all.
|
||||
|
||||
**Which of the two you are in is a separate question again**, because both are on
|
||||
screen at once. Opening a chapter puts you in it; pressing in the notebook's own
|
||||
list puts you back in the notebook without closing the chapter. Whichever it is
|
||||
wears a line along its top and the word *here*, and the + button names the place
|
||||
it would make the note in. Before, a new note went into the chapter however far
|
||||
away you had since clicked, and nothing on screen said so.
|
||||
|
||||
### A chapter is a row like any other
|
||||
|
||||
Chapters sit at the same level as notes and separators: same grip, same drag,
|
||||
|
||||
Reference in new issue
Block a user