אתם יכולים להשתמש באזור של סרגל הכותרת לצד פקדי החלונות כדי להפוך את ה-PWA ליותר דומה לאפליקציה.
אם אתם זוכרים את המאמר שלי איך להפוך את אפליקציית ה-PWA ליותר 'אפליקצייתית', יכול להיות שזכרתם שציינתי שהתאמה אישית של שורת הכותרת של האפליקציה היא אסטרטגיה ליצירת חוויה יותר 'אפליקצייתית'. הנה דוגמה לאיך זה יכול להיראות, באפליקציית Podcasts ל-macOS.
עכשיו יכול להיות שתתעורר לכם נטייה להתנגד ולומר ש-Podcasts היא אפליקציה ספציפית לפלטפורמת macOS שלא פועלת בדפדפן, ולכן היא יכולה לעשות מה שהיא רוצה בלי לציית לכללים של הדפדפן. זה נכון, אבל החדשות הטובות הן שבקרוב תוכלו ליצור ממשקי משתמש דומים ל-PWA שלכם באמצעות התכונה 'שכבת-על של פקדי חלונות', שהיא הנושא של המאמר הזה.
רכיבים של שכבת-העל של פקדי החלונות
שכבת-העל של פקדי החלונות מורכבת מארבעה תתי-תכונות:
- הערך
"window-controls-overlay"
בשדה"display_override"
במניפסט של אפליקציית האינטרנט. - משתני הסביבה של CSS
titlebar-area-x
,titlebar-area-y
,titlebar-area-width
ו-titlebar-area-height
. - סטנדרטיזציה של מאפיין ה-CSS הקנייני הקודם
-webkit-app-region
כנכסapp-region
, כדי להגדיר אזורים שניתן לגרור בתוכן אינטרנט. - מנגנון לשליחת שאילתות לגבי אזור הפקדים של החלון ולפתרון בעיות שקשורות אליו באמצעות המאפיין
windowControlsOverlay
שלwindow.navigator
.
מהי שכבת-העל של פקדי החלונות
אזור סרגל הכותרת מתייחס למרחב שמשמאל או מימין לפקדי החלון (כלומר, הלחצנים למזעור, להגדלה למסך מלא, לסגירה וכו'), ולרוב מכיל את שם האפליקציה. שכבת-העל של פקדי החלונות מאפשרת לאפליקציות אינטרנט מתקדמות (PWAs) לספק חוויה יותר דומה לאפליקציה, על ידי החלפת סרגל הכותרת הקיים ברוחב מלא בשכבת-על קטנה שמכילה את פקדי החלון. כך המפתחים יכולים להציב תוכן מותאם אישית באזור שבו בעבר הייתה סרגל הכותרת שבשליטת הדפדפן.
הסטטוס הנוכחי
שלב | סטטוס |
---|---|
1. יצירת הסבר | הושלם |
2. יצירת טיוטה ראשונית של המפרט | הושלם |
3. איסוף משוב וביצוע שינויים בעיצוב | בתהליך |
4. גרסת מקור לניסיון | הושלם |
5. השקה | הושלם (ב-Chromium 104) |
איך משתמשים בשכבת-העל של פקדי החלונות
הוספת window-controls-overlay
למניפסט של אפליקציית האינטרנט
כדי להביע הסכמה לשימוש בשכבת-העל של אמצעי הבקרה של החלון באפליקציית האינטרנט, צריך להוסיף את "window-controls-overlay"
כחבר הראשי ב-"display_override"
במניפסט של אפליקציית האינטרנט:
{
"display_override": ["window-controls-overlay"]
}
שכבת-העל של פקדי החלון תהיה גלויה רק אם כל התנאים הבאים מתקיימים:
- האפליקציה לא נפתחת בדפדפן, אלא בחלון נפרד של אפליקציית PWA.
- המניפסט כולל את
"display_override": ["window-controls-overlay"]
. (לאחר מכן מותר להשתמש בערכים אחרים). - אפליקציית ה-PWA פועלת במערכת הפעלה למחשב.
- המקור הנוכחי תואם למקור שבו ה-PWA הותקן.
התוצאה היא אזור ריק בסרגל הכותרת עם פקדי החלון הרגילים בצד ימין או שמאל, בהתאם למערכת ההפעלה.
העברת תוכן לסרגל הכותרת
עכשיו יש מקום בסרגל הכותרת, ואפשר להעביר אליו משהו. לצורך כתיבת המאמר הזה, פיתחתי אפליקציית PWA של תכנים נבחרים ב-Wikimedia. תכונה שימושית לאפליקציה הזו יכולה להיות חיפוש מילים בשמות המאמרים. הקוד ה-HTML של תכונת החיפוש נראה כך:
<div class="search">
<img src="logo.svg" alt="Wikimedia logo." width="32" height="32" />
<label>
<input type="search" />
Search for words in articles
</label>
</div>
כדי להעביר את div
למעלה לסרגל הכותרת, צריך קצת CSS:
.search {
/* Make sure the `div` stays there, even when scrolling. */
position: fixed;
/**
* Gradient, because why not. Endless opportunities.
* The gradient ends in `#36c`, which happens to be the app's
* `<meta name="theme-color" content="#36c">`.
*/
background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
/* Use the environment variable for the left anchoring with a fallback. */
left: env(titlebar-area-x, 0);
/* Use the environment variable for the top anchoring with a fallback. */
top: env(titlebar-area-y, 0);
/* Use the environment variable for setting the width with a fallback. */
width: env(titlebar-area-width, 100%);
/* Use the environment variable for setting the height with a fallback. */
height: env(titlebar-area-height, 33px);
}
אפשר לראות את ההשפעה של הקוד הזה בצילום המסך שבהמשך. סרגל הכותרת רספונסיבי לחלוטין. כשמשנים את גודל החלון של ה-PWA, סרגל הכותרת מגיב כאילו הוא מורכב מתוכן HTML רגיל, וזה אכן המצב.
איך קובעים אילו חלקים בסרגל הכותרת אפשר לגרור
צילום המסך שלמעלה עשוי להטעות אתכם ולגרום לכם לחשוב שהשלמתם את התהליך, אבל זה לא המצב. אי אפשר יותר לגרור את חלון ה-PWA (מלבד אזור קטן מאוד), כי לחצני פקדי החלון הם לא אזורים לגרירה, ושאר סרגל הכותרת מורכב מווידג'ט החיפוש. כדי לפתור את הבעיה, צריך להשתמש במאפיין ה-CSS app-region
עם הערך drag
. במקרה הזה, אפשר לגרור את כל הרכיבים חוץ מהרכיב input
.
/* The entire search `div` is draggable… */
.search {
-webkit-app-region: drag;
app-region: drag;
}
/* …except for the `input`. */
input {
-webkit-app-region: no-drag;
app-region: no-drag;
}
אחרי שמוסיפים את הקוד הזה, המשתמש יכול לגרור את חלון האפליקציה כרגיל על ידי גרירה של div
, img
או label
. רק הרכיב input
הוא אינטראקטיבי, כך שאפשר להזין את שאילתת החיפוש.
זיהוי תכונות
כדי לבדוק אם יש תמיכה בשכבת-העל של פקדי החלונות, אפשר לבדוק אם קיים windowControlsOverlay
:
if ('windowControlsOverlay' in navigator) {
// Window Controls Overlay is supported.
}
שליחת שאילתה לאזור של פקדי החלון באמצעות windowControlsOverlay
עד כה יש בעיה אחת בקוד: בפלטפורמות מסוימות הפקדים של החלון נמצאים בצד ימין, ובפלטפורמות אחרות הם נמצאים בצד ימין. גרוע מכך, גם המיקום של תפריט Chrome עם שלוש הנקודות ישתנה בהתאם לפלטפורמה. כלומר, צריך להתאים באופן דינמי את תמונת הרקע של העקומה הליניארית כך שתתחיל ב-#131313
→maroon
או ב-maroon
→#131313
→maroon
, כדי שתשתלב בצבע הרקע maroon
של סרגל הכותרת, שנקבע על ידי <meta name="theme-color" content="maroon">
. אפשר לעשות זאת על ידי שליחת שאילתה ל-getTitlebarAreaRect()
API בנכס navigator.windowControlsOverlay
.
if ('windowControlsOverlay' in navigator) {
const { x } = navigator.windowControlsOverlay.getTitlebarAreaRect();
// Window controls are on the right (like on Windows).
// Chrome menu is left of the window controls.
// [ windowControlsOverlay___________________ […] [_] [■] [X] ]
if (x === 0) {
div.classList.add('search-controls-right');
}
// Window controls are on the left (like on macOS).
// Chrome menu is right of the window controls overlay.
// [ [X] [_] [■] ___________________windowControlsOverlay [⋮] ]
else {
div.classList.add('search-controls-left');
}
} else {
// When running in a non-supporting browser tab.
div.classList.add('search-controls-right');
}
במקום שתצוגת תמונת הרקע תהיה ישירות בכללי ה-CSS של הכיתה .search
(כמו קודם), הקוד המשופר משתמש עכשיו בשתי כיתות שהקוד שלמעלה מגדיר באופן דינמי.
/* For macOS: */
.search-controls-left {
background-image: linear-gradient(90deg, #36c, 45%, #131313, 90%, #36c);
}
/* For Windows: */
.search-controls-right {
background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
}
איך בודקים אם שכבת-העל של פקדי החלונות מוצגת
שכבת-העל של פקדי החלונות לא תהיה גלויה באזור של סרגל הכותרת בכל הנסיבות. הוא לא יופיע בדפדפנים שלא תומכים בתכונה 'שכבת-על של פקדי חלון', אבל הוא לא יופיע גם כשאפליקציית ה-PWA הרלוונטית פועלת בכרטיסייה. כדי לזהות את המצב הזה, אפשר להריץ שאילתה על המאפיין visible
של windowControlsOverlay
:
if (navigator.windowControlsOverlay.visible) {
// The window controls overlay is visible in the title bar area.
}
לחלופין, אפשר גם להשתמש בשאילתת המדיה display-mode
ב-JavaScript ו/או ב-CSS:
// Create the query list.
const mediaQueryList = window.matchMedia('(display-mode: window-controls-overlay)');
// Define a callback function for the event listener.
function handleDisplayModeChange(mql) {
// React on display mode changes.
}
// Run the display mode change handler once.
handleDisplayChange(mediaQueryList);
// Add the callback function as a listener to the query list.
mediaQueryList.addEventListener('change', handleDisplayModeChange);
@media (display-mode: window-controls-overlay) {
/* React on display mode changes. */
}
קבלת התראות על שינויים בגיאומטריה
שליחת שאילתה לאזור שכבת-העל של פקדי החלונות באמצעות getTitlebarAreaRect()
יכולה להספיק למקרים חד-פעמיים, כמו הגדרת תמונת הרקע הנכונה על סמך המיקום של פקדי החלונות, אבל במקרים אחרים נדרשת שליטה פרטנית יותר. לדוגמה, תרחיש לדוגמה יכול להיות התאמה של שכבת-העל של פקדי החלונות בהתאם למרחב הזמין, והוספת בדיחה ישירות לשכבת-העל של פקדי החלונות כשיש מספיק מקום.
כדי לקבל התראות על שינויים בגיאומטריה, אפשר להירשם ל-navigator.windowControlsOverlay.ongeometrychange
או להגדיר מאזין לאירועים עבור האירוע geometrychange
. האירוע הזה יופעל רק כששכבת-העל של אמצעי הבקרה של החלון גלויה, כלומר כש-navigator.windowControlsOverlay.visible
הוא true
.
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
if ('windowControlsOverlay' in navigator) {
navigator.windowControlsOverlay.ongeometrychange = debounce((e) => {
span.hidden = e.titlebarAreaRect.width < 800;
}, 250);
}
במקום להקצות פונקציה ל-ongeometrychange
, אפשר גם להוסיף מאזין לאירועים ל-windowControlsOverlay
, כפי שמתואר בהמשך. אפשר לקרוא על ההבדל בין השניים ב-MDN.
navigator.windowControlsOverlay.addEventListener(
'geometrychange',
debounce((e) => {
span.hidden = e.titlebarAreaRect.width < 800;
}, 250),
);
תאימות כשהיא פועלת בכרטיסייה ובדפדפנים שלא תומכים בה
יש שני מקרים אפשריים שכדאי לשקול:
- המצב שבו אפליקציה פועלת בדפדפן שתומך בשכבת-העל של פקדי החלון, אבל האפליקציה משמשת בכרטיסייה בדפדפן.
- המצב שבו אפליקציה פועלת בדפדפן שלא תומך בשכבת-העל של פקדי החלונות.
בשני המקרים, כברירת מחדל, ה-HTML שנוצר לשכבת-העל של פקדי החלון יוצג בשורה כמו תוכן HTML רגיל, וערכי ברירת המחדל של המשתנים env()
ייכנסו לתוקף לצורך המיקום. בדפדפנים שתומכים בכך, אפשר גם להחליט לא להציג את ה-HTML שמיועד לשכבת-העל של אמצעי הבקרה של החלון. לשם כך, בודקים את המאפיין visible
של שכבת-העל, ואם הוא מדווח על הערך false
, מסתירים את תוכן ה-HTML הזה.
תזכורת: בדפדפנים שלא תומכים ב-Manifest, נכס המניפסט של אפליקציית האינטרנט "display_override"
לא יילקח בחשבון בכלל, או שהם לא יזהו את "window-controls-overlay"
, ולכן ישתמשו בערך האפשרי הבא לפי שרשרת החלופות, למשל "standalone"
.
שיקולים לגבי ממשק המשתמש
יכול להיות שתרצו לעשות זאת, אבל לא מומלץ ליצור תפריט נפתח קלאסי באזור שכבת-העל של אמצעי הבקרה של החלון. הפעולה הזו תהיה הפרה של הנחיות העיצוב ב-macOS, פלטפורמה שבה המשתמשים מצפים שסרגי תפריטים (גם אלה שסופקו על ידי המערכת וגם אלה בהתאמה אישית) יופיעו בחלק העליון של המסך.
אם האפליקציה שלכם מספקת חוויית שימוש במסך מלא, כדאי לשקול היטב אם שכבת-העל של פקדי החלון צריכה להיות חלק מהתצוגה במסך מלא. יכול להיות שתרצו לשנות את הפריסה כשהאירוע onfullscreenchange
יופעל.
הדגמה (דמו)
יצרתי דמו שאפשר לשחק בו בדפדפנים שונים, נתמכים ולא נתמכים, במצב מותקן ובמצב לא מותקן. כדי ליהנות מחוויית השימוש בפועל של שכבת-העל של פקדי החלונות, צריך להתקין את האפליקציה. בהמשך מופיעים שני צילומי מסך של מה שצפוי. קוד המקור של האפליקציה זמין ב-Glitch.
תכונת החיפוש בשכבת-העל של פקדי החלונות פועלת באופן מלא:
שיקולי אבטחה
צוות Chromium תכנן ויישם את Window Controls Overlay API בהתאם לעקרונות המרכזיים שמוגדרים במאמר בקרת הגישה לתכונות מתקדמות של פלטפורמת האינטרנט, כולל בקרת משתמשים, שקיפות וארגונומיה.
זיוף
מתן שליטה חלקית לאתרים בסרגל הכותרת משאיר מקום למפתחים לזייף תוכן באזור שהיה בעבר מהימן ושנושלט על ידי הדפדפן. נכון לעכשיו, בדפדפני Chromium, המצב העצמאי כולל שורת כותרת שבה מוצגים בהתחלה השם של דף האינטרנט בצד ימין והמקור של הדף בצד ימין (אחרי הלחצן 'הגדרות ועוד' ואמצעי הבקרה של החלון). אחרי כמה שניות, טקסט המקור נעלם. אם הדפדפן מוגדר לשפה עם כיוון מימין לשמאל (RTL), הפריסה הזו תתהפך כך שטקסט המקור יופיע בצד ימין. הפעולה הזו פותחת את שכבת-העל של אמצעי הבקרה על החלון כדי לזייף את המקור, אם אין מספיק ריפוד בין המקור לבין הקצה הימני של שכבת-העל. לדוגמה, אפשר לצרף לאתר הלא מהימן evil.ltd את האתר המהימן google.com, וכך להטעות את המשתמשים ולגרום להם לחשוב שהמקור מהימן. אנחנו מתכננים להשאיר את הטקסט הזה כדי שהמשתמשים ידעו מה המקור של האפליקציה ויוכלו לוודא שהיא עומדת בציפיות שלהם. בדפדפנים שהוגדרו ל-RTL, צריך להיות מספיק מרווח מימין לטקסט של המקור כדי למנוע מאתר זדוני לצרף למקור הלא בטוח מקור מהימן.
יצירה של טביעת אצבע דיגיטלית (fingerprinting)
הפעלת שכבת-העל של פקדי החלונות והאזורים שניתן לגרור לא יוצרת בעיות פרטיות משמעותיות, מלבד זיהוי התכונות. עם זאת, בגלל הבדלים בגדלים ובמיקומים של לחצני הבקרה של החלונות במערכות הפעלה שונות, השיטה navigator.
מחזירה DOMRect
שהמיקום והמידות שלו חושפים מידע על מערכת ההפעלה שבה הדפדפן פועל. נכון לעכשיו, המפתחים כבר יכולים לגלות את מערכת ההפעלה מתוך מחרוזת סוכן המשתמש, אבל בגלל חששות לגבי טביעת אצבע דיגיטלית, מתנהל דיון על הקפאת מחרוזת ה-UA ואיחוד הגרסאות של מערכת ההפעלה. קהילת הדפדפנים מנסה להבין באיזו תדירות משתנה הגודל של שכבת-העל של פקדי החלון בפלטפורמות שונות. ההנחה הנוכחית היא שהם יציבים למדי בגרסאות שונות של מערכת ההפעלה, ולכן לא יהיו שימושיים למעקב אחרי גרסאות משנה של מערכת ההפעלה. זוהי בעיה פוטנציאלית של זיהוי טביעות אצבע, אבל היא רלוונטית רק לאפליקציות PWA מותקנות שמשתמשות בתכונה בהתאמה אישית של שורת הכותרת, ולא לשימוש כללי בדפדפן. בנוסף, ממשק ה-API של navigator.
לא יהיה זמין ל-iframes שמוטמעים בתוך אפליקציית PWA.
ניווט
ניווט למקור אחר בתוך אפליקציית PWA יגרום להחזרה לסרגל הכותרת הרגיל והעצמאי, גם אם היא עומדת בקריטריונים שלמעלה ונפתחת עם שכבת-העל של פקדי החלונות. הסיבה לכך היא כדי להתאים את התצוגה לעמודה השחורה שמופיעה בעת ניווט לנקודת מוצא אחרת. אחרי שתחזרו למקור המקורי, השכבה העליונה של פקדי החלון תופעל שוב.
משוב
צוות Chromium רוצה לשמוע על החוויה שלכם עם Window Controls Overlay API.
תיאור של עיצוב ה-API
האם יש משהו ב-API שלא פועל כצפוי? או אולי חסרות שיטות או מאפיינים שאתם צריכים כדי להטמיע את הרעיון? יש לכם שאלות או הערות לגבי מודל האבטחה? אפשר לשלוח דיווח על בעיה במפרט במאגר GitHub המתאים, או להוסיף את המחשבות שלכם לבעיה קיימת.
דיווח על בעיה בהטמעה
מצאתם באג בהטמעה של Chromium? או שההטמעה שונה מהמפרט?
שולחים דיווח על באג בכתובת new.crbug.com. חשוב לכלול כמה שיותר פרטים, הוראות פשוטות לשחזור הבעיה ולהזין את הערך UI>Browser>WebAppInstalls
בתיבה Components. Glitch הוא כלי מצוין לשיתוף שחזור מהיר וקל של באגים.
תמיכה ב-API
אתם מתכננים להשתמש ב-Window Controls Overlay API? התמיכה הציבורית שלכם עוזרת לצוות Chromium לתת עדיפות לתכונות, ומראה לספקי דפדפנים אחרים כמה חשובה התמיכה בהן.
אפשר לשלוח ציוץ אל @ChromiumDev עם ה-hashtag #WindowControlsOverlay
ולספר לנו איפה ואיך אתם משתמשים בו.
קישורים שימושיים
- הסבר
- טיוטת מפרט
- באג ב-Chromium
- הרשומה 'סטטוס הפלטפורמה של Chrome'
- בדיקת התג
- מסמכים קשורים של Microsoft Edge
תודות
Amanda Baker מצוות Microsoft Edge הטמיעה את שכבת-העל של פקדי החלונות והגדירה אותה. המאמר נבדק על ידי Joe Medley ו-Kenneth Rohde Christiansen. התמונה הראשית (Hero) של Sigmund ב-Unsplash.