Skip to content

פס גלילה: המסילה נעלמה בקצה הרשימה כי maxScrollExtent מתאפס - #1177

Merged
Y-PLONI merged 3 commits into
Otzaria:devfrom
yakov100:fix/1169-scrollbar-hidden-at-list-end
Sep 5, 2026
Merged

פס גלילה: המסילה נעלמה בקצה הרשימה כי maxScrollExtent מתאפס#1177
Y-PLONI merged 3 commits into
Otzaria:devfrom
yakov100:fix/1169-scrollbar-hidden-at-list-end

Conversation

@yakov100

@yakov100 yakov100 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

מה השינוי?

פס הגלילה נעלם או לא הגיב בכמה מצבים ולא חזר עד לפתיחה מחדש של הספר. הדיווח כלל תסמינים שנראו שונים; מתחתם שני שורשים נפרדים, ושניהם מטופלים כאן.

שורש א׳ — הנראות נגזרה ממדד של החלון המרונדר

final canScroll = notification.metrics.maxScrollExtent > precisionErrorTolerance;

ScrollablePositionedList מרנדר חלון סביב העוגן, ולכן maxScrollExtent מתאר את החלון ולא את הרשימה. בקצה הרשימה אין תוכן קדימה, המדד מתאפס והמסילה מוסתרת — גם כשיש מאות פריטים מעל. הוספת מפרשים מגדילה את החלון והמדד חוזר; מסך גדול מרנדר יותר ולכן המדד לא מתאפס. זה מסביר גם את ההיעלמות בגרירה לסוף, גם את זו שבחלונית המפרשים, וגם את תלות גודל המסך.

התיקון נשען על שני סימנים במקום על המדד: פריט שנמצא מחוץ לחלון הנראה (minIndex > 0 || maxIndex < itemCount - 1) הוא הוכחה ישירה שיש לאן לגלול, ובנוסף מדידת התוכן עצמו (avgItemHeight * itemCount, ביחידות viewport). האומדן לבדו אינו מספיק: ברשימה קצרה עם פריטים בגבהים שונים ייתכן שרק פריט קצר נמדד והמכפלה נשארת מתחת ל-viewport.

הסתרה כשכל התוכן נראה נשמרת, והטסט הקיים שנועל אותה ממשיך לעבור.

שורש ב׳ — מסכי הקריאה לא העבירו offsetController לסרגל

גרירת הסרגל גוללת בתוך קטע גבוה מהמסך רק דרך offsetController; בלעדיו _jumpDuringDrag נופל ל-jumpTo(index:) בלבד. בספר שכולו קטע אחד אין אינדקס אחר לקפוץ אליו, ולכן הגרירה לא הזיזה דבר — התסמין שדווח על 'אגדה בבני יעקב' (otzaria://open/book/7288).

הרשימות בשני מסכי הקריאה כבר מחוברות ל-ScrollOffsetController; רק הסרגל שעוטף אותן לא קיבל אותו. חלונית המפרשים, חלונית הקישורים וההערות האישיות כבר העבירו אותו — ולכן שם הגרירה עבדה, וזה חידד היכן הפער.

בדיקות

  • טסט שחזור לשורש א׳: 200 פריטים עם maxScrollExtent: 0 (העוגן בקצה) — המסילה נשארת.
  • טסט לרשימה קצרה שרק פריט אחד ממנה נמדד — המסילה מוצגת בזכות הפריט שמחוץ לחלון.
  • טסט לשורש ב׳: קטע יחיד גבוה מהמסך — הגרירה מייצרת גלילה בתוך הפריט דרך offsetController.
  • טסט שומר שנועל את שני אתרי הקריאה: כל סרגל במסך קריאה מקבל offsetController (אומת שנכשל בלי התיקון).
  • כל הטסטים הקיימים בקובץ הסרגל עוברים, כולל זה שנועל את ההסתרה. test/widgets/ + test/text_book/ — 2,386 עוברים.

מה לא נכלל

הדיווח כלל גם היעלמות שהמדווח לא הצליח לשחזר במדויק ותיאר בהקלטה. המנגנון של שורש א׳ מסביר אותה, אך היא לא נבדקה ישירות.

קישור לבעיה

Fixes #1169

הצהרות התורם

  • אני מאשר שה-PR שלי עומד בתנאי התרומה המפורטים ב-README
  • פיצ'ר חדש? — התייעצתי לפני כן (בפורום או ב-issue)
  • שינוי UI? — צירפתי צילומי מסך לפני/אחרי בסוף התיאור
  • הרצתי flutter analyze על הקוד ואין שגיאות

צילומי מסך

השינוי הוא בתנאי הנראות של המסילה ובחיווט בקר הגלילה, בלי שינוי בעיצוב. ההבדל מודגם בטסטים: אותה רשימה ואותם נתונים, מסילה שנעלמה מול מסילה שנשארת; וקטע יחיד שהגרירה לא הזיזה מול כזה שנגלל.

🤖 Generated with Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment on lines +297 to +299
if (totalContent > 1.0 + precisionErrorTolerance) {
_canScroll = true;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge אל תסיקו יכולת גלילה מממוצע הפריטים שנמדדו

בפתיחה או בקפיצה לסוף רשימה קצרה עם פריטים בגבהים שונים, ייתכן שרק הפריט האחרון והקצר נמדד; למשל, עם שני פריטים כשהאחרון בגובה ‎0.4‎ viewport מתקבל totalContent == 0.8, אף שהפריט הראשון שמחוץ למסך מוכיח שיש תוכן לגלול אליו. לאחר ש־maxScrollExtent מאפס את _canScroll, התנאי הזה אינו מחזיר אותו ל־true והמסילה עדיין נעלמת. הטסט החדש מסתיר זאת באמצעות itemCount: 200, שמבטיח שהמכפלה גדולה מ־1; יש לבסס את הנראות גם על minIndex > 0 או maxIndex < itemCount - 1, ולא רק על אומדן הגובה.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

תודה — צדקת, וזה שוחזר בטסט.

itemCount: 2 עם הפריט האחרון בלבד ב-0.4..0.8 נותן totalContent == 0.8, המסילה נעלמה. הוספתי minIndex > 0 || maxIndex < itemCount - 1 כתנאי מקדים: פריט מחוץ לחלון הנראה הוא הוכחה ישירה לגלילות, לא אומדן.

השארתי גם את תנאי totalContent — הוא מכסה את המקרה ההפוך, שבו כל הפריטים מרונדרים אבל התוכן גבוה מה-viewport.

הטסט השלילי הקיים (שני הפריטים גלויים ⇒ אין מסילה) ממשיך לעבור. 37/37.

yakov100 and others added 3 commits September 5, 2026 23:34
…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>
@Y-PLONI
Y-PLONI force-pushed the fix/1169-scrollbar-hidden-at-list-end branch from 7a8aa8f to 6269518 Compare September 5, 2026 20:34
@Y-PLONI
Y-PLONI merged commit 4b3d6c6 into Otzaria:dev Sep 5, 2026
7 checks passed
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