Skip to content

feat: Add default ImageView for App Inbox when media orientation is missing#972

Open
darshanclevertap wants to merge 5 commits intotask/release/8.1.0from
claude/add-media-orientation-default-ZPW6n
Open

feat: Add default ImageView for App Inbox when media orientation is missing#972
darshanclevertap wants to merge 5 commits intotask/release/8.1.0from
claude/add-media-orientation-default-ZPW6n

Conversation

@darshanclevertap
Copy link
Copy Markdown
Collaborator

@darshanclevertap darshanclevertap commented Mar 30, 2026

When the backend does not provide an orientation key ("l" or "p") in the App Inbox payload, the SDK now falls back to a plain ImageView with match_parent width and wrap_content height, rendering the image at its natural aspect ratio using FIT_CENTER scale type. This supports the new Personalized Media feature, where customers paste arbitrary image URLs without dimension validation.

Summary by CodeRabbit

  • Bug Fixes

    • Restored media display for non-standard orientations by adding a fallback media view and ensuring it participates in image binding.
  • New Features

    • Added a default/fallback media view across carousel, icon, and simple message layouts supporting images, GIFs, video posters and audio thumbnails.
    • Improved image scaling (FIT_CENTER) and refined aspect-ratio/sizing for landscape, portrait, and other orientations.
    • Sample app: added a "Push Custom Event" dialog and corresponding Events list entry.

@francispereira
Copy link
Copy Markdown

francispereira commented Mar 30, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • \b(master|main|develop)(_\w*)?

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 29e9b0f6-fb4d-47db-b71b-feff5bc0c509

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds hidden fallback/default ImageView elements to carousel, icon, and simple inbox layouts and wires them into adapter and view-holder logic to handle non-"l"/"p" orientations; also adjusts media/video sizing calculations to use the new default image dimensions or aspect-ratio fallbacks. Additionally adds a custom-event dialog and related ViewModel changes in the sample app.

Changes

Cohort / File(s) Summary
Carousel adapter & layouts
clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTCarouselViewPagerAdapter.java, clevertap-core/src/main/res/layout/inbox_carousel_image_layout.xml, clevertap-core/src/main/res/layout-land/inbox_carousel_image_layout.xml
instantiateItem now handles non-"l"/"p" orientations by finding defaultImageView, setting ScaleType.FIT_CENTER, and routing to existing image binding/click wiring. Added defaultImageView to portrait/land layouts (hidden by default).
Icon message view holder & layouts
clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTIconMessageViewHolder.java, clevertap-core/src/main/res/layout/inbox_icon_message_layout.xml, clevertap-core/src/main/res/layout-land/inbox_icon_message_layout.xml
Wired default_media_image ImageView; added default-orientation branch to render media into it (image/GIF/video/audio) using FIT_CENTER, preserved Glide NoSuchMethodError fallback, and adjusted non-landscape progress bar height logic.
Simple message view holder & layouts
clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTSimpleMessageViewHolder.java, clevertap-core/src/main/res/layout/inbox_simple_message_layout.xml, clevertap-core/src/main/res/layout-land/inbox_simple_message_layout.xml
Hooked up default_media_image, added default-orientation media handling into it (image/GIF/video/audio) with FIT_CENTER, and updated progress/frame height calculations to treat "p" explicitly.
Base message view holder sizing
clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTInboxBaseMessageViewHolder.java
Refined media/video sizing: treat "p" separately, introduce defaultImage dimension sourcing for non-standard orientations, and fall back to screen-based 0.5625 aspect ratio when needed.
Layouts (land + portrait)
clevertap-core/src/main/res/layout/...inbox_*_message_layout.xml, clevertap-core/src/main/res/layout-land/...inbox_*_message_layout.xml
Added default_media_image / defaultImageView ImageView resources (hidden by default, fitCenter, adjustViewBounds) to several layouts to support the new fallback image paths.
Sample app: custom event UI
sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt, sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt, sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt
Added dialog flow to push a custom event: new LiveData showCustomEventDialog, dialog builder in Fragment, pushCustomEvent and resetShowCustomEventDialog in ViewModel, and added "Custom Event" entry to sample list.

Sequence Diagram(s)

