Skip to content

Dice Lock - #81

Merged
ndleyton merged 4 commits into
ndleyton:masterfrom
lnevado:feat/dice-lock
Sep 11, 2026
Merged

ndleyton merged 4 commits into
ndleyton:masterfrom
lnevado:feat/dice-lock

Conversation

@lnevado

@lnevado lnevado commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

This pull request introduces the ability to lock and unlock dice in the dice-rolling UI, enhancing user interaction and control. The changes span UI updates, state management, and persistence to support the new locking feature. Additionally, debug build configuration improvements were made to facilitate parallel installation and clearer identification.

Dice Locking Feature

  • Added a lock/unlock button to each die in the UI, allowing users to toggle the locked state. Locked dice cannot be rolled, and attempting to roll them provides visual feedback via a nudge animation. The lock button also supports long-press to remove the die. (DiceAdapter.java, DiceFragment.java) [1] [2] [3] [4]
  • Updated the die UI to visually indicate locked state, including icon, color, and stroke width changes. (DiceAdapter.java)
  • Only roll dice that are not locked when triggering "roll all" or individual roll actions. (DiceAdapter.java, DiceFragment.java) [1] [2] [3] [4]

State and Persistence Enhancements

  • Extended DiceUiState and DiceViewModel to track and expose which dice are locked and which are rollable, enabling UI and menu updates based on current state. (DiceUiState.java, DiceViewModel.java) [1] [2] [3] [4]
  • Updated equality checks and adapter diff logic to account for the locked state, ensuring UI updates reflect lock changes. (DiceAdapter.java)

Menu and Action Improvements

  • Added "Unlock All" menu action, visible only when locked dice are present, and disabled "Roll All" when no rollable dice are available. (DiceFragment.java)
  • Menu state dynamically updates in response to dice state changes. (DiceFragment.java) [1] [2]

Debug Build Improvements

  • Added a distinct debug build type with unique application ID and version suffix, and a separate app name for debug builds to allow parallel installation and easier identification. (app/build.gradle, strings.xml) [1] [2]

User Feedback

  • Added vibration feedback for lock/unlock actions and improved vibration utility methods for user interactions. (DiceFragment.java)

These changes together provide a more interactive and user-friendly dice-rolling experience, with robust state management and improved development workflow.

lnevado and others added 4 commits September 3, 2026 16:54
Each die tile gains a small lock button in its top-end corner. A locked
die keeps its value and is skipped by both Roll All and the tap-to-roll
gesture on its own tile, so "hold some, reroll the rest" no longer means
rerolling each unwanted die by hand.

Lock state lives in SavedStateHandle for the session only. Persisting it
would be incoherent today, because DicePrefsDataSource stores faces but
not values, so a restored "locked" die would show a face-count
placeholder rather than the value that was locked.

Behaviour details:

- Tapping a locked tile shakes it instead of rolling. The card keeps a
  selectableItemBackground foreground and ripples on touch regardless, so
  a silent no-op would read as a bug.
- Locked tiles do not play the roll animation during Roll All.
- Roll All suppresses its haptic and summary bounce when nothing is
  rollable. This also covers an empty board, which previously buzzed and
  bounced a total that could not change.
- Locked tiles take a 2dp stroke in the luminance-derived contrast colour
  the adapter already computes, not colorPrimary, which would disappear
  against neighbouring diceColors entries.
- An Unlock All app-bar item appears only while at least one die is
  locked. There is no Lock All: its only outcome is a dead Roll All.
- Lock does not block delete, and the summary chips and total are
  unchanged.

Adds isLocked to the DiffUtil contents check, or lock icons would not
refresh when nothing else about a die changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvVWNNqvJ3zwwWbA18Uvvq
Three defects in the lock toggle, all cases where a control did something
invisible or nothing at all.

The locked-tile shake used raw pixels. setTranslationX takes pixels, not
dp, so the 6f nudge was about 2dp on a 3x-density screen. Since the
locked path also returns before any haptic fires, tapping a locked tile
produced a ripple and no other feedback, which is exactly the "reads as a
bug" outcome the shake existed to prevent. Now scaled by display density,
matching how the same class already computes the locked stroke width.

The lock button swallowed long presses. A clickable child consumes the
touch stream, and the button is not long-clickable, so a long press in
the top-end corner never reached the card's delete handler: the gesture
deleted the die everywhere on the tile except a 44dp square. The button
now forwards long presses to the same handler.

Roll All stayed enabled while inert. When nothing is rollable the action
suppressed its haptic, animation and roll, but still looked available.
onPrepareMenu now disables it, so the dead state is visible rather than
silent. This also required invalidating the menu when the rollable flag
changes on its own, not just the locked flag; otherwise Roll All stayed
disabled after adding the first die to an empty board.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvVWNNqvJ3zwwWbA18Uvvq
@lnevado lnevado changed the title Dice lock Dice Lock Sep 4, 2026
@ndleyton

Copy link
Copy Markdown
Owner

Sorry for the delay, checking the UI

@ndleyton

Copy link
Copy Markdown
Owner

Thanks! this looks great

@ndleyton
ndleyton merged commit c743ed3 into ndleyton:master Sep 11, 2026
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.

2 participants