LivaPwaInstall
Web uygulamasını ana ekrana kurmayı teklif eden banner ve tarayıcının kurulum
yeteneğini tek bir duruma indiren useLivaPwaInstall hook'u. Chromium tabanlı
tarayıcılarda (Android Chrome, Edge, masaüstü Chrome) "Yükle" butonu
tarayıcının yerel kurulum diyaloğunu açar. iOS'ta böyle bir diyalog olmadığı
için Paylaş menüsü adımlarını anlatan bir pencere gösterilir. Uygulama ana
ekrandan (standalone) açıldıysa bileşen hiçbir şey çizmez.
import { LivaPwaInstall, useLivaPwaInstall } from "@dataliva/livalib";
Temel kullanım
Bileşen uygulamada bir kez, teklifin görünmesini istediğiniz yere (ör. giriş
sayfası ya da kök layout) eklenir. document.body içine portal ile, ekranın
altına (position="top" ile üstüne) sabitlenmiş olarak çizilir. Telefonda
kenardan kenara bir çubuk, 576px ve üzeri genişlikte sağ köşeye oturan en
fazla 420px'lik bir kart olur; 400px'ten dar ekranlarda açıklama gizlenir ve
buton tam genişliğe iner. Alt/üst boşluk iOS'un güvenli alanını
(safe-area-inset) hesaba katar.
import { LivaPwaInstall } from "@dataliva/livalib";
import logo from "./assets/logo.png";
<LivaPwaInstall appName="LivaBudget" icon={<img src={logo} alt="LivaBudget" />} />
Bu sitede çalışan bir banner örneği yoktur: dokümantasyon sitesinin web app manifest'i olmadığı için tarayıcı kurulum olayını hiç tetiklemez ve bileşen (iOS dışında) görünmez. Bileşen önizleme amaçlı zorla gösterilemez; aşağıdaki canlı örnek bu yüzden hook'un döndürdüğü durumu gösterir.
Banner ne zaman görünür
Banner, delayMs (varsayılan 1500 ms) dolduktan sonra ve aşağıdaki koşulların
hepsi sağlandığında çizilir (shouldOffer):
- Kurulu değil — bu oturumda
appinstalledolayı görülmedi ve sayfa kurulu kabuk içinde açılmadı (display-modestandalone,fullscreenya daminimal-uideğil; iOS'tanavigator.standalonedeğil;android-app://yönlendiricisinden gelinmedi). - Ertelenmemiş — kullanıcı kapat (×) butonuna basmadı ya da basalı
remindAfterDaysgün geçti. - Platform listede — cihaz
platformslistesindeki bir platform. Varsayılan['ios', 'android']olduğu için masaüstünde varsayılan olarak görünmez. - Kurulum yolu var — tarayıcı
beforeinstallpromptolayını tetikledi (isPromptAvailable) ya da cihaz iOS ve adımların anlatılması gerekiyor (needsManualSteps). iOS'ta uygulama içi tarayıcılarda (Facebook, Instagram, Line, Twitter, WeChat)needsManualStepsfalseolduğundan teklif gösterilmez.
Platform userAgent'tan belirlenir; kendini masaüstü Safari gibi tanıtan
iPadOS 13+ dokunma noktası sayısından ayırt edilip ios sayılır.
Butonların davranışı
- Yükle — Tarayıcı olayı yakalanmışsa yerel diyaloğu açar ve kullanıcının
seçimini (
'accepted'/'dismissed') döner. Olay tek kullanımlıktır; diyalog kapandıktan sonra banner, tarayıcı olayı yeniden tetikleyene kadar (genellikle bir sonraki sayfa yüklemesi) kaybolur. Kurulum kabul edilirseisInstalledtrueolur. iOS'ta sonuç'manual'olur ve adım penceresi açılır; banner açık kalır. Diğer durumlarda'unavailable'döner. SonuçonInstall(result)ile bildirilir. - Kapat (×) — Teklifi erteler: zaman damgası
storageKeyanahtarıylalocalStorage'a yazılır ve teklifremindAfterDaysgün sonra yeniden görünür (0= bir daha sorma). ArdındanonDismissçağrılır. Tarayıcının yerel diyaloğundaki "İptal" erteleme sayılmaz.localStorageerişilemiyorsa (gizli sekme, engellenmiş depolama) erteleme yalnızca sayfa açık kaldığı sürece geçerli olur; sonraki açılışta teklif yeniden görünür.
Türkçe metinler ve sade görünüm
Bileşenin yerleşik metinleri İngilizcedir (Install Liva, Install App,
Not now…); Türkçe arayüzde i18n ile verilmelidir. appName yalnızca
i18n.title verilmediğinde başlıkta (Install <appName>) kullanılır.
compact banner'da yalnızca simge ile kurulum butonunu bırakır; başlık ve
açıklama çizilmez, başlık banner'ın erişilebilirlik etiketi olarak kalır.
iOS adım metinlerindeki {icon} belirteci ilgili simgeyle (Paylaş, Ana
Ekrana Ekle, Ekle) değiştirilir; çeviride simgenin cümledeki yeri bu sayede
kaydırılabilir. Adım penceresinin başlığı yalnızca instructionsTitle
verildiğinde çizilir. LivaBudget giriş sayfası bileşeni şöyle kullanır:
<LivaPwaInstall
appName="LivaBudget"
icon={<img src={logoIcon} alt="LivaBudget" />}
storageKey="livabudget-pwa-install-dismissed"
remindAfterDays={14}
compact
i18n={{
// compact modda çizilmez; banner'ın erişilebilirlik etiketi olur
title: "LivaBudget'ı Yükle",
installText: "Uygulamayı Yükle",
dismissText: "Şimdi değil",
instructionsTitle: "Ana ekrana eklemek için",
iosStep1: "Safari'de alttaki {icon} Paylaş butonuna dokunun",
iosStep2: '"Ana Ekrana Ekle" seçeneğine dokunun',
iosStep3: 'Sağ üstteki "Ekle" butonuna dokunun',
gotItText: "Anladım",
}}
/>
Aynı origin'de birden fazla uygulama çalışıyorsa her birine ayrı bir
storageKey verin; aksi hâlde birinde yapılan erteleme diğerini de susturur.
Not: Adım metinleri iOS tarayıcısına göre değişmez (varsayılan metin
Safari'yi anlatır). Chrome ya da Firefox için farklı metin göstermek
isterseniz hook'un döndürdüğü iosBrowser değerine göre i18n'i kendiniz
seçebilirsiniz.
Masaüstünde de teklif etmek
platforms listesine 'desktop' eklenirse teklif, kurulabilir durumdaki
masaüstü Chromium tarayıcılarında da görünür.
<LivaPwaInstall
appName="LivaBudget"
platforms={["ios", "android", "desktop"]}
position="top"
delayMs={3000}
onInstall={(result) => console.log("PWA kurulum sonucu:", result)}
onDismiss={() => console.log("Kurulum teklifi ertelendi")}
/>
useLivaPwaInstall
Banner'ın kullandığı durum hook'u; kendi arayüzünüzü (ör. kullanıcı menüsünde
kalıcı bir "Uygulamayı yükle" satırı) kurmak için doğrudan kullanılabilir.
Aşağıdaki örnek hook'u 'desktop' dahil tüm platformlarla çağırır ve şu anki
tarayıcınızın değerlerini gösterir. Bu sitede manifest olmadığı için
masaüstünde ve Android'de isPromptAvailable false'tur ve install()
'unavailable' döner; iPhone/iPad Safari'de ise needsManualSteps true olur
ve install() 'manual' döner. dismiss() ve resetDismissal() erteleme
kaydını yazar/siler; isDismissed ve shouldOffer anında güncellenir.
shouldOffer erteleme ve platform koşullarını da içerir. Kullanıcının
ertelemesinden etkilenmemesi gereken kalıcı bir menü öğesi için tekil
alanları kullanın:
import { useLivaPwaInstall } from "@dataliva/livalib";
function InstallMenuItem({ onShowIosSteps }: { onShowIosSteps: () => void }) {
const pwa = useLivaPwaInstall();
if (pwa.isInstalled || (!pwa.isPromptAvailable && !pwa.needsManualSteps)) return null;
return (
<button
type="button"
onClick={async () => {
const result = await pwa.install();
if (result === "manual") onShowIosSteps(); // iOS: adımları kendi pencerenizde anlatın
}}
>
Uygulamayı yükle
</button>
);
}
platforms seçeneği yalnızca shouldOffer'ı etkiler; isPromptAvailable,
needsManualSteps ve isInstalled her platformda doğru değeri taşır.
Kurulum olayının yakalanması
beforeinstallprompt sayfa başına bir kez ve erken tetiklenir; React ağacı
kurulana kadar beklenirse kaçar. Bu yüzden livalib, modül yüklenir yüklenmez
window'a dinleyici bağlar (primeLivaPwaInstall), olayı saklar ve
preventDefault() ile tarayıcının kendi otomatik kurulum teklifini bastırır.
Durum modül düzeyinde tutulduğu için aynı sayfadaki tüm hook örnekleri ve
banner aynı olayı paylaşır; appinstalled olayı hepsinde isInstalled'ı
true yapar.
Önemli: Dinleyici LivaPwaInstall kullanılmasa bile livalib import edildiği
anda bağlanır. Yani livalib kullanan her uygulamada tarayıcının otomatik
kurulum teklifi (Android Chrome'daki mini bilgi çubuğu) görünmez; kurulum
teklifi bu bileşen ya da hook ile sunulmalıdır.
livalib geç yüklenen bir chunk içindeyse olay chunk yüklenmeden tetiklenip
kaçabilir. Bu durumda primeLivaPwaInstall()'ı uygulamanın giriş dosyasında
erkenden çağırın; birden fazla çağrı güvenlidir:
// main.tsx
import { primeLivaPwaInstall } from "@dataliva/livalib";
primeLivaPwaInstall();
Uygulama tarafında gerekenler
Bileşen manifest üretmez ve service worker kaydetmez; yalnızca tarayıcının
verdiği kurulum olayını yönetir. Chromium'un beforeinstallprompt olayını
tetiklemesi için uygulamanın tarayıcının kurulabilirlik ölçütlerini karşılaması
gerekir: HTTPS (geliştirmede localhost) üzerinden sunulmalı ve name /
short_name, icons, start_url ile display alanlarını içeren bir web app
manifest'i bulunmalıdır. LivaBudget'ta manifest ve service worker
vite-plugin-pwa ile üretilir.
Manifest'teki display değerini standalone (ya da fullscreen /
minimal-ui) yapın: bileşen kurulu açılışı bu display-mode medya
sorgularıyla tanır ve ana ekrandan açılan uygulamada teklifi göstermez.
LivaPwaInstall
| Prop | Tip | Varsayılan |
|---|---|---|
appName | string | 'Liva' |
icon | ReactNode | — (verilmezse simge alanı çizilmez) |
i18n | LivaPwaInstallI18n | — (İngilizce metinler) |
storageKey | string | 'liva-pwa-install-dismissed' |
remindAfterDays | number | 7 (0 = bir daha sorma) |
platforms | LivaPwaPlatform[] | ['ios', 'android'] |
delayMs | number | 1500 (0 ya da altı = hemen) |
position | 'bottom' | 'top' | 'bottom' |
compact | boolean | false |
onInstall | (result: LivaPwaInstallResult) => void | — |
onDismiss | () => void | — |
className | string | '' |
LivaPwaInstallI18n
| Alan | Kullanıldığı yer | Varsayılan |
|---|---|---|
title | Banner başlığı ve erişilebilirlik etiketi | `Install ${appName}` |
description | Banner açıklaması | 'Add it to your home screen and open it like a native app.' |
installText | Kurulum butonu | 'Install App' |
dismissText | Kapat butonunun etiketi ve ipucu | 'Not now' |
instructionsTitle | iOS adım penceresinin başlığı | — (verilmezse başlık çizilmez) |
iosStep1 | 1. adım ({icon} = Paylaş simgesi) | 'Tap the {icon} Share button in the bottom bar of Safari' |
iosStep2 | 2. adım ({icon} = Ana Ekrana Ekle simgesi) | 'Choose "Add to Home Screen"' |
iosStep3 | 3. adım ({icon} = Ekle simgesi) | 'Tap "Add" at the top right' |
gotItText | Adım penceresini kapatan buton | 'Got it' |
useLivaPwaInstall seçenekleri
| Alan | Tip | Varsayılan |
|---|---|---|
storageKey | string | 'liva-pwa-install-dismissed' |
remindAfterDays | number | 7 |
platforms | LivaPwaPlatform[] | ['ios', 'android'] |
useLivaPwaInstall — dönen değer (LivaPwaInstallState)
| Alan | Tip | Açıklama |
|---|---|---|
platform | LivaPwaPlatform | 'ios', 'android' ya da 'desktop'. |
iosBrowser | LivaPwaIosBrowser | iOS'taki tarayıcı: 'safari', 'chrome', 'firefox', 'edge', 'in-app'. iOS dışında da hesaplanır (genellikle 'safari'). |
isStandalone | boolean | Uygulama ana ekrandan / kurulu kabuktan açılmış. |
isInstalled | boolean | Bu oturumda kurulum tamamlandı ya da zaten kabuk içindeyiz. |
isPromptAvailable | boolean | Tarayıcının yerel kurulum diyaloğu açılabilir. |
needsManualSteps | boolean | iOS, yerel diyalog yok ve uygulama içi tarayıcı değil — adımlar anlatılmalı. |
isDismissed | boolean | Teklif ertelendi ve süre dolmadı. |
shouldOffer | boolean | Teklif gösterilmeli mi — yukarıdakilerin ve platforms'un bileşkesi. |
install | () => Promise<LivaPwaInstallResult> | Yerel diyaloğu açar; diyalog yoksa iOS'ta 'manual', diğerlerinde 'unavailable' döner. |
dismiss | () => void | Teklifi erteler (süre remindAfterDays). |
resetDismissal | () => void | Erteleme kaydını siler. |
Tipler ve yardımcılar
| Ad | Değer |
|---|---|
LivaPwaPlatform | 'ios' | 'android' | 'desktop' |
LivaPwaIosBrowser | 'safari' | 'chrome' | 'firefox' | 'edge' | 'in-app' |
LivaPwaInstallResult | 'accepted' | 'dismissed' | 'manual' | 'unavailable' |
LivaBeforeInstallPromptEvent | Chromium'un standart dışı beforeinstallprompt olayı: platforms, userChoice, prompt() |
primeLivaPwaInstall | () => void — olay dinleyicisini bağlar; modül yüklenirken kendiliğinden çağrılır, tekrar çağrı güvenlidir. |
Ayrıca LivaPwaInstallProps, UseLivaPwaInstallOptions ve
LivaPwaInstallState tipleri dışa açıktır.