sequenceDiagram
    participant Adapter as CTCarouselViewPagerAdapter
    participant Layout as defaultImageView/Layout
    participant ViewHolder as InboxViewHolder
    participant ImageLoader as Glide

    Adapter->>Layout: inflate / findViewById(`defaultImageView`)
    Adapter->>ViewHolder: addImageAndSetClick(`defaultImageView`, media)
    ViewHolder->>ImageLoader: load(media.url) { scaleType: FIT_CENTER }
    ImageLoader-->>ViewHolder: image/thumbnail or fallback
    ViewHolder-->>Layout: setImageDrawable / setVisibility(VISIBLE)
    ViewHolder-->>Adapter: attach view to container
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

sampleapp

Suggested reviewers

  • piyush-kukadiya
  • CTLalit
  • vasct
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: adding a default ImageView for App Inbox when media orientation is missing, which aligns with the changeset's primary objective.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/add-media-orientation-default-ZPW6n

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.

@darshanclevertap
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTCarouselViewPagerAdapter.java (1)

81-81: Minor: Redundant scale type assignment.

The scaleType is already defined as fitCenter in the XML layout. The programmatic assignment here is redundant but harmless. You can remove this line if desired, or keep it for explicit clarity.

♻️ Optional cleanup
            } else {
                ImageView imageView = view.findViewById(R.id.defaultImageView);
-               imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                addImageAndSetClick(imageView, view, position, container);
            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTCarouselViewPagerAdapter.java`
at line 81, The line imageView.setScaleType(ImageView.ScaleType.FIT_CENTER) in
CTCarouselViewPagerAdapter is redundant because the ImageView's scaleType is
already set to fitCenter in the XML; remove that programmatic assignment to
clean up the code (or, if you prefer explicitness, leave it)—locate the call to
imageView.setScaleType in the CTCarouselViewPagerAdapter class and delete it if
opting for the cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTInboxBaseMessageViewHolder.java`:
- Around line 97-102: In CTInboxBaseMessageViewHolder.addMediaPlayer(), guard
against defaultImage being null before calling
getMeasuredWidth()/getMeasuredHeight(): wrap the dereferences of
this.defaultImage in a null check and only use its measured dimensions when
non-null, otherwise fall back to the existing resources-based width/height
computation; apply the same null-guard to both the landscape and portrait
branches so CTCarouselImageViewHolder/CTCarouselMessageViewHolder callers won’t
trigger a NullPointerException if they haven’t bound defaultImage.

In
`@clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTSimpleMessageViewHolder.java`:
- Around line 459-465: The fallback branch currently sets height to
RelativeLayout.LayoutParams.WRAP_CONTENT, which only sizes to the spinner
instead of the media area; change the else branch in CTSimpleMessageViewHolder
(the block using inboxMessage.getOrientation()) to set height = width (or
another fixed media-height calculation consistent with the portrait case) so the
progress frame overlays the full media area, and make the identical change in
the mirrored block in CTIconMessageViewHolder (replace WRAP_CONTENT with the
same calculated height variable).
- Around line 164-165: When binding a new message in CTSimpleMessageViewHolder,
clear the recycled ImageView's accessibility label so a previous item's media
description isn't announced for the current fallback image: when you call
defaultImage.setVisibility(View.GONE) / defaultImage.setBackgroundColor(...)
also call defaultImage.setContentDescription(null) (or set to an appropriate new
description) to reset the content description; apply the same change in the
other bind branch referenced around the second occurrence (the lines
corresponding to the 359-360 block) so reused holders never retain stale content
descriptions.

---

Nitpick comments:
In
`@clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTCarouselViewPagerAdapter.java`:
- Line 81: The line imageView.setScaleType(ImageView.ScaleType.FIT_CENTER) in
CTCarouselViewPagerAdapter is redundant because the ImageView's scaleType is
already set to fitCenter in the XML; remove that programmatic assignment to
clean up the code (or, if you prefer explicitness, leave it)—locate the call to
imageView.setScaleType in the CTCarouselViewPagerAdapter class and delete it if
opting for the cleanup.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e5ed75f0-19f2-44df-ac20-d1831d3cf3c3

📥 Commits

Reviewing files that changed from the base of the PR and between c26db7a and 109ee1e.

📒 Files selected for processing (10)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTCarouselViewPagerAdapter.java
  • clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTIconMessageViewHolder.java
  • clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTInboxBaseMessageViewHolder.java
  • clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTSimpleMessageViewHolder.java
  • clevertap-core/src/main/res/layout-land/inbox_carousel_image_layout.xml
  • clevertap-core/src/main/res/layout-land/inbox_icon_message_layout.xml
  • clevertap-core/src/main/res/layout-land/inbox_simple_message_layout.xml
  • clevertap-core/src/main/res/layout/inbox_carousel_image_layout.xml
  • clevertap-core/src/main/res/layout/inbox_icon_message_layout.xml
  • clevertap-core/src/main/res/layout/inbox_simple_message_layout.xml

Comment on lines +164 to +165
this.defaultImage.setVisibility(View.GONE);
this.defaultImage.setBackgroundColor(Color.parseColor(inboxMessage.getBgColor()));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Reset defaultImage's content description during reuse.

A recycled holder can otherwise announce the previous item's custom media description when the next fallback-orientation row doesn't provide one.

♿ Suggested fix
         this.defaultImage.setVisibility(View.GONE);
         this.defaultImage.setBackgroundColor(Color.parseColor(inboxMessage.getBgColor()));
+        this.defaultImage.setContentDescription(
+                context.getString(R.string.ct_inbox_media_content_description));

Also applies to: 359-360

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTSimpleMessageViewHolder.java`
around lines 164 - 165, When binding a new message in CTSimpleMessageViewHolder,
clear the recycled ImageView's accessibility label so a previous item's media
description isn't announced for the current fallback image: when you call
defaultImage.setVisibility(View.GONE) / defaultImage.setBackgroundColor(...)
also call defaultImage.setContentDescription(null) (or set to an appropriate new
description) to reset the content description; apply the same change in the
other bind branch referenced around the second occurrence (the lines
corresponding to the 359-360 block) so reused holders never retain stale content
descriptions.

Comment on lines +459 to +465
if (inboxMessage.getOrientation().equalsIgnoreCase("l")) {
height = Math.round(width * 0.5625f);
} else if (inboxMessage.getOrientation().equalsIgnoreCase("p")) {
height = width;
} else {
height = RelativeLayout.LayoutParams.WRAP_CONTENT;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don't size the fallback progress frame with WRAP_CONTENT.

That only wraps the spinner, so buffering audio/video in the missing-orientation path won't overlay the media area. The mirrored block in CTIconMessageViewHolder needs the same fix.

🛠️ Suggested fix
         } else {
             width = resources.getDisplayMetrics().widthPixels;
             if (inboxMessage.getOrientation().equalsIgnoreCase("l")) {
                 height = Math.round(width * 0.5625f);
             } else if (inboxMessage.getOrientation().equalsIgnoreCase("p")) {
                 height = width;
             } else {
-                height = RelativeLayout.LayoutParams.WRAP_CONTENT;
+                height = this.defaultImage.getMeasuredHeight();
+                if (height == 0) {
+                    height = Math.round(width * 0.5625f);
+                }
             }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@clevertap-core/src/main/java/com/clevertap/android/sdk/inbox/CTSimpleMessageViewHolder.java`
around lines 459 - 465, The fallback branch currently sets height to
RelativeLayout.LayoutParams.WRAP_CONTENT, which only sizes to the spinner
instead of the media area; change the else branch in CTSimpleMessageViewHolder
(the block using inboxMessage.getOrientation()) to set height = width (or
another fixed media-height calculation consistent with the portrait case) so the
progress frame overlays the full media area, and make the identical change in
the mirrored block in CTIconMessageViewHolder (replace WRAP_CONTENT with the
same calculated height variable).

@darshanclevertap
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@Anush-Shand Anush-Shand left a comment

Choose a reason for hiding this comment

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

Approved with small comments

}
}
break;
default:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Duplicate code with CTIconMessageViewHolder.java

