:summary: העמוד הציבורי שמציג את צילומי המסך של הוובאפ: איפה מוגדרים הצילומים והכיתובים, איך מחליפים או מוסיפים צילום, ואיך עובדים המעבר בין הצילומים, הטעינה ותגיות השיתוף. .. _webapp-gallery: גלריית צילומי המסך (``/gallery``) ================================== עמוד ציבורי, בלי התחברות, שמראה איך המוצר נראה: צילום אחד בכל פעם על כל רוחב המסך, ומתחתיו כותרת, משפט הסבר, "הקודם" ו"הבא", מונה "X מתוך N", וקישור לעורך הציבורי (:ref:`webapp-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``). החלפה או הוספה של צילום ------------------------- 1. מכינים את הקובץ מצילום המסך המקורי עם ``scripts/build_gallery_image.py``. הסקריפט חותך מלמעלה ומלמטה (``--top`` / ``--bottom``), מקטין ל-``MAX_WIDTH`` לכל היותר, ושומר WebP בדחיסה אחת מהמקור, בלי המטא-דאטה של המכשיר. את מספר הפיקסלים לחיתוך מודדים מהקובץ עצמו: למעלה שורת הסטטוס של המכשיר ושורת הכרטיסיות של הדפדפן, ולמטה סרגל הניווט של המערכת, כשהוא בצילום. צילום בלי שורת סטטוס מתחיל ישר בכרטיסיות, ולכן החיתוך שלו קטן יותר. 2. כשהצילום עומד ראשון ברשימה, מריצים עם ``--share``: הסקריפט שומר גם את ה-JPEG לתצוגה המקדימה. הצילום נחתך ליחס של ``SHARE_SIZE`` בלי מתיחה — הרוחב מהמרכז והגובה מלמטה, כך ששורת הכתובת שבראשו נשארת — והסקריפט נכשל לפני שהוא כותב משהו כשהתמונה יוצאת מעל ``SHARE_MAX_BYTES``. 3. מעדכנים או מוסיפים את השורה ב-``GALLERY_SLIDES``. 4. כשהשם השתנה, מוחקים את הקובץ הישן מהתיקייה (וכשהצילום הראשון התחלף, גם את ה-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 לא סופר.