Skip to content

ADFA-3071 | Refactor BottomSheet behavior and clean up attribute dialogs#1179

Merged
jatezzz merged 1 commit into
stagefrom
refactor/ADFA-3071-bottom-sheet-behavior
Apr 15, 2026
Merged

ADFA-3071 | Refactor BottomSheet behavior and clean up attribute dialogs#1179
jatezzz merged 1 commit into
stagefrom
refactor/ADFA-3071-bottom-sheet-behavior

Conversation

@jatezzz
Copy link
Copy Markdown
Collaborator

@jatezzz jatezzz commented Apr 14, 2026

Description

Refactored the BottomSheetDialog configurations in DesignEditor.kt to ensure proper rendering on larger screens (Tablets/DeX). By replacing STATE_HALF_EXPANDED with a combination of isFitToContents = true and STATE_EXPANDED, the dialogs now properly anchor to the bottom and wrap their content dynamically.

Details

Tablet/DeX

document_5114392780575081850.mp4

Phone

Screen.Recording.2026-04-14.at.11.42.34.AM.mov

Ticket

ADFA-3071

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 14, 2026

📝 Walkthrough

Release Notes - ADFA-3071: BottomSheet Behavior Refactor & Attribute Dialogs Cleanup

Features & Improvements

  • Improved tablet/DeX rendering: Refactored BottomSheetDialog configurations to use isFitToContents = true and STATE_EXPANDED instead of STATE_HALF_EXPANDED, ensuring dialogs anchor to the bottom and wrap content dynamically on larger screens
  • Enhanced attribute management UI: Cleaned up attribute dialogs with improved layout binding patterns using apply {} blocks and explicit adapter configurations
  • Improved search functionality: Added text change listener to available attributes dialog for real-time attribute filtering
  • Better code organization: Extracted confirmViewDeletion() helper method to reduce code duplication and improve maintainability
  • Idiomatic Kotlin refactoring: Applied Kotlin best practices to dialog and adapter initialization

⚠️ Risk: Potential Index-Based Collection Mismatch

  • Critical Issue in showDefinedAttributes(): The code iterates over allKeysAndValues.keySet().forEachIndexed { i, key -> but accesses allKeysAndValues.values()[i] by index. This assumes the order of keySet() and values() are synchronized in a HashMap, which is not guaranteed and can lead to attribute value mismatches.
    • Recommendation: Use allKeysAndValues[key] instead of allKeysAndValues.values()[i] to safely retrieve the corresponding value

Other Observations

  • Recursive call to showDefinedAttributes() when removing attributes may cause memory overhead if users remove multiple attributes in quick succession
  • Bottom sheet behavior now consistently uses skipCollapsed = true across both defined and available attributes dialogs

Walkthrough

Refactors attribute UI handling in DesignEditor: rebuilds displayed attribute lists, standardizes BottomSheetDialog/BottomSheetBehavior configuration, replaces inline adapter/binding setup with dedicated adapters, centralizes deletion confirmation into confirmViewDeletion, and simplifies search TextWatcher usage. No public API changes.

Changes

Cohort / File(s) Summary
Design editor UI & attribute handling
layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt
Rebuilt display key/value generation, replaced inline adapter/binding with AppliedAttributesAdapter / AvailableAttributesAdapter, unified tooltip call sites, switched to android.text.TextWatcher/Editable for search filtering, and configured BottomSheetBehavior properties (isFitToContents, state = STATE_EXPANDED, skipCollapsed).
Deletion confirmation extraction
layouteditor/src/main/java/.../DesignEditor.kt (same file, new helper)
Extracted inline delete-confirm flow into confirmViewDeletion(target, dialog: BottomSheetDialog) which performs removeId, removeViewAttributes, removeWidget, updateStructure, updateUndoRedoHistory and dismisses the dialog.

Sequence Diagram(s)

sequenceDiagram
    rect rgba(70,130,180,0.5)
    participant User
    end
    rect rgba(46,204,113,0.5)
    participant DesignEditor
    end
    rect rgba(155,89,182,0.5)
    participant BottomSheetDialog
    end
    rect rgba(241,196,15,0.5)
    participant Adapter
    end

    User->>DesignEditor: open attributes (defined/available)
    DesignEditor->>BottomSheetDialog: create & configure behavior (fitToContents, expand, skipCollapsed)
    DesignEditor->>Adapter: instantiate with click handlers
    Adapter->>DesignEditor: on attribute click -> showAttributeEdit / confirm deletion
    DesignEditor->>BottomSheetDialog: dismiss (after edit or via confirmViewDeletion)
    DesignEditor->>DesignEditor: removeWidget/removeViewAttributes/updateUndoRedoHistory (on deletion)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • jomen-adfa
  • Daniel-ADFA
  • itsaky-adfa

Poem

🐇 I hopped into the editor bright,

Adapters tuned and sheets take flight,
I nudged a dialog, tidy and neat,
Removed a view with nimble feet—
Code carrots crisp, the layout's light.

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: refactoring BottomSheet behavior and cleaning up attribute dialogs in the pull request.
Description check ✅ Passed The description is directly related to the changeset, explaining the rationale for BottomSheetDialog refactoring and providing visual evidence with screenshots.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/ADFA-3071-bottom-sheet-behavior

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt (2)

685-691: Decouple key/value assembly from positional indexing.

Line 690 depends on index alignment between keySet() and values(). It works today but is fragile and less maintainable than key-based access.

♻️ Suggested refactor
-		allKeysAndValues.keySet().forEachIndexed { i, key ->
+		allKeysAndValues.keySet().forEach { key ->
 			val foundAttrDef = allAttrs.find { it[Constants.KEY_ATTRIBUTE_NAME].toString() == key }

 			if (foundAttrDef != null) {
 				displayKeys.add(key)
-				displayValues.add(allKeysAndValues.values()[i])
+				displayValues.add(allKeysAndValues.getValue(key))
 				displayAttrs.add(foundAttrDef)
 			}
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt`
around lines 685 - 691, The loop currently relies on positional indexing between
allKeysAndValues.keySet() and allKeysAndValues.values(), which is fragile;
change the iteration to use key-based access: iterate over entries or keys and
retrieve the value by key (e.g., allKeysAndValues[key]) so that when
foundAttrDef (found via allAttrs.find {
it[Constants.KEY_ATTRIBUTE_NAME].toString() == key }) you push the correct value
into displayValues alongside displayKeys and displayAttrs; update the block that
references allKeysAndValues.values()[i] to use key-based lookup and keep adding
to displayKeys, displayValues, and displayAttrs the corresponding matched items.

772-779: Replace verbose TextWatcher with doAfterTextChanged from core-ktx.

Lines 774–775 are empty overrides that can be eliminated. The doAfterTextChanged extension function from androidx.core.widget is already used elsewhere in the codebase and is the idiomatic Kotlin approach.

♻️ Suggested refactor
-import android.text.Editable
-import android.text.TextWatcher
+import androidx.core.widget.doAfterTextChanged
...
-		binding.searchEditText.addTextChangedListener(
-			object : TextWatcher {
-				override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
-				override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
-				override fun afterTextChanged(s: Editable?) {
-					adapter.filter(s?.toString() ?: "")
-				}
-			}
-		)
+		binding.searchEditText.doAfterTextChanged { s ->
+			adapter.filter(s?.toString().orEmpty())
+		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt`
around lines 772 - 779, Replace the anonymous TextWatcher on
binding.searchEditText with the core-ktx doAfterTextChanged extension: remove
the redundant beforeTextChanged/onTextChanged overrides and call
binding.searchEditText.doAfterTextChanged { adapter.filter(it?.toString() ?: "")
} instead, keeping the adapter.filter call intact so behavior is unchanged;
locate the TextWatcher registration around
binding.searchEditText.addTextChangedListener to make this swap.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt`:
- Around line 685-691: The loop currently relies on positional indexing between
allKeysAndValues.keySet() and allKeysAndValues.values(), which is fragile;
change the iteration to use key-based access: iterate over entries or keys and
retrieve the value by key (e.g., allKeysAndValues[key]) so that when
foundAttrDef (found via allAttrs.find {
it[Constants.KEY_ATTRIBUTE_NAME].toString() == key }) you push the correct value
into displayValues alongside displayKeys and displayAttrs; update the block that
references allKeysAndValues.values()[i] to use key-based lookup and keep adding
to displayKeys, displayValues, and displayAttrs the corresponding matched items.
- Around line 772-779: Replace the anonymous TextWatcher on
binding.searchEditText with the core-ktx doAfterTextChanged extension: remove
the redundant beforeTextChanged/onTextChanged overrides and call
binding.searchEditText.doAfterTextChanged { adapter.filter(it?.toString() ?: "")
} instead, keeping the adapter.filter call intact so behavior is unchanged;
locate the TextWatcher registration around
binding.searchEditText.addTextChangedListener to make this swap.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 07554516-bce1-42bb-adb0-05bd6fb54622

📥 Commits

Reviewing files that changed from the base of the PR and between 8787677 and 4488fa4.

📒 Files selected for processing (1)
  • layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt

@jatezzz jatezzz force-pushed the refactor/ADFA-3071-bottom-sheet-behavior branch from 4488fa4 to 069f193 Compare April 15, 2026 14:33
Apply fit-to-contents behavior and idiomatic Kotlin refactoring to DesignEditor
@jatezzz jatezzz force-pushed the refactor/ADFA-3071-bottom-sheet-behavior branch from 069f193 to 8cfcc41 Compare April 15, 2026 15:53
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt (1)

772-780: Consider using doAfterTextChanged extension to simplify TextWatcher.

The empty beforeTextChanged and onTextChanged methods are boilerplate required by the interface. AndroidX Core KTX provides doAfterTextChanged which is more concise.

♻️ Optional: Use doAfterTextChanged extension

Add the import:

import androidx.core.widget.doAfterTextChanged

Then simplify the listener:

-binding.searchEditText.addTextChangedListener(
-	object : TextWatcher {
-		override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
-		override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
-		override fun afterTextChanged(s: Editable?) {
-			adapter.filter(s?.toString() ?: "")
-		}
-	}
-)
+binding.searchEditText.doAfterTextChanged { s ->
+	adapter.filter(s?.toString() ?: "")
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt`
around lines 772 - 780, Replace the verbose TextWatcher on
binding.searchEditText with the doAfterTextChanged extension: remove the
anonymous TextWatcher, add import androidx.core.widget.doAfterTextChanged, and
call binding.searchEditText.doAfterTextChanged { adapter.filter(it?.toString()
?: "") } so adapter.filter is invoked after text changes; ensure you remove the
unused override methods and keep the same behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt`:
- Around line 772-780: Replace the verbose TextWatcher on binding.searchEditText
with the doAfterTextChanged extension: remove the anonymous TextWatcher, add
import androidx.core.widget.doAfterTextChanged, and call
binding.searchEditText.doAfterTextChanged { adapter.filter(it?.toString() ?: "")
} so adapter.filter is invoked after text changes; ensure you remove the unused
override methods and keep the same behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 301c45e0-ebf5-4545-95d2-4d8e20348e07

📥 Commits

Reviewing files that changed from the base of the PR and between 4488fa4 and 8cfcc41.

📒 Files selected for processing (1)
  • layouteditor/src/main/java/org/appdevforall/codeonthego/layouteditor/editor/DesignEditor.kt

@jatezzz jatezzz merged commit 017ffd5 into stage Apr 15, 2026
2 checks passed
@jatezzz jatezzz deleted the refactor/ADFA-3071-bottom-sheet-behavior branch April 15, 2026 16:05
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