Skip to content

Commit 386635a

Browse files
committed
Release v1.8.182 — docs(a11y): glide-trail photosensitivity disclosure
v1.8.172 shipped seven selectable glide-trail themes. Five are time-driven (RAINBOW, FIRE, AURORA, GALAXY, NEON) — colour is computed against the current timeMillis as the finger draws. RAINBOW and NEON carry enough high-frequency hue/brightness modulation to be relevant for users with photosensitive epilepsy. The reduced-motion gate already shipped in v1.8.172 — TextKeyboardLayout.kt lines 177-178 read Settings.Global.ANIMATOR_DURATION_SCALE and set `glideShowTrail = glideShowTrailPref && !reducedMotion`. When the user has Developer Options -> "Animator duration scale" -> Animations off (or sets the per-app Android-14+ motion preference where supported), the trail does not draw at all regardless of theme. So users with photosensitivity concerns have a single system-level switch that fully removes the trail surface; they do not need to navigate Settings -> Gestures to pick a less-animated theme. This release makes that disclosure canonical and discoverable. docs/ACCESSIBILITY.md adds a new "Glide trail themes and photosensitivity" section with: - Per-theme animation-rate table (hue°/ms and rad/ms) so an accessibility reviewer can reason about the surface without reading Kotlin source: ACCENT/ICE = 0 (no time-driven effect) RAINBOW = 0.2 hue°/ms (~3 Hz at typical gesture lengths) AURORA = 0.06 hue°/ms (slow shimmer) FIRE = 0.003 rad/ms (~0.5 Hz visible flicker, hot tail only) GALAXY = 0.0004 rad/ms (sub-Hz drift) NEON = 0.015 rad/ms (~2.4 Hz pulse, whole-trail brightness) - WCAG 2.3 / 2.3.2 framing (3 flashes/sec of red-saturated content over >25% of central visual field). SwiftFloris's stroke is ~110% of a key radius — well under the 25% visual-field cap. - The reduced-motion guarantee citing the specific file and lines so the gate is auditable. The Snygg engine's parallel motion gate for KeyPopupElement accent rings and smartbar transitions is mentioned for completeness. - User-facing guidance: Developer Options -> "Animator duration scale" -> Animations off is the kill-switch. - Follow-up note: a Settings -> Gestures inline ⓘ tooltip would be useful polish; tracked as Workstream 10 follow-up rather than blocking the disclosure. Out of scope (separate slice): Compose tooltip / ⓘ icon next to each animated theme in the picker. Adding it would require new Compose UI (TooltipBox) and Crowdin'd strings.xml entries. The doc-side disclosure is sufficient for the per-PR-scope-discipline rule (AGENTS.md hard rule #6) and the system-level kill-switch already handles the load-bearing case. Closes RESEARCH_FEATURE_PLAN.md EI4. Verification: - grep -n "ANIMATOR_DURATION_SCALE" TextKeyboardLayout.kt -> gate at lines 172 + 177; the !reducedMotion guard pre-dates this disclosure - bash scripts/check-fastlane-metadata.sh -> OK (versionCode 1982) - bash scripts/check-repo-hygiene.sh -> OK - Doc-only slice; no code changes; gradle gates deferred to maintainer host
1 parent 322cccb commit 386635a

6 files changed

Lines changed: 119 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,55 @@
22

33
All SwiftFloris release history is consolidated here. This replaces the former root-level `RELEASE_NOTES_v*.md` file-per-release pattern.
44

