-
-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Fix inconsistent auto-scroll behavior in Actions log viewer #34957
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
- Resolves auto-scroll becoming unreliable after manual scrolling - Improves auto-scroll reliability when following logs of running actions - Added comprehensive unit tests covering auto-scroll scenarios Eliminates the need for repeated manual intervention to re-enable auto-scroll when following long-running actions.
Written by AI? I can see duplicate code and the tests are not easy to read.
Can you show a screenshot (picture or video) to elaborate the problem? |
With a lot of help from AI, yep. The tests are not easy to read because the Vue code is very difficult to test (there weren't any for this view previously). We could just continue that trend and I can delete the tests ... I'll see if I can record a quick video - the behavior isn't subtle, though - the auto scroll just basically doesn't work for more than a few log updates, at least from my experience. I've checked Safari and Chrome both, no difference. |
I can understand this part.
I can understand this part, but I think we can simplify the code. Ideally, we only need to check "if the last element's bottom (the last group's bottom) is in the viewport", no need to use recursive traversal to find the "last line".
understand
Do we really need the animation and use "requestAnimationFrame"?
Don't quite understand |
Some more thoughts: can we only maintain a "autoscroll-able" flag and avoid more "if" checks? The brief idea is:
|
I'll see what I can do with your ideas, thanks for the feedback! The "status-aware scrolling" is more of a side-effect fix of the other parts - I was noticing while testing that if an earlier group was expanded and completed, with no subsequent groups expanded, the logic kept scrolling me back to the last line of the previous group when I was trying to get to a subsequent group to expand it. So, that was the simplest approach I could think of - don't scroll to the bottom of a group that's already completed. |
Reviewed the "Root Causes" (again):
We can relax the check (as implemented in this PR, relax about 10%), and check the last item's bottom line. Maybe we can have a separate function and have a simple test for it, then no need these vue mock tricks.
Although I proposed to handle "scroll" event, after I asked GitHub Copilot, it says that it's almost impossible to correctly distinguish the "scroll" events triggered by scrollIntoView or user's input. So maybe we should use |
Your tests pass this simple change (your test line 338 should be I don't understand why AI makes the problem that complex (this change is just a draft demo, still not quite right) diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue
index 2eb2211269..f717e88711 100644
--- a/web_src/js/components/RepoActionView.vue
+++ b/web_src/js/components/RepoActionView.vue
@@ -56,7 +56,7 @@ function parseLineCommand(line: LogLine): LogLineCommand | null {
function isLogElementInViewport(el: Element): boolean {
const rect = el.getBoundingClientRect();
- return rect.top >= 0 && rect.bottom <= window.innerHeight; // only check height but not width
+ return rect.bottom >= 0 && rect.bottom <= window.innerHeight + rect.height / 2; // only check height but not width
}
type LocaleStorageOptions = {
@@ -290,9 +290,13 @@ export default defineComponent({
shouldAutoScroll(stepIndex: number): boolean {
if (!this.optionAlwaysAutoScroll) return false;
+ if (!this.currentJobStepsStates[stepIndex]?.expanded) return false;
+ const step = this.currentJob?.steps?.[stepIndex];
+ if (!step || step.status !== 'running') return false;
+
const el = this.getJobStepLogsContainer(stepIndex);
// if the logs container is empty, then auto-scroll if the step is expanded
- if (!el.lastChild) return this.currentJobStepsStates[stepIndex].expanded;
+ if (!el.lastChild) return this.currentJobStepsStates[stepIndex].expanded && isLogElementInViewport(el);
return isLogElementInViewport(el.lastChild as Element);
}, |
I'll give this a shot and test it - some of the changes in the PR weren't strictly to pass the test but were additional because of odd behavior that I saw (like the mentioned snapping back up to earlier expanded steps) when I was manually testing it. |
I can see many problems in the test code, it doesn't test the real cases. AI Hallucination. |
Can you point out the hallucinations? I went through the tests manually and verified what was being tested. Maybe there's hallucinations in what's being mocked? I just trusted the mock setups, for the most part, as there's very little I can do to determine how accurate they are without a vastly deeper understanding of the frontend. Maybe it's just easier to remove the test? |
At least, the elements are wrong. See this comment: #34957 (comment) , for example, around line 338, why an empty container can have a "last element" with "bounding client rect" ? I think I won't spend more time on AI code. Please understand the code first, feel free to ask questions directly (but don't post AI contents) |
I'm not sure I understand what you're referring to on line 338 of the test - it's necessary to avoid an undefined TypeError - it doesn't need to contain anything for the purpose of the test, it just needs to not be undefined.
I'll close this and take another run at it without any tests. Thanks for your time. |
The problem is: the test code uses an empty container to test the behavior which requires a "last line element". The test itself is not right, then it introduces more hacks to workaround such wrong test case. |
Problem
Auto-scroll in the Actions log viewer becomes unreliable after manual scrolling, requiring repeated manual intervention to re-enable auto-scroll when following long-running actions.
Root Cause
The original auto-scroll logic had several issues:
Solution
requestAnimationFrame
, throttling, andscrollIntoView
withbehavior: 'instant'
Testing
Files Changed
web_src/js/components/RepoActionView.vue
- Enhanced auto-scroll logic and viewport detectionweb_src/js/components/RepoActionView.test.ts
- Added behavioral tests for auto-scroll scenarios