sujitha-saranam commented on code in PR #54447:
URL: https://github.com/apache/airflow/pull/54447#discussion_r2300619240


##########
airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/TaskLogContent.tsx:
##########
@@ -94,16 +90,114 @@ export const TaskLogContent = ({ error, isLoading, 
logError, parsedLogs, wrap }:
     return parsedLogs.length > 1 && contentHeight > containerHeight;
   }, [rowVirtualizer, parsedLogs]);
 
+  // Precise jump to hash index
   useLayoutEffect(() => {
-    if (location.hash && !isLoading) {
-      rowVirtualizer.scrollToIndex(Math.min(Number(hash) + 5, 
parsedLogs.length - 1));
+    if (!location.hash || isLoading || parsedLogs.length === 0) {
+      return;
+    }
+
+    const targetIndex = Math.max(0, Math.min(parsedLogs.length - 1, 
Number(hash) || 0));
+    const el = parentRef.current;
+
+    // Prefer exact offset if we already have the virtual item measured
+    const total = rowVirtualizer.getTotalSize();
+    const clientH = el?.clientHeight ?? 0;
+
+    // If the item is currently virtualized, use its start; otherwise 
approximate
+    const vItem = rowVirtualizer.getVirtualItems().find((virtualRow) => 
virtualRow.index === targetIndex);
+    const approxPerItem = 20; // same as estimateSize
+    const anchor = vItem?.start ?? targetIndex * approxPerItem;
+
+    const offset = Math.max(0, Math.min(total - clientH, anchor));
+
+    if (el) {
+      // Force both virtualizer and DOM to the exact offset to avoid slow 
incremental scrolling
+      if (typeof rowVirtualizer.scrollToOffset === "function") {
+        try {
+          rowVirtualizer.scrollToOffset(offset);
+        } catch {
+          rowVirtualizer.scrollToIndex(targetIndex, { align: "start" });
+        }
+      } else {
+        rowVirtualizer.scrollToIndex(targetIndex, { align: "start" });
+      }
+
+      el.scrollTop = offset;
+
+      // One more frame to settle measurements for large lists
+      requestAnimationFrame(() => {
+        el.scrollTop = offset;
+      });
+    } else {
+      rowVirtualizer.scrollToIndex(targetIndex, { align: "start" });
     }
   }, [isLoading, rowVirtualizer, hash, parsedLogs]);
 
+  // Robust, instant jump-to handler
   const handleScrollTo = (to: "bottom" | "top") => {
-    if (parsedLogs.length > 0) {
-      rowVirtualizer.scrollToIndex(to === "bottom" ? parsedLogs.length - 1 : 
0);
+    if (parsedLogs.length === 0) {
+      return;
+    }
+
+    const el = rowVirtualizer.scrollElement ?? parentRef.current;
+
+    if (!el) {
+      return;
+    }
+
+    if (to === "top") {
+      // Jump instantly to top
+      if (typeof rowVirtualizer.scrollToOffset === "function") {
+        try {
+          rowVirtualizer.scrollToOffset(0);
+        } catch {
+          rowVirtualizer.scrollToIndex(0, { align: "start" });
+        }
+      } else {
+        rowVirtualizer.scrollToIndex(0, { align: "start" });
+      }
+      el.scrollTop = 0;
+      requestAnimationFrame(() => {
+        el.scrollTop = 0;
+      });
+
+      return;
     }
+
+    // === bottom === (instant jump even for huge lists)
+    const total = rowVirtualizer.getTotalSize();
+    const clientH = el.clientHeight || 0;
+    const offset = Math.max(0, Math.floor(total - clientH));
+
+    // First tell the virtualizer where we want to be
+    if (typeof rowVirtualizer.scrollToOffset === "function") {
+      try {
+        rowVirtualizer.scrollToOffset(offset);
+      } catch {
+        rowVirtualizer.scrollToIndex(parsedLogs.length - 1, { align: "end" });
+      }
+    } else {
+      rowVirtualizer.scrollToIndex(parsedLogs.length - 1, { align: "end" });
+    }
+
+    // Then force the DOM to that exact pixel offset
+    el.scrollTop = offset;
+
+    // A couple of RAFs to ensure post-measurement settling for very large 
lists
+    requestAnimationFrame(() => {
+      el.scrollTop = offset;
+      requestAnimationFrame(() => {
+        // final nudge + fallback to last item visibility if needed
+        el.scrollTop = offset;
+        const lastItem = el.querySelector<HTMLElement>(
+          `[data-testid="virtualized-item-${parsedLogs.length - 1}"]`,
+        );
+
+        if (lastItem) {
+          lastItem.scrollIntoView({ behavior: "auto", block: "end" });
+        }
+      });
+    });

Review Comment:
   hi @pierrejeambrun 
   Thank you for the feedback. I’m still new to React, so I’d really appreciate 
any suggestions on a simpler or more idiomatic way to achieve this behavior. I 
tried a few other approaches earlier, but this one gave the best results, so I 
went ahead with it.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to