פס גלילה: המסילה נעלמה בקצה הרשימה כי maxScrollExtent מתאפס - #1177
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: acb6d66e17
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (totalContent > 1.0 + precisionErrorTolerance) { | ||
| _canScroll = true; | ||
| } |
There was a problem hiding this comment.
אל תסיקו יכולת גלילה מממוצע הפריטים שנמדדו
בפתיחה או בקפיצה לסוף רשימה קצרה עם פריטים בגבהים שונים, ייתכן שרק הפריט האחרון והקצר נמדד; למשל, עם שני פריטים כשהאחרון בגובה 0.4 viewport מתקבל totalContent == 0.8, אף שהפריט הראשון שמחוץ למסך מוכיח שיש תוכן לגלול אליו. לאחר ש־maxScrollExtent מאפס את _canScroll, התנאי הזה אינו מחזיר אותו ל־true והמסילה עדיין נעלמת. הטסט החדש מסתיר זאת באמצעות itemCount: 200, שמבטיח שהמכפלה גדולה מ־1; יש לבסס את הנראות גם על minIndex > 0 או maxIndex < itemCount - 1, ולא רק על אומדן הגובה.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
תודה — צדקת, וזה שוחזר בטסט.
itemCount: 2 עם הפריט האחרון בלבד ב-0.4..0.8 נותן totalContent == 0.8, המסילה נעלמה. הוספתי minIndex > 0 || maxIndex < itemCount - 1 כתנאי מקדים: פריט מחוץ לחלון הנראה הוא הוכחה ישירה לגלילות, לא אומדן.
השארתי גם את תנאי totalContent — הוא מכסה את המקרה ההפוך, שבו כל הפריטים מרונדרים אבל התוכן גבוה מה-viewport.
הטסט השלילי הקיים (שני הפריטים גלויים ⇒ אין מסילה) ממשיך לעבור. 37/37.
…zaria#1169) הנראות נגזרה מ-notification.metrics.maxScrollExtent, אך ScrollablePositionedList מרנדר חלון סביב העוגן בלבד: בקצה הרשימה אין תוכן קדימה, המדד מתאפס והמסילה נעלמה אף שיש מאות פריטים. אותו מנגנון הסביר גם את ההיעלמות בחלונית המפרשים (חזרה אחרי בחירת מפרשים נוספים) ואת התלות בגודל המסך. התוכן הנמדד (avgItemHeight * itemCount, ביחידות viewport) הוא סימן יציב: כשהוא עולה על viewport אחד יש מה לגלול, בלי תלות בחלון המרונדר. הסתרה כשכל התוכן נראה נשמרת — שם התוכן קטן מ-viewport. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
אומדן הגובה הממוצע לבדו אינו מספיק: ברשימה קצרה עם פריטים בגבהים שונים ייתכן שרק פריט אחד וקצר נמדד, והמכפלה נשארת מתחת ל-viewport אחד אף שיש לאן לגלול. minIndex/maxIndex שמחוץ לקצוות הם הוכחה ישירה, לא אומדן.
…#1169) גרירת הסרגל גוללת בתוך קטע גבוה מהמסך רק דרך offsetController; בלעדיו _jumpDuringDrag נופל ל-jumpTo(index:) בלבד. בספר שכולו קטע אחד אין אינדקס אחר לקפוץ אליו, ולכן הגרירה לא הזיזה דבר — התסמין שדווח על 'אגדה בבני יעקב'. הרשימות בשני מסכי הקריאה כבר מחוברות ל-ScrollOffsetController; רק הסרגל שעוטף אותן לא קיבל אותו. חלונית המפרשים, חלונית הקישורים וההערות האישיות כבר העבירו אותו, ולכן שם הגרירה עבדה. טסט השומר נועל את שני האתרים: כל סרגל במסך קריאה חייב לקבל offsetController. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7a8aa8f to
6269518
Compare
מה השינוי?
פס הגלילה נעלם או לא הגיב בכמה מצבים ולא חזר עד לפתיחה מחדש של הספר. הדיווח כלל תסמינים שנראו שונים; מתחתם שני שורשים נפרדים, ושניהם מטופלים כאן.
שורש א׳ — הנראות נגזרה ממדד של החלון המרונדר
ScrollablePositionedListמרנדר חלון סביב העוגן, ולכןmaxScrollExtentמתאר את החלון ולא את הרשימה. בקצה הרשימה אין תוכן קדימה, המדד מתאפס והמסילה מוסתרת — גם כשיש מאות פריטים מעל. הוספת מפרשים מגדילה את החלון והמדד חוזר; מסך גדול מרנדר יותר ולכן המדד לא מתאפס. זה מסביר גם את ההיעלמות בגרירה לסוף, גם את זו שבחלונית המפרשים, וגם את תלות גודל המסך.התיקון נשען על שני סימנים במקום על המדד: פריט שנמצא מחוץ לחלון הנראה (
minIndex > 0 || maxIndex < itemCount - 1) הוא הוכחה ישירה שיש לאן לגלול, ובנוסף מדידת התוכן עצמו (avgItemHeight * itemCount, ביחידות viewport). האומדן לבדו אינו מספיק: ברשימה קצרה עם פריטים בגבהים שונים ייתכן שרק פריט קצר נמדד והמכפלה נשארת מתחת ל-viewport.הסתרה כשכל התוכן נראה נשמרת, והטסט הקיים שנועל אותה ממשיך לעבור.
שורש ב׳ — מסכי הקריאה לא העבירו
offsetControllerלסרגלגרירת הסרגל גוללת בתוך קטע גבוה מהמסך רק דרך
offsetController; בלעדיו_jumpDuringDragנופל ל-jumpTo(index:)בלבד. בספר שכולו קטע אחד אין אינדקס אחר לקפוץ אליו, ולכן הגרירה לא הזיזה דבר — התסמין שדווח על 'אגדה בבני יעקב' (otzaria://open/book/7288).הרשימות בשני מסכי הקריאה כבר מחוברות ל-
ScrollOffsetController; רק הסרגל שעוטף אותן לא קיבל אותו. חלונית המפרשים, חלונית הקישורים וההערות האישיות כבר העבירו אותו — ולכן שם הגרירה עבדה, וזה חידד היכן הפער.בדיקות
maxScrollExtent: 0(העוגן בקצה) — המסילה נשארת.offsetController.offsetController(אומת שנכשל בלי התיקון).test/widgets/+test/text_book/— 2,386 עוברים.מה לא נכלל
הדיווח כלל גם היעלמות שהמדווח לא הצליח לשחזר במדויק ותיאר בהקלטה. המנגנון של שורש א׳ מסביר אותה, אך היא לא נבדקה ישירות.
קישור לבעיה
Fixes #1169
הצהרות התורם
flutter analyzeעל הקוד ואין שגיאותצילומי מסך
השינוי הוא בתנאי הנראות של המסילה ובחיווט בקר הגלילה, בלי שינוי בעיצוב. ההבדל מודגם בטסטים: אותה רשימה ואותם נתונים, מסילה שנעלמה מול מסילה שנשארת; וקטע יחיד שהגרירה לא הזיזה מול כזה שנגלל.
🤖 Generated with Claude Code