Skip to content

Task/sdk 4048/ctas pt #786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

Anush-Shand
Copy link
Contributor

@Anush-Shand Anush-Shand commented Apr 3, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced push notifications now support interactive action buttons and rich media, improving the display of images and message summaries.
  • Style

    • Redesigned layouts offer a cleaner, modern look across carousel, big image, and timer notifications with refined button visuals and consistent color themes.
  • Chores

    • Internal updates streamline notification rendering and improve performance, ensuring a smoother and more reliable user experience.

# Conflicts:
#	gradle/libs.versions.toml
…ask/SDK-4048/ctas_pt

# Conflicts:
#	clevertap-pushtemplates/src/main/res/layout-v23/content_view_small_multi_line_msg.xml
Copy link
Contributor

coderabbitai bot commented Apr 3, 2025

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.

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

Walkthrough

This pull request makes extensive updates to the push notification modules by replacing Java implementations with their Kotlin counterparts and standardizing action button handling. A new ActionButton data class is introduced while old renderer files are removed and replaced with new ones that include improved error handling and modern Kotlin idioms. In addition, many push template content view and style classes have been refactored for better visibility management and inheritance (favoring action button–aware base classes), and numerous XML layouts and resources have been updated to support flexible UI arrangements and integrated action button layouts. A new string extension function is also added.

Changes

