Skip to content

Add volume presets feature#25

Open
Wanyal wants to merge 6 commits into
jonathanklee:mainfrom
Wanyal:main
Open

Add volume presets feature#25
Wanyal wants to merge 6 commits into
jonathanklee:mainfrom
Wanyal:main

Conversation

@Wanyal

@Wanyal Wanyal commented Jul 10, 2026

Copy link
Copy Markdown

Added a feature that allows the user to set pre-determined volumes for when they apply a lock. The user can choose if they want to apply the presets when they lock a single volume, lock all volumes, or both. This is my first contribution to an Android app, so feedback is welcome.

The new dialog in preferences to set the presets uses the existing VolumeFragment to lower potential burden of adding new sliders in the future.

Summary by CodeRabbit

  • New Features
    • Added configurable preset volume levels for music, calls, notifications, and alarms.
    • Added settings to apply presets to all locks or individual locks.
    • Added a preset editor with sliders and validation for permitted volume ranges.
    • Preset values are now applied when creating volume locks and retained for future use.
  • User Interface
    • Added preset-related settings, labels, and editing controls.
    • Lock controls are hidden while editing presets to prevent accidental locking.

Wanyal added 3 commits July 10, 2026 18:32
…efault to when locking volumes. Tries to reuse existing layouts/views where possible.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d6df098-b9f1-4b01-b665-089ad22bb4b7

📥 Commits

Reviewing files that changed from the base of the PR and between 480270a and df1beda.

📒 Files selected for processing (1)
  • app/src/main/java/com/klee/volumelockr/service/VolumeService.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/klee/volumelockr/service/VolumeService.kt

📝 Walkthrough

Walkthrough

Added configurable per-stream volume presets, preference-mode slider editing, preset-aware locking, settings UI, navigation arguments, and Safe Args Gradle configuration.

Changes

Preset volume locking

Layer / File(s) Summary
Volume preset contracts and service behavior
app/src/main/java/com/klee/volumelockr/service/VolumeProvider.kt, app/src/main/java/com/klee/volumelockr/service/VolumeService.kt
Minimum volume constants, in-memory preset values, persisted preset retrieval, preset updates, and preset-aware locking were added.
Preference-mode volume editing
app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt, app/src/main/java/com/klee/volumelockr/ui/VolumeSliderFragment.kt
Sliders edit presets without changing system volumes, while lock controls are hidden in preference mode.
Settings preset dialog and resource wiring
app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt, app/src/main/res/layout/dialog_presets.xml, app/src/main/res/xml/root_preferences.xml, app/src/main/res/values/strings.xml, app/src/main/res/values-ar/strings.xml, app/src/main/res/navigation/navigation_graph.xml
Settings preferences launch a preset dialog, return edited stream values, clamp them, and persist them through shared preferences.
Safe Args build wiring
build.gradle, app/build.gradle
The Safe Args Gradle classpath and application plugin configuration were added.2

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SettingsFragment
  participant ChangePresetDialog
  participant VolumeSliderFragment
  participant VolumeService
  SettingsFragment->>ChangePresetDialog: launch preset editor
  ChangePresetDialog->>VolumeSliderFragment: embed preference-mode slider
  VolumeSliderFragment->>VolumeService: read volume presets
  VolumeSliderFragment-->>ChangePresetDialog: return edited presets
  ChangePresetDialog-->>SettingsFragment: return fragment result
  SettingsFragment->>SettingsFragment: persist clamped presets
Loading

Possibly related PRs

Suggested reviewers: jonathanklee

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding volume presets support.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt (1)

119-145: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Clear slider touch listeners before re-registering callbacks registerSeekBarCallback() adds a new OnSliderTouchListener on every bind, so recycled holders can accumulate duplicate onStopTrackingTouch() calls. Add clearOnSliderTouchListeners() next to clearOnChangeListeners().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt` around lines 119
- 145, Clear existing slider touch listeners at the start of
registerSeekBarCallback, alongside clearOnChangeListeners(), before adding the
new OnSliderTouchListener to prevent duplicate callbacks on recycled holders.
🧹 Nitpick comments (3)
app/src/main/java/com/klee/volumelockr/service/VolumeService.kt (1)

180-219: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Duplicated preset-resolution logic.

getPresetVolumeForLockedStream mirrors VolumeAdapter.getVolumePresetLevel almost verbatim (same preference keys, same per-stream clamp), differing only in the min/max source. Consider extracting a single shared helper to keep the two paths from diverging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/klee/volumelockr/service/VolumeService.kt` around lines
180 - 219, Extract the duplicated per-stream preset lookup and clamping logic
from getPresetVolumeForLockedStream and VolumeAdapter.getVolumePresetLevel into
a shared helper. The helper should accept the stream and resolve the
corresponding preference key, minimum volume, and maximum-volume provider, while
preserving each method’s current behavior; update both callers to use it and
retain their distinct min/max sources where required.
build.gradle (1)

15-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Version-catalog consistency (optional).

The other buildscript classpaths use the libs.* version catalog while this one hardcodes 2.8.9. Consider moving navigation-safe-args-gradle-plugin into the catalog to keep the Navigation version aligned with the runtime androidx.navigation dependencies and avoid drift.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.gradle` at line 15, Move the hardcoded
navigation-safe-args-gradle-plugin dependency from the buildscript classpath
into the project’s version catalog, defining its version alongside the existing
AndroidX Navigation entries, then update the buildscript declaration to
reference the generated libs.* alias and keep it aligned with runtime Navigation
dependencies.
app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt (1)

173-204: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Combine the four edit {} blocks into a single commit.

Each stream branch opens a separate SharedPreferences.Editor via ?.edit { }, resulting in four independent async apply() calls. A single edit {} block wrapping the forEach would be atomic and more efficient.

♻️ Proposed refactor
             volumes.forEach {
                 when (it.stream) {
                     AudioManager.STREAM_MUSIC ->
-                        preferenceManager.sharedPreferences?.edit {
-                            putInt(
-                                MEDIA_VOLUME_PRESET_PREFERENCE,
-                                it.value.coerceIn(it.min, it.max)
-                            )
-                        }
+                        putInt(
+                            MEDIA_VOLUME_PRESET_PREFERENCE,
+                            it.value.coerceIn(it.min, it.max)
+                        )

                     AudioManager.STREAM_VOICE_CALL ->
-                        preferenceManager.sharedPreferences?.edit {
-                            putInt(CALL_VOLUME_PRESET_PREFERENCE, it.value.coerceIn(it.min, it.max))
-                        }
+                        putInt(CALL_VOLUME_PRESET_PREFERENCE, it.value.coerceIn(it.min, it.max))

                     AudioManager.STREAM_NOTIFICATION ->
-                        preferenceManager.sharedPreferences?.edit {
-                            putInt(
-                                NOTIFICATION_VOLUME_PRESET_PREFERENCE,
-                                it.value.coerceIn(it.min, it.max)
-                            )
-                        }
+                        putInt(
+                            NOTIFICATION_VOLUME_PRESET_PREFERENCE,
+                            it.value.coerceIn(it.min, it.max)
+                        )

                     AudioManager.STREAM_ALARM ->
-                        preferenceManager.sharedPreferences?.edit {
-                            putInt(
-                                ALARM_VOLUME_PRESET_PREFERENCE,
-                                it.value.coerceIn(it.min, it.max)
-                            )
-                        }
+                        putInt(
+                            ALARM_VOLUME_PRESET_PREFERENCE,
+                            it.value.coerceIn(it.min, it.max)
+                        )
                 }
             }
+        }

Full replacement for clarity:

preferenceManager.sharedPreferences?.edit {
    volumes.forEach {
        when (it.stream) {
            AudioManager.STREAM_MUSIC ->
                putInt(MEDIA_VOLUME_PRESET_PREFERENCE, it.value.coerceIn(it.min, it.max))
            AudioManager.STREAM_VOICE_CALL ->
                putInt(CALL_VOLUME_PRESET_PREFERENCE, it.value.coerceIn(it.min, it.max))
            AudioManager.STREAM_NOTIFICATION ->
                putInt(NOTIFICATION_VOLUME_PRESET_PREFERENCE, it.value.coerceIn(it.min, it.max))
            AudioManager.STREAM_ALARM ->
                putInt(ALARM_VOLUME_PRESET_PREFERENCE, it.value.coerceIn(it.min, it.max))
        }
    }
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt` around lines
173 - 204, Refactor the volume persistence logic in the volumes.forEach block to
open one sharedPreferences?.edit { } transaction around the entire iteration.
Keep the existing stream-to-preference mappings and value coercion, but call
putInt directly within each when branch so all updates use a single atomic
commit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/com/klee/volumelockr/service/VolumeService.kt`:
- Around line 113-119: Update getVolumesPresets() to initialize missing
mVolumePreset entries from persisted preferences, using
getPresetVolumeForLockedStream(volume.stream) as the fallback instead of 0,
while preserving any values already present in mVolumePreset.

In `@app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt`:
- Around line 310-315: Make the Volume model implement Parcelable (for example,
via `@Parcelize` and the required plugin/dependency), then keep the "volumes"
fragment-result payload in SettingsFragment’s positive-button listener as an
ArrayList<Volume> so BundleCompat.getParcelableArrayList can round-trip it
correctly.

In `@app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt`:
- Line 96: Update the call to handleRingerMode in VolumeAdapter so it only runs
when !mInPreferencesMode, preventing the notification slider from being disabled
while editing preferences.

---

Outside diff comments:
In `@app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt`:
- Around line 119-145: Clear existing slider touch listeners at the start of
registerSeekBarCallback, alongside clearOnChangeListeners(), before adding the
new OnSliderTouchListener to prevent duplicate callbacks on recycled holders.

---

Nitpick comments:
In `@app/src/main/java/com/klee/volumelockr/service/VolumeService.kt`:
- Around line 180-219: Extract the duplicated per-stream preset lookup and
clamping logic from getPresetVolumeForLockedStream and
VolumeAdapter.getVolumePresetLevel into a shared helper. The helper should
accept the stream and resolve the corresponding preference key, minimum volume,
and maximum-volume provider, while preserving each method’s current behavior;
update both callers to use it and retain their distinct min/max sources where
required.

In `@app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt`:
- Around line 173-204: Refactor the volume persistence logic in the
volumes.forEach block to open one sharedPreferences?.edit { } transaction around
the entire iteration. Keep the existing stream-to-preference mappings and value
coercion, but call putInt directly within each when branch so all updates use a
single atomic commit.

In `@build.gradle`:
- Line 15: Move the hardcoded navigation-safe-args-gradle-plugin dependency from
the buildscript classpath into the project’s version catalog, defining its
version alongside the existing AndroidX Navigation entries, then update the
buildscript declaration to reference the generated libs.* alias and keep it
aligned with runtime Navigation dependencies.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 72258480-eb47-4bb7-a1f9-39be252b24c2

📥 Commits

Reviewing files that changed from the base of the PR and between b965029 and 480270a.

📒 Files selected for processing (12)
  • app/build.gradle
  • app/src/main/java/com/klee/volumelockr/service/VolumeProvider.kt
  • app/src/main/java/com/klee/volumelockr/service/VolumeService.kt
  • app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt
  • app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt
  • app/src/main/java/com/klee/volumelockr/ui/VolumeSliderFragment.kt
  • app/src/main/res/layout/dialog_presets.xml
  • app/src/main/res/navigation/navigation_graph.xml
  • app/src/main/res/values-ar/strings.xml
  • app/src/main/res/values/strings.xml
  • app/src/main/res/xml/root_preferences.xml
  • build.gradle
💤 Files with no reviewable changes (1)
  • app/src/main/res/values-ar/strings.xml

Comment thread app/src/main/java/com/klee/volumelockr/service/VolumeService.kt
Comment thread app/src/main/java/com/klee/volumelockr/ui/SettingsFragment.kt
Comment thread app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt Outdated
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