From 38227862c0c9511afdf3d6bda9f70a77dcaa4f30 Mon Sep 17 00:00:00 2001
From: ht
Date: Sun, 6 Sep 2026 14:41:24 +0300
Subject: [PATCH] fix: guide users through blocked notification permissions
---
docs/quality/uygulama-durumu.md | 7 +++++
src/components/tools/PwaSettings.jsx | 46 +++++++++++++++++++++++-----
src/context/AppContext.jsx | 4 +--
3 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md
index 9abd3f6..f8ab2cc 100644
--- a/docs/quality/uygulama-durumu.md
+++ b/docs/quality/uygulama-durumu.md
@@ -1094,3 +1094,10 @@ Taslak türü seçicisine erişilebilir ad eklendi. Üretim derlemesi geçti. Ö
- Kaynak: Telegram Bot API `sendMessage` başarılı yanıtta Message döndürür: https://core.telegram.org/bots/api#sendmessage . Kabul kaydı alıcının mesajı okuduğu anlamına gelmez.
- Doğrulama: 262 test geçti; değişen sunucu dosyaları sözdizimi kontrolünden geçti. Yeni testler geçerli negatif sohbet kimliği, eksik/geçersiz kimlikler, yanlış sohbet, HTTP hata gövdesinde yanıltıcı ok, kalıcı kabul kimliği ve eksik kabul sonrası belirsiz durumu kapsıyor. Gerçek sağlayıcı çağrısı yapılmadı. Ön yüz değişmediği için son başarılı build tekrar çalıştırılmadı.
- Genel plan, izinli gerçek sağlayıcı kabulü ve kalan uçtan uca kontroller açısından henüz tamamlanmadı.
+
+### 2026-09-06 — Tarayıcı bildirim izni kullanıcı deneyimi
+
+- Engellenmiş izin durumunda tekrar izin isteme düğmesi kaldırıldı; site ayarlarına yönlendirme ve mevcut izni yeniden okuma düğmesi gösteriliyor. Desteklenmeyen tarayıcıya kullanılamayan izin düğmesi yerine uygulama içi liste açıklaması veriliyor.
+- Sekmeye/pencereye geri dönüldüğünde izin durumu yeniden okunuyor. İzin isteme beklerken ikinci çağrı engelleniyor; kapanmış ekran güncellenmiyor. Teknik izin hatası artık doğrudan `denied` sayılmıyor; hata mesajı ve tarayıcının gerçek durumu korunuyor. Kayıtlı bildirim tercihi ile cihazın izin durumu arasındaki fark açıklandı.
+- Doğrulama: son build başarılı. İzole gerçek tarayıcıda beş kontrol geçti: engellenmiş durum, site ayarı açıklaması, tekrar izin düğmesinin yokluğu, yeniden kontrolde durumun korunması ve kayıtlı tercih açıklaması. Kanıt `rapor/qa-notification-permission.json`. Test sekmesi ve bu çalışmanın geçici sunucusu kapatıldı. Bu UI değişikliğinde tam otomatik süit tekrar çalıştırılmadı; önceki süit 262 testte geçmişti.
+- Desteklenmeyen/ilk izin/işletim sistemi penceresi ve farklı tarayıcıların izin değişimi olayları ayrıca kabul edilmeli. Gerçek bildirim gönderilmedi; genel plan tamamlanmadı.
diff --git a/src/components/tools/PwaSettings.jsx b/src/components/tools/PwaSettings.jsx
index 5b6b45f..02f8b36 100644
--- a/src/components/tools/PwaSettings.jsx
+++ b/src/components/tools/PwaSettings.jsx
@@ -36,7 +36,17 @@ const PwaPanel = () => {
return () => { window.removeEventListener('online', changed); window.removeEventListener('offline', changed); };
}, []);
const [installed, setInstalled] = useState(false);
- const [permission, setPermission] = useState(typeof Notification !== 'undefined' ? Notification.permission : 'unsupported');
+ const readPermission = () => typeof Notification !== 'undefined' ? Notification.permission : 'unsupported';
+ const [permission, setPermission] = useState(readPermission);
+ const [permissionBusy,setPermissionBusy]=useState(false),[permissionError,setPermissionError]=useState(null);
+ const permissionLock=useRef(false);
+ const refreshPermission=()=>setPermission(readPermission());
+ useEffect(()=>{
+ const refresh=()=>{if(document.visibilityState==='visible')refreshPermission();};
+ window.addEventListener('focus',refresh);
+ document.addEventListener('visibilitychange',refresh);
+ return()=>{window.removeEventListener('focus',refresh);document.removeEventListener('visibilitychange',refresh);};
+ },[]);
// E-posta (Resend) durumu + test gönderimi
const [emailCfg, setEmailCfg] = useState(null); // null=bilinmiyor, true/false
@@ -64,12 +74,23 @@ const PwaPanel = () => {
};
const handleEnablePush = async () => {
- const p = await requestPushPermission();
- setPermission(p);
- if (p === 'granted') {
- await saveReminderSettings((s) => ({ ...s, pushEnabled: true }));
+ if(permissionLock.current || reminderSaving)return;
+ const current=readPermission();setPermission(current);
+ if(current==='denied'||current==='unsupported')return;
+ permissionLock.current=true;setPermissionBusy(true);setPermissionError(null);
+ try {
+ const p = await requestPushPermission();
+ if(!alive.current)return;
+ setPermission(p);
+ if(p==='granted')await saveReminderSettings(s=>({...s,pushEnabled:true}));
+ } catch(error) {
+ if(alive.current){refreshPermission();setPermissionError(error.message || 'Bildirim izni alınamadı.');}
+ } finally {
+ permissionLock.current=false;
+ if(alive.current)setPermissionBusy(false);
}
};
+
const setQuiet = (patch) => saveReminderSettings((s) => ({ ...s, ...patch }));
// Gerçek PWA kurulumu: tarayıcı beforeinstallprompt verirse yerel diyalog;
@@ -168,10 +189,17 @@ const PwaPanel = () => {
Bu uygulama açıkken alınan uyarıları tarayıcı bildirimi olarak gösterebilirsiniz. Kapalı uygulamaya arka plan push teslimi sağlanmaz.