Skip to content

feat: add two-button navigation to dictionary word select - #2981

Open
kroer wants to merge 1 commit into
crosspoint-reader:developfrom
kroer:feature/dict-two-button-nav
Open

feat: add two-button navigation to dictionary word select#2981
kroer wants to merge 1 commit into
crosspoint-reader:developfrom
kroer:feature/dict-two-button-nav

Conversation

@kroer

@kroer kroer commented Aug 12, 2026

Copy link
Copy Markdown

Summary

  • What is the goal of this PR? Add a two-button navigation mode for the dictionary word-select screen, for comfortable one-handed reading.
  • What changes are included?
    • New dictWordNavMode setting: existing four-button scheme (Left/Right step words, Up/Down jump rows) vs. a two-button scheme where Up+Left both step to the previous word and Down+Right both step to the next.
    • In two-button mode, a tap steps one word; holding either pair instead repeats as row jumps, at a configurable dictWordNavSpeed (Normal/Fast).
    • The nav-mode setting only shows in Settings when the long-press menu is set to Dictionary; the speed setting only shows when two-button mode is selected.

Scope Check

CrossPoint is intentionally narrow. See SCOPE.md and ROADMAP.md.
Please confirm:

  • I have read SCOPE.md and ROADMAP.md.
  • This PR is not a new built-in theme (themes are temporarily closed pending the move to SD-loaded themes).
  • This PR is not a new external network connector (sync engine, cloud storage, remote file access, etc.).
  • This PR is not an interactive app, writing tool, RSS/news/browser, media playback, or PDF feature.
  • The stock firmware does not already handle this well, and no other popular CrossPoint fork already does
    (or, if one does, I explain why CrossPoint still needs it below).
  • If this PR touches freeink-sdk/, lib/hal/, the bootloader, OTA, or recovery code, I have coordinated with
    the relevant maintainer.

Additional Context

  • Left-handed / one-handed reading is not addressed by the stock firmware's dictionary lookup, which requires four
    distinct front buttons; this closes that gap with a settings-gated alternative that doesn't change default behavior.
  • Memory impact: two new uint8_t settings fields (~2 bytes permanent RAM). The two-button repeat logic reuses the
    existing ButtonNavigator hold-to-repeat mechanism (same one DictionaryDefinitionActivity uses for page turns),
    with its button-list vectors held as activity members rather than rebuilt per tick, so there's no additional
    per-loop heap allocation.
  • Tested end-to-end on real Xteink X4 hardware (build + flash + on-device verification of both modes, hold-to-jump
    speed settings, and the conditional settings visibility).

AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? YES

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 823855a6-ffe6-447d-b759-e78e8879f7bb

📥 Commits

Reviewing files that changed from the base of the PR and between 86eb1cb and 89d13f8.

📒 Files selected for processing (7)
  • lib/I18n/translations/english.yaml
  • src/CrossPointSettings.cpp
  • src/CrossPointSettings.h
  • src/SettingsList.h
  • src/activities/reader/DictionaryWordSelectActivity.cpp
  • src/activities/reader/DictionaryWordSelectActivity.h
  • src/activities/settings/SettingsActivity.cpp
📜 Recent review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Build default
  • GitHub Check: cppcheck
  • GitHub Check: Build sticky
🧰 Additional context used
🧠 Learnings (22)
📓 Common learnings
Learnt from: zgredex
Repo: crosspoint-reader/crosspoint-reader PR: 1775
File: src/components/themes/lyra/LyraCarouselTheme.cpp:55-72
Timestamp: 2026-04-28T09:44:20.329Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/home/HomeActivity.cpp, carousel navigation loop, lines ~386-403), the Up/Down button symmetry — where both Up and Down toggle between the carousel row and the icon menu row — is intentional by design. Do not flag this as a UX inconsistency or suggest differentiated directional behavior in future reviews.
Learnt from: Pankaj-Patil22
Repo: crosspoint-reader/crosspoint-reader PR: 1650
File: src/activities/reader/EpubReaderActivity.cpp:1038-1075
Timestamp: 2026-04-22T16:29:04.799Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/reader/EpubReaderActivity.cpp, EpubReaderActivity::adaptReadingSpeed), setting `lastForwardWasAccidental = true` before the short-page guard is intentional by design. Any forward turn under MIN_ADAPT_ELAPSED_MS (2 s) — regardless of page length — is treated as a potentially accidental tap. A subsequent Back press always cancels it unconditionally (without applying slowdown or incrementing skipForwardAdaptCount), so the short-page guard ordering is irrelevant. Do not flag this ordering as a bug in future reviews.
Learnt from: Pankaj-Patil22
Repo: crosspoint-reader/crosspoint-reader PR: 1650
File: src/activities/reader/EpubReaderActivity.cpp:155-158
Timestamp: 2026-04-22T16:28:42.649Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/reader/EpubReaderActivity.cpp, EpubReaderActivity::loop), the condition `skipForwardAdaptCount == 0 && (millis() - lastPageTurnTime) >= pageTurnDuration` is intentional. After a Smart Back turn, auto-turn is deliberately paused (skipForwardAdaptCount > 0) so the user has full manual control while re-reading the page they returned to. Auto-turn resumes only after the user manually advances through the partial re-read pages (decrementing the counter to 0). Do not flag this as a bug in future reviews.
📚 Learning: 2026-02-23T22:11:42.181Z
Learnt from: ariel-lindemann
Repo: crosspoint-reader/crosspoint-reader PR: 1133
File: lib/I18n/translations/finnish.yaml:92-92
Timestamp: 2026-02-23T22:11:42.181Z
Learning: In translation YAML files located in lib/I18n/translations/, literal percent signs (%) in strings (e.g., STR_HIDE_BATTERY, STR_GO_TO_PERCENT, STR_PERCENT_STEP_HINT) do not require escaping as %% and this convention is consistent across all language translations. Ensure that this pattern is followed for all YAML files in this directory to avoid introducing incorrect formatting markers in localized strings.

Applied to files:

  • lib/I18n/translations/english.yaml
📚 Learning: 2026-03-25T10:28:30.516Z
Learnt from: jpirnay
Repo: crosspoint-reader/crosspoint-reader PR: 1495
File: lib/I18n/translations/german.yaml:294-322
Timestamp: 2026-03-25T10:28:30.516Z
Learning: In crosspoint-reader, it is expected to include “pre-emptive” translation keys in non-English YAML files before the corresponding English keys exist (e.g., german.yaml ahead of en.yaml). When reviewing changes to files under lib/I18n/translations/*.yaml, do not flag missing corresponding English keys in non-English locales as an error if the repo’s gen_i18n.py fallback mechanism is intended to handle missing English keys safely until the pending PRs land.

Applied to files:

  • lib/I18n/translations/english.yaml
📚 Learning: 2026-04-17T18:59:20.878Z
Learnt from: KymAndriy
Repo: crosspoint-reader/crosspoint-reader PR: 1684
File: lib/I18n/translations/ukrainian.yaml:29-29
Timestamp: 2026-04-17T18:59:20.878Z
Learning: For Ukrainian (and other Slavic-language) translation YAML strings in lib/I18n/translations/*.yaml: if a format string contains a numeric placeholder produced via snprintf-style formatting (e.g., %zu) and runtime noun inflection is not feasible, place the relevant noun in genitive plural before the number in the string (e.g., "мереж %zu") rather than after it (e.g., "мережу %zu"). This avoids incorrect case forms that would otherwise result from the value affecting inflection (e.g., wrong forms like "мережу/мережі/мереж"). In such cases, do not flag the word order as incorrect.

Applied to files:

  • lib/I18n/translations/english.yaml
📚 Learning: 2026-08-10T20:39:38.043Z
Learnt from: loic-daigle
Repo: crosspoint-reader/crosspoint-reader PR: 2961
File: src/MappedInputManager.h:111-116
Timestamp: 2026-08-10T20:39:38.043Z
Learning: For power-button duration classification, `src/main.cpp` treats a press as long only when `heldTime > CrossPointSettings::getPowerButtonDuration()`. `MappedInputManager::wasShortPowerSelectClick()` intentionally uses `heldTime <= CrossPointSettings::getPowerButtonDuration()` so the classifications are complementary. A duration equal to the threshold is a short press and must produce the configured Select action.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
📚 Learning: 2026-02-23T06:18:08.408Z
Learnt from: raygan
Repo: crosspoint-reader/crosspoint-reader PR: 1116
File: src/activities/settings/WallabagSettingsActivity.cpp:57-75
Timestamp: 2026-02-23T06:18:08.408Z
Learning: When navigating from a settings activity to KeyboardEntryActivity (e.g., KOReaderSettingsActivity, WallabagSettingsActivity), call exitActivity() on the parent before calling enterNewActivity(new KeyboardEntryActivity(...)). The KeyboardEntryActivity should then call exitActivity() via its callbacks to return to the parent. Note: ConfirmationActivity does not require exitActivity() before entering KeyboardEntryActivity. Apply this pattern to similar settings activities in this module.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
📚 Learning: 2026-02-27T22:49:59.600Z
Learnt from: ngxson
Repo: crosspoint-reader/crosspoint-reader PR: 1218
File: src/activities/ActivityManager.cpp:254-265
Timestamp: 2026-02-27T22:49:59.600Z
Learning: In this codebase, assertions are always enabled (no NDEBUG). Use assert() to crash on programmer errors and surface logic bugs during development and in production builds. Do not rely on asserts for runtime error handling; they should enforce invariants that must always hold. Keep asserts side-effect free and inexpensive, and avoid relying on them for user-visible failures. Include <cassert> where appropriate and document the invariant being tested.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
  • src/CrossPointSettings.cpp
  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-03-02T10:14:16.036Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1245
File: lib/Epub/Epub/Section.cpp:277-308
Timestamp: 2026-03-02T10:14:16.036Z
Learning: Guideline: Strengthen serialization::readString to defend against unbounded growth when reading from disk data. Implement and enforce a maximum allowed length (e.g., a configured or reasonable constant) and validate the incoming length before resizing or allocating. Audit all call sites (e.g., BookMetadataCache, TextBlock, KOReaderCredentialStore, Section cache readers) to ensure they do not rely on unbounded len-based resizing. If the readString API must remain, add internal safeguards (bounds checks, length validation, and error handling) so per-call-site validations are not required. Ensure Section cache files remain versioned (SECTION_FILE_VERSION) and parameter mismatches invalidate caches, but do not rely on unsafe allocations; prefer safe, bounded reads with explicit errors on invalid data.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
  • src/CrossPointSettings.cpp
  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-12T12:28:33.205Z
Learnt from: Uri-Tauber
Repo: crosspoint-reader/crosspoint-reader PR: 1629
File: src/activities/home/HomeActivity.cpp:119-120
Timestamp: 2026-04-12T12:28:33.205Z
Learning: When reviewing code in this repository (C/C++ sources), set review comment severity according to this policy:
- Use **Major** (🟠) only for defects with realistic risk of crash, out-of-memory (OOM), invalid pointer dereference, data corruption, or other severe issues that are unlikely to be caught in casual/manual device testing.
- Use **Minor** or informational for UX gaps, logic edge-cases, style issues, or missing feature completeness that the author can verify (or has verified) through normal device use.
- Do **not** escalate severity to Major based on behavioral/UX observations alone; assume the author has already tested the feature on their own device and only treat issues as Major if they match the high-risk defect categories above.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
  • src/CrossPointSettings.cpp
  • src/SettingsList.h
  • src/activities/reader/DictionaryWordSelectActivity.h
  • src/activities/reader/DictionaryWordSelectActivity.cpp
  • src/CrossPointSettings.h
📚 Learning: 2026-05-24T21:10:19.897Z
Learnt from: jeremydk
Repo: crosspoint-reader/crosspoint-reader PR: 2076
File: src/network/HttpDownloader.cpp:166-171
Timestamp: 2026-05-24T21:10:19.897Z
Learning: Follow the repo’s CLAUDE.md guidance: avoid adding error handling, fallbacks, or extra validation for scenarios that are provably unreachable given existing internal invariants and framework guarantees. Only add validation/guards at true system boundaries (e.g., user input, external APIs/network/IPC). For internal C++ APIs like HttpDownloader, do not add defensive checks against misuse (e.g., an empty std::function callback) when there is no reachable call site that can supply such values—guards in those cases are explicitly discouraged.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
  • src/CrossPointSettings.cpp
  • src/SettingsList.h
  • src/activities/reader/DictionaryWordSelectActivity.h
  • src/activities/reader/DictionaryWordSelectActivity.cpp
  • src/CrossPointSettings.h
📚 Learning: 2026-08-10T19:01:20.991Z
Learnt from: itsthisjustin
Repo: crosspoint-reader/crosspoint-reader PR: 2957
File: src/activities/browser/OpdsBookBrowserActivity.cpp:58-64
Timestamp: 2026-08-10T19:01:20.991Z
Learning: In crosspoint-reader activities, navigation heap-allocates activity instances and exitActivity() in src/main.cpp deletes them. Treat each activity instance's onEnter() as running exactly once; per-instance UI actions registered there do not accumulate across navigations, so do not flag them as duplicate registrations unless the lifecycle or ownership model changes.

Applied to files:

  • src/activities/settings/SettingsActivity.cpp
  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-28T09:44:20.329Z
Learnt from: zgredex
Repo: crosspoint-reader/crosspoint-reader PR: 1775
File: src/components/themes/lyra/LyraCarouselTheme.cpp:55-72
Timestamp: 2026-04-28T09:44:20.329Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/home/HomeActivity.cpp, carousel navigation loop, lines ~386-403), the Up/Down button symmetry — where both Up and Down toggle between the carousel row and the icon menu row — is intentional by design. Do not flag this as a UX inconsistency or suggest differentiated directional behavior in future reviews.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.h
  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-05T19:21:32.486Z
Learnt from: Zyd8
Repo: crosspoint-reader/crosspoint-reader PR: 1576
File: src/activities/home/RecentBooksActivity.cpp:65-90
Timestamp: 2026-04-05T19:21:32.486Z
Learning: In crosspoint-reader/crosspoint-reader (src/util/ButtonNavigator.cpp, shouldSuppressListNavForMidpointChord), the guard-clearing tick intentionally still returns `true` when it clears `s_midpointChordReleaseGuard`. This is correct because all list navigation in the activity uses `onNextRelease`/`onPreviousRelease`, which only fire on a fresh press+release cycle. The clearing tick therefore only swallows the stale release from the chord buttons themselves. Any subsequent Up/Down tap starts a new press+release cycle and will not be suppressed. Do not flag this as a dropped-input bug in future reviews.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.h
  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-13T23:10:44.397Z
Learnt from: aarons
Repo: crosspoint-reader/crosspoint-reader PR: 1659
File: src/activities/reader/ReaderUtils.h:48-51
Timestamp: 2026-04-13T23:10:44.397Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/reader/ReaderUtils.h, detectRotation), the rotation logic uses "content rotation" semantics, not "device rotation" semantics. The bottom button (isBottom=true) rotates the on-screen content clockwise, which physically corresponds to rotating the device counter-clockwise. The enum step `(orientation - 1 + COUNT) % COUNT` achieves CW content rotation; `(orientation + 1) % COUNT` achieves CCW content rotation. This is intentional. Do not flag as reversed. Named helpers `rotateContentCW` / `rotateContentCCW` were suggested by the author as a potential future clarity improvement.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.h
  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-22T16:29:04.799Z
Learnt from: Pankaj-Patil22
Repo: crosspoint-reader/crosspoint-reader PR: 1650
File: src/activities/reader/EpubReaderActivity.cpp:1038-1075
Timestamp: 2026-04-22T16:29:04.799Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/reader/EpubReaderActivity.cpp, EpubReaderActivity::adaptReadingSpeed), setting `lastForwardWasAccidental = true` before the short-page guard is intentional by design. Any forward turn under MIN_ADAPT_ELAPSED_MS (2 s) — regardless of page length — is treated as a potentially accidental tap. A subsequent Back press always cancels it unconditionally (without applying slowdown or incrementing skipForwardAdaptCount), so the short-page guard ordering is irrelevant. Do not flag this ordering as a bug in future reviews.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-22T16:28:42.649Z
Learnt from: Pankaj-Patil22
Repo: crosspoint-reader/crosspoint-reader PR: 1650
File: src/activities/reader/EpubReaderActivity.cpp:155-158
Timestamp: 2026-04-22T16:28:42.649Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/reader/EpubReaderActivity.cpp, EpubReaderActivity::loop), the condition `skipForwardAdaptCount == 0 && (millis() - lastPageTurnTime) >= pageTurnDuration` is intentional. After a Smart Back turn, auto-turn is deliberately paused (skipForwardAdaptCount > 0) so the user has full manual control while re-reading the page they returned to. Auto-turn resumes only after the user manually advances through the partial re-read pages (decrementing the counter to 0). Do not flag this as a bug in future reviews.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-08-02T12:14:47.878Z
Learnt from: winst0niuss
Repo: crosspoint-reader/crosspoint-reader PR: 2840
File: src/activities/util/KeyboardEntryActivity.cpp:733-738
Timestamp: 2026-08-02T12:14:47.878Z
Learning: In `src/activities/util/KeyboardEntryActivity.cpp`, `KeyboardEntryActivity::lineBreakEnd()` must return UTF-8 code-point boundaries. Its byte-index binary search can stop inside a multi-byte sequence, so it snaps the result backward to a boundary, remeasures the range, and steps backward by complete code points until it fits. It must retain at least one complete code point to guarantee that the render wrapping loop advances. `KeyboardEntryActivity::loop()` already snaps touch-derived cursor positions backward from UTF-8 continuation bytes before assigning `cursorPos`.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-07-24T21:15:54.622Z
Learnt from: W-Floyd
Repo: crosspoint-reader/crosspoint-reader PR: 0
File: :0-0
Timestamp: 2026-07-24T21:15:54.622Z
Learning: In `src/util/Dictionary.cpp`, a definition read that returns fewer nonnegative bytes than requested intentionally succeeds and resizes the definition to the bytes read. This preserves compatibility with dictionaries whose final index entry extends beyond EOF; do not treat this short-read case as a hard lookup failure without an intentional behavior change.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-06-27T20:07:32.056Z
Learnt from: IjonFryderyk
Repo: crosspoint-reader/crosspoint-reader PR: 2453
File: src/activities/reader/EpubReaderActivity.cpp:354-364
Timestamp: 2026-06-27T20:07:32.056Z
Learning: In `src/activities/reader/EpubReaderFootnotesActivity`, when the activity is entered from `src/activities/reader/EpubReaderActivity.cpp` via the long-press Confirm footnotes flow, Confirm may still be held on entry. `EpubReaderFootnotesActivity::onEnter()` should detect a held select button (Confirm or Power) and use a one-shot `ignoreFirstSelectRelease` latch so the opening release is swallowed and does not immediately select footnote index 0. Other entry paths such as the reader menu and short power-button footnotes path do not need this latch because no select button is held on entry.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-05T19:31:31.692Z
Learnt from: Zyd8
Repo: crosspoint-reader/crosspoint-reader PR: 1576
File: src/util/ButtonNavigator.h:43-47
Timestamp: 2026-04-05T19:31:31.692Z
Learning: In crosspoint-reader/crosspoint-reader (src/util/ButtonNavigator.cpp), `clearMidpointChordReleaseGuard()` intentionally sets `s_suppressUntilChordRelease` in addition to resetting the post-release guard. This blocks `beginUpDownChord()` from firing on the first loop tick of a new activity if the midpoint chord was still physically held during the `Activity::onEnter()` transition. The fix prevents cross-screen midpoint chord leaks without requiring each activity's `onEnter()` to call `isMidpointChordHeld()`. Do not flag this dual-write as redundant in future reviews.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-13T22:45:24.939Z
Learnt from: aarons
Repo: crosspoint-reader/crosspoint-reader PR: 1659
File: src/activities/reader/ReaderUtils.h:48-51
Timestamp: 2026-04-13T22:45:24.939Z
Learning: In crosspoint-reader/crosspoint-reader (src/activities/reader/ReaderUtils.h, detectRotation), the rotation direction logic `isBottom ? (orientation - 1 + COUNT) % COUNT : (orientation + 1) % COUNT` is intentionally correct as written. Despite the enum ordering PORTRAIT→LANDSCAPE_CW→INVERTED→LANDSCAPE_CCW suggesting "+1 = clockwise", on the actual device hardware the bottom button (isBottom=true) stepping backward through the enum (-1) produces a clockwise rotation and the top button (+1) produces counter-clockwise. Do not flag this as reversed in future reviews.

Applied to files:

  • src/activities/reader/DictionaryWordSelectActivity.cpp
📚 Learning: 2026-04-05T10:43:16.171Z
Learnt from: pablohc
Repo: crosspoint-reader/crosspoint-reader PR: 1534
File: src/activities/boot_sleep/SleepActivity.cpp:0-0
Timestamp: 2026-04-05T10:43:16.171Z
Learning: In crosspoint-reader/crosspoint-reader (src/CrossPointSettings.h), CrossPointSettings::SLEEP_COVER_OVERLAY enum has values: OVERLAY_OFF=0, OVERLAY_WHITE=1, OVERLAY_GRAY=2, OVERLAY_BLACK=3 (as of commit 2471b5a in PR `#1534`). The default sleepCoverOverlay byte is 0 (OVERLAY_OFF). Do not use the old ordering WHITE=0/GRAY=1/BLACK=2/OFF=3 in future reviews.

Applied to files:

  • src/CrossPointSettings.h
🔇 Additional comments (7)
src/CrossPointSettings.h (1)

173-180: LGTM!

Also applies to: 293-295, 368-368

src/CrossPointSettings.cpp (1)

313-321: LGTM!

src/SettingsList.h (1)

301-306: LGTM!

lib/I18n/translations/english.yaml (1)

104-109: LGTM!

src/activities/reader/DictionaryWordSelectActivity.h (1)

10-10: LGTM!

Also applies to: 47-61, 81-96

src/activities/reader/DictionaryWordSelectActivity.cpp (1)

153-162: LGTM!

Also applies to: 283-313

src/activities/settings/SettingsActivity.cpp (1)

62-70: LGTM!


📝 Walkthrough

Walkthrough

The change adds persisted dictionary word-navigation mode and speed settings. The reader activity supports four-button and two-button navigation, including configurable hold-to-repeat intervals. Settings visibility depends on dictionary access and the selected navigation mode.

Changes

Dictionary navigation settings and controls

Layer / File(s) Summary
Navigation settings contract
src/CrossPointSettings.h, src/CrossPointSettings.cpp, src/SettingsList.h, lib/I18n/translations/english.yaml
Adds persisted four-button/two-button modes and normal/fast speeds. The repeat interval resolves to 500 ms or 250 ms. Controls and English labels expose these options.
Word-selection navigation
src/activities/reader/DictionaryWordSelectActivity.h, src/activities/reader/DictionaryWordSelectActivity.cpp
Adds bounded word stepping. Two-button releases move between words, while held button pairs perform continuous row jumps. Four-button navigation retains left/right word movement.
Conditional settings visibility
src/activities/settings/SettingsActivity.cpp
Shows navigation mode only when dictionary access is configured. Shows navigation speed only for two-button navigation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SettingsActivity
  participant CrossPointSettings
  participant DictionaryWordSelectActivity
  participant ButtonNavigator

  User->>SettingsActivity: Select navigation mode or speed
  SettingsActivity->>CrossPointSettings: Persist setting
  User->>DictionaryWordSelectActivity: Open dictionary word selection
  DictionaryWordSelectActivity->>CrossPointSettings: Read navigation mode and interval
  DictionaryWordSelectActivity->>ButtonNavigator: Configure two-button navigation
  ButtonNavigator->>DictionaryWordSelectActivity: Report release or hold
  DictionaryWordSelectActivity->>DictionaryWordSelectActivity: Move word or jump rows
Loading

Possibly related PRs

Suggested reviewers: itsthisjustin

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: adding two-button navigation to dictionary word selection.
Description check ✅ Passed The description directly explains the two-button navigation mode, settings, behavior, visibility rules, and testing.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant