Conversation
📝 WalkthroughWalkthroughAdds user-default note color support: new preference to store default color, UI updates to mark/manage default (star icon, long-press to set/revert), color dialogs/adapters converted to ColorString with default handling, persistence/viewmodel updates to sync defaults, plus translation and resource changes. Changes
Sequence DiagramsequenceDiagram
actor User
participant UI as Color UI (Adapter / ColorVH)
participant Dialog as Color Dialog (ColorActivityExtensions)
participant Prefs as NotallyXPreferences
participant VM as ViewModel (BaseNoteModel / NotallyModel)
participant DB as Database (BaseNoteDao)
User->>UI: Long-press color item
UI->>Dialog: Open confirm/set-default dialog
User->>Dialog: Confirm set as default
Dialog->>Prefs: set defaultNoteColor.value(newColor)
Prefs-->>VM: notify observers (default changed)
VM->>DB: persist color/default updates (if required)
DB-->>VM: ack
VM-->>UI: refresh displayed default state (star icon)
Dialog-->>UI: update dialog (neutral text/icon)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~28 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
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/philkes/notallyx/presentation/view/main/ColorVH.kt (1)
35-58:⚠️ Potential issue | 🟠 MajorExpose the default-state on the swatch, not only via the star icon.
CardViewis the accessible click target here, but itscontentDescriptionis still justcolor. That means the new default marker is visual-only for TalkBack users. Please include the default state in the swatch announcement/state description and treat the icon itself as decorative.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/presentation/view/main/ColorVH.kt` around lines 35 - 58, CardView's contentDescription currently only contains the color and doesn't announce the default state, leaving TalkBack users unaware; update the code that sets CardView.contentDescription to include the default marker when isDefault is true (e.g., append or build a localized string like "ColorName, default" using the same logic that reads isDefault), and make the DefaultColorIcon decorative for accessibility by clearing its contentDescription (or setting it as not important for accessibility) while keeping CardIcon behavior unchanged; reference CardView, DefaultColorIcon, CardIcon, contentDescription, isDefault and showAddIcon when making these changes.
🧹 Nitpick comments (3)
app/src/main/java/com/philkes/notallyx/presentation/activity/note/NoteActionHandler.kt (1)
273-281: Consider simplifying the intermediate set conversion.The inner
.toMutableSet()at line 279 is redundant since the+operator returns an immutableSetregardless of the input type, and the outer.toMutableSet()at line 281 handles the final conversion.♻️ Simplified version
val colors: MutableSet<ColorString> = (withContext(Dispatchers.IO) { NotallyDatabase.getDatabase(activity, observePreferences = false) .value .getBaseNoteDao() .getAllColors() - .toMutableSet() - } + activity.preferences.defaultNoteColor.value) - .toMutableSet() + }.toSet() + activity.preferences.defaultNoteColor.value) + .toMutableSet()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/presentation/activity/note/NoteActionHandler.kt` around lines 273 - 281, The temporary call to .toMutableSet() inside the withContext block is redundant because the set concatenation using + returns an immutable Set which you then convert to mutable with the outer .toMutableSet(); update the code in NoteActionHandler (where the local val colors is built inside the withContext(Dispatchers.IO) block calling NotallyDatabase.getDatabase(...).getBaseNoteDao().getAllColors()) by removing the inner .toMutableSet() so only the final .toMutableSet() is used to produce the MutableSet<ColorString>.app/src/main/java/com/philkes/notallyx/presentation/viewmodel/BaseNoteModel.kt (1)
631-637: Good synchronization of default color when a color is deleted/changed.The logic correctly updates the
defaultNoteColorpreference when the deleted color matches the current default. This prevents orphaned default color references.Minor consistency note: The direct
preferences.defaultNoteColor.save(newColor)call differs from thesavePreference()pattern used elsewhere (line 392-394) that wraps inDispatchers.IO. While SharedPreferences commits are typically fast, consider using the existing pattern for consistency:♻️ Optional refactor for consistency
fun changeColor(oldColor: String, newColor: String) { val defaultColor = preferences.defaultNoteColor.value if (oldColor == defaultColor) { - preferences.defaultNoteColor.save(newColor) + savePreference(preferences.defaultNoteColor, newColor) } viewModelScope.launch(Dispatchers.IO) { baseNoteDao.updateColor(oldColor, newColor) } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/presentation/viewmodel/BaseNoteModel.kt` around lines 631 - 637, changeColor in BaseNoteModel directly calls preferences.defaultNoteColor.save(newColor) on the calling thread; for consistency with other code (e.g., the savePreference(...) pattern used elsewhere) move this preference write onto the IO dispatcher — either call the existing savePreference(preferences.defaultNoteColor, newColor) helper or wrap the save(...) call in viewModelScope.launch(Dispatchers.IO) { preferences.defaultNoteColor.save(newColor) } so the default preference update matches the IO-dispatched pattern used in this class.app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt (1)
71-86: Consider whether long-pressing onCOLOR_DEFAULTshould behave differently.Currently, long-pressing the transparent/no-color option (
COLOR_DEFAULT) prompts to set it as the default color for new notes. While functionally correct, users might find it confusing that "no color" can be the "default color."If this is intentional (allowing users to reset default to "no color"), the UX is acceptable. Otherwise, consider showing a different message or skipping this dialog entirely for
COLOR_DEFAULT.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt` around lines 71 - 86, Long-pressing the transparent option (BaseNote.COLOR_DEFAULT) currently shows the same "set as default color" dialog which can be confusing; update the long-press branch inside showColorSelectDialog to either skip showing a dialog for BaseNote.COLOR_DEFAULT or present a clearer confirmation that the default will be set to "no color" (use new string resources like R.string.clear_default_color_title and R.string.clear_default_color_message if needed). If you keep a dialog, call preferences.defaultNoteColor.save(BaseNote.COLOR_DEFAULT) and set colorAdapter.defaultColor = BaseNote.COLOR_DEFAULT then notify via colorAdapter.notifyDataSetChanged(); if you prefer skipping, simply return without showing MaterialAlertDialogBuilder when oldColor == BaseNote.COLOR_DEFAULT. Ensure you reference BaseNote.COLOR_DEFAULT, showColorSelectDialog, preferences.defaultNoteColor.save, and colorAdapter.defaultColor in the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/src/main/res/layout/dialog_color_picker.xml`:
- Around line 24-31: The DeleteColor ImageButton is visible by default but only
enabled in the old-color flow; change its default visibility to hidden so it
doesn't appear as a dead action in new-color flow: update the DeleteColor view
(android:id="@+id/DeleteColor") in the layout to use a non-visible default
(e.g., GONE or INVISIBLE) and let showEditColorDialog() continue to set it
visible inside the oldColor?.let { ... } block when appropriate.
In `@app/src/main/res/layout/recycler_color.xml`:
- Around line 29-37: The ImageView with id DefaultColorIcon in
recycler_color.xml uses a hardcoded contentDescription "DefaultNoteColor" which
prevents localization; replace the inline string by pointing contentDescription
to a string resource (e.g., `@string/default_note_color`) defined in strings.xml,
or if the parent swatch already exposes the default state to accessibility, make
the icon decorative by setting android:contentDescription="@null" and
android:importantForAccessibility="no" on DefaultColorIcon so it doesn't
duplicate the announcement.
---
Outside diff comments:
In `@app/src/main/java/com/philkes/notallyx/presentation/view/main/ColorVH.kt`:
- Around line 35-58: CardView's contentDescription currently only contains the
color and doesn't announce the default state, leaving TalkBack users unaware;
update the code that sets CardView.contentDescription to include the default
marker when isDefault is true (e.g., append or build a localized string like
"ColorName, default" using the same logic that reads isDefault), and make the
DefaultColorIcon decorative for accessibility by clearing its contentDescription
(or setting it as not important for accessibility) while keeping CardIcon
behavior unchanged; reference CardView, DefaultColorIcon, CardIcon,
contentDescription, isDefault and showAddIcon when making these changes.
---
Nitpick comments:
In
`@app/src/main/java/com/philkes/notallyx/presentation/activity/note/NoteActionHandler.kt`:
- Around line 273-281: The temporary call to .toMutableSet() inside the
withContext block is redundant because the set concatenation using + returns an
immutable Set which you then convert to mutable with the outer .toMutableSet();
update the code in NoteActionHandler (where the local val colors is built inside
the withContext(Dispatchers.IO) block calling
NotallyDatabase.getDatabase(...).getBaseNoteDao().getAllColors()) by removing
the inner .toMutableSet() so only the final .toMutableSet() is used to produce
the MutableSet<ColorString>.
In
`@app/src/main/java/com/philkes/notallyx/presentation/viewmodel/BaseNoteModel.kt`:
- Around line 631-637: changeColor in BaseNoteModel directly calls
preferences.defaultNoteColor.save(newColor) on the calling thread; for
consistency with other code (e.g., the savePreference(...) pattern used
elsewhere) move this preference write onto the IO dispatcher — either call the
existing savePreference(preferences.defaultNoteColor, newColor) helper or wrap
the save(...) call in viewModelScope.launch(Dispatchers.IO) {
preferences.defaultNoteColor.save(newColor) } so the default preference update
matches the IO-dispatched pattern used in this class.
In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt`:
- Around line 71-86: Long-pressing the transparent option
(BaseNote.COLOR_DEFAULT) currently shows the same "set as default color" dialog
which can be confusing; update the long-press branch inside
showColorSelectDialog to either skip showing a dialog for BaseNote.COLOR_DEFAULT
or present a clearer confirmation that the default will be set to "no color"
(use new string resources like R.string.clear_default_color_title and
R.string.clear_default_color_message if needed). If you keep a dialog, call
preferences.defaultNoteColor.save(BaseNote.COLOR_DEFAULT) and set
colorAdapter.defaultColor = BaseNote.COLOR_DEFAULT then notify via
colorAdapter.notifyDataSetChanged(); if you prefer skipping, simply return
without showing MaterialAlertDialogBuilder when oldColor ==
BaseNote.COLOR_DEFAULT. Ensure you reference BaseNote.COLOR_DEFAULT,
showColorSelectDialog, preferences.defaultNoteColor.save, and
colorAdapter.defaultColor in the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9ca35dba-448d-41ca-ab83-f2de10482293
⛔ Files ignored due to path filters (1)
app/translations.xlsxis excluded by!**/*.xlsx
📒 Files selected for processing (16)
TRANSLATIONS.mdapp/src/main/java/com/philkes/notallyx/data/dao/BaseNoteDao.ktapp/src/main/java/com/philkes/notallyx/presentation/activity/LockedActivity.ktapp/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.ktapp/src/main/java/com/philkes/notallyx/presentation/activity/note/NoteActionHandler.ktapp/src/main/java/com/philkes/notallyx/presentation/view/main/ColorAdapter.ktapp/src/main/java/com/philkes/notallyx/presentation/view/main/ColorVH.ktapp/src/main/java/com/philkes/notallyx/presentation/viewmodel/BaseNoteModel.ktapp/src/main/java/com/philkes/notallyx/presentation/viewmodel/NotallyModel.ktapp/src/main/java/com/philkes/notallyx/presentation/viewmodel/preference/NotallyXPreferences.ktapp/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.ktapp/src/main/res/drawable/star.xmlapp/src/main/res/drawable/star_rate_filled.xmlapp/src/main/res/layout/dialog_color_picker.xmlapp/src/main/res/layout/recycler_color.xmlapp/src/main/res/values/strings.xml
💤 Files with no reviewable changes (1)
- app/src/main/java/com/philkes/notallyx/data/dao/BaseNoteDao.kt
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt`:
- Around line 74-83: The code is persisting the sentinel BaseNote.COLOR_DEFAULT
into preferences via preferences.defaultNoteColor.save(oldColor), which stores a
placeholder instead of a concrete swatch and can break consumers that expect an
actual color string; change the branch so it does not save the sentinel value —
either resolve the real swatch before saving (e.g. determine the concrete color
from the adapter/item list and call
preferences.defaultNoteColor.save(resolvedColor) and set
colorAdapter.defaultColor = resolvedColor) or simply skip
preferences.defaultNoteColor.save when oldColor == BaseNote.COLOR_DEFAULT and
only update the UI state (colorAdapter.defaultColor and notifyDataSetChanged).
- Around line 215-259: The neutral button is only updated when
preferences.defaultNoteColor changes and its "revert" path calls
performLongClick() with no long-click listener, making it stale and a no-op
after picker moves; fix by wiring the neutral Button (found via
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)) to be updated whenever
binding.ColorPicker.colorEnvelope changes (reuse the existing
ColorPicker.setColorListener or the observer callback to recompute
isDefaultColor, set text/icon/tooltips and onClick), and implement a real revert
action: store the dialog's initial color (e.g., oldColor/initialColor) and have
the neutral button's onClick restore that color into
binding.ColorPicker.setColor / setPaintColor and update ColorCode and
preferences.defaultNoteColor.save as appropriate so the button stays in sync and
actually reverts.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1223abb2-3241-46eb-b1b4-20c4e3b39a44
📒 Files selected for processing (5)
app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.ktapp/src/main/java/com/philkes/notallyx/presentation/activity/note/NoteActionHandler.ktapp/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.ktapp/src/main/res/layout/dialog_color_picker.xmlapp/src/main/res/layout/recycler_color.xml
🚧 Files skipped from review as they are similar to previous changes (3)
- app/src/main/java/com/philkes/notallyx/presentation/activity/main/MainActivity.kt
- app/src/main/res/layout/recycler_color.xml
- app/src/main/java/com/philkes/notallyx/presentation/activity/note/NoteActionHandler.kt
| if (oldColor == BaseNote.COLOR_DEFAULT) { | ||
| MaterialAlertDialogBuilder(this@showColorSelectDialog) | ||
| .setTitle(R.string.set_as_default_color) | ||
| .setMessage(R.string.set_as_default_color_message) | ||
| .setPositiveButton(R.string.make_default) { _, _ -> | ||
| preferences.defaultNoteColor.save(oldColor) | ||
| colorAdapter.defaultColor = oldColor | ||
| colorAdapter.notifyDataSetChanged() | ||
| } | ||
| .setNegativeButton(android.R.string.cancel, null) |
There was a problem hiding this comment.
Don't persist BaseNote.COLOR_DEFAULT as the preference value.
Line 79 saves the placeholder entry, not a concrete swatch. That can overwrite defaultNoteColor with the sentinel token and break later code paths that expect an actual color string. This branch should resolve the real default color value before saving, or avoid writing the preference here altogether.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt`
around lines 74 - 83, The code is persisting the sentinel BaseNote.COLOR_DEFAULT
into preferences via preferences.defaultNoteColor.save(oldColor), which stores a
placeholder instead of a concrete swatch and can break consumers that expect an
actual color string; change the branch so it does not save the sentinel value —
either resolve the real swatch before saving (e.g. determine the concrete color
from the adapter/item list and call
preferences.defaultNoteColor.save(resolvedColor) and set
colorAdapter.defaultColor = resolvedColor) or simply skip
preferences.defaultNoteColor.save when oldColor == BaseNote.COLOR_DEFAULT and
only update the UI state (colorAdapter.defaultColor and notifyDataSetChanged).
| ColorPicker.setColorListener( | ||
| ColorEnvelopeListener { color, _ -> | ||
| TileView.setPaintColor(color.color) | ||
| val colorString = color.toColorString() | ||
| val isSaveEnabled = | ||
| colorString == oldColor || colorString !in colors | ||
| positiveButton.isEnabled = isSaveEnabled | ||
| ColorExistsText.visibility = | ||
| if (isSaveEnabled) View.GONE else View.VISIBLE | ||
| if (!editTextChangedByUser) { | ||
| ColorCode.setText(color.hexCode.argbToRgbString()) | ||
| } else editTextChangedByUser = false | ||
| } | ||
| ) | ||
| } | ||
| }, | ||
| ) | ||
| } | ||
| showAndFocus( | ||
| allowFullSize = true, | ||
| onShowListener = { | ||
| setNavigationbarLight?.let { | ||
| window?.apply { setLightStatusAndNavBar(it, binding.root) } | ||
| } | ||
| }, | ||
| applyToPositiveButton = { positiveButton -> | ||
| binding.apply { | ||
| BrightnessSlideBar.setSelectorDrawableRes( | ||
| com.skydoves.colorpickerview.R.drawable.colorpickerview_wheel | ||
| ) | ||
| ColorPicker.setColorListener( | ||
| ColorEnvelopeListener { color, _ -> | ||
| TileView.setPaintColor(color.color) | ||
| val colorString = color.toColorString() | ||
| val isSaveEnabled = colorString == oldColor || colorString !in colors | ||
| positiveButton.isEnabled = isSaveEnabled | ||
| ColorExistsText.visibility = | ||
| if (isSaveEnabled) View.INVISIBLE else View.VISIBLE | ||
| if (!editTextChangedByUser) { | ||
| ColorCode.setText(color.hexCode.argbToRgbString()) | ||
| } else editTextChangedByUser = false | ||
| } | ||
| ) | ||
| val observer: Observer<ColorString> = Observer { defaultColor -> | ||
| dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.apply { | ||
| val currentColor = binding.ColorPicker.colorEnvelope.toColorString() | ||
| val isDefaultColor = currentColor == defaultColor | ||
| setText(if (isDefaultColor) R.string.text_default else R.string.make_default) | ||
| if (!isDefaultColor) { | ||
| TooltipCompat.setTooltipText(this, getString(R.string.set_as_default_color_message)) | ||
| setOnClickListener { | ||
| val newColor = binding.ColorPicker.colorEnvelope.toColorString() | ||
| preferences.defaultNoteColor.save(newColor) | ||
| } | ||
| }, | ||
| ) | ||
| } else { | ||
| TooltipCompat.setTooltipText(this, getString(R.string.default_color_hint)) | ||
| setOnClickListener { performLongClick() } | ||
| } | ||
| (this as? MaterialButton)?.apply { | ||
| icon = | ||
| if (isDefaultColor) | ||
| ContextCompat.getDrawable( | ||
| this@showEditColorDialog, | ||
| R.drawable.star_rate_filled, | ||
| ) | ||
| else ContextCompat.getDrawable(this@showEditColorDialog, R.drawable.star) | ||
| iconGravity = MaterialButton.ICON_GRAVITY_TEXT_START | ||
| iconPadding = 0 | ||
| } | ||
| } |
There was a problem hiding this comment.
Keep the neutral button in sync with the picker, and wire a real revert action.
This button is only refreshed when defaultNoteColor changes, so after the user moves the picker it can keep stale text/icon/click behavior. In the isDefaultColor branch, Line 246 routes clicks to performLongClick(), but no long-click listener is attached here, so the control becomes a no-op.
Suggested direction
+ fun updateDefaultButton(defaultColor: ColorString = preferences.defaultNoteColor.value) {
+ dialog?.getButton(AlertDialog.BUTTON_NEUTRAL)?.apply {
+ val currentColor = binding.ColorPicker.colorEnvelope.toColorString()
+ val isDefaultColor = currentColor == defaultColor
+ setText(if (isDefaultColor) R.string.text_default else R.string.make_default)
+ TooltipCompat.setTooltipText(
+ this,
+ getString(
+ if (isDefaultColor) R.string.default_color_hint
+ else R.string.set_as_default_color_message
+ )
+ )
+ setOnClickListener {
+ if (!isDefaultColor) {
+ preferences.defaultNoteColor.save(currentColor)
+ }
+ }
+ setOnLongClickListener {
+ if (isDefaultColor) {
+ // show revert/reset-default dialog here
+ true
+ } else {
+ false
+ }
+ }
+ }
+ }
...
ColorEnvelopeListener { color, _ ->
TileView.setPaintColor(color.color)
val colorString = color.toColorString()
val isSaveEnabled =
colorString == oldColor || colorString !in colors
positiveButton.isEnabled = isSaveEnabled
ColorExistsText.visibility =
if (isSaveEnabled) View.GONE else View.VISIBLE
+ updateDefaultButton()
if (!editTextChangedByUser) {
ColorCode.setText(color.hexCode.argbToRgbString())
} else editTextChangedByUser = false
}
...
- val observer: Observer<ColorString> = Observer { defaultColor ->
- dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.apply {
- ...
- }
- }
+ val observer: Observer<ColorString> = Observer { defaultColor ->
+ updateDefaultButton(defaultColor)
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt`
around lines 215 - 259, The neutral button is only updated when
preferences.defaultNoteColor changes and its "revert" path calls
performLongClick() with no long-click listener, making it stale and a no-op
after picker moves; fix by wiring the neutral Button (found via
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)) to be updated whenever
binding.ColorPicker.colorEnvelope changes (reuse the existing
ColorPicker.setColorListener or the observer callback to recompute
isDefaultColor, set text/icon/tooltips and onClick), and implement a real revert
action: store the dialog's initial color (e.g., oldColor/initialColor) and have
the neutral button's onClick restore that color into
binding.ColorPicker.setColor / setPaintColor and update ColorCode and
preferences.defaultNoteColor.save as appropriate so the button stays in sync and
actually reverts.
There was a problem hiding this comment.
♻️ Duplicate comments (2)
app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt (2)
75-92:⚠️ Potential issue | 🔴 CriticalPersisting sentinel
COLOR_DEFAULTas the preference value corrupts default color state.When
oldColor == BaseNote.COLOR_DEFAULT(the sentinel tile), this branch can save the sentinel itself intopreferences.defaultNoteColor(line 84). Downstream code expecting an actual hex color string will break.The logic here appears inverted—the
COLOR_DEFAULTtile represents "use the preference," not a color that can become the new default. Consider removing this branch entirely or re-evaluating the UX intent: long-pressing the default placeholder tile shouldn't prompt to "set as default.",
Suggested fix: remove sentinel-saving path
if (oldColor == BaseNote.COLOR_DEFAULT) { - if (oldColor == preferences.defaultNoteColor.value) { - showToast(R.string.default_color_hint) - return - } else { - MaterialAlertDialogBuilder(this@showColorSelectDialog) - .setTitle(R.string.set_as_default_color) - .setMessage(R.string.set_as_default_color_message) - .setPositiveButton(R.string.make_default) { _, _ -> - preferences.defaultNoteColor.save(oldColor) - colorAdapter.defaultColor = oldColor - colorAdapter.notifyItemRangeChanged(1, actualColors.size - 1) - } - .setNegativeButton(android.R.string.cancel, null) - .show() - return - } + // The default placeholder tile cannot be set as default itself + showToast(R.string.default_color_hint) + return }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt` around lines 75 - 92, The branch inside showColorSelectDialog that handles oldColor == BaseNote.COLOR_DEFAULT is saving the sentinel value into preferences (via preferences.defaultNoteColor.save(oldColor)) which corrupts default color state; remove or change this branch so long-pressing the sentinel tile does not prompt to "set as default" or save BaseNote.COLOR_DEFAULT—either delete the entire if (oldColor == BaseNote.COLOR_DEFAULT) block or short-circuit it to just return/ignore, and ensure you do not call preferences.defaultNoteColor.save(...) or update colorAdapter.defaultColor/notifyItemRangeChanged with the sentinel value.
239-265:⚠️ Potential issue | 🟠 MajorNeutral button becomes stale after picker moves;
performLongClick()is a no-op.Two issues remain from prior review:
Stale state: The observer (line 239) only fires when
defaultNoteColorLiveData changes. After the user drags the color picker,currentColorchanges but the button text/icon/click-handler stay frozen until the next preference emission.No-op click: Line 252 calls
performLongClick(), but nosetOnLongClickListeneris registered on this button, so the click does nothing.,
Suggested direction
Extract the button-update logic into a local function and call it both from the observer and from the
ColorEnvelopeListenercallback (lines 221-234):fun updateNeutralButton(defaultColor: ColorString) { dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.apply { val currentColor = binding.ColorPicker.colorEnvelope.toColorString() val isDefaultColor = currentColor == defaultColor setText(if (isDefaultColor) R.string.text_default else R.string.make_default) // ... icon, tooltip ... setOnClickListener { if (!isDefaultColor) { preferences.defaultNoteColor.save(currentColor) } } // Either implement a real long-click action or remove the branch } }Then invoke
updateNeutralButton(preferences.defaultNoteColor.value)insideColorEnvelopeListenerafter updatingpositiveButton.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt` around lines 239 - 265, The neutral button UI/code is stale because the Observer on preferences.defaultNoteColor only updates when the LiveData emits and performLongClick() is a no-op; extract the button update logic into a helper like updateNeutralButton(defaultColor: ColorString) that reads binding.ColorPicker.colorEnvelope.toColorString(), sets text/icon/tooltip, and installs a real setOnClickListener that calls preferences.defaultNoteColor.save(currentColor) when not default (and either remove the performLongClick branch or implement setOnLongClickListener for the intended behavior); call updateNeutralButton(preferences.defaultNoteColor.value) from both the Observer (observer: Observer<ColorString>) and from the ColorEnvelopeListener callback (after you update the positive button) so the neutral button reflects picker moves immediately.
🧹 Nitpick comments (1)
app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt (1)
271-276: UseColorStringtype consistently across function signatures.
showDeleteColorDialogusesList<String>andStringparameters whileshowColorSelectDialogandshowEditColorDialoguseColorString. SinceColorStringis a typealias forString, this compiles but weakens type semantics and makes the API inconsistent.Suggested alignment
-private fun AppCompatActivity.showDeleteColorDialog( - colors: List<String>, - oldColor: String, - setNavigationbarLight: Boolean?, - callback: (selectedColor: String, oldColor: String?) -> Unit, - deleteCallback: (colorToDelete: String, newColor: String) -> Unit, +private fun AppCompatActivity.showDeleteColorDialog( + colors: List<ColorString>, + oldColor: ColorString, + setNavigationbarLight: Boolean?, + callback: (selectedColor: ColorString, oldColor: ColorString?) -> Unit, + deleteCallback: (colorToDelete: ColorString, newColor: ColorString) -> Unit, ) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt` around lines 271 - 276, The function showDeleteColorDialog should use the ColorString typealias instead of raw String to match other APIs; update its signature to accept colors: List<ColorString>, oldColor: ColorString (nullable if previously nullable), and change the callback and deleteCallback parameter types to use ColorString/ColorString? (i.e., callback: (selectedColor: ColorString, oldColor: ColorString?) -> Unit and deleteCallback: (colorToDelete: ColorString, newColor: ColorString) -> Unit). After changing the signature in showDeleteColorDialog, update any call sites to pass/expect ColorString types accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt`:
- Around line 75-92: The branch inside showColorSelectDialog that handles
oldColor == BaseNote.COLOR_DEFAULT is saving the sentinel value into preferences
(via preferences.defaultNoteColor.save(oldColor)) which corrupts default color
state; remove or change this branch so long-pressing the sentinel tile does not
prompt to "set as default" or save BaseNote.COLOR_DEFAULT—either delete the
entire if (oldColor == BaseNote.COLOR_DEFAULT) block or short-circuit it to just
return/ignore, and ensure you do not call preferences.defaultNoteColor.save(...)
or update colorAdapter.defaultColor/notifyItemRangeChanged with the sentinel
value.
- Around line 239-265: The neutral button UI/code is stale because the Observer
on preferences.defaultNoteColor only updates when the LiveData emits and
performLongClick() is a no-op; extract the button update logic into a helper
like updateNeutralButton(defaultColor: ColorString) that reads
binding.ColorPicker.colorEnvelope.toColorString(), sets text/icon/tooltip, and
installs a real setOnClickListener that calls
preferences.defaultNoteColor.save(currentColor) when not default (and either
remove the performLongClick branch or implement setOnLongClickListener for the
intended behavior); call updateNeutralButton(preferences.defaultNoteColor.value)
from both the Observer (observer: Observer<ColorString>) and from the
ColorEnvelopeListener callback (after you update the positive button) so the
neutral button reflects picker moves immediately.
---
Nitpick comments:
In `@app/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.kt`:
- Around line 271-276: The function showDeleteColorDialog should use the
ColorString typealias instead of raw String to match other APIs; update its
signature to accept colors: List<ColorString>, oldColor: ColorString (nullable
if previously nullable), and change the callback and deleteCallback parameter
types to use ColorString/ColorString? (i.e., callback: (selectedColor:
ColorString, oldColor: ColorString?) -> Unit and deleteCallback: (colorToDelete:
ColorString, newColor: ColorString) -> Unit). After changing the signature in
showDeleteColorDialog, update any call sites to pass/expect ColorString types
accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9290e8c4-f030-420a-8a9c-d775a856010e
📒 Files selected for processing (3)
app/src/main/java/com/philkes/notallyx/presentation/view/main/ColorVH.ktapp/src/main/java/com/philkes/notallyx/utils/ColorActivityExtensions.ktapp/src/main/res/drawable/dashed_background.xml
🚧 Files skipped from review as they are similar to previous changes (1)
- app/src/main/java/com/philkes/notallyx/presentation/view/main/ColorVH.kt
Closes #630
Summary by CodeRabbit
New Features
Documentation