feat: mobil uyumlu PWA — manifest, service worker, gercek kurulum, filtre cekmecesi

- public/manifest.webmanifest (standalone, tr, kisayollar) + 192/512 ve
  maskable ikonlar + apple-touch-icon; index.html PWA meta etiketleri
- public/sw.js: /assets cache-first (hash'li adlar), kabuk network-first,
  /api ASLA onbellekten (eski ihale gosterilmesin); surum degisince temizlik
- main.jsx: SW yalniz uretimde kaydedilir (dev'de HMR ile cakismasin)
- Mobil PWA sayfasindaki "Cihaza Yukle" dugmesi sahteydi (setInstalled(true));
  artik beforeinstallprompt ile gercek kurulum, standalone algilama, iOS/
  Android/masaustu yol tarifi
- Kucuk ekranda sol filtre paneli listeyi 72 satir asagi itiyordu: lg altinda
  "Filtreler" dugmesiyle acilan cekmece; sag panel xl altinda gizli

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 00:39:40 +03:00
co-authored by Claude Fable 5.1
parent acec88a4c4
commit fabff18fe9
12 changed files with 136 additions and 7 deletions
+30 -4
View File
@@ -57,9 +57,28 @@ export const PwaSettings = () => {
};
const setQuiet = (patch) => setReminderSettings((s) => ({ ...s, ...patch }));
const handleInstallPwa = () => {
setInstalled(true);
confetti({ particleCount: 70 });
// Gerçek PWA kurulumu: tarayıcı beforeinstallprompt verirse yerel diyalog;
// zaten standalone açıldıysa "yüklü"; iOS Safari'de olay yok → yol tarifi.
const [kurulumOlayi, setKurulumOlayi] = useState(null);
const [iosIpucu, setIosIpucu] = useState(false);
useEffect(() => {
const standalone = window.matchMedia?.('(display-mode: standalone)')?.matches || window.navigator.standalone === true;
if (standalone) setInstalled(true);
const yakala = (e) => { e.preventDefault(); setKurulumOlayi(e); };
const kuruldu = () => { setInstalled(true); setKurulumOlayi(null); };
window.addEventListener('beforeinstallprompt', yakala);
window.addEventListener('appinstalled', kuruldu);
return () => { window.removeEventListener('beforeinstallprompt', yakala); window.removeEventListener('appinstalled', kuruldu); };
}, []);
const handleInstallPwa = async () => {
if (kurulumOlayi) {
kurulumOlayi.prompt();
const { outcome } = await kurulumOlayi.userChoice.catch(() => ({ outcome: 'dismissed' }));
if (outcome === 'accepted') setInstalled(true);
setKurulumOlayi(null);
return;
}
setIosIpucu(true); // olay yoksa (iOS / zaten yüklü / desteklenmiyor) yol tarifi göster
};
return (
@@ -237,7 +256,7 @@ export const PwaSettings = () => {
{installed ? (
<>
<CheckCircle2 className="w-4 h-4 text-emerald-950" />
<span>Cihaza Yüklendi!</span>
<span>Uygulama olarak yüklü</span>
</>
) : (
<>
@@ -246,6 +265,13 @@ export const PwaSettings = () => {
</>
)}
</button>
{iosIpucu && !installed && (
<div className="bg-white/10 border border-white/15 rounded-xl p-3 text-[11px] text-slate-200 leading-relaxed space-y-1">
<p><strong className="text-white">iPhone / iPad (Safari):</strong> alttaki Paylaş simgesi → <strong>Ana Ekrana Ekle</strong>.</p>
<p><strong className="text-white">Android (Chrome):</strong> sağ üst ⋮ menü → <strong>Uygulamayı yükle</strong> / Ana ekrana ekle.</p>
<p><strong className="text-white">Masaüstü (Chrome/Edge):</strong> adres çubuğunun sağındaki yükleme simgesi.</p>
</div>
)}
</div>
</div>