android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/ct_audio"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this default src intentional?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt (1)

29-29: Expose immutable LiveData instead of public MutableLiveData.

The Fragment directly mutates this property (line 118 of HomeScreenFragment.kt: viewModel.showCustomEventDialog.value = false), breaking unidirectional data flow and allowing the UI layer to control ViewModel state. The ViewModel should be the sole owner and mutator of its own state.

Suggested refactor
+import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
@@
-    val showCustomEventDialog: MutableLiveData<Boolean> by lazy { MutableLiveData<Boolean>() }
+    private val _showCustomEventDialog = MutableLiveData<Boolean>()
+    val showCustomEventDialog: LiveData<Boolean> get() = _showCustomEventDialog
@@
-            9 -> showCustomEventDialog.value = true
+            9 -> _showCustomEventDialog.value = true

Add a ViewModel method to handle external reset requests instead of exposing mutable state.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt` at
line 29, Replace the public MutableLiveData with a private MutableLiveData and
expose it as immutable LiveData from HomeScreenViewModel (keep the existing
showCustomEventDialog symbol but make it privateMutableShowCustomEventDialog and
add a public val showCustomEventDialog: LiveData<Boolean>); stop letting
fragments set .value directly and instead add a ViewModel method (e.g.,
hideCustomEventDialog() or resetShowCustomEventDialog()) that updates the
private MutableLiveData, and update callers (HomeScreenFragment) to call that
method rather than writing to the MutableLiveData.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt`:
- Around line 145-153: The dialog currently uses
AlertDialog.Builder.setPositiveButton which auto-dismisses regardless of your
early return; change to create the AlertDialog via
AlertDialog.Builder(...).create() and after calling show(), attach an
OnShowListener and override the positive button click with
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener to validate
eventNameInput.text.toString().trim() and only call dialog.dismiss() when
non-empty (otherwise show the Toast), updating the code around the existing
AlertDialog.Builder / setPositiveButton usage to instead build, show, and wire
the custom click handler.

---

Nitpick comments:
In `@sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt`:
- Line 29: Replace the public MutableLiveData with a private MutableLiveData and
expose it as immutable LiveData from HomeScreenViewModel (keep the existing
showCustomEventDialog symbol but make it privateMutableShowCustomEventDialog and
add a public val showCustomEventDialog: LiveData<Boolean>); stop letting
fragments set .value directly and instead add a ViewModel method (e.g.,
hideCustomEventDialog() or resetShowCustomEventDialog()) that updates the
private MutableLiveData, and update callers (HomeScreenFragment) to call that
method rather than writing to the MutableLiveData.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5a95f88b-eb2d-4325-bc46-671ff1f3f2db

📥 Commits

Reviewing files that changed from the base of the PR and between d436d3a and 8e1eb65.

📒 Files selected for processing (3)
  • sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt
  • sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt
  • sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt
✅ Files skipped from review due to trivial changes (1)
  • sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt

Comment on lines +145 to +153
AlertDialog.Builder(ctx)
.setTitle("Push Custom Event")
.setView(layout)
.setPositiveButton("Push") { _, _ ->
val eventName = eventNameInput.text.toString().trim()
if (eventName.isEmpty()) {
Toast.makeText(ctx, "Event name cannot be empty", Toast.LENGTH_SHORT).show()
return@setPositiveButton
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In androidx.appcompat.app.AlertDialog, does setPositiveButton(...) always dismiss the dialog after click, even if the callback returns early?

💡 Result:

Yes. For androidx.appcompat.app.AlertDialog, buttons added via AlertDialog.Builder.setPositiveButton(...) will dismiss the dialog after a click regardless of what your callback does (there’s no “return true/false” to control it—the listener returns void). The AppCompat implementation invokes your OnClickListener and then posts a separate message that calls dismiss() unconditionally. [1], [2]

If you need to keep the dialog open (e.g., validation fails), create/show the dialog first and then replace the positive button’s click handler with your own View.OnClickListener (and call dialog.dismiss() only when you want). [1], [2]

Sources:
[1] Android Developers – Dialogs guide (auto-dismiss behavior) (developer.android.com)
[2] AppCompat AlertController source (always posts dismiss after handler) (android.googlesource.com)

Citations:


Prevent auto-dismiss when event name is invalid.

On line 150, empty input shows a toast but the dialog still dismisses, forcing users to reopen it to correct the input. The setPositiveButton callback uses return@setPositiveButton to exit early, but AlertDialog.Builder still posts a separate dismiss message regardless of the callback's behavior.

Suggested fix
-        AlertDialog.Builder(ctx)
-            .setTitle("Push Custom Event")
-            .setView(layout)
-            .setPositiveButton("Push") { _, _ ->
-                val eventName = eventNameInput.text.toString().trim()
-                if (eventName.isEmpty()) {
-                    Toast.makeText(ctx, "Event name cannot be empty", Toast.LENGTH_SHORT).show()
-                    return@setPositiveButton
-                }
-                val propertiesText = propertiesInput.text.toString().trim()
-                val properties = parseProperties(propertiesText)
-                viewModel.pushCustomEvent(eventName, properties)
-                Toast.makeText(ctx, "Event '$eventName' pushed", Toast.LENGTH_SHORT).show()
-            }
-            .setNegativeButton("Cancel", null)
-            .show()
+        val dialog = AlertDialog.Builder(ctx)
+            .setTitle("Push Custom Event")
+            .setView(layout)
+            .setPositiveButton("Push", null)
+            .setNegativeButton("Cancel", null)
+            .create()
+
+        dialog.setOnShowListener {
+            dialog.getButton(android.content.DialogInterface.BUTTON_POSITIVE).setOnClickListener {
+                val eventName = eventNameInput.text.toString().trim()
+                if (eventName.isEmpty()) {
+                    Toast.makeText(ctx, "Event name cannot be empty", Toast.LENGTH_SHORT).show()
+                    return@setOnClickListener
+                }
+                val properties = parseProperties(propertiesInput.text.toString().trim())
+                viewModel.pushCustomEvent(eventName, properties)
+                Toast.makeText(ctx, "Event '$eventName' pushed", Toast.LENGTH_SHORT).show()
+                dialog.dismiss()
+            }
+        }
+        dialog.show()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt` around
lines 145 - 153, The dialog currently uses AlertDialog.Builder.setPositiveButton
which auto-dismisses regardless of your early return; change to create the
AlertDialog via AlertDialog.Builder(...).create() and after calling show(),
attach an OnShowListener and override the positive button click with
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener to validate
eventNameInput.text.toString().trim() and only call dialog.dismiss() when
non-empty (otherwise show the Toast), updating the code around the existing
AlertDialog.Builder / setPositiveButton usage to instead build, show, and wire
the custom click handler.

@CTLalit CTLalit changed the base branch from develop to task/release/8.1.0 April 7, 2026 10:00
claude and others added 5 commits April 7, 2026 15:31
…issing

When the backend does not provide an orientation key ("l" or "p") in the
App Inbox payload, the SDK now falls back to a plain ImageView with
match_parent width and wrap_content height, rendering the image at its
natural aspect ratio using FIT_CENTER scale type. This supports the new
Personalized Media feature where customers paste arbitrary image URLs
without dimension validation.

https://claude.ai/code/session_01C7qvo8dKQfZ8tkbnWdyKFW
- Null-guard defaultImage in addMediaPlayer() to prevent NPE when
  called from carousel ViewHolders that don't bind defaultImage
- Reset contentDescription on recycled defaultImage to prevent stale
  accessibility labels from previous messages
- Replace WRAP_CONTENT with calculated 16:9 height for progress bar
  frame so the loading overlay properly covers the media area

https://claude.ai/code/session_01C7qvo8dKQfZ8tkbnWdyKFW
Variables could be used before assignment in the else branch when
defaultImage is null, causing "variable might not have been initialized"
compiler errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…operties

Adds a "Custom Event" entry in the Events section that opens an AlertDialog
where users can enter an event name and optional key:value properties, then
pushes the event via CleverTapAPI.pushEvent().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Make showCustomEventDialog a private MutableLiveData with a public
LiveData getter, following standard MVVM encapsulation. Add
resetShowCustomEventDialog() method so the fragment no longer writes
directly to the MutableLiveData.

https://claude.ai/code/session_01C7qvo8dKQfZ8tkbnWdyKFW
@CTLalit CTLalit force-pushed the claude/add-media-orientation-default-ZPW6n branch from 621bbf1 to 080e7e7 Compare April 7, 2026 10:01
Copy link
Copy Markdown
Contributor

@piyush-kukadiya piyush-kukadiya left a comment

Choose a reason for hiding this comment

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

code duplication for media handling in switch case between CTIconMessageViewHolder and CTSimpleMessageViewHolder

android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/ct_audio"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1

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.

6 participants