Skip to content

fix(preferences): persist customized timebox limit when disabled - #22815

Open
Ratnesh5 wants to merge 2 commits into
ankidroid:mainfrom
Ratnesh5:fix-22720-persist-customized-timebox-limit
Open

Ratnesh5 wants to merge 2 commits into
ankidroid:mainfrom
Ratnesh5:fix-22720-persist-customized-timebox-limit

Conversation

@Ratnesh5

Copy link
Copy Markdown
Contributor

Note

Assisted-by: Gemini Flash

Purpose / Description

When disabling the review timebox toggle, the collection timebox limit is set to 0. Previously, when re-enabling the toggle or leaving and re-entering the screen while disabled, the duration defaulted back to 20 minutes (DEFAULT_TIMEBOX_MINUTES), losing any custom duration (e.g. 45 minutes) the user had configured.
This PR persists the user's customized timebox limit in Android preferences (Prefs.customTimeboxLimit), so that:

  1. When the toggle is re-enabled, the customized limit is restored and written to collection preferences.
  2. When the user re-enters the screen while timeboxing is disabled, the previously configured duration is preserved and displayed.
  3. If an existing non-zero limit is present in the collection (e.g., from desktop sync), it updates the local preference so it is remembered if subsequently disabled.

Fixes

Approach

  • Added custom_timebox_limit_key in preferences.xml.
  • Added customTimeboxLimit property delegate in Prefs.kt with a default of 20 (DEFAULT_TIMEBOX_MINUTES).
  • In TimeboxSettingsViewModel:
    • Injected PrefsRepository = Prefs.
    • In loadSettings(): if disabled, initialize with prefs.customTimeboxLimit; if enabled, record the limit in prefs.customTimeboxLimit.
    • In setMinutes(): update prefs.customTimeboxLimit.
    • In toggleEnabled(): restore _uiState.value.minutes when enabled, or set 0 to collection when disabled while keeping the minutes in state/prefs.
  • Added comprehensive unit tests in TimeboxSettingsViewModelTest.

How Has This Been Tested?

  • Ran :AnkiDroid:testPlayDebugUnitTest --tests "com.ichi2.anki.preferences.TimeboxSettingsViewModelTest" (all passed).
  • Ran :AnkiDroid:testPlayDebugUnitTest --tests "com.ichi2.anki.settings.Prefs*" (all passed).
  • Ran :AnkiDroid:ktlintCheck (passed).

Checklist

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

- Store last customized timebox limit in Android preferences.
- Restore custom limit on toggle re-enable and screen reload.

Fixes ankidroid#22720

Assisted-by: Gemini Flash

@david-allison david-allison left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The domain logic feels a little too mixed up with the ViewModel, let's split it out

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Oct 27, 2026
david-allison

This comment was marked as outdated.

@Ratnesh5

Ratnesh5 commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @david-allison thanks for the review

  • Extracted TimeboxTimeLimit as an inline value class with validation and limits.
  • Defined extension properties and functions in TimeboxTimeLimitExtensions.kt mapping TimeboxTimeLimit to both PrefsRepository and CollectionPreferences.
  • Removed clamping and duration conversions from TimeboxSettingsViewModel.
  • Updated TimeboxSettingsScreen and the domain validation so desktop timebox limits greater than 999 minutes (such as 1440 minutes) are preserved without truncation.
  • Added TimeboxPersistenceReviewTest and verified that all tests and ktlint pass.

@david-allison

david-allison commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Could you have another round at the abstraction work, to start things off:

  • Only the minimum is validated
  • I would expect TimeboxTimeLimit.INPUT_RANGE to be available
  • I would expect a null result on validation, rather than clamping

Look to see what else you find

@Ratnesh5
Ratnesh5 force-pushed the fix-22720-persist-customized-timebox-limit branch from bd3d180 to ed66c5f Compare October 28, 2026 17:20
@Ratnesh5

Copy link
Copy Markdown
Contributor Author

Had another round at the abstraction work:

  • Validated both bounds, TimeboxTimeLimit.fromMinutes now returns null on invalid input rather than clamping
  • Exposed TimeboxTimeLimit.INPUT_RANGE (1..999)
  • TimeboxUiState now uses limit: TimeboxTimeLimit directly rather than raw Int minutes
  • Removed redundant timebox constants from TimeboxSettingsViewModel
  • Added Duration.toTimeboxTimeLimit() and TimeboxTimeLimit.toDuration() extensions
  • Preserved desktop values > 999 minutes without clamping

@david-allison david-allison left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much nicer!

@david-allison

Copy link
Copy Markdown
Member

Sorry, this is only a partial review

@Ratnesh5
Ratnesh5 force-pushed the fix-22720-persist-customized-timebox-limit branch from ed66c5f to e5da4a3 Compare October 28, 2026 22:28

@david-allison david-allison left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, optional thoughts on the domain. Cheers!

@david-allison david-allison added Needs Second Approval Has one approval, one more approval to merge and removed Needs Review Needs Author Reply Waiting for a reply from the original author labels Nov 2, 2026
… desktop limits

- Extract TimeboxTimeLimit domain type with INPUT_RANGE (1..9999) matching Anki Desktop
- Provide TimeboxTimeLimit.fromMinutes returning null on invalid input
- Provide canIncrement, canDecrement, and orElse helper methods on TimeboxTimeLimit
- Provide resolveDisplayLimit extension to sync custom limit
- Add Duration.toTimeboxTimeLimit() and TimeboxTimeLimit.toDuration() extensions
- Type ViewModel UI state with TimeboxTimeLimit
- Document Desktop source links alongside values
- Add TimeboxPersistenceReviewTest and domain unit tests

Fixes ankidroid#22720
@Ratnesh5
Ratnesh5 force-pushed the fix-22720-persist-customized-timebox-limit branch from e5da4a3 to 43a7b71 Compare November 2, 2026 19:06

@mikehardy mikehardy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assisted-by: Grok 4.7

Thank you — the TimeboxTimeLimit split and custom-prefs round-trip keep desktop limits intact without clamping surprises in the UI.

Locally I rebased onto main without force-pushing (prep stayed at the PR tip). I ran lint (lintAll, ktlintCheck, lint-rules:test), unit tests (jacocoUnitTestReport), and release emulator tests (TEST_RELEASE_BUILD=true via run_emulator_tests.py on emulator-5556 / API35_GAPI); all passed.

Reviewed TimeboxTimeLimit validation with null on bad input, extension mapping to prefs/collection, ViewModel load/save preserving values above 999 minutes, and Compose settings wired from the fragment.

some acceptable findings, no action required, just leaving for posterity: long refactor commit title; unused helpers; stepper can snap sub-9999 desktop values on first decrement.

@mikehardy mikehardy added Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) and removed Needs Second Approval Has one approval, one more approval to merge labels Nov 3, 2026
@mikehardy
mikehardy added this pull request to the merge queue Nov 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Has Conflicts Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persist customized timebox time limit when disabling the toggle

3 participants