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

Assistant: Fix scroll glitch on initial render #804

Merged
merged 3 commits into from
Jan 15, 2025

Conversation

fredrikekelund
Copy link
Contributor

Related issues

Proposed Changes

As described in https://github.com/Automattic/dotcom-forge/issues/9281, there are currently some glitches in how the viewport scrolls when the Assistant tab is opened. This PR fixes those by changing endOfMessagesRef into a ref on the topmost wrapper in the Assistant tab and by computing whether AIClearHistoryReminder should be displayed instantly instead of doing it in a useEffect callback.

Testing Instructions

  1. Have two or more Studio sites
  2. Have an Assistant conversation where the last message is older than 2 hours
  3. Switch back and forth between the Assistant and Settings tabs and ensure that the viewport scroll starts at the very bottom every time the Assistant tab is opened
  4. Switch between two sites and ensure that the scroll behaves well in this scenario, too

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@fredrikekelund fredrikekelund requested a review from a team January 14, 2025 15:30
@fredrikekelund fredrikekelund self-assigned this Jan 14, 2025
Comment on lines -22 to 39
if ( ! lastMessage || lastMessage.role === 'user' ) {
clearTimeout( timeoutId.current );
setShowReminder( false );
return;
}

if ( lastMessage.id === currentMessage.current ) {
return;
}
let timeoutId: NodeJS.Timeout;
const nextValue = shouldShowReminder( lastMessage );
setShowReminder( nextValue );

const messageTime = Date.now() - lastMessage?.createdAt;
const timeToRemind = CLEAR_HISTORY_REMINDER_TIME - messageTime;
if ( timeToRemind > 0 ) {
clearTimeout( timeoutId.current );
setShowReminder( false );
timeoutId.current = setTimeout( () => {
if ( nextValue && lastMessage ) {
timeoutId = setTimeout( () => {
setShowReminder( true );
}, timeToRemind );
} else {
setShowReminder( true );
}, Date.now() - lastMessage.createdAt );
}

return () => {
clearTimeout( timeoutId.current );
clearTimeout( timeoutId );
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's no need to store timeoutId outside the hook callback, so a big part of this change is just simplifying the existing logic and moving timeoutId inside this closure.

@wojtekn
Copy link
Contributor

wojtekn commented Jan 15, 2025

@fredrikekelund Assistant still lives its own life and scrolls up and down when I switch tabs. Is it caused by double rendering in dev mode? Should we test PRs related to the scrolling using proper build instead of running the app on local?

@fredrikekelund
Copy link
Contributor Author

fredrikekelund commented Jan 15, 2025

@wojtekn, oh yeah, StrictMode could definitely be messing things up. Try applying the following diff and see if that fixes the problem:

diff --git a/src/renderer.ts b/src/renderer.ts
index c496ade..32a275c 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -128,6 +128,6 @@ getIpcApi()
                const rootEl = document.getElementById( 'root' );
                if ( rootEl ) {
                        const root = createRoot( rootEl );
-                       root.render( createElement( StrictMode, null, createElement( Root ) ) );
+                       root.render( createElement( Root ) );
                }
        } );

@wojtekn
Copy link
Contributor

wojtekn commented Jan 15, 2025

@fredrikekelund applying the patch improves it, so it doesn't scroll to the top of the message. However, the glitch is still there:

ai-scroll.mp4

@fredrikekelund
Copy link
Contributor Author

fredrikekelund commented Jan 15, 2025

applying the patch improves it

Great 👍

However, the glitch is still there

The movement that happens when you open the Assistant tab in your screencast is actually an animation—not the viewport scrolling 🙂

@wojtekn
Copy link
Contributor

wojtekn commented Jan 15, 2025

The movement that happens when you open the Assistant tab in your screencast is actually an animation—not the viewport scrolling 🙂

Not sure. The scrollbar appears, and the content moves until the view becomes static. 🤔

@fredrikekelund
Copy link
Contributor Author

I applied the following diff to confirm my theory. You can do the same to check, @wojtekn.

diff --git a/src/components/content-tab-assistant.tsx b/src/components/content-tab-assistant.tsx
index 74da799..d5cec49 100644
--- a/src/components/content-tab-assistant.tsx
+++ b/src/components/content-tab-assistant.tsx
@@ -240,24 +240,11 @@ const AuthenticatedView = memo(
                                                >
                                                        <AnimatePresence mode="wait">
                                                                { showThinking ? (
-                                                                       <motion.div
-                                                                               key="thinking"
-                                                                               initial="initial"
-                                                                               animate="animate"
-                                                                               exit="exit"
-                                                                               variants={ thinkingAnimation }
-                                                                               transition={ { duration: 0.3 } }
-                                                                       >
+                                                                       <div key="thinking">
                                                                                <MessageThinking />
-                                                                       </motion.div>
+                                                                       </div>
                                                                ) : (
-                                                                       <motion.div
-                                                                               key="content"
-                                                                               variants={ messageAnimation }
-                                                                               transition={ { duration: 0.3 } }
-                                                                               initial="initial"
-                                                                               animate="animate"
-                                                                       >
+                                                                       <div key="content">
                                                                                <MarkDownWithCode
                                                                                        message={ message }
                                                                                        siteId={ siteId }
@@ -265,7 +252,7 @@ const AuthenticatedView = memo(
                                                                                        content={ message.content }
                                                                                />
                                                                                { children }
-                                                                       </motion.div>
+                                                                       </div>
                                                                ) }
                                                        </AnimatePresence>
                                                </ChatMessage>

@wojtekn
Copy link
Contributor

wojtekn commented Jan 15, 2025

Thanks for checking it more @fredrikekelund . It looks much better after removing those animations.

It seems we've added them under https://github.com/Automattic/dotcom-forge/issues/7679. Let's remove those if we can't fix them.

While testing that, I noticed small remaining issue and added https://github.com/Automattic/dotcom-forge/issues/10254 for that.

CC @sejas

@fredrikekelund
Copy link
Contributor Author

I created https://github.com/Automattic/dotcom-forge/issues/10256 for removing the animation on the most recent message when the tab is opened. I think it's a nice touch when you're chatting with the Assistant and a new message appears, but I agree it makes less sense on initial render.

@fredrikekelund fredrikekelund merged commit 2f28308 into trunk Jan 15, 2025
6 checks passed
@fredrikekelund fredrikekelund deleted the f26d/fix-assistant-tab-scroll-glitch branch January 15, 2025 13:53
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