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

Communication: Fix scrolling error for long messages #9997

Merged

Conversation

PaRangger
Copy link
Contributor

@PaRangger PaRangger commented Dec 11, 2024

Checklist

General

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the client coding and design guidelines.

Motivation and Context

Currently, when a message is displayed on-screen that is bigger than the entire message area, multiple errors will get thrown and reported when scrolling. The errors are caused due to a programming error where checking an empty array was assumed to be falsy. The error looks like this:

Bildschirmfoto 2024-12-11 um 10 25 18

Description

I added a check on the length of the array to avoid accessing an out of bounds index. I also added a test case to increase the line coverage.

Steps for Testing

Prerequisites:

  • 1 Stundent/Tutor/Instructor
  • 1 Course with communication enabled
  1. Log in to Artemis
  2. Navigate to course
  3. Go to the communication tab
  4. Create a very long message (you may use the lorem ipsum text i attached at the end)
  5. Open "Inspect Element" and go to the Console in your browser by right-clicking (developer tools must be enabled for Safari)
  6. Scroll around and check if the mentioned error is thrown

Sample Text:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus.

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Performance Review

Code Review

  • Code Review 1

Manual Tests

  • Test 1
  • Test 2

Summary by CodeRabbit

  • Bug Fixes
    • Improved logic for saving scroll position in the conversation messages component to prevent errors when no messages are visible.
  • Tests
    • Added a new test case to verify scrolling behavior and state management in the conversation messages component.

@PaRangger PaRangger added client Pull requests that update TypeScript code. (Added Automatically!) small bugfix labels Dec 11, 2024
@PaRangger PaRangger self-assigned this Dec 11, 2024
@PaRangger PaRangger temporarily deployed to artemis-test5.artemis.cit.tum.de December 11, 2024 09:53 — with GitHub Actions Inactive
@PaRangger PaRangger added ready for review communication Pull requests that affect the corresponding module and removed lock:artemis-test5 labels Dec 11, 2024
@PaRangger PaRangger marked this pull request as ready for review December 11, 2024 10:03
@PaRangger PaRangger requested a review from a team as a code owner December 11, 2024 10:03
Copy link

coderabbitai bot commented Dec 11, 2024

Walkthrough

The changes in this pull request involve a modification to the findElementsAtScrollPosition method within the ConversationMessagesComponent class. The update enhances the condition for saving the scroll position by adding a check to ensure that there are visible messages before saving. This prevents potential errors when no messages are present. Additionally, a new test case has been added to verify the behavior of the component when the last scroll position is falsy. There are no changes to the declarations of exported or public entities.

Changes

File Change Summary
src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts Updated the findElementsAtScrollPosition method to include a check for this.elementsAtScrollPosition.length > 0 before saving the scroll position.
src/test/javascript/spec/component/overview/course-conversations/layout/conversation-messages/conversation-messages.component.spec.ts Added a test case to verify that goToLastSelectedElement correctly invokes scrollToBottomOfMessages and sets canStartSaving to true when the last scroll position is falsy.

Possibly related PRs

Suggested labels

tests, component:Communication, ready for review

Suggested reviewers

  • krusche
  • FelberMartin
  • HawKhiem
  • SimonEntholzer

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:

  • 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. (Experiment)
  • @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 or @coderabbitai title anywhere in the PR title to generate the title automatically.

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

🧹 Outside diff range and nitpick comments (2)
src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts (2)

444-444: LGTM! Consider refactoring for better readability.

The fix correctly addresses the scrolling error by checking array length. However, the code could be more readable with an early return pattern.

Consider this refactoring to improve readability:

-        if (this.elementsAtScrollPosition && this.elementsAtScrollPosition.length > 0 && this.canStartSaving) {
-            this.saveScrollPosition(this.elementsAtScrollPosition[0].post.id!);
-        }
+        if (!this.elementsAtScrollPosition?.length || !this.canStartSaving) {
+            return;
+        }
+        this.saveScrollPosition(this.elementsAtScrollPosition[0].post.id!);

Line range hint 429-446: Consider architectural improvements for better maintainability.

The method currently handles both finding visible messages and saving scroll position. Consider these improvements:

  1. Split into separate methods for better separation of concerns
  2. Add type safety for post.id
  3. Make array type explicit

Here's a suggested refactoring:

private findVisibleMessages(): PostingThreadComponent[] {
    const containerRect = this.content.nativeElement.getBoundingClientRect();
    const visibleMessages: PostingThreadComponent[] = [];
    
    for (const message of this.messages.toArray()) {
        if (!message.elementRef?.nativeElement || !message.post?.id) {
            continue;
        }
        
        const rect = message.elementRef.nativeElement.getBoundingClientRect();
        if (rect.top >= containerRect.top && rect.bottom <= containerRect.bottom) {
            visibleMessages.push(message);
            break;
        }
    }
    
    return visibleMessages;
}

private updateScrollPosition(): void {
    this.elementsAtScrollPosition = this.findVisibleMessages();
    
    if (!this.elementsAtScrollPosition?.length || !this.canStartSaving) {
        return;
    }
    
    const firstVisibleMessage = this.elementsAtScrollPosition[0];
    if (firstVisibleMessage.post?.id) {
        this.saveScrollPosition(firstVisibleMessage.post.id);
    }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between da468e2 and e356639.

📒 Files selected for processing (1)
  • src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts (1)

Pattern src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

🔇 Additional comments (1)
src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts (1)

Line range hint 171-171: Verify scroll event handling and cleanup.

The scroll event listener is added in ngAfterViewInit but the cleanup could be improved to prevent memory leaks.

Let's verify the scroll event handling implementation:

✅ Verification successful

Based on the results, I can now generate the final response:

Scroll event handling is properly cleaned up in ngOnDestroy.

The code shows that:

  • The scroll event listener is added in ngAfterViewInit using addEventListener
  • The cleanup is properly handled in ngOnDestroy using removeEventListener
  • The component also properly cleans up other subscriptions via ngUnsubscribe and scrollSubject
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for proper scroll event handling and cleanup in Angular components

# Look for scroll event listeners and their cleanup
rg -A 5 "addEventListener.*scroll" 

# Check for other scroll position saving implementations
ast-grep --pattern 'saveScrollPosition($$$)'

# Look for potential memory leaks in event listeners
rg -A 10 "addEventListener" | rg -B 10 "removeEventListener"

Length of output: 101512

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 11, 2024
@github-actions github-actions bot added tests and removed communication Pull requests that affect the corresponding module labels Dec 11, 2024
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

🧹 Outside diff range and nitpick comments (1)
src/test/javascript/spec/component/overview/course-conversations/layout/conversation-messages/conversation-messages.component.spec.ts (1)

288-295: LGTM! Consider adding test isolation.

The test case effectively verifies the scrolling behavior with falsy scroll position, using proper assertions as per guidelines.

Consider adding test isolation by resetting the component state in a beforeEach block:

 beforeEach(() => {
     // ... existing setup ...
+    component.canStartSaving = false;  // Reset to known state
 });
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e356639 and 90e9ee3.

📒 Files selected for processing (1)
  • src/test/javascript/spec/component/overview/course-conversations/layout/conversation-messages/conversation-messages.component.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/test/javascript/spec/component/overview/course-conversations/layout/conversation-messages/conversation-messages.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Tested on TS3. The mentioned error or similar errors are not thrown as expected

image

Copy link
Contributor

@cremertim cremertim left a comment

Choose a reason for hiding this comment

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

Code lgtm

Copy link
Contributor

@eceeeren eceeeren left a comment

Choose a reason for hiding this comment

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

Tested on TS6, LGTM

Copy link

@ahbitaqu ahbitaqu left a comment

Choose a reason for hiding this comment

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

[Tested on TS3]
No error is thrown while scrolling anymore, works as inteded

@krusche krusche added this to the 7.8.0 milestone Dec 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix client Pull requests that update TypeScript code. (Added Automatically!) ready to merge small tests
Projects
Status: Merged
Status: Done
Development

Successfully merging this pull request may close these issues.

7 participants