SettingsRepository: adds lastFontCss (String?) / lastFontSizePt (Int?) to AppSettings, their Keys/toAppSettings() mapping, and setLastFont(fontCss, fontSizePt) — following the same null-clears-the-key pattern as setDefaultAccountId (and the same shape as the licenseAccepted field added by #172).
ComposeViewModel (SettingsRepository was already injected, from #163's default-account work — no constructor change, so no call sites needed updating):
On send: after a successful send, parses the outgoing bodyHtml with RichTextHtml.fromHtml and persists the font — the message-wide RichBaseStyle if one is set, else the last FontFamily/FontSize inline span (each axis independently). A plaintext send, or a formatted one that never touched a font, leaves the stored preference untouched.
On brand-new compositions only (draftId == null — replies/forwards always arrive as drafts): after the sending account's signature is applied, seeds a RichBaseStyle from the remembered font so the whole message (including the signature) defaults to it. No-op when nothing has been remembered yet, so an unformatted message doesn't gain an HTML body for no visible reason.
No Room schema change — this is Preferences DataStore only.
Test plan
MockK ComposeViewModelTest: persists the base-style font on send; persists the last matching span per axis when there's no base style; does not persist when the sent message has no font styling or is plaintext-only; seeds a brand-new composition (bare and with a signature) with the remembered font; does not seed an existing/resumed draft; stays plaintext-only when composing new with no remembered font.
AppSettingsTest: lastFontCss/lastFontSizePt default/round-trip/independent-nullability coverage at the toAppSettings() mapping layer, matching the existing licenseAccepted/defaultAccountId pattern.
## Summary
- `SettingsRepository`: adds `lastFontCss` (String?) / `lastFontSizePt` (Int?) to `AppSettings`, their `Keys`/`toAppSettings()` mapping, and `setLastFont(fontCss, fontSizePt)` — following the same null-clears-the-key pattern as `setDefaultAccountId` (and the same shape as the `licenseAccepted` field added by #172).
- `ComposeViewModel` (SettingsRepository was already injected, from #163's default-account work — no constructor change, so no call sites needed updating):
- **On send**: after a successful send, parses the outgoing `bodyHtml` with `RichTextHtml.fromHtml` and persists the font — the message-wide `RichBaseStyle` if one is set, else the last `FontFamily`/`FontSize` inline span (each axis independently). A plaintext send, or a formatted one that never touched a font, leaves the stored preference untouched.
- **On brand-new compositions only** (`draftId == null` — replies/forwards always arrive as drafts): after the sending account's signature is applied, seeds a `RichBaseStyle` from the remembered font so the whole message (including the signature) defaults to it. No-op when nothing has been remembered yet, so an unformatted message doesn't gain an HTML body for no visible reason.
No Room schema change — this is Preferences DataStore only.
## Test plan
- [x] MockK `ComposeViewModelTest`: persists the base-style font on send; persists the last matching span per axis when there's no base style; does *not* persist when the sent message has no font styling or is plaintext-only; seeds a brand-new composition (bare and with a signature) with the remembered font; does *not* seed an existing/resumed draft; stays plaintext-only when composing new with no remembered font.
- [x] `AppSettingsTest`: `lastFontCss`/`lastFontSizePt` default/round-trip/independent-nullability coverage at the `toAppSettings()` mapping layer, matching the existing `licenseAccepted`/`defaultAccountId` pattern.
- [x] `.\gradlew :app:assembleDebug`
- [x] `.\gradlew :app:testDebugUnitTest` (28/28 `ComposeViewModelTest`, 11/11 `AppSettingsTest`)
- [x] `.\gradlew :app:lintDebug`
- [x] `.\gradlew :app:ktlintCheck :app:detekt`
- [x] `.\gradlew :app:compileDebugAndroidTestKotlin` (confirms `ComposeScreenTest`'s direct VM construction still compiles)
Closes #78
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
SettingsRepository: addslastFontCss(String?) /lastFontSizePt(Int?) toAppSettings, theirKeys/toAppSettings()mapping, andsetLastFont(fontCss, fontSizePt)— following the same null-clears-the-key pattern assetDefaultAccountId(and the same shape as thelicenseAcceptedfield added by #172).ComposeViewModel(SettingsRepository was already injected, from #163's default-account work — no constructor change, so no call sites needed updating):bodyHtmlwithRichTextHtml.fromHtmland persists the font — the message-wideRichBaseStyleif one is set, else the lastFontFamily/FontSizeinline span (each axis independently). A plaintext send, or a formatted one that never touched a font, leaves the stored preference untouched.draftId == null— replies/forwards always arrive as drafts): after the sending account's signature is applied, seeds aRichBaseStylefrom the remembered font so the whole message (including the signature) defaults to it. No-op when nothing has been remembered yet, so an unformatted message doesn't gain an HTML body for no visible reason.No Room schema change — this is Preferences DataStore only.
Test plan
ComposeViewModelTest: persists the base-style font on send; persists the last matching span per axis when there's no base style; does not persist when the sent message has no font styling or is plaintext-only; seeds a brand-new composition (bare and with a signature) with the remembered font; does not seed an existing/resumed draft; stays plaintext-only when composing new with no remembered font.AppSettingsTest:lastFontCss/lastFontSizePtdefault/round-trip/independent-nullability coverage at thetoAppSettings()mapping layer, matching the existinglicenseAccepted/defaultAccountIdpattern..\gradlew :app:assembleDebug.\gradlew :app:testDebugUnitTest(28/28ComposeViewModelTest, 11/11AppSettingsTest).\gradlew :app:lintDebug.\gradlew :app:ktlintCheck :app:detekt.\gradlew :app:compileDebugAndroidTestKotlin(confirmsComposeScreenTest's direct VM construction still compiles)Closes #78
🤖 Generated with Claude Code