File(s) Change Summary
clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/ActionButton.kt
CoreNotificationRenderer.java
CoreNotificationRenderer.kt
INotificationRenderer.java
INotificationRenderer.kt
Introduced a new Kotlin data class ActionButton; removed Java-based notification renderer and interface; added Kotlin implementations with enhanced methods for extracting notification details and handling action buttons.
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt Updated method signatures to use NotificationCompat.Builder (renaming to Builder), renamed setActionButtons to getActionButtons (now returning a List<ActionButton>), introduced a property for actionButtons, and updated the actionButtonIconKey to a read-only property.
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/Utils.java Changed the access level of setPackageNameFromResolveInfoList from package‑private to public.
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/* Various content view classes (e.g., ActionButtonsContentView.kt, BigImageContentView.kt, ContentView.kt, TimerSmallContentView.kt, ZeroBezelBigContentView.kt, etc.) have been updated to change visibility (often to internal) and, in several cases, to switch the base class from ContentView to ActionButtonsContentView. Additionally, string checks have been streamlined using the new extension function.
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/* Multiple style classes (e.g., BasicStyle.kt, InputBoxStyle.kt, Style.kt, StyleWithActionButtons.kt, TimerStyle.kt, ZeroBezelStyle.kt, etc.) are refactored to update visibility and inheritance (now extending StyleWithActionButtons where applicable) and modify notification builder styling logic.
clevertap-pushtemplates/src/main/res/layout/* Layout files (e.g., action_buttons.xml, auto_carousel.xml, image_only_big.xml, manual_carousel.xml, timer.xml, zero_bezel.xml) were restructured: root elements changed (from RelativeLayout to LinearLayout), fixed dimensions replaced with weighted values, new <include> tags for action buttons were added, and overall view hierarchy adjustments were made.
clevertap-pushtemplates/src/main/res/values/colors.xml
clevertap-pushtemplates/src/main/res/drawable/pt_button_background.xml
Added a new color (lightGray) and introduced a drawable selector (pt_button_background.xml) to define button background states.
clevertap-core/src/main/java/com/clevertap/android/sdk/CTXtensions.kt Added a new Kotlin extension function isNotNullAndEmpty() for String?, providing a concise way to check for non‑null and non‑empty strings.

Sequence Diagram(s)

sequenceDiagram
    participant TR as TemplateRenderer
    participant NR as INotificationRenderer
    participant B as Builder
    participant AB as ActionButton
    participant Sys as System

    TR->>NR: renderNotification(extras, context, nb, config, notificationId)
    Note over NR: Extracts collapse key, message, title<br>and determines notification style
    NR->>B: Initialize and configure notification builder
    NR->>NR: getActionButtons(context, extras, notificationId, actions)
    NR->>AB: Create ActionButton instances for each valid action
    AB-->>NR: Return list of ActionButton(s)
    NR->>B: attachActionButtons(nb, List<ActionButton>)
    B->>Sys: Deliver and display notification
Loading

Suggested reviewers

  • CTLalit
  • piyush-kukadiya

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Anush-Shand Anush-Shand changed the base branch from task/SDK-1556/replace_multi_layouts_with_dimens to develop April 3, 2025 11:48
@Anush-Shand Anush-Shand changed the base branch from develop to task/SDK-1556/replace_multi_layouts_with_dimens April 3, 2025 11:50
Anush-Shand and others added 4 commits April 3, 2025 17:21
- For API 31 and above StyleWithActionButtons is responsible
- For API 30 and below ActionButtonsContentView is responsible
@Anush-Shand
Copy link
Contributor Author

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Apr 4, 2025

✅ 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.

@Anush-Shand Anush-Shand added the ptv2.0.0 Push Template Release label Apr 4, 2025
Copy link
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: 0

🔭 Outside diff range comments (1)
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt (1)

452-580: 🛠️ Refactor suggestion

Code duplication with INotificationRenderer default implementation

The implementation of getActionButtons in TemplateRenderer is nearly identical to the default implementation in the INotificationRenderer interface. This creates maintenance challenges as changes would need to be made in multiple places.

Consider removing the duplicate implementation and delegating to the interface's default implementation, or extract common logic to a shared utility class:

override fun getActionButtons(
    context: Context,
    extras: Bundle,
    notificationId: Int,
    actions: JSONArray?
): List<ActionButton> {
-   // Current duplicate implementation
-   val actionButtons = mutableListOf<ActionButton>()
-   // ... rest of the duplicate implementation
+   // Either delegate to super implementation if possible:
+   return super.getActionButtons(context, extras, notificationId, actions)
+   
+   // Or use a shared utility class:
+   // return ActionButtonUtils.createActionButtons(context, extras, notificationId, actions, actionButtonIconKey)
}

Alternatively, if there are template-specific behaviors that need to be preserved, clearly document what's different between the implementations and extract the common parts.

🧰 Tools
🪛 detekt (1.23.7)

[warning] 464-464: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


[warning] 467-467: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


[warning] 474-474: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🧹 Nitpick comments (12)
clevertap-pushtemplates/src/main/res/layout/image_only_big.xml (1)

13-18: ImageView Layout Adjustments
Changing the ImageView's height to 0dp and using layout_weight="1" allows dynamic resizing while still enforcing a minHeight of 196dp. This approach helps the UI adapt to varying screen sizes. Please verify on different devices that the aspect ratio and spacing remain as intended.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/Utils.java (1)

282-282: Add documentation for the newly public method.

Making setPackageNameFromResolveInfoList public is appropriate for its use in action button handling, but as part of the public API, it should have JavaDoc documentation to explain its purpose, parameters, and behavior.

+/**
+ * Sets the package name for the provided intent based on the package's resolved activities.
+ * This ensures that the intent will only target activities within the current application.
+ *
+ * @param context The context used to access the PackageManager
+ * @param launchIntent The intent to be updated with the package name
+ */
 public static void setPackageNameFromResolveInfoList(Context context, Intent launchIntent) {
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ActionButtonsContentView.kt (1)

23-41: Consider using named constants for button indices

The implementation effectively limits buttons to a maximum of two and handles validation, but would benefit from named constants instead of magic numbers for button indices.

- var visibleButtonCount = 0
+ private companion object {
+     const val FIRST_BUTTON_INDEX = 0
+     const val SECOND_BUTTON_INDEX = 1
+     const val MAX_BUTTONS = 2
+ }
+ var visibleButtonCount = 0

And then:

- val buttonId = when (visibleButtonCount) {
-     0 -> R.id.action0
-     1 -> R.id.action1
-     else -> return@forEach // Skip if we already have 2 buttons
+ val buttonId = when (visibleButtonCount) {
+     FIRST_BUTTON_INDEX -> R.id.action0
+     SECOND_BUTTON_INDEX -> R.id.action1
+     else -> return@forEach // Skip if we already have MAX_BUTTONS
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ZeroBezelBigContentView.kt (1)

40-41: Validate fallback behavior.
When Utils.getFallback() is true, you hide the image. Confirm that this aligns with the desired visual experience for users who expect an alternative image or text.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/BigImageContentView.kt (1)

42-43: Fallback logic for the big image.
Hiding the image upon fallback may be acceptable, but consider whether users should see a textual placeholder or alternative asset.

clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/CoreNotificationRenderer.kt (1)

23-28: Solid introduction of CoreNotificationRenderer.
The fields notifMessage, notifTitle, and smallIcon are stored at the class level. Consider making them private and verifying a new instance is created for each notification render to avoid potential conflicts in multi-threaded scenarios.

clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.kt (2)

34-143: Consider breaking down the complex getActionButtons implementation

The default implementation for getActionButtons is quite complex (over 100 lines) and handles multiple responsibilities including service detection, intent creation, action processing, and error handling. Consider decomposing this method into smaller, focused helper methods to improve readability and maintainability.

For example:

  • findIntentServiceClass(context)
  • createActionIntent(context, action, sendToCTIntentService)
  • createPendingIntent(context, actionLaunchIntent, sendToCTIntentService)
fun getActionButtons(
    context: Context,
    extras: Bundle,
    notificationId: Int,
    actions: JSONArray?
): List<ActionButton> {
    val actionButtons = mutableListOf<ActionButton>()
-   val intentServiceName = ManifestInfo.getInstance(context).intentServiceName
-   var clazz: Class<*>? = null
-   if (intentServiceName != null) {
-       try {
-           clazz = Class.forName(intentServiceName)
-       } catch (e: ClassNotFoundException) {
-           try {
-               clazz = Class.forName("com.clevertap.android.sdk.pushnotification.CTNotificationIntentService")
-           } catch (ex: ClassNotFoundException) {
-               Logger.d("No Intent Service found")
-           }
-       }
-   } else {
-       try {
-           clazz = Class.forName("com.clevertap.android.sdk.pushnotification.CTNotificationIntentService")
-       } catch (ex: ClassNotFoundException) {
-           Logger.d("No Intent Service found")
-       }
-   }
-   val isCTIntentServiceAvailable = Utils.isServiceAvailable(context, clazz)
+   val clazz = findIntentServiceClass(context)
+   val isCTIntentServiceAvailable = Utils.isServiceAvailable(context, clazz)
    
    if (actions != null && actions.length() > 0) {
        for (i in 0 until actions.length()) {
            try {
                // Process action and create ActionButton
                // ...rest of implementation...
            } catch (t: Throwable) {
                Logger.d("error adding notification action : " + t.localizedMessage)
            }
        }
    }
    return actionButtons
}

+ // Helper method to find the intent service class
+ private fun findIntentServiceClass(context: Context): Class<*>? {
+     val intentServiceName = ManifestInfo.getInstance(context).intentServiceName
+     if (intentServiceName != null) {
+         try {
+             return Class.forName(intentServiceName)
+         } catch (e: ClassNotFoundException) {
+             try {
+                 return Class.forName("com.clevertap.android.sdk.pushnotification.CTNotificationIntentService")
+             } catch (ex: ClassNotFoundException) {
+                 Logger.d("No Intent Service found")
+             }
+         }
+     } else {
+         try {
+             return Class.forName("com.clevertap.android.sdk.pushnotification.CTNotificationIntentService")
+         } catch (ex: ClassNotFoundException) {
+             Logger.d("No Intent Service found")
+         }
+     }
+     return null
+ }

83-84: Consider extracting version checks to a utility method

The SDK appears to have multiple version checks for Android version compatibility. Consider extracting these version checks to a utility method to maintain consistency and avoid duplication.

- val sendToCTIntentService = (Build.VERSION.SDK_INT < Build.VERSION_CODES.S && autoCancel
-         && isCTIntentServiceAvailable)
+ val sendToCTIntentService = shouldSendToCTIntentService(autoCancel, isCTIntentServiceAvailable)

// Add this utility method
+ private fun shouldSendToCTIntentService(autoCancel: Boolean, isServiceAvailable: Boolean): Boolean {
+     return Build.VERSION.SDK_INT < Build.VERSION_CODES.S && autoCancel && isServiceAvailable
+ }
clevertap-pushtemplates/src/main/res/layout/zero_bezel.xml (4)

11-18: RelativeLayout Configuration Check
The new RelativeLayout (@+id/content_view_rl) inside the LinearLayout is set up with weight parameters to dynamically fill space. However, note that the attribute android:orientation="vertical" (line 18) is not applicable to RelativeLayout and can be safely removed.


32-42: Embedded Content Container (rel_lyt) Enhancements
The new RelativeLayout with id rel_lyt effectively groups the metadata and textual content. There is redundancy in the padding definitions (using both paddingStart/paddingLeft and paddingEnd/paddingRight). For improved clarity and to fully leverage RTL support, consider retaining only paddingStart and paddingEnd (and if necessary, paddingTop/paddingBottom).


48-58: Title TextView: Review Alignment Attributes
The Title TextView is positioned below the metadata include and uses both android:layout_alignStart and android:layout_alignLeft attributes. To avoid redundancy and better support RTL layouts, it is advisable to retain only android:layout_alignStart.


60-69: Message TextView: Simplify Alignment Attributes
Similar to the title, the message TextView employs both android:layout_alignStart and android:layout_alignLeft. Simplify the attribute list by keeping only android:layout_alignStart for clarity and consistency with RTL best practices.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fca1dd7 and a7a7140.

📒 Files selected for processing (26)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/ActionButton.kt (1 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/CoreNotificationRenderer.java (0 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/CoreNotificationRenderer.kt (1 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.java (0 hunks)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt (10 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/Utils.java (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ActionButtonsContentView.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/BigImageContentView.kt (3 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ContentView.kt (7 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/TimerSmallContentView.kt (3 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ZeroBezelBigContentView.kt (3 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/BasicStyle.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/InputBoxStyle.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/Style.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/StyleWithActionButtons.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/TimerStyle.kt (1 hunks)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/ZeroBezelStyle.kt (2 hunks)
  • clevertap-pushtemplates/src/main/res/drawable/button_background.xml (1 hunks)
  • clevertap-pushtemplates/src/main/res/layout/action_buttons.xml (1 hunks)
  • clevertap-pushtemplates/src/main/res/layout/auto_carousel.xml (2 hunks)
  • clevertap-pushtemplates/src/main/res/layout/image_only_big.xml (1 hunks)
  • clevertap-pushtemplates/src/main/res/layout/manual_carousel.xml (2 hunks)
  • clevertap-pushtemplates/src/main/res/layout/timer.xml (2 hunks)
  • clevertap-pushtemplates/src/main/res/layout/zero_bezel.xml (1 hunks)
  • clevertap-pushtemplates/src/main/res/values/colors.xml (1 hunks)
💤 Files with no reviewable changes (2)
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/CoreNotificationRenderer.java
  • clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.java
🧰 Additional context used
🧬 Code Definitions (3)
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/Utils.java (2)
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ActionButtonsContentView.kt (1)
  • context (11-43)
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ContentView.kt (1)
  • context (14-147)
clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/CoreNotificationRenderer.kt (1)
clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.kt (2)
  • getActionButtons (34-143)
  • attachActionButtons (145-149)
clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt (1)
clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.kt (1)
  • getActionButtons (34-143)
🔇 Additional comments (55)
clevertap-pushtemplates/src/main/res/values/colors.xml (1)

3-4: New Color Addition
The addition of the lightGray color with the hex value #E0E0E0 is clear and consistent with the existing palette. Confirm that this color is used purposefully—for example, in the button's pressed state—to enhance UI feedback.

clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/ActionButton.kt (1)

1-10: New ActionButton Data Class
The new Kotlin data class ActionButton is well-defined and encapsulates the properties (label, icon, pendingIntent) needed for action buttons. The use of immutability and clear property definitions aligns with Kotlin best practices. Consider adding KDoc comments for future maintainability if desired.

clevertap-pushtemplates/src/main/res/drawable/button_background.xml (1)

1-16: Well-Defined Button Background Drawable
The drawable selector is correctly structured to provide visual feedback for button states. Using a rounded rectangle with a solid fill of @color/lightGray in the pressed state and a transparent state by default is both modern and user-friendly.

clevertap-pushtemplates/src/main/res/layout/image_only_big.xml (1)

19-21: Inclusion of Action Buttons Layout
The inclusion of the <include> tag for @layout/action_buttons effectively integrates action buttons into the layout. Ensure that the placement and spacing of these CTAs harmonize with the overall design, and that they do not overlap or interfere with other UI elements.

clevertap-pushtemplates/src/main/res/layout/action_buttons.xml (1)

1-45: New Action Buttons Layout
This new layout defines a horizontal LinearLayout acting as a container for action buttons with two TextView elements. The configuration—with properties like android:visibility="gone", text ellipsizing, and a drawable background—sets up the structural foundation for dynamically displaying CTAs. Ensure that the corresponding logic toggles these buttons’ visibility based on application needs.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/TimerStyle.kt (1)

15-15: Good refactoring to use StyleWithActionButtons inheritance.

The change to extend StyleWithActionButtons instead of Style improves code organization by centralizing action button functionality in a shared parent class. This reduces code duplication across style implementations.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/Style.kt (2)

44-50: Good addition of DecoratedCustomViewStyle for Android S+ compatibility.

The conditional application of NotificationCompat.DecoratedCustomViewStyle() for Android S (API 31) and above improves the appearance of custom notifications on newer Android versions, ensuring proper rendering of notification decorations.


44-50:

❓ Verification inconclusive

Is the removal of setOnlyAlertOnce(true) intentional?

The previous implementation included .setOnlyAlertOnce(true), which prevents notifications from alerting (sound, vibration, lights) multiple times when updated. Without this, notifications might alert users each time they're updated, potentially causing disruption.


🏁 Script executed:

#!/bin/bash
# Check if setOnlyAlertOnce is used elsewhere in the codebase

echo "Checking for setOnlyAlertOnce usage in the codebase..."
rg --type kotlin --type java "setOnlyAlertOnce" -A 1 -B 1

Length of output: 176


Clarification Needed on Notification Behavior Change

  • Can you confirm if the removal of .setOnlyAlertOnce(true) was intentional? Previously, this flag ensured that notifications alerted (sound, vibration, LED) only once; without it, updates might trigger alerts multiple times.
  • The new conditional addition using NotificationCompat.DecoratedCustomViewStyle() for Android S (API 31) and above looks appropriate for maintaining proper notification appearance on newer devices.

Please verify manually that the change in notification behavior aligns with the intended functionality before finalizing this update.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/BasicStyle.kt (1)

13-13: Consistent inheritance update aligns with other style classes.

Changing BasicStyle to extend StyleWithActionButtons is consistent with the same pattern applied to other style classes. This refactoring centralizes action button functionality in a common parent class, improving code organization and reducing duplication.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/StyleWithActionButtons.kt (1)

9-24: Excellent abstraction for action button handling!

This new abstract class centralizes action button handling for different notification styles, which improves code organization. The conditional check for Android S or InputBoxStyle is well-explained with comments and helps maintain backward compatibility.

For even better maintainability, consider adding KDoc documentation to explain the class purpose and behavior.

clevertap-pushtemplates/src/main/res/layout/timer.xml (2)

71-73: Good layout enhancement for image flexibility

Using layout_weight="1" with 0dp height allows the image to scale dynamically, while minHeight="196dp" ensures it maintains visibility. This is a better approach than the previous fixed height.


76-78: Proper integration of action buttons

Including the action_buttons layout aligns with the architectural changes in StyleWithActionButtons, providing a consistent approach across different notification styles.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/InputBoxStyle.kt (1)

17-17: Correct inheritance update for action button handling

Changing the parent class from Style to StyleWithActionButtons properly leverages the centralized action button handling logic. This is consistent with the architectural refactoring.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ContentView.kt (2)

15-17: Improved constructor parameter formatting

The reformatted constructor parameters enhance readability while maintaining the same functionality.


69-69: Idiomatic Kotlin improvements

Replacing verbose null and emptiness checks with Kotlin's isNullOrEmpty() extension function makes the code more concise and readable while maintaining the same behavior.

Also applies to: 82-82, 95-95, 105-105, 114-114, 131-131, 139-139

clevertap-pushtemplates/src/main/res/layout/auto_carousel.xml (3)

2-6: Improved layout hierarchy with LinearLayout

The change from RelativeLayout to LinearLayout with vertical orientation provides a more straightforward, predictable layout flow for this notification template.


14-16: Enhanced flexibility with weight-based layout

Changing the ViewFlipper's height from fixed to weight-based (0dp with weight=1) while preserving minimum dimensions improves how the component adapts to different screen sizes and content.


22-24: Standardized action buttons implementation

Adding the action_buttons layout inclusion aligns with the architectural improvements seen across the notification templates, providing consistent button handling.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/TimerSmallContentView.kt (2)

17-17: Improved inheritance structure

Changing the base class from ContentView to ActionButtonsContentView properly leverages inheritance to gain action button handling capabilities without code duplication.


44-44: Kotlin idiomatic null checking

Using isNullOrEmpty() extension function instead of separate null and empty string checks makes the code more concise and readable, following Kotlin best practices.

Also applies to: 57-57, 63-63

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ActionButtonsContentView.kt (2)

11-16: Well-structured class hierarchy for action button support

The new ActionButtonsContentView class appropriately extends ContentView and initializes action buttons from the renderer, providing a clean inheritance structure.


17-21: Good platform compatibility handling

The conditional check for Android 12 (API 31) and above properly accounts for platform-specific notification behavior differences.

clevertap-pushtemplates/src/main/res/layout/manual_carousel.xml (3)

2-6: Improved layout structure

The change from RelativeLayout to LinearLayout with vertical orientation creates a more predictable layout flow that aligns with the architectural changes across other notification templates.


12-17: Enhanced flexibility with weight-based container

Adding a RelativeLayout with id "view_flipper" using weight-based height while maintaining a minimum height improves adaptability to different screen sizes and content lengths.


68-70: Standardized action buttons implementation

Adding the action_buttons layout inclusion provides consistent button handling across different notification templates, aligning with the new ActionButtonsContentView architecture.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/ZeroBezelBigContentView.kt (2)

12-12: Switching to ActionButtonsContentView is consistent with the new action-button architecture.
The inheritance change ensures you can neatly incorporate action buttons.


27-27: Cleaner null and empty check.
Replacing separate null/empty checks with isNullOrEmpty() is succinct and clear.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/BigImageContentView.kt (3)

4-5: Explicit imports for VERSION and VERSION_CODES provide clarity.
This makes it more apparent which constants are being referenced.


13-14: Extending ActionButtonsContentView
Good alignment with the action-button feature set. Verify that any inherited lifecycle or overrides from the previous base class are accounted for if necessary.


30-31: Use of isNullOrEmpty()
A straightforward, readable approach for combined null/empty checks.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/ZeroBezelStyle.kt (3)

15-15: Extending StyleWithActionButtons
This helps unify action-button handling across different styles.


17-20: Improved readability with multiline parameters.
This formatting makes it easier to scan and modify parameters.


30-33: Ensure big content logic is fully verified.
While the code looks fine, confirm that any new big content rendering paths remain stable.

clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/CoreNotificationRenderer.kt (5)

30-43: Getter methods for push details.
They correctly fetch message/title from bundles. The fallback to context.applicationInfo.name is appropriate for empty titles.


45-149: renderNotification is large—ensure no main-thread blocking.
Downloading images synchronously can risk UI thread stalls if invoked in certain contexts. Verify that this code always runs in a background or service context and consider factoring out image download logic into a helper.


153-155: Setting the small icon is straightforward.
No issues noted.


157-159: Action button icon key usage
Matches the existing pattern for retrieving icon resources in getActionButtons().


160-197: Robust sound handling with fallback.
Nicely wrapped in a try-catch for safety. The code handles both boolean and string forms of WZRK_SOUND.

clevertap-pushtemplates/src/main/res/layout/zero_bezel.xml (9)

2-9: Improved layout structure using LinearLayout as root

The change from RelativeLayout to LinearLayout as the root element with a vertical orientation is a good improvement for this type of layout structure. LinearLayout provides more predictable rendering behavior for vertically stacked components.


11-18: Good use of layout weights for content scaling

Using layout_height="0dp" with layout_weight="1" for the content view RelativeLayout allows the image content to expand and fill available space while maintaining proper proportions. The specified minHeight ensures the content area has reasonable dimensions even with minimal content.


73-75: Action buttons integration properly added

The addition of the action buttons layout at the bottom of the notification completes the refactoring to support the new action button framework. This change aligns well with the new ActionButton data class and notification rendering architecture.


32-42: Simplified positioning with improved layout attributes

The relative positioning has been improved with clearer padding specifications using more modern attributes like paddingStart/paddingEnd alongside paddingLeft/paddingRight for backward compatibility.


2-9: Root Element Updated to LinearLayout
The root element has been changed from a RelativeLayout to a LinearLayout with a vertical orientation. This simplifies the overall layout structure and makes the vertical stacking of child elements clearer.


20-24: Big Image Configuration Looks Good
The ImageView with the id big_image is properly configured with match_parent dimensions and a centerCrop scale type to ensure the image scales appropriately.


26-30: Overlay ImageView for Scrim Effect
This ImageView overlays big_image with a scrim drawable, using android:layout_alignBottom="@+id/big_image" to correctly align its bottom edge. Verify on different device sizes that the overlay provides the desired visual effect.


44-47: Modularization via Metadata Include
The inclusion of the metadata layout through the <include> tag is correctly placed within rel_lyt, promoting reuse and modularity in your layout design.


73-75: Action Buttons Inclusion Supports New CTA Functionality
The addition of the <include> tag for action_buttons at the bottom of the LinearLayout integrates the new CTA section. This change aligns well with the overall objective of enhancing action button support in the push notification framework.

clevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/INotificationRenderer.kt (2)

18-32: Well-defined interface with clear method contracts

The interface provides a clean, well-organized contract for notification renderers with appropriate method signatures that separate different concerns (getting content, rendering, handling actions).


145-149: Clean implementation of attachActionButtons

The attachActionButtons method provides a concise and clear implementation using Kotlin's collection processing functions, which is a great improvement over imperative-style loops.

clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt (6)

26-26: Good import for new ActionButton class

Properly importing the new ActionButton data class to support the refactored notification action button architecture.


78-78: Clean change to use ActionButton list instead of direct builder manipulation

The change from directly manipulating notification builders to storing action buttons in a list improves encapsulation and separation of concerns.


111-121: Properly adapted renderNotification to use the new action button approach

The method now correctly initializes the actionButtons list by calling getActionButtons, which aligns with the new architecture for handling notification actions.


337-337: Good use of Kotlin idioms for string checks

Replacing !s.isEmpty() with s.isNotEmpty() improves readability and follows Kotlin idioms. These changes make the code more idiomatic and easier to understand.

Also applies to: 493-493


573-573: Clean implementation for ActionButton creation

The code now cleanly creates an ActionButton instance with label, icon, and pendingIntent, adhering to the new data class pattern, which improves type safety and readability.


317-318: Simplified actionButtonIconKey property

Using Kotlin property syntax with a getter that returns the constant value makes the code more concise and follows Kotlin best practices.

Copy link
Collaborator

@CTLalit CTLalit left a comment

Choose a reason for hiding this comment

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

Requested some changes @Anush-Shand

- Makes classes internal
- Removes redundant colour attribute
- Adds pt_ prefix
- Removes return@forEach
- Adds extension function to increase readability
- Adds UTs for TemplateRenderer
Copy link
Collaborator

@CTLalit CTLalit left a comment

Choose a reason for hiding this comment

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

Requested some comments.

private lateinit var shadowPackageManager: ShadowPackageManager

@Before
fun setup() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we simplify the setup by bubbling up dependencies or wrapping them and also using less mocking

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will fix, improve and add more tests after all PRs have been merged into a feature branch

@Anush-Shand
Copy link
Contributor Author

@CTLalit @piyush-kukadiya please check

* task(SDK-4655) - Dark mode for push templates

- Adds dark mode support for push templates
- Removes bg as mandatory key
- Parses colour based on dark mode of phone

* task(SDK-4655) - Addresses few todos

* task(SDK-4655) - Makes product display action colour optional

* task(SDK-4655) - Addresses todos

* task(SDK-4655) -Fixes typo and deletes redundant files

* task(SDK-4655) - Color for CTA in clicked state

* task(SDK-4655) - Fixes default colour for title

* task(SDK-4655) - Fixes default colour for small icon

* task(SDK-4655) - Adds color for rating confirm button for light and dark mode

* task(SDK-4655) - Fixes default colour for product template buttons

* task(SDK-4655) - Extracts dimens

* task(SDK-4655) - Improves code reuse by refactoring setting of colours

* task(SDK-4655) - Improves code reuse by refactoring dark mode colors

* task(SDK-4834) - Makes image in notification configurable for scaletype (#808)

* task(SDK-4834) - Makes image in notification configurable for scaletype

* task(SDK-4834) - Improves code reuse by refactoring dark mode colors

* task(SDK-4834) - Minor PR comments
@Anush-Shand Anush-Shand merged commit 514c91f into task/SDK-1556/replace_multi_layouts_with_dimens May 27, 2025
1 of 4 checks passed
@Anush-Shand Anush-Shand deleted the task/SDK-4048/ctas_pt branch May 27, 2025 11:14
Anush-Shand added a commit that referenced this pull request Jun 5, 2025
* task(SDK-1556) - Deletes all v19 layouts since minSDKVersion is 21

* task(SDK-1556) - Deletes files in v22 and v23 that are same as v21

* task(SDK-1556) - Deletes files in v22 that are same as v21

* task(SDK-1556) - Deletes files in v31 that are same as default folder

* task(SDK-1556) - Fixes manual_carousel in default folder and deletes redundant file in v31

* task(SDK-4057) - Makes v21 layouts as the default layouts
Also removes redundant attributes like marginLeft which were needed for v17

* task(SDK-4057) - Replaces redundant layout files with different dimensions

* task(SDK-4057) - Replaces for five cta, redundant layout files with different dimensions

* task(SDK-4057) - Introduces pt_render_terminal to render the final notification

- Some refactoring
- Introduces key

* task(SDK-4536) - Fixes negative value for timer template

- Changes support for timer template to Android O and above
- Updates docs

* task(SDK-4465) - Adds prefix pt_ to res files of push-templates to avoid conflicts

- Also removes redundant attributes

* task(SDK-4465)

- Changes marginLeft to marginStart
- Changes marginRight to marginEnd

* Task/sdk 4595/replicate standard and basic (#788)

* task(SDK-4595) - Replicate Standard Android Notification with Basic Push Template

- Changes in dimens
- Removes redundant styles.xml for sw-400

* task(SDK-4595) - Fixes color

* task(SDK-1556) - Makes timer margin and padding same as other templates

* fix(SDK-1556) - fixes zero bezel on API 31 and above

* Task/sdk 4048/ctas pt (#786)

* POC for FG service based timer notif

* task(SDK-4048) - Adds CTAs in the remote view for push templates below API level 31

* task(SDK-4048) - Reverts rating view changes

* Rename .java to .kt

* task(SDK-4048) - Adds action buttons to remote view

- For API 31 and above StyleWithActionButtons is responsible
- For API 30 and below ActionButtonsContentView is responsible

* task(SDK-4048) - Resolves comments

- Makes classes internal
- Removes redundant colour attribute
- Adds pt_ prefix

* task(SDK-4048) - Resolves comments

- Removes return@forEach

* task(SDK-4048) - Resolves comments

- Adds extension function to increase readability

* task(SDK-4048) - Resolves comments

- Removes public access modifier

* task(SDK-4048) - Testing

- Adds UTs for TemplateRenderer

* task(SDK-4537) - Removes extra space from manual_carousel.xml (#794)

- Removes padding from shape and adds margin

* task(SDK-4048) - Removes dependency from core-sdk

* task(SDK-4040) - Adds CTA for manual carousel

* task(SDK-4040) - Adds CTA for auto carousel

* task(SDK-4048) - Compresses forward and backward arrows for manual carousel

* task(SDK-4048) - Separates PendingIntent from ActionButton.kt

* task(SDK-4048) - Uses composition instead of inheritance for action buttons

* task(SDK-4048) - Fixes image in rating template

* task(SDK-4048) - Fixes string resource name

* task(SDK-4048) - Fixes rating template padding

* task(SDK-4048) - Minor PR comments

* task(SDK-4655) - Dark mode for push templates (#795)

* task(SDK-4655) - Dark mode for push templates

- Adds dark mode support for push templates
- Removes bg as mandatory key
- Parses colour based on dark mode of phone

* task(SDK-4655) - Addresses few todos

* task(SDK-4655) - Makes product display action colour optional

* task(SDK-4655) - Addresses todos

* task(SDK-4655) -Fixes typo and deletes redundant files

* task(SDK-4655) - Color for CTA in clicked state

* task(SDK-4655) - Fixes default colour for title

* task(SDK-4655) - Fixes default colour for small icon

* task(SDK-4655) - Adds color for rating confirm button for light and dark mode

* task(SDK-4655) - Fixes default colour for product template buttons

* task(SDK-4655) - Extracts dimens

* task(SDK-4655) - Improves code reuse by refactoring setting of colours

* task(SDK-4655) - Improves code reuse by refactoring dark mode colors

* task(SDK-4834) - Makes image in notification configurable for scaletype (#808)

* task(SDK-4834) - Makes image in notification configurable for scaletype

* task(SDK-4834) - Improves code reuse by refactoring dark mode colors

* task(SDK-4834) - Minor PR comments

* task(SDK-1556) - Fixes tests

* Tests/sdk 1556/pt unit tests (#811)

* task(SDK-1556) - Adds test for getFlipInterval

* task(SDK-1556) - Adds test for getColour

* task(SDK-1556) - Adds test for createColourMap

* task(SDK-1556) - Adds test for getFallback, getTimerEnd, getApplicationName, getTimeStamp, loadImageRidIntoRemoteView

* task(SDK-1556) - Adds test for getImageListFromExtras, getCTAListFromExtras, getDeepLinkListFromExtras, getBigTextFromExtras, getSmallTextFromExtras, getPriceFromExtras

* task(SDK-1556) - Adds test for convertRatingBundleObjectToHashMap, getEventNameFromExtras

* task(SDK-1556) - Adds test for getEventPropertiesFromExtras

* task(SDK-1556) - Adds test

* task(SDK-1556) - Adds test for raiseNotificationClicked, getActionKeys

* task(SDK-1556) - Adds test for raiseNotificationClicked

* task(SDK-1556) - Adds test for deleteImageFromStorage

* task(SDK-1556) - Adds test for isNotificationChannelEnabled

* task(SDK-1556) - Adds test

* task(SDK-1556) - Adds test for getTimerThreshold

* task(SDK-1556) - Adds test for fromJson

* task(SDK-1556) - Adds test for loadImageUrLIntoRemoteView

* tests(SDK-1556) - Improves timer template test

* tests(SDK-1556) - Improves timer template test

* task(SDK-1556) - Improves tests and Utils function

* task(SDK-1556) - Moves mockkStatic inside a code-block

* task(SDK-1556) - Minor improvements around dot sep (#815)

* task(SDK-1556) - Minor improvements around dot sep

* task(SDK-1556) - Minor colour improvement

* task(SDK-1556) - Minor improvements around message summary for timer template

* task(SDK-1556) - Coderabbit pr comments

* task(SDK-1556) - Fixes flaky test

* docs(SDK-1556) - CHANGELOG and version upgrade for PT (#814)

* docs(SDK-1556) - CHANGELOG and version upgrade for PT

* task(SDK-1556) - Improves docs and updates dates

* task(SDK-1556) - copyTemplates

* docs(SDK-1556) - Improves changelog
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ptv2.0.0 Push Template Release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants