Skip to content
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

Update seen by id field in message threads #156

Merged
merged 4 commits into from
Jan 7, 2025

Conversation

kaushiksaliya
Copy link
Collaborator

@kaushiksaliya kaushiksaliya commented Jan 7, 2025

Changelog

  • Update seen by id field in message threads.
  • Removed seen_by field from chat message.

Sender device:

message.test.webm

Receiver device:

Record_2025-01-07-16-48-47.mp4

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced message tracking with thread-level seen status
    • Added last message preview and timestamp to threads
  • Improvements

    • Simplified message seen status management
    • Improved message bubble color and visibility logic
    • Optimized message marking and tracking mechanisms
  • Bug Fixes

    • Resolved inconsistencies in message read/unread status tracking

The update focuses on refining the messaging experience with more efficient status tracking and improved visual indicators.

Copy link

coderabbitai bot commented Jan 7, 2025

Walkthrough

This pull request introduces modifications to the messaging system's architecture, focusing on how message visibility and thread status are managed. Key changes include adding a new parameter state.thread to the MessageList function, updating the markMessagesAsSeen method to remove its parameter, and enhancing the ApiThread data class with new properties for tracking the last message and seen status. The changes streamline the handling of message visibility, shifting the focus from individual messages to thread-level management.

Changes

File Change Summary
app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesScreen.kt Added state.thread parameter to MessageList function call
app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesViewModel.kt Simplified markMessagesAsSeen() method by removing its parameter
Updated logic in listenMessages, loadMore, and sendNewMessage functions to reflect the new method signature
app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/components/MessagesList.kt Added thread: ApiThread? parameter to MessageList
Updated logic for seenBy list and message text color calculation based on sender
app/src/main/java/com/canopas/yourspace/ui/flow/messages/thread/ThreadsScreen.kt Modified unread message detection logic to use thread's seen_by_ids
data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt Added last_message, last_message_at, and seen_by_ids properties
Removed seen_by from ApiThreadMessage
data/src/main/java/com/canopas/yourspace/data/repository/MessagesRepository.kt Simplified markMessagesAsSeen() method signature by removing the messageIds parameter
data/src/main/java/com/canopas/yourspace/data/service/messages/ApiMessagesService.kt Updated sendMessage and generateMessage methods to remove seen_by field
Refactored markMessagesAsSeen to update a single field seen_by_ids

Sequence Diagram

sequenceDiagram
    participant User
    participant MessagesViewModel
    participant MessagesRepository
    participant ApiMessagesService
    participant Thread

    User->>MessagesViewModel: Send/View Messages
    MessagesViewModel->>Thread: Check seen_by_ids
    MessagesViewModel->>MessagesRepository: Mark Messages Seen
    MessagesRepository->>ApiMessagesService: Update Thread Seen Status
    ApiMessagesService->>Thread: Update seen_by_ids
Loading

Possibly related PRs

Suggested reviewers

  • cp-megh-l

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1da9bec and def5a1d.

📒 Files selected for processing (2)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesViewModel.kt (3 hunks)
  • data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (3)
app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesViewModel.kt (3)

19-19: LGTM!

The addition of the delay import is appropriate for the new implementation.


90-90: LGTM!

The update to the markMessagesAsSeen call correctly aligns with the new implementation.


96-106: Consider potential race conditions and configuration improvements.

The current implementation has two areas for improvement:

  1. Race condition risk: The thread state could become stale between the check and the update.
  2. Hard-coded delay: Consider making the 2-second delay configurable for easier testing and adjustment.
+ private companion object {
+     private const val MARK_AS_SEEN_DELAY_MS = 2000L
+ }

- private fun markMessagesAsSeen() =
+ private fun markMessagesAsSeen() {
+     val userId = state.value.currentUserId
+     val threadId = state.value.thread?.id ?: return
      viewModelScope.launch(appDispatcher.IO) {
-         delay(2000)
+         delay(MARK_AS_SEEN_DELAY_MS)
          try {
-             val thread = state.value.thread ?: return@launch
-             val userId = state.value.currentUserId
-             if (thread.seen_by_ids.contains(userId)) {
-                 return@launch
-             }
              messagesRepository.markMessagesAsSeen(threadId, userId)
          } catch (e: Exception) {
              Timber.e(e, "Error marking messages as seen")
          }
      }
+ }

Run this script to verify the race condition concerns:


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • 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. (Beta)
  • @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 or 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: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9861bdb and d9afcdc.

📒 Files selected for processing (8)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesScreen.kt (1 hunks)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesViewModel.kt (3 hunks)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/components/MessagesList.kt (5 hunks)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/thread/ThreadsScreen.kt (1 hunks)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/thread/ThreadsViewModel.kt (1 hunks)
  • data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt (1 hunks)
  • data/src/main/java/com/canopas/yourspace/data/repository/MessagesRepository.kt (1 hunks)
  • data/src/main/java/com/canopas/yourspace/data/service/messages/ApiMessagesService.kt (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/thread/ThreadsViewModel.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (10)
data/src/main/java/com/canopas/yourspace/data/repository/MessagesRepository.kt (2)

61-62: LGTM! Clean implementation of thread-level message tracking.

The simplified function signature and implementation aligns well with the architectural change from per-message to thread-level seen status tracking. This change reduces complexity and improves efficiency by updating a single document instead of performing batch updates.


61-62: Verify data migration strategy for existing messages.

Since this is a breaking change that moves from per-message seen_by to thread-level seen_by_ids, please ensure there's a migration strategy in place for existing messages.

Let's verify the migration approach:

data/src/main/java/com/canopas/yourspace/data/service/messages/ApiMessagesService.kt (3)

Line range hint 93-100: 'sendMessage' method updated correctly to remove seen_by field

The sendMessage method has been updated to construct ApiThreadMessage without the seen_by field, which aligns with the new approach of tracking message visibility at the thread level using seen_by_ids in the thread document.


Line range hint 105-111: generateMessage method modification is consistent with the new data model

The generateMessage method now creates ApiThreadMessage instances without the seen_by field. This change is consistent with the updated data model where the seen status is managed at the thread level.


116-117: Ensure thread-level seen_by_ids updates handle concurrency appropriately

The markMessagesAsSeen method now updates the seen_by_ids field in the thread document to track which users have seen the messages. It's important to ensure that concurrent updates from multiple users do not cause data inconsistencies or overwrite issues.

Please run the following script to verify that seen_by_ids is consistently used across the codebase and that there are no remaining references to the old seen_by field:

✅ Verification successful

Thread-level seen_by_ids updates are properly implemented with atomic operations

The implementation uses Firestore's atomic arrayUnion operation which safely handles concurrent updates without data inconsistencies. The field is consistently used across the codebase with no remaining references to the old seen_by field.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all references to 'seen_by' have been updated to 'seen_by_ids' and check for proper usage.

# Expectation: No occurrences of 'seen_by' except in field definitions or comments explaining the change.

# Search for any remaining references to 'seen_by' outside of model definitions.
rg 'seen_by' --type kotlin

# Confirm that 'seen_by_ids' is used in the appropriate places.
rg 'seen_by_ids' --type kotlin

Length of output: 2153

data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt (1)

17-17: LGTM! Consider data migration impact.

The consolidation of message visibility tracking at thread level is a good architectural decision that reduces data duplication.

Please ensure there's a migration plan to handle existing data. Run this script to check for any direct usage of the removed seen_by field:

✅ Verification successful

No migration concerns found

The change only affects the API model and the UI is already aligned with the new structure. No local database migrations are needed as the project appears to use remote storage only.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of the removed seen_by field
# Test: Search for seen_by references that might need updating
rg "seen_by\W" --type kotlin

Length of output: 172


Script:

#!/bin/bash
# Check data layer for seen_by field usage
echo "=== Checking Room DAOs ==="
rg "seen_by\W" --type kotlin -g "*Dao.kt"

echo -e "\n=== Checking data mappers ==="
rg "seen_by\W" --type kotlin -g "*Mapper.kt"

echo -e "\n=== Checking database migrations ==="
fd "Migration" --type f --exec rg "seen_by\W" {} \;

echo -e "\n=== Checking database schemas ==="
fd "schema" --type f --extension json --exec cat {} \;

Length of output: 811


Script:

#!/bin/bash
# Find database and persistence related files
echo "=== Checking for database related files ==="
fd "\.kt$" --type f --exec rg -l "import.*\b(Room|SQLite|Database)\b" {} \;

echo -e "\n=== Checking for thread/message persistence ==="
rg -l "Thread|Message" --type kotlin -g "*Repository.kt"

echo -e "\n=== Looking for data storage implementations ==="
fd "storage|database|dao|repository" --type f --extension kt

Length of output: 914

app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesScreen.kt (1)

146-146: LGTM! Clean integration of thread parameter.

The addition of the thread parameter to MessageList is a necessary change to support the new visibility tracking mechanism.

app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/components/MessagesList.kt (2)

103-107: LGTM! Robust null safety handling.

The seenBy calculation properly handles the null case for thread and correctly filters the members list.


240-244: Improved message text color contrast.

The message text color now properly adapts based on the sender status, improving readability.

app/src/main/java/com/canopas/yourspace/ui/flow/messages/thread/ThreadsScreen.kt (1)

386-386: LGTM! Improved architecture for tracking message visibility.

The change from message-level seen_by to thread-level seen_by_ids is a good architectural improvement that reduces data duplication.

Please verify that existing threads have been properly migrated to include seen_by_ids. Run this script to check for any threads without the field:

✅ Verification successful

Implementation verified - Properly handles message visibility tracking

The seen_by_ids field is properly implemented with:

  • Default initialization in the data model
  • Correct updates in cloud functions
  • Proper handling in the UI
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for threads that might be missing seen_by_ids field
# Note: Adjust the pattern based on your data storage implementation

# Search for thread definitions or database schemas
rg -l "seen_by_ids" 

# Search for migration files
fd -e kt -e java -e xml "migration|schema" 

Length of output: 496


Script:

#!/bin/bash
# Check the data model implementation
echo "=== ApiThread.kt ==="
cat data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt

echo -e "\n=== Cloud Functions ==="
cat functions/index.js

Length of output: 19378

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: 1

♻️ Duplicate comments (3)
app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesViewModel.kt (3)

95-104: ⚠️ Potential issue

Race condition still needs to be addressed.

While the early return optimization is good, the race condition concern from previous reviews still exists. Consider using a transaction to handle concurrent updates to seen_by_ids.

Suggested implementation using transaction:

 private fun markMessagesAsSeen() =
     viewModelScope.launch(appDispatcher.IO) {
         try {
             val thread = state.value.thread ?: return@launch
             val userId = state.value.currentUserId
             if (thread.seen_by_ids.contains(userId)) {
                 return@launch
             }

-            messagesRepository.markMessagesAsSeen(threadId, userId)
+            messagesRepository.runTransaction { transaction ->
+                val threadRef = messagesRepository.getThreadRef(threadId)
+                val currentThread = transaction.get(threadRef).toObject(ApiThread::class.java)
+                    ?: return@runTransaction
+                
+                if (!currentThread.seen_by_ids.contains(userId)) {
+                    transaction.update(threadRef, "seen_by_ids", 
+                        currentThread.seen_by_ids + userId)
+                }
+            }
         } catch (e: Exception) {
             Timber.e(e, "Error marking messages as seen")
         }
     }

310-312: ⚠️ Potential issue

Remove unnecessary seen status reset.

Clearing seen_by_ids before sending a message is incorrect as it causes loss of existing seen status. The Firebase backend already handles seen status initialization for new messages.

Apply this diff:

-            val thread = state.value.thread?.copy(seen_by_ids = emptyList())
+            val thread = state.value.thread
             _state.emit(_state.value.copy(newMessagesToAppend = newMessages, thread = thread))

178-178: 🛠️ Refactor suggestion

Remove duplicate markMessagesAsSeen call.

The call to markMessagesAsSeen() in fetchThread is unnecessary since listenMessages() already handles marking messages as seen.

Apply this diff:

-                    markMessagesAsSeen()
                     if (messagesJob == null) listenMessages()
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d9afcdc and 1da9bec.

📒 Files selected for processing (2)
  • app/src/main/java/com/canopas/yourspace/ui/flow/messages/chat/MessagesViewModel.kt (3 hunks)
  • data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Android Build
data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt

[error] 16-16: Missing spacing after ':' at column 22


[error] 21-21: Unnecessary trailing comma before ')' at column 38

🔇 Additional comments (2)
data/src/main/java/com/canopas/yourspace/data/models/messages/ApiThread.kt (2)

16-21: LGTM! Thread-level message tracking implementation looks good.

The new properties support tracking message status at thread level:

  • last_message stores the latest message content
  • seen_by_ids tracks who has seen the thread
  • last_message_at tracks the timestamp of the last message
🧰 Tools
🪛 GitHub Actions: Android Build

[error] 16-16: Missing spacing after ':' at column 22


[error] 21-21: Unnecessary trailing comma before ')' at column 38


Line range hint 29-36: LGTM! Removal of message-level seen tracking.

The removal of seen_by from ApiThreadMessage aligns with the architectural change to track message visibility at thread level instead of individual messages.

🧰 Tools
🪛 GitHub Actions: Android Build

[error] 16-16: Missing spacing after ':' at column 22


[error] 21-21: Unnecessary trailing comma before ')' at column 38

@kaushiksaliya kaushiksaliya merged commit cd11194 into main Jan 7, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants