refactor(folders): derive roleOf and isServerSpecial from one attribute table #117

Merged
JMR-dev merged 2 commits from refactor-folder-role-table into main 2026-07-02 08:39:35 +00:00
JMR-dev commented 2026-07-02 07:49:43 +00:00 (Migrated from github.com)

What

Unifies FolderRole's two hand-maintained RFC 6154 attribute tables into a single source of truth, and adds \Important (RFC 8457) to it.

#65 — one attribute-to-role table

Before, the companion held two tables that had already drifted:

  • roleOf's attribute when-ladder (\Sent→SENT, \Drafts→DRAFTS, \Junk→SPAM, \Trash→TRASH, \Archive→ARCHIVE), and
  • a separate SPECIAL_USE_ATTRIBUTES set for isServerSpecial that also listed \All and \Flagged — attributes with no role branch, so the two disagreed (e.g. a localized Gmail "All Mail" advertising \All was server-special yet classified NORMAL).

Both now read from one ordered ATTRIBUTE_ROLES: Map<String, FolderRole?> (a null value = server-special but role-less):

  • roleOf = first role-bearing entry the folder advertises (insertion order preserves the old ladder's precedence),
  • isServerSpecial = the folder advertises any key.

Behavior-preserving: every existing attribute keeps its exact (role, specialUse). PR #113's fidelity tests stay green.

#62 — add \Important

Adds "\important" to null as one more role-less special-use key. Gmail advertises \Important on [Gmail]/Important; it's now recognized as server-provisioned, so the drawer de-dup renders Important - Gmail instead of leaking the raw Important ([Gmail]) namespace form.

Migration

None. The addition is purely additive — no (role, specialUse) mapping changed for any existing attribute, and specialUse remains a plain Boolean column re-derived from the server LIST response on the next folder refresh. No specialUse encoding change, so no Room migration.

Tests

  • FolderRoleTest: \Important in the isServerSpecial cases; a comprehensive table assertion pinning every attribute's (role, specialUse) incl. \Important; a table-order precedence guard; and a role-less-fallback guard (\All/\Important don't suppress the display-name role).
  • FolderMapperTest: extends the #64 role-less family (\All, \Flagged) with \Important at the FetchedFolder.toEntity mapper level.

Fast gate green locally: assembleDebug, testDebugUnitTest, lintDebug, ktlintCheck, detekt, compileDebugAndroidTestKotlin.

Closes #65
Closes #62

🤖 Generated with Claude Code

## What Unifies `FolderRole`'s two hand-maintained RFC 6154 attribute tables into a single source of truth, and adds `\Important` (RFC 8457) to it. ### #65 — one attribute-to-role table Before, the companion held two tables that had already drifted: - `roleOf`'s attribute `when`-ladder (`\Sent`→SENT, `\Drafts`→DRAFTS, `\Junk`→SPAM, `\Trash`→TRASH, `\Archive`→ARCHIVE), and - a separate `SPECIAL_USE_ATTRIBUTES` set for `isServerSpecial` that also listed `\All` and `\Flagged` — attributes with **no** role branch, so the two disagreed (e.g. a localized Gmail "All Mail" advertising `\All` was server-special yet classified NORMAL). Both now read from one ordered `ATTRIBUTE_ROLES: Map<String, FolderRole?>` (a `null` value = server-special but role-less): - `roleOf` = first role-bearing entry the folder advertises (insertion order preserves the old ladder's precedence), - `isServerSpecial` = the folder advertises any key. Behavior-preserving: every existing attribute keeps its exact `(role, specialUse)`. PR #113's fidelity tests stay green. ### #62 — add `\Important` Adds `"\important" to null` as one more role-less special-use key. Gmail advertises `\Important` on `[Gmail]/Important`; it's now recognized as server-provisioned, so the drawer de-dup renders `Important - Gmail` instead of leaking the raw `Important ([Gmail])` namespace form. ## Migration None. The addition is purely additive — no `(role, specialUse)` mapping changed for any existing attribute, and `specialUse` remains a plain Boolean column re-derived from the server LIST response on the next folder refresh. No `specialUse` encoding change, so no Room migration. ## Tests - `FolderRoleTest`: `\Important` in the `isServerSpecial` cases; a comprehensive table assertion pinning every attribute's `(role, specialUse)` incl. `\Important`; a table-order precedence guard; and a role-less-fallback guard (`\All`/`\Important` don't suppress the display-name role). - `FolderMapperTest`: extends the #64 role-less family (`\All`, `\Flagged`) with `\Important` at the `FetchedFolder.toEntity` mapper level. Fast gate green locally: `assembleDebug`, `testDebugUnitTest`, `lintDebug`, `ktlintCheck`, `detekt`, `compileDebugAndroidTestKotlin`. Closes #65 Closes #62 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.