Dostosuj nakładkę elementów sterujących oknami na pasku tytułu PWA

Użyj obszaru paska tytułu obok elementów sterujących oknem, aby aplikacja PWA wyglądała bardziej jak aplikacja.

Jeśli pamiętasz mój artykuł Uczynienie aplikacji internetowej bardziej zbliżoną do aplikacji, być może pamiętasz, że dostosowywanie paska tytułu aplikacji wymieniłem jako strategię na zwiększenie podobieństwa aplikacji internetowej do aplikacji. Oto przykład tego, jak może to wyglądać w przypadku aplikacji Podcasty na macOS.

Pasek tytułu aplikacji Podcasty na macOS z przyciskami sterowania multimediami i metadanymi dotyczącymi odtwarzanego podcastu.
Niestandardowy pasek tytułu sprawia, że aplikacja PWA przypomina aplikację na daną platformę.

Możesz teraz zaprotestować, mówiąc, że Podcasty to aplikacja na macOS, która nie działa w przeglądarce, a więc może robić, co chce, bez konieczności przestrzegania zasad przeglądarki. To prawda, ale mamy dobrą wiadomość: funkcja nakładki z elementami sterującymi okna, która jest tematem tego artykułu, pozwoli Ci wkrótce tworzyć podobne interfejsy użytkownika dla aplikacji PWA.

Komponenty nakładki z elementami sterującymi okna

Nakładka z elementami sterującymi okna składa się z 4 podfunkcji:

  1. Wartość "window-controls-overlay" w polu "display_override" w pliku manifestu aplikacji internetowej.
  2. Zmienne środowiskowe CSS titlebar-area-x, titlebar-area-y, titlebar-area-width i titlebar-area-height.
  3. Standardizacja wcześniej zastrzeżonej właściwości CSS -webkit-app-region jako właściwości app-region służącej do definiowania obszarów do przeciągania w treściach internetowych.
  4. Mechanizm umożliwiający wysyłanie zapytań do regionu elementów sterujących okna i obchodzenie go za pomocą elementu windowControlsOverlay w klasie window.navigator.

Co to jest nakładka z elementami sterującymi okna

Obszar paska tytułu to przestrzeń po lewej lub prawej stronie elementów sterujących oknem (czyli przycisków minimalizowania, maksymalizowania, zamykania itp.) i często zawiera tytuł aplikacji. Nakładka z elementami sterującymi okna umożliwia progresywnym aplikacjom internetowym (PWA) działanie bardziej zbliżone do aplikacji natywnych. Wystarczy zastąpić dotychczasowy pasek tytułu o pełnej szerokości nakładką z elementami sterującymi okna. Umożliwia to deweloperom umieszczanie treści niestandardowych w obszarze paska tytułu kontrolowanym wcześniej przez przeglądarkę.

Obecny stan,

Krok Stan
1. Tworzenie wyjaśnienia Zakończono
2. Tworzenie wstępnej wersji specyfikacji Zakończono
3. Zbieraj opinie i ulepszaj projekt W toku
4. Wersja próbna origin Zakończone
5. Wprowadzenie na rynek Ukończone (w Chromium 104)

Jak korzystać z nakładki z elementami sterującymi okna

Dodawanie window-controls-overlay do pliku manifestu aplikacji internetowej

Progresywna aplikacja internetowa może włączyć nakładkę elementów sterujących oknem, dodając "window-controls-overlay" jako głównego członka "display_override" w pliku manifestu aplikacji internetowej:

{
  "display_override": ["window-controls-overlay"]
}

Nakładka elementów sterujących oknem będzie widoczna tylko wtedy, gdy spełnione są wszystkie te warunki:

  1. Aplikacja nie otwiera się w przeglądarce, ale w osobnym oknie PWA.
  2. Manifest zawiera "display_override": ["window-controls-overlay"]. (inne wartości są dozwolone).
  3. Progresywna aplikacja internetowa działa w systemie operacyjnym na komputery.
  4. Bieżące źródło jest zgodne ze źródłem, w którym zainstalowano PWA.

W efekcie jest to pusta belka tytułu z zwykłymi elementami sterowania oknem po lewej lub prawej stronie, w zależności od systemu operacyjnego.

Okno aplikacji z pustym paskiem tytułu i elementami sterującymi po lewej stronie.
Pusty pasek tytułu gotowy na treści niestandardowe.

Przenoszenie treści na pasek tytułu

Teraz, gdy na pasku tytułu jest miejsce, możesz tam coś przenieść. Na potrzeby tego artykułu utworzyłem PWA z treściami wyróżnionymi w Wikimedii. Przydatną funkcją w tej aplikacji może być wyszukiwanie słów w tytułach artykułów. Kod HTML funkcji wyszukiwania wygląda tak:

<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>

Aby przenieść element div do paska tytułu, musisz użyć odrobiny kodu 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);
}

Efekt działania tego kodu możesz zobaczyć na zrzucie ekranu poniżej. Pasek tytułu jest w pełni responsywny. Gdy zmieniasz rozmiar okna PWA, pasek tytułu reaguje tak, jakby składał się z treści HTML, co w istocie jest prawdą.

Okno aplikacji z paskiem wyszukiwania na pasku tytułu
Nowa aktywna i responsywna pasek tytułu.

Określanie, które części paska tytułu można przeciągać

Na powyższym zrzucie ekranu widać, że wszystko jest już gotowe, ale tak naprawdę nie jest. Okno aplikacji PWA nie można już przeciągać (poza bardzo małym obszarem), ponieważ przyciski elementów sterujących oknem nie są obszarami przeciągania, a pozostałości paska tytułu składają się z widżetu wyszukiwania. Aby to naprawić, użyj właściwości CSS app-region o wartości drag. W tym konkretnym przypadku możesz dopuścić przeciąganie wszystkich elementów z wyjątkiem elementu 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;
}

Dzięki temu użytkownik może przeciągać okno aplikacji jak zwykle, przeciągając div, img lub label. Tylko element input jest interaktywny, więc można w nim wpisać zapytanie.

Wykrywanie cech

Obsługę nakładki z elementami sterującymi okna można wykryć, testując obecność: windowControlsOverlay:

if ('windowControlsOverlay' in navigator) {
  // Window Controls Overlay is supported.
}

Wysyłanie zapytania do regionu elementów sterowania okna za pomocą windowControlsOverlay

Kod ma jednak pewien problem: na niektórych platformach kontrolki okna znajdują się po prawej stronie, a na innych – po lewej. Co gorsza, menu z 3 kropkami w Chrome również zmieni swoją pozycję w zależności od platformy. Oznacza to, że obraz tła z gradientem liniowym musi być dostosowywany dynamicznie, aby biegł od #131313maroon lub maroon#131313maroon, tak aby zlewał się z maroon kolorem tła paska tytułu, który jest określany przez <meta name="theme-color" content="maroon">. Można to zrobić, wysyłając zapytanie do interfejsu API getTitlebarAreaRect() dotyczące właściwości 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');
}

Zamiast umieszczać obraz tła bezpośrednio w regułach CSS klasy .search (jak poprzednio), zmodyfikowany kod używa teraz 2 klas, które kod powyżej ustawia dynamicznie.

/* 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);
}

Określanie, czy nakładka z elementami sterującymi okna jest widoczna

Nakładka z elementami sterującymi okna nie będzie widoczna w pasku tytułu w każdych okolicznościach. Oczywiście nie będzie ona dostępna w przeglądarkach, które nie obsługują funkcji nakładki elementów sterujących oknem, ale też nie będzie widoczna, gdy PWA będzie działać w karcie. Aby wykryć taką sytuację, możesz wysłać zapytanie do właściwości visible obiektu windowControlsOverlay:

if (navigator.windowControlsOverlay.visible) {
  // The window controls overlay is visible in the title bar area.
}

Możesz też użyć zapytania o multimedia display-mode w JavaScript lub 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. */ 
}

otrzymywanie powiadomień o zmianach geometrii;

Zapytanie obszaru nakładki elementów sterujących okna za pomocą getTitlebarAreaRect() może wystarczyć do jednorazowych zadań, takich jak ustawienie prawidłowego obrazu tła na podstawie położenia elementów sterujących okna, ale w innych przypadkach konieczna jest bardziej szczegółowa kontrola. Przykładem zastosowania może być dostosowanie nakładki elementów sterujących okna w zależności od dostępnej przestrzeni i dodanie dowczasy żartu, gdy jest wystarczająco dużo miejsca.

Nakładka z elementami sterującymi okna w wąskim oknie z skróconą treścią.
Elementy sterujące na pasku tytułu dostosowane do wąskiego okna.

Aby otrzymywać powiadomienia o zmianach geometrii, możesz subskrybować zdarzenie navigator.windowControlsOverlay.ongeometrychange lub skonfigurować odbiornik zdarzeń dla zdarzenia geometrychange. To zdarzenie zostanie wywołane tylko wtedy, gdy nakładka elementów sterujących okna jest widoczna, czyli gdy navigator.windowControlsOverlay.visible ma wartość 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);
}

Zamiast przypisywać funkcję do ongeometrychange, możesz też dodać do windowControlsOverlay obiekt nasłuchujący zdarzeń, jak pokazano poniżej. Różnice między tymi dwoma typami znajdziesz w dokumentacji MDN.

navigator.windowControlsOverlay.addEventListener(
  'geometrychange',
  debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250),
);

Zgodność podczas uruchamiania w zakładce i w przeglądarkach, które nie obsługują tej funkcji

Rozważ 2 możliwe przypadki:

  • Przypadek, gdy aplikacja działa w przeglądarce, która obsługuje nakładkę Window Controls, ale aplikacja jest używana na karcie przeglądarki.
  • aplikacja działa w przeglądarce, która nie obsługuje nakładki z elementami sterującymi okna;

W obu przypadkach kod HTML utworzony na potrzeby okna kontrolnego będzie domyślnie wyświetlany wbudowany, tak jak zwykłe treści HTML, a wartości zastępcze zmiennych env() będą używane do pozycjonowania. W obsługiwanych przeglądarkach możesz też zdecydować, aby nie wyświetlać kodu HTML przeznaczonego dla nakładki elementów sterujących okna. Aby to zrobić, sprawdź właściwość visible nakładki. Jeśli zwróci ona wartość false, ukryj ten kod HTML.

PWA działająca na karcie przeglądarki z elementami sterowania oknem wyświetlanymi w polu treści.
Sterowanie przeznaczone dla paska tytułu można łatwo wyświetlić w starszych przeglądarkach.

Przypominamy, że przeglądarki, które nie obsługują tej funkcji, nie będą w ogóle uwzględniać właściwości pliku manifestu aplikacji internetowej "display_override" lub nie będą rozpoznawać wartości "window-controls-overlay", a dlatego użyją następnej możliwej wartości zgodnie z łańcuchem zastępczym, na przykład "standalone".

PWA działająca w trybie samodzielnym z elementami sterowania oknem wyświetlanymi w ciele.
Sterowanie przeznaczone dla paska tytułu można łatwo wyświetlić w starszych przeglądarkach.

Interfejs użytkownika

Chociaż może to być kuszące, nie zalecamy tworzenia klasycznego menu w obszarze okna kontrolnego. Spowoduje to naruszenie wytycznych dotyczących projektowania na system macOS, na którym użytkownicy oczekują, że paski menu (zarówno systemowe, jak i niestandardowe) będą znajdować się u góry ekranu.

Jeśli Twoja aplikacja działa w trybie pełnoekranowym, dokładnie zastanów się, czy ma sens wyświetlanie nakładki elementów sterujących oknem w tym trybie. Gdy nastąpi zdarzenie onfullscreenchange, warto zmienić układ.

Prezentacja

Stworzyłem demo, które możesz uruchomić w różnych przeglądarkach obsługujących i nieobsługujących tę grę oraz w stanie zainstalowanej i niezainstalowanej. Aby zobaczyć, jak działa nakładka sterowania oknem, musisz zainstalować aplikację. Poniżej znajdziesz 2 zrzuty ekranu pokazujące, czego się spodziewać. Kod źródłowy aplikacji jest dostępny na stronie Glitch.

Aplikacja demo z elementami sterującymi okna w ramach polecanych treści w Wikimedii
Aplikacja demonstracyjna jest dostępna do eksperymentowania.

Funkcja wyszukiwania w nakładce z elementami sterującymi okna działa w pełni:

Aplikacja demo z rekomendowanymi treściami z Wikimedii z oknem kontrolnym i aktywnym wyszukiwaniem hasła „cleopa…”, które podświetla jeden z artykułów z odpowiednim hasłem „Cleopatra”.
Funkcja wyszukiwania korzystająca z nakładki z elementami sterującymi okna.

Zagadnienia związane z bezpieczeństwem

Zespół Chromium zaprojektował i wdrżał interfejs Window Controls Overlay API, korzystając z podstawowych zasad określonych w artykule Controlling Access to Powerful Web Platform Features (Zarządzanie dostępem do zaawansowanych funkcji platformy internetowej) (w języku angielskim), w tym kontroli użytkownika, przejrzystości i ergonomii.

Podszywanie się

