Write down what the mail list does under a finger
FEATURES.md and the touch gestures were written at the same time on separate branches, so the inventory of everything ihasmail does landed knowing about none of them: the mobile layout was still one line about a tab bar, and the Appearance row of the settings table did not mention the two settings that had just been added to it. The gestures get a section of their own under Layout rather than a bullet, because the interesting part is not the list of five -- it is why they are gated on `(pointer: coarse)` rather than on width, why a direction with no meaning in this folder refuses to move rather than moving and doing nothing, and why the axis lock gives a diagonal drag to the scroller. The same reasoning is in the code; this is where somebody reads it without opening lib/touch.ts. Also here: the `dvh` and safe-area notes alongside the mobile layout, a long press added to the list's multi-select bullet, and a short note in the settings-sync section on why the swipe actions follow the account despite looking like a per-device setting.
This commit is contained in:
+60
-3
@@ -75,7 +75,57 @@ the few settings that does not follow the account.
|
|||||||
- **Density** comfortable, cozy or compact, which changes row height as well as padding.
|
- **Density** comfortable, cozy or compact, which changes row height as well as padding.
|
||||||
- **Font size** small, medium or large.
|
- **Font size** small, medium or large.
|
||||||
- **Sidebar** collapsible to icons; a drawer on mobile.
|
- **Sidebar** collapsible to icons; a drawer on mobile.
|
||||||
- **Mobile layout** with a bottom tab bar, full-screen composer and full-screen reading.
|
- **Mobile layout** with a bottom tab bar, full-screen composer and full-screen
|
||||||
|
reading. Full-screen surfaces measure in `dvh` rather than `vh`, because a
|
||||||
|
phone browser's `100vh` is the taller viewport that ignores the address bar —
|
||||||
|
a composer sized that way puts Send behind the toolbar. The tab bar, drawer,
|
||||||
|
dialogs and compose button all keep clear of the notch and the home
|
||||||
|
indicator; `index.html` asks for `viewport-fit=cover`, so the app paints
|
||||||
|
under both and the stylesheet is what keeps anything readable out from
|
||||||
|
beneath them.
|
||||||
|
|
||||||
|
### On a touchscreen
|
||||||
|
|
||||||
|
Five gestures, every one of them decided by `(pointer: coarse)` rather than by
|
||||||
|
screen width. The two questions are different and both get asked: a tablet in
|
||||||
|
landscape is a wide screen that swipes, and a phone plugged into a mouse is a
|
||||||
|
narrow one that should not. A mouse keeps drag-and-drop onto folders, which
|
||||||
|
shares the same pointer stream and would otherwise be fighting a swipe for
|
||||||
|
every drag.
|
||||||
|
|
||||||
|
- **Swipe a row** sideways to act on it. Each direction is a setting — right
|
||||||
|
archives and left deletes by default, which is what the mail app the phone
|
||||||
|
came with already does. Either direction can be set to archive, delete,
|
||||||
|
report spam, read/unread, star or move to… — or to nothing, which turns that
|
||||||
|
direction off. The coloured strip revealed behind the row names what will
|
||||||
|
actually happen *in the folder it is happening in*: "Delete forever" out of
|
||||||
|
Deleted Items, "Not spam" inside Junk Mail. Where an action
|
||||||
|
is meaningless there — archiving out of the archive, calling your own drafts
|
||||||
|
spam — the row will not move that way at all, because a row that slides open
|
||||||
|
to reveal a word and then does nothing is worse than one that does not slide.
|
||||||
|
- **Hold a row** to select it, which is how selection starts on a phone.
|
||||||
|
Checkboxes are visible wherever there is no hover, but a checkbox beside an
|
||||||
|
avatar is not what a thumb aims at. Once one row is selected, plain taps
|
||||||
|
toggle the rest.
|
||||||
|
- **Hold a folder** in the drawer for the menu its ⋮ button opens.
|
||||||
|
- **Pull the message list** down to refresh it.
|
||||||
|
- **Drag in from the left edge** of a conversation to go back to the list.
|
||||||
|
|
||||||
|
The toolbar's refresh button and the thread's back arrow both stay. A gesture
|
||||||
|
with no visible control is one only the people who already know about it can
|
||||||
|
use, and none of these announce themselves.
|
||||||
|
|
||||||
|
Each threshold crossing taps the vibration motor where there is one, which is
|
||||||
|
confirmation for the hand rather than the eye — a swipe fires at the moment the
|
||||||
|
finger passes a line it cannot see. iOS supports none of that and never has, so
|
||||||
|
it is silently nothing there.
|
||||||
|
|
||||||
|
The arithmetic lives in `web/src/lib/touch.ts`, away from the components and
|
||||||
|
under test, because the numbers are the whole thing. The axis lock is
|
||||||
|
deliberately biased towards the vertical: scrolling is what a finger on a
|
||||||
|
message list is doing almost every time, and a scroll misread as a swipe grabs
|
||||||
|
the list out from under the reader, while a swipe misread as a scroll costs one
|
||||||
|
more attempt. A drag that is merely more sideways than not stays a scroll.
|
||||||
|
|
||||||
## The message list
|
## The message list
|
||||||
|
|
||||||
@@ -85,7 +135,8 @@ the few settings that does not follow the account.
|
|||||||
- **Infinite scroll** with server-side paging, 50 at a time by default.
|
- **Infinite scroll** with server-side paging, 50 at a time by default.
|
||||||
- **Conversation view** groups a thread into one row, with the thread's own
|
- **Conversation view** groups a thread into one row, with the thread's own
|
||||||
message count; it can be switched off to list messages individually.
|
message count; it can be switched off to list messages individually.
|
||||||
- **Multi-select** with `x`, shift-click for ranges, `Ctrl/Cmd+A` for all.
|
- **Multi-select** with `x`, shift-click for ranges, `Ctrl/Cmd+A` for all, and
|
||||||
|
a long press on a touchscreen.
|
||||||
- **Drag and drop** onto any folder in the tree, moving the selection or the
|
- **Drag and drop** onto any folder in the tree, moving the selection or the
|
||||||
row under the cursor.
|
row under the cursor.
|
||||||
- **Context menu** on any row: reply, forward, archive, delete, spam, read/unread,
|
- **Context menu** on any row: reply, forward, archive, delete, spam, read/unread,
|
||||||
@@ -529,6 +580,12 @@ size, sidebar state, the two pane sizes, and the notification toggles, which
|
|||||||
track a permission the browser grants per device. The list is written as the
|
track a permission the browser grants per device. The list is written as the
|
||||||
exceptions rather than the rule, so a setting added later syncs by default.
|
exceptions rather than the rule, so a setting added later syncs by default.
|
||||||
|
|
||||||
|
The swipe actions are a deliberate non-exception, and look like one at a
|
||||||
|
glance: they only do anything on a touchscreen, so they read as belonging to
|
||||||
|
the device. But someone who has decided that a left swipe deletes has decided
|
||||||
|
it for their phone and their tablet both, and the desktop that ignores them is
|
||||||
|
the odd one out rather than the case to design around.
|
||||||
|
|
||||||
Two limits: conflicts are last-write-wins, and a change made on one device does
|
Two limits: conflicts are last-write-wins, and a change made on one device does
|
||||||
not reach another that already has ihasmail open until it signs in again.
|
not reach another that already has ihasmail open until it signs in again.
|
||||||
|
|
||||||
@@ -537,7 +594,7 @@ not reach another that already has ihasmail open until it signs in again.
|
|||||||
| Section | Holds |
|
| Section | Holds |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| **General** | Reading pane, mark-as-read delay, auto-advance, remote images, conversation view, snippets, avatars, confirm-before-delete; compose format, undo-send window, quoting, signature placement, attachment reminder, read-receipt policy, spell check; time zone, week start, language & region, date format, time format; `mailto:` handler; export / import / reset |
|
| **General** | Reading pane, mark-as-read delay, auto-advance, remote images, conversation view, snippets, avatars, confirm-before-delete; compose format, undo-send window, quoting, signature placement, attachment reminder, read-receipt policy, spell check; time zone, week start, language & region, date format, time format; `mailto:` handler; export / import / reset |
|
||||||
| **Appearance** | Theme, accent colour, density, font size, sidebar |
|
| **Appearance** | Theme, accent colour, density, font size, sidebar, swipe actions |
|
||||||
| **Identities & signatures** | Addresses, names, Reply-To, HTML signatures, the default, and which to hide from the picker |
|
| **Identities & signatures** | Addresses, names, Reply-To, HTML signatures, the default, and which to hide from the picker |
|
||||||
| **Filters & rules** | The visual builder and raw Sieve editor |
|
| **Filters & rules** | The visual builder and raw Sieve editor |
|
||||||
| **Out of office** | Vacation response |
|
| **Out of office** | Vacation response |
|
||||||
|
|||||||
Reference in New Issue
Block a user