גלריית צילומי המסך (/gallery)
עמוד ציבורי, בלי התחברות, שמראה איך המוצר נראה: צילום אחד בכל פעם על כל רוחב המסך, ומתחתיו כותרת, משפט הסבר, ”הקודם“ ו“הבא“, מונה ”X מתוך N“, וקישור לעורך הציבורי (העורך הציבורי (/markdown-editor)). נועד לקישור מפוסטים, מה-README ומהיועץ בבוט. הראוט הוא gallery ב-webapp/app.py, והתבנית webapp/templates/gallery.html.
הצילומים והכיתובים
הרשימה במקום אחד. הצילומים, הסדר והכיתובים ב-
GALLERY_SLIDESב-webapp/gallery.py— שורה לכל צילום:image(שם הקובץ),title,descו-alt.altמתאר את מה שרואים בתמונה, לקורא מסך ולמי שהתמונה לא נטענה אצלו, ואינו חוזר על הכותרת.הקבצים ב-
webapp/static/gallery/: WebP לכל צילום, ולצידו JPEG אחד — תמונת התצוגה המקדימה של הקישור.tests/test_gallery_page.pyנופל על קובץ שאין לו שורה ברשימה, ועל שורה שאין לה קובץ.תמונת התצוגה המקדימה (
og:image) היא JPEG של הצילום הראשון ברשימה, בקובץ נפרד באותו שם (share_imageב-webapp/gallery.py), ב-SHARE_SIZEומתחת ל-SHARE_MAX_BYTES(שניהם ב-scripts/build_gallery_image.py).
החלפה או הוספה של צילום
מכינים את הקובץ מצילום המסך המקורי עם
scripts/build_gallery_image.py. הסקריפט חותך מלמעלה ומלמטה (--top/--bottom), מקטין ל-MAX_WIDTHלכל היותר, ושומר WebP בדחיסה אחת מהמקור, בלי המטא-דאטה של המכשיר. את מספר הפיקסלים לחיתוך מודדים מהקובץ עצמו: למעלה שורת הסטטוס של המכשיר ושורת הכרטיסיות של הדפדפן, ולמטה סרגל הניווט של המערכת, כשהוא בצילום. צילום בלי שורת סטטוס מתחיל ישר בכרטיסיות, ולכן החיתוך שלו קטן יותר.כשהצילום עומד ראשון ברשימה, מריצים עם
--share: הסקריפט שומר גם את ה-JPEG לתצוגה המקדימה. הצילום נחתך ליחס שלSHARE_SIZEבלי מתיחה — הרוחב מהמרכז והגובה מלמטה, כך ששורת הכתובת שבראשו נשארת — והסקריפט נכשל לפני שהוא כותב משהו כשהתמונה יוצאת מעלSHARE_MAX_BYTES.מעדכנים או מוסיפים את השורה ב-
GALLERY_SLIDES.כשהשם השתנה, מוחקים את הקובץ הישן מהתיקייה (וכשהצילום הראשון התחלף, גם את ה-JPEG הקודם).
צילומי המקור אינם נשמרים בענף הראשי.
המעבר בין הצילומים
כתובת לכל צילום.
/gallery#3פותח ישר את הצילום השלישי, בלי שהראשון יופיע לפניו. המעבר מעדכן את הכתובת ב-history.replaceState, כך שלא נוצרת רשומה בהיסטוריה לכל צילום, ו“אחורה“ יוצא מהגלריה.כיוון. בכפתורים, בחיצים במקלדת ובהחלקה, ה“הבא“ הוא הצילום שמשמאל, כמו בכל פריסה מימין לשמאל: חץ שמאלה, והזזת האצבע ימינה. הכיוון נגזר מ-
directionשל העמוד ולא מוקשח.overscroll-behavior-x: noneעלhtmlועלbodyנדרש כדי שהחלקה לרוחב לא תתפרש בכרומיום כמחוות ”אחורה“ של הדפדפן.זום. הגדלה בשתי אצבעות היא הזום של הדפדפן עצמו, וכל עוד העמוד מוגדל (
visualViewport.scale), גרירה באצבע אחת מזיזה את התצוגה ולא מחליפה צילום. לחיצה על התמונה פותחת אותה בגודל מלא.טעינה. צילום מוצג רק אחרי שהוא ירד ופוענח (
decode()), והכיתוב והמונה מתחלפים יחד איתו; עד אז נשאר הצילום הקודם, ומעבר שלוקח זמן מציג מחוון טעינה. אחרי כל מעבר נטענים מראש הצילום הבא והקודם. כשכמה מעברים נשלחים מהר, מוצג רק האחרון.
שיתוף, cache ומגבלת קצב
תגיות השיתוף. תגיות ה-
og:נותנות לקישור כותרת, תיאור ותמונה בוואטסאפ ובטלגרם.og:urlו-og:imageבכתובת מלאה (_webapp_base_urlב-webapp/app.py), כי העמוד של וואטסאפ על תצוגה מקדימה (https://developers.facebook.com/documentation/business-messaging/whatsapp/link-previews/) דורש כתובת מלאה. התמונה היא ה-JPEG שבסעיף הקודם, ו-tests/test_gallery_page.pyבודק שהיא בגודלSHARE_SIZEולא מעלSHARE_MAX_BYTES.Cache. כל כתובת של תמונה נושאת
?v={{ static_version }}, כיSEND_FILE_MAX_AGE_DEFAULTשומר סטטיקה בדפדפן לזמן ארוך — בלעדיו צילום שהוחלף באותו שם לא היה מגיע למבקרים.מגבלת קצב. הראוט פטור מהמגבלה הגורפת, כמו
/: המפתח של המגביל הוא ה-IP, וקישור שמתפרסם בקבוצה מביא מבקרים רבים, חלקם מאחורי אותה כתובת. התמונות מוגשות מ-static, ש-Flask-Limiter לא סופר.