Przyznanie stronom częściowej kontroli nad paskiem tytułu daje deweloperom możliwość podszywania treści w obszarze, który był wcześniej zaufanym obszarem kontrolowanym przez przeglądarkę. Obecnie w pełnowymiarowym trybie przeglądarek Chromium znajduje się pasek tytułu, na którym po pierwszym uruchomieniu wyświetla się tytuł strony internetowej po lewej stronie, a po prawej stronie – źródło strony (a zaraz potem przycisk „Ustawienia i więcej” oraz elementy sterujące oknem). Po kilku sekundach tekst źródłowy znika. Jeśli przeglądarka jest skonfigurowana pod kątem języka zapisywanego od prawej do lewej, układ jest odwrócony, tak aby tekst źródłowy znajdował się po lewej stronie. Spowoduje to otwarcie nakładki elementów sterujących oknem, aby oszukać źródło, jeśli między źródłem a prawą krawędzią nakładki jest za mało miejsca. Źródło „evil.ltd” może na przykład zawierać zaufany adres „google.com”, co może sprawić, że użytkownicy uznają, że źródło jest godne zaufania. Planujemy zachować ten tekst, aby użytkownicy wiedzieli, skąd pochodzi aplikacja, i mogli się upewnić, że spełnia ich oczekiwania. W przypadku przeglądarek skonfigurowanych do wyświetlania tekstu od prawej do lewej musi być wystarczająca ilość miejsca po prawej stronie tekstu źródła, aby uniemożliwić złośliwej witrynie dodanie do niebezpiecznego źródła zaufanej domeny.

Odciski cyfrowe

Włączenie nakładki z elementami sterującymi okna i przeciągalnych obszarów nie wiąże się z poważniejszymi problemami z prywatnością niż wykrywanie funkcji. Jednak ze względu na różne rozmiary i położenia przycisków sterowania oknem w różnych systemach operacyjnych metoda navigator.windowControlsOverlay.getTitlebarAreaRect() zwraca DOMRect, której położenie i wymiary zawierają informacje o systemie operacyjnym, w którym działa przeglądarka. Obecnie deweloperzy mogą już wykrywać system operacyjny na podstawie ciągu user-agenta, ale ze względu na problemy związane z odciskami cyfrowymi toczy się dyskusja na temat zamrożenia ciągu user-agenta i ujednolicania wersji systemu operacyjnego. W środowisku społeczności przeglądarek trwają prace nad ustaleniem, jak często zmienia się rozmiar nakładki elementów sterujących oknem na różnych platformach, ponieważ obecnie zakłada się, że te elementy są dość stabilne w różnych wersjach systemu operacyjnego i nie będą przydatne do obserwacji drobnych wersji systemu. Chociaż jest to potencjalny problem z odciskami palców, dotyczy on tylko zainstalowanych PWA, które korzystają z niestandardowej funkcji paska tytułu. Nie ma zastosowania do ogólnego korzystania z przeglądarki. Dodatkowo interfejs API navigator.windowControlsOverlay nie będzie dostępny dla ramek iframe umieszczonych w PWA.

Przejście do innego źródła w aplikacji PWA spowoduje przejście do zwykłego okna samodzielnego, nawet jeśli spełnia ono powyższe kryteria i jest uruchamiane z nakładką elementów sterujących okna. Jest to spowodowane czarnym paskiem, który pojawia się podczas nawigacji do innego miejsca wyjazdu. Po powrocie do pierwotnego źródła ponownie będzie używana nakładka elementów sterujących oknem.

Czarny pasek adresu URL do nawigacji poza domeną.
Gdy użytkownik przechodzi do innego źródła, wyświetla się czarny pasek.

Prześlij opinię

Zespół Chromium chce poznać Twoje wrażenia związane z interfejsem Window Controls Overlay API.

Prześlij informacje o projektowaniu interfejsu API

Czy coś w interfejsie API nie działa zgodnie z oczekiwaniami? A może brakuje metod lub właściwości, których potrzebujesz do wdrożenia swojego pomysłu? Masz pytania lub uwagi dotyczące modelu bezpieczeństwa? Zgłoś problem ze specyfikacją w odpowiednim repozytorium GitHub lub dodaj swoje uwagi do istniejącego problemu.

Zgłaszanie problemów z implementacją

Czy znalazłeś/znalazłaś błąd w implementacji Chromium? A może implementacja różni się od specyfikacji? Zgłoś błąd na stronie new.crbug.com. Podaj jak najwięcej szczegółów, proste instrukcje odtwarzania błędu i wpisz UI>Browser>WebAppInstalls w polu Składniki. Glitch to świetne narzędzie do szybkiego i łatwego udostępniania informacji o powtarzających się problemach.

Pokaż informacje o pomocy dotyczącej interfejsu API

Zamierzasz używać interfejsu Window Controls Overlay API? Twoja publiczna pomoc pomaga zespołowi Chromium ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest wspieranie Chromium.

Wyślij tweeta do @ChromiumDev z hasztagiem #WindowControlsOverlay i powiedz nam, gdzie i jak go używasz.

Przydatne linki

Podziękowania

Nakładkę z elementami sterującymi okna wdrożyła i opisywała Amanda Baker z zespołu Microsoft Edge. Ten artykuł został sprawdzony przez Joe MedleyaKennetha Rohde Christiansena. Baner powitalny autorstwa SigmundUnsplash.