Takes the flat module count from 66 to 42, continuing what admin/ and
calendar/ started.
lib/mailbox/ archiveDate, emptyFolder, folderMove, labelTree,
mailboxName, mailboxRoute
lib/sieve/ sieve, sieveApply, sieveFolders
lib/input/ keyboard, swipe, touch, listSelection, dropUpload
lib/notify/ notify, webpush, webpushEnable
lib/sw/ swCache, swFacts, staleBuild
lib/text/ html, markdown, text, emlName
FOUR THINGS THE FILENAMES GET WRONG, each checked by reading the file
rather than trusting what it is called:
- appFolder is not a mailbox. It is the `ihasmail` folder in JMAP
*Files*, where the client keeps signature images and synced settings.
It stays flat.
- format holds no formatting of text. It re-exports the date and clock
formatters, so it belongs with dates/datetime, not with text/.
- preview is the file viewer deciding what it can show without
downloading, and source is where to point someone asking for this
instance's AGPL source. Neither is about text.
- notify is not Web Push. It is the tab title, the favicon badge and
the new-mail sound -- in-app notification, which is why it sits with
webpush rather than under sw/ with the service worker's own concerns.
threadScroll stays flat too: it decides where a conversation opens, which
is view state rather than a gesture, and input/ is honest only if
everything in it interprets something the reader did.
No behavior change. Almost every reference was on the @/ alias; eight
relative imports in files that did not move, or that moved away from a
sibling, needed rewriting by hand.
store/mail.ts was 1,463 lines. It is now a directory, so `@/store/mail`
resolves to index.ts and none of the 36 modules importing `useMail`
changes a line:
mail/props.ts 72 MAILBOX_PROPS, LIST_PROPS, FULL_PROPS, BODY_PROPS
mail/types.ts 125 ListQuery, ListState, MailState, DEFAULT_SORT
mail/mailboxes.ts 28 mailboxIcon, ROLE_ORDER
mail/index.ts 1,266 the store, and everything bound to it
Everything exported before is still exported from index.ts, so this is
file layout and nothing else. No behavior change, no call-site change.
WHAT THIS DOES NOT DO, and why. index.ts is still 1,266 lines because
947 of them are one `create<MailState>((set, get) => ({ ... }))`. Cutting
that up means Zustand slices -- splitting the state object itself and
recombining it -- which is a change to how the store is built rather than
to where its text lives, in the part of the app that every screen leans
on. That deserves its own PR and its own argument, not a quiet ride along
with a file move.
Three things had to stay behind and are worth knowing about, because the
obvious boundary is wrong in each case:
- `listKey` sits among the type declarations but is a function the
store calls, not a type.
- `ensureFolderPath`, `folderRefs` and `followFolders` read like folder
helpers and look like they belong beside mailboxIcon, but they close
over `useMail`. Moving them makes mailboxes.ts import index.ts, which
imports mailboxes.ts.
- the sieve import inside index.ts is `await import(...)`, not a static
one, so rewriting import paths by their `from` clause misses it.