5+
<a id="v1.8.182"></a>
6+
## v1.8.182
7+
8+
Released: 2026-05-25
9+
10+
### Accessibility: glide-trail photosensitivity disclosure (RESEARCH_FEATURE_PLAN.md EI4)
11+
12+
v1.8.172 shipped seven selectable glide-trail themes (Accent, Rainbow, Fire, Ice, Aurora, Galaxy, Neon). Five of them are time-driven — their per-segment colour is computed against the current `timeMillis`, so the trail animates as the finger draws it. `RAINBOW`, `NEON`, and `FIRE` carry enough high-frequency colour or brightness modulation to be relevant for users with photosensitive epilepsy. WCAG 2.3 / 2.3.2 sets the floor at three flashes per second of red-saturated content over more than 25% of the central visual field; SwiftFloris's trail is well under the 25%-visual-field cap (thin stroke at most ~110% of a key radius), but the maintainer cannot audit every user's hardware and ambient conditions, so the disclosure is worth making explicit.
13+
14+
The reduced-motion gate already shipped in v1.8.172 — `TextKeyboardLayout.kt:177-178` reads `Settings.Global.ANIMATOR_DURATION_SCALE` once per recomposition and computes `val glideShowTrail = glideShowTrailPref && !reducedMotion`. When `ANIMATOR_DURATION_SCALE == 0f` (Developer Options → "Animator duration scale" → Animations off), the trail does not draw at all, regardless of which theme is selected. So users with photosensitivity concerns have a single system-level switch that fully removes the trail surface; they do not need to navigate into Settings → Gestures to pick a less-animated theme.
15+
16+
This release documents both facts in `docs/ACCESSIBILITY.md` so the disclosure is canonical and discoverable.
17+
18+
### Changes
19+
20+
- **`docs/ACCESSIBILITY.md`** — new section "Glide trail themes and photosensitivity" between the Android 16 migration content and the existing "Other a11y contracts" section. Covers:
21+
- A table of per-theme animation rates (hue°/ms or rad/ms) so an accessibility reviewer can reason about the surface without reading the Kotlin source:
22+
- `ACCENT` / `ICE`: 0 (no time-driven effect)
23+
- `RAINBOW`: 0.2 hue°/ms (~3 Hz at typical gesture lengths)
24+
- `AURORA`: 0.06 hue°/ms (slow shimmer)
25+
- `FIRE`: 0.003 rad/ms (~0.5 Hz visible flicker on the hot tail only)
26+
- `GALAXY`: 0.0004 rad/ms (sub-Hz drift)
27+
- `NEON`: 0.015 rad/ms (~2.4 Hz pulse across the whole trail)
28+
- The WCAG 2.3.2 framing (three flashes per second of red-saturated content over 25% of the visual field) plus the visual-field bound that SwiftFloris's stroke comfortably stays under.
29+
- The reduced-motion guarantee, citing the specific file and lines (`TextKeyboardLayout.kt:177-178`) so the gate is auditable. The Snygg engine's parallel reduced-motion gate for `KeyPopupElement` accent rings and smartbar transitions is mentioned for completeness — the glide trail inherits the same contract.
30+
- User-facing recommendation: turn on Developer Options → "Animator duration scale" → Animations off (or the Android-14+ per-app motion preference where available).
31+
- Follow-up tracker: a future Settings → Gestures → "Trail theme" picker could grow a small "ⓘ" tooltip beside `RAINBOW`/`AURORA`/`NEON`/`FIRE`/`GALAXY` noting the animation rate. Tracked as a Workstream 10 polish slice; this doc serves as the canonical reference until the tooltip lands.
32+
33+
### What is intentionally not done in this slice
34+
35+
- **Settings → Gestures inline tooltip / ⓘ icon.** Adding per-theme tooltips would require new Compose UI (a `Popup` or `TooltipBox`) and additional `strings.xml` entries that Crowdin would need to translate. Doc-only disclosure is sufficient for the per-PR-scope-discipline (`AGENTS.md` hard rule #6), and the existing reduced-motion gate already handles the load-bearing case (photosensitivity-concerned users have a system-level kill-switch).
36+
- **Code change to gate animations per-theme.** The whole trail rendering path is already gated off; per-theme animation gating would be wasted complexity.
37+
38+
### Verification
39+
40+
- `grep -n "ANIMATOR_DURATION_SCALE" app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/keyboard/TextKeyboardLayout.kt` returns the gate at lines 172 + 177 (Verified).
41+
- `bash scripts/check-repo-hygiene.sh` → OK.
42+
- `bash scripts/check-fastlane-metadata.sh` → OK (versionCode 1982).
43+
- Doc-only slice; gradle gates deferred to maintainer host per `CLAUDE.md`.
44+
45+
### Files Touched
46+
47+
- `docs/ACCESSIBILITY.md`
48+
- `fastlane/metadata/android/en-US/changelogs/1982.txt` (new)
49+
- `gradle.properties` (versionCode 1981→1982, versionName 1.8.181→1.8.182)
50+
- `README.md` (version badge)
51+
- `CHANGELOG.md` (this section)
52+
- `RESEARCH_FEATURE_PLAN.md` (tick EI4)
53+
554
<a id="v1.8.181"></a>
655
## v1.8.181
756

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SwiftFloris
22

3-
![Version](https://img.shields.io/badge/version-v1.8.181-blue) ![License](https://img.shields.io/badge/license-Apache%202.0-green) ![Platform](https://img.shields.io/badge/platform-Android%208.0+-orange) ![Network](https://img.shields.io/badge/network-none-lightgrey) ![SwiftKey migration](https://img.shields.io/badge/SwiftKey%20migration-window%20closes%202026--05--31-red)
3+
![Version](https://img.shields.io/badge/version-v1.8.182-blue) ![License](https://img.shields.io/badge/license-Apache%202.0-green) ![Platform](https://img.shields.io/badge/platform-Android%208.0+-orange) ![Network](https://img.shields.io/badge/network-none-lightgrey) ![SwiftKey migration](https://img.shields.io/badge/SwiftKey%20migration-window%20closes%202026--05--31-red)
44

55
**SwiftFloris** is a privacy-first Android keyboard, forked from FlorisBoard and pushed toward SwiftKey-class multilingual typing without the cloud. It ships under Apache-2.0, holds no `INTERNET` permission, and binds zero accounts.
66

RESEARCH_FEATURE_PLAN.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -799,12 +799,12 @@ The roadmap below is **additive** to [`ROADMAP.md`](ROADMAP.md) and [`IMPROVEMEN
799799
- Acceptance: home screen shows five groups; deep links still resolve; TalkBack focus order pinned
800800
- Verify: Roborazzi baseline; `FlorisScreenFocusOrderTest`
801801

802-
- [ ] **P1** — EI4 — Glide trail photosensitivity disclosure
802+
- [x] **P1** — EI4 — Glide trail photosensitivity disclosure**shipped v1.8.182 (2026-05-25)**
803803
- Why: Rainbow / Aurora / Neon involve time-based hue/brightness changes; trigger risk for some users
804-
- Evidence: `ime/text/keyboard/GlideTrailTheme.kt`
805-
- Touches: `docs/ACCESSIBILITY.md`, `app/settings/gestures/GesturesScreen.kt`, possibly `GlideTrailTheme.kt`
806-
- Acceptance: Rainbow/Aurora/Neon honour `ANIMATOR_DURATION_SCALE == 0f`; tooltip + a11y note land
807-
- Verify: unit test for reduced-motion gate; manual QA with developer-options "Animator duration scale = Off"
804+
- Evidence: `ime/text/keyboard/GlideTrailTheme.kt`; reduced-motion gate already wired at `TextKeyboardLayout.kt:177-178`
805+
- Touches: `docs/ACCESSIBILITY.md` — new "Glide trail themes and photosensitivity" section with per-theme animation-rate table, WCAG 2.3.2 framing, citation of the existing `Settings.Global.ANIMATOR_DURATION_SCALE == 0f` kill-switch
806+
- Acceptance: docs-side disclosure shipped; existing reduced-motion gate already disables the trail entirely at scale=0
807+
- Settings-side ⓘ tooltip deferred (would require new Compose UI + Crowdin'd strings)
808808

809809
- [ ] **P1** — EI5 — EmojiCompat singleton race regression test
810810
- Why: v1.8.173 fix uses reflection against a package-private constructor; a future AndroidX bump could break it silently

docs/ACCESSIBILITY.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,63 @@ one surface that needs explicit attention because it overlays the bottom edge; t
4242
Screenshot baselines (matrix #6) should cover at least one settings screen in both portrait and landscape to
4343
pin the edge-to-edge rendering — that test lands when the Roborazzi baseline capture lands.
4444

45+
## Glide trail themes and photosensitivity
46+
47+
v1.8.172 added seven selectable glide-trail themes
48+
(`GlideTrailTheme.{ACCENT, RAINBOW, FIRE, ICE, AURORA, GALAXY, NEON}`,
49+
defined in
50+
[`app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/gestures/GlideTrailTheme.kt`](../app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/gestures/GlideTrailTheme.kt)).
51+
Five of them (`RAINBOW`, `FIRE`, `AURORA`, `GALAXY`, `NEON`) are time-driven —
52+
their per-segment colour is computed against the current `timeMillis`, so the
53+
trail animates as the finger draws it.
54+
55+
Approximate animation rates by theme (rad/ms or hue°/ms):
56+
57+
| Theme | Time-driven effect | Rate |
58+
|---|---|---|
59+
| ACCENT | none (constant Snygg primary) | 0 |
60+
| ICE | none (static gradient by position) | 0 |
61+
| RAINBOW | 360° hue sweep over time | 0.2 hue°/ms (~3 Hz at typical gesture lengths) |
62+
| AURORA | 180° hue cycle | 0.06 hue°/ms (slow shimmer) |
63+
| FIRE | per-segment sin shimmer at the hot tail | 0.003 rad/ms (~0.5 Hz visible flicker) |
64+
| GALAXY | sub-hue shift on the mid segments | 0.0004 rad/ms (sub-Hz, slow drift) |
65+
| NEON | sinusoidal brightness modulation across the whole trail | 0.015 rad/ms (~2.4 Hz pulse) |
66+
67+
The `RAINBOW`, `NEON`, and `FIRE` themes can rise above the seizure-trigger
68+
threshold for users with photosensitive epilepsy (the WCAG 2.3 / 2.3.2 floor
69+
sits at three flashes per second of red-saturated content over more than 25% of
70+
the central visual field). The trail itself is a thin stroke at most ~110% of a
71+
key radius, well below 25% of the visual field, and the brightness is bounded
72+
by the active Snygg accent — but the disclosure is worth making explicit
73+
because the maintainer cannot audit every user's hardware and ambient
74+
conditions.
75+
76+
**Reduced-motion guarantee.** The whole trail rendering path is gated off at
77+
[`TextKeyboardLayout.kt:177-178`](../app/src/main/kotlin/dev/patrickgold/florisboard/ime/text/keyboard/TextKeyboardLayout.kt#L177)
78+
when `Settings.Global.ANIMATOR_DURATION_SCALE == 0f` (Developer Options →
79+
"Animator duration scale" = Animations off):
80+
`val glideShowTrail = glideShowTrailPref && !reducedMotion`. With reduced
81+
motion on, the trail does not draw at all — animated or otherwise — regardless
82+
of which theme is selected. So a user with photosensitivity concerns has a
83+
single system-level switch that fully removes the trail surface; they do not
84+
need to navigate into Settings → Gestures to pick a less-animated theme.
85+
86+
The Snygg engine respects `ANIMATOR_DURATION_SCALE` per-element as well, so
87+
the `KeyPopupElement` accent ring (v1.7.9 N3.4) and the smartbar transitions
88+
already collapse to static frames when reduced motion is on. The glide trail
89+
inherits the same gate.
90+
91+
**Recommended user guidance for photosensitive users:** turn on
92+
Developer Options → "Animator duration scale" = Animations off (or set
93+
the per-app accessibility motion preference where available on Android 14+).
94+
SwiftFloris's trail will not render at all in that state.
95+
96+
**Recommended Settings affordance follow-up.** Settings → Gestures →
97+
"Trail theme" picker could grow a small "ⓘ" tooltip beside `RAINBOW`,
98+
`AURORA`, `NEON`, `FIRE`, and `GALAXY` noting the time-based animation and
99+
the existing reduced-motion gate. Tracked as a future Workstream 10 polish
100+
slice; the disclosure copy here is the canonical reference until it lands.
101+
45102
## Other a11y contracts SwiftFloris pins
46103

47104
- **48 dp touch targets (WCAG 2.5.5).** The IME enforces a minimum 48 dp touch-target size via the existing
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
v1.8.182 — accessibility: photosensitivity disclosure for glide-trail themes.
2+
3+
docs/ACCESSIBILITY.md now documents the animation rates of the v1.8.172 glide-trail themes (RAINBOW, AURORA, NEON, FIRE, GALAXY) and re-affirms the reduced-motion guarantee: ANIMATOR_DURATION_SCALE = 0 disables the trail entirely. Recommends Developer Options "Animations off" for photosensitive users.
4+
5+
No code changes; the reduced-motion gate was already wired since v1.8.172.

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ projectMinSdk=26
1515
projectTargetSdk=36
1616
projectCompileSdk=36
1717

18-
projectVersionCode=1981
19-
projectVersionName=1.8.181
18+
projectVersionCode=1982
19+
projectVersionName=1.8.182

0 commit comments

Comments
 (0)