Skip to content

Conversation

@Jignesh-dimagi
Copy link
Contributor

@Jignesh-dimagi Jignesh-dimagi commented Mar 5, 2025

Product Description

For Outgoing message: read/unread icon + message body
For incoming message: message body

When last message was outgoing:
image

When last message was incoming:
image

Technical Summary

https://dimagi.atlassian.net/browse/CCCT-711

Feature Flag

This is kind of feature where display of message preview changed

Safety Assurance

Safety story

Limited effect on safety, UI change

QA Plan

Need general review for message preview

@Jignesh-dimagi Jignesh-dimagi self-assigned this Mar 5, 2025
@Jignesh-dimagi Jignesh-dimagi changed the title Preview in message channel changed Preview of message in messages channel changed Mar 5, 2025
@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2025

📝 Walkthrough

Walkthrough

This pull request modifies how message previews are handled within the messaging channel components. In the ConnectMessagingChannelRecord class, the preview field’s data type is changed from a String to a SpannableString along with corresponding adjustments to its getter and setter methods, enabling richer text formatting. Similarly, in the ConnectDatabaseHelper class, the logic for constructing message previews is updated to create and manipulate SpannableString objects. This allows dynamic inclusion of drawables (icons) in the preview based on conditions like message direction and status. Additionally, a new utility method convertDpToPixel(float dp) is added to the StringUtils class to assist in translating density-independent pixel values to actual pixel values, supporting the formatted text display enhancements. These changes collectively improve the visual representation and flexibility of preview text formatting in messaging channels.

Sequence Diagram(s)

sequenceDiagram
    participant DBHelper as ConnectDatabaseHelper
    participant ChannelRecord as ConnectMessagingChannelRecord
    participant StringUtil as StringUtils

    %% Preview construction flow in ConnectDatabaseHelper
    DBHelper->>ChannelRecord: Initialize preview
    alt Unconsented Channel
        ChannelRecord-->>DBHelper: Returns SpannableString from resource
    else Channel with messages
        DBHelper->>DBHelper: Check last message properties
        alt Outgoing and confirmed message
            DBHelper->>StringUtil: convertDpToPixel(dp)
            DBHelper->>ChannelRecord: Construct SpannableString with drawable icon
        else
            DBHelper->>ChannelRecord: Construct simple SpannableString preview
        end
    end
Loading

Possibly related PRs

Suggested labels

cross requested

Suggested reviewers

  • shubham1g5
  • pm-dimagi
✨ Finishing Touches
  • 📝 Generate Docstrings

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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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

Copy link

@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

🧹 Nitpick comments (2)
app/src/org/commcare/utils/StringUtils.java (1)

55-59: Good implementation of the DP to pixel conversion utility.

This is a standard and correct implementation for converting density-independent pixels to raw pixels in Android. The method properly retrieves system display metrics and applies the standard formula, including rounding to ensure integer pixel values.

However, consider adding a brief documentation comment explaining the purpose of this method and how it handles device density.

+    /**
+     * Converts a value in density-independent pixels (dp) to pixels (px)
+     * based on the device's screen density.
+     * 
+     * @param dp The value in density-independent pixels to convert
+     * @return The equivalent value in pixels
+     */
     public static float convertDpToPixel(float dp){
         DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
         float px = dp * (metrics.densityDpi / 160f);
         return Math.round(px);
     }
app/src/org/commcare/connect/ConnectDatabaseHelper.java (1)

864-883: Enhanced message preview with read/unread indicators for outgoing messages.

The implementation correctly handles different preview scenarios:

  1. For unconsented channels - displays appropriate text
  2. For outgoing messages - adds read/unread icon based on message status
  3. For incoming messages - displays only the message text
  4. For empty channels - creates an empty preview

The code effectively uses SpannableString and ImageSpan to create a richer UI that distinguishes between read and unread outgoing messages, aligning with the PR objectives.

A few suggestions for improvement:

  1. Extract the magic number 14dp (line height) to a constant for better maintainability:
+    private static final float MESSAGE_ICON_SIZE_DP = 14f;
     
     // Then in the method:
-    float lineHeight = convertDpToPixel(14);
+    float lineHeight = convertDpToPixel(MESSAGE_ICON_SIZE_DP);
  1. Consider handling potential edge cases like very long messages more gracefully, perhaps by respecting word boundaries when trimming.
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 15334bf and c32b3d7.

📒 Files selected for processing (3)
  • app/src/org/commcare/android/database/connect/models/ConnectMessagingChannelRecord.java (3 hunks)
  • app/src/org/commcare/connect/ConnectDatabaseHelper.java (2 hunks)
  • app/src/org/commcare/utils/StringUtils.java (2 hunks)
🔇 Additional comments (6)
app/src/org/commcare/utils/StringUtils.java (1)

4-6: LGTM: Imports added to support the new utility method.

The imports for Resources and DisplayMetrics are appropriately added to support the new conversion utility method.

app/src/org/commcare/connect/ConnectDatabaseHelper.java (2)

3-11: New imports added correctly to support the modified preview functionality.

The imports have been properly organized and include all necessary dependencies for handling spannable text and drawables within the message preview.


874-880: Well-implemented drawable integration for message status indicators.

The code correctly sets up the drawable based on the message confirmation status and applies appropriate sizing and positioning. The use of the newly created convertDpToPixel method ensures consistent visual appearance across different device densities.

app/src/org/commcare/android/database/connect/models/ConnectMessagingChannelRecord.java (3)

3-4: Added required import for SpannableString type.

The SpannableString import is correctly added to support the field type change.


67-67: Field type changed from String to SpannableString to support rich text previews.

This change is essential to support the new preview rendering approach with read/unread icons.


158-164:

Details

✅ Verification successful

Updated getter and setter methods to use SpannableString type.

The getter and setter methods have been properly updated to match the new field type. This change ensures type consistency throughout the codebase when working with message previews.

Run the following script to verify that all uses of this getter method are compatible with the new return type:


🏁 Script executed:

#!/bin/bash
# Search for uses of the getPreview method to ensure they can handle SpannableString
rg -A 3 "getPreview\(\)" --type java

Length of output: 876


Verification Successful: SpannableString Update Approved

  • The updated getter and setter in app/src/org/commcare/android/database/connect/models/ConnectMessagingChannelRecord.java correctly use the SpannableString type.
  • The usage in app/src/org/commcare/adapters/ChannelAdapter.java (i.e., binding.tvChannelDescription.setText(channel.getPreview());) is compatible since SpannableString implements CharSequence.

No further changes are needed.

Comment on lines 874 to 883
preview = new SpannableString(lastMessage.getIsOutgoing()? " "+trimmed:trimmed);
if(lastMessage.getIsOutgoing()){
Drawable drawable = lastMessage.getConfirmed() ? ContextCompat.getDrawable(context, R.drawable.ic_connect_message_read) : ContextCompat.getDrawable(context, R.drawable.ic_connect_message_unread);
float lineHeight = convertDpToPixel(14);
drawable.setBounds(0,0,(int) lineHeight, (int) lineHeight);
preview.setSpan(new ImageSpan(drawable), 0, 1, SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
preview = new SpannableString("");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

can we make sure to format the code here as per our style file.

return MarkupUtil.styleSpannable(c, ret);
}

public static float convertDpToPixel(float dp){
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe better to create a separate Util class , something like -

public class DimensionUtils {
   // I am a little worried about performance here if we end up calling this too many times in a loop or something and therefore might be best retained as a static variable
    private static final float density = Resources.getSystem().getDisplayMetrics(). densityDpi; 

    public static int convertDpToPixel(float dp) { }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I was thinking of creating new but I can see lots of Util files so thought to keep in StringUtils but anyways created new DimensionUtils file

@OrangeAndGreen OrangeAndGreen merged commit 60a2199 into connect_qa Mar 7, 2025
1 of 2 checks passed
@OrangeAndGreen OrangeAndGreen deleted the jignesh/fix/ccct-711 branch March 7, 2025 18:31
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.

4 participants