fix: guide users through blocked notification permissions
This commit is contained in:
@@ -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.
|
- 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ı.
|
- 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ı.
|
- 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ı.
|
||||||
|
|||||||
@@ -36,7 +36,17 @@ const PwaPanel = () => {
|
|||||||
return () => { window.removeEventListener('online', changed); window.removeEventListener('offline', changed); };
|
return () => { window.removeEventListener('online', changed); window.removeEventListener('offline', changed); };
|
||||||
}, []);
|
}, []);
|
||||||
const [installed, setInstalled] = useState(false);
|
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
|
// E-posta (Resend) durumu + test gönderimi
|
||||||
const [emailCfg, setEmailCfg] = useState(null); // null=bilinmiyor, true/false
|
const [emailCfg, setEmailCfg] = useState(null); // null=bilinmiyor, true/false
|
||||||
@@ -64,12 +74,23 @@ const PwaPanel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEnablePush = async () => {
|
const handleEnablePush = async () => {
|
||||||
|
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();
|
const p = await requestPushPermission();
|
||||||
|
if(!alive.current)return;
|
||||||
setPermission(p);
|
setPermission(p);
|
||||||
if (p === 'granted') {
|
if(p==='granted')await saveReminderSettings(s=>({...s,pushEnabled:true}));
|
||||||
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 }));
|
const setQuiet = (patch) => saveReminderSettings((s) => ({ ...s, ...patch }));
|
||||||
|
|
||||||
// Gerçek PWA kurulumu: tarayıcı beforeinstallprompt verirse yerel diyalog;
|
// 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.
|
Bu uygulama açıkken alınan uyarıları tarayıcı bildirimi olarak gösterebilirsiniz. Kapalı uygulamaya arka plan push teslimi sağlanmaz.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{permission !== 'granted' ? (
|
{permission === 'denied' ? (
|
||||||
<button onClick={handleEnablePush} disabled={reminderSaving || permission === 'unsupported'}
|
<div className="space-y-2 text-xs text-slate-700">
|
||||||
|
<p>Bu site için bildirimler tarayıcı tarafından engellenmiş. Adres çubuğundaki site bilgileri veya tarayıcının site ayarlarından bildirim iznini değiştirin, ardından buraya dönün.</p>
|
||||||
|
<button onClick={refreshPermission} className="border rounded px-3 py-2">Bildirim iznini yeniden kontrol et</button>
|
||||||
|
</div>
|
||||||
|
) : permission === 'unsupported' ? (
|
||||||
|
<p className="text-xs text-slate-700">Bu tarayıcıda bildirim özelliği kullanılamıyor. Uygulama içindeki bildirim listesini kullanabilirsiniz.</p>
|
||||||
|
) : permission !== 'granted' ? (
|
||||||
|
<button onClick={handleEnablePush} disabled={reminderSaving || permissionBusy}
|
||||||
className="w-full bg-amber-500 hover:bg-amber-400 disabled:opacity-40 text-white font-bold text-xs py-2.5 rounded-xl">
|
className="w-full bg-amber-500 hover:bg-amber-400 disabled:opacity-40 text-white font-bold text-xs py-2.5 rounded-xl">
|
||||||
Bildirimlere İzin Ver
|
{permissionBusy?'İzin yanıtı bekleniyor…':'Bildirimlere İzin Ver'}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button onClick={() => notify('Test bildirimi', isQuietNow() || !reminderSettings.pushEnabled ? 'Tarayıcı bildirimi kapalı veya sessiz saatte — listeye eklendi.' : 'Tarayıcı bildirimi gösterim denemesi.')}
|
<button onClick={() => notify('Test bildirimi', isQuietNow() || !reminderSettings.pushEnabled ? 'Tarayıcı bildirimi kapalı veya sessiz saatte — listeye eklendi.' : 'Tarayıcı bildirimi gösterim denemesi.')}
|
||||||
@@ -180,11 +208,13 @@ const PwaPanel = () => {
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{permissionError&&<p role="alert" className="text-xs text-red-700">{permissionError}</p>}
|
||||||
{reminderError&&<p role="alert" className="text-xs text-red-700">{reminderError}</p>}
|
{reminderError&&<p role="alert" className="text-xs text-red-700">{reminderError}</p>}
|
||||||
{reminderSaving&&<p role="status" className="text-xs">Bildirim ayarları kaydediliyor…</p>}
|
{reminderSaving&&<p role="status" className="text-xs">Bildirim ayarları kaydediliyor…</p>}
|
||||||
<label className="flex justify-between text-xs font-bold">Tarayıcı bildirimlerini göster
|
<label className="flex justify-between text-xs font-bold">Tarayıcı bildirimlerini göster
|
||||||
<input type="checkbox" checked={reminderSettings.pushEnabled} disabled={reminderSaving} onChange={e=>setQuiet({pushEnabled:e.target.checked})}/>
|
<input type="checkbox" checked={reminderSettings.pushEnabled} disabled={reminderSaving} onChange={e=>setQuiet({pushEnabled:e.target.checked})}/>
|
||||||
</label>
|
</label>
|
||||||
|
{permission!=='granted'&&<p className="text-xs text-slate-600">Bildirim tercihiniz kaydedilir; tarayıcı izni verilmeden masaüstü bildirimi gösterilemez.</p>}
|
||||||
{/* Sessiz saatler — gerçek */}
|
{/* Sessiz saatler — gerçek */}
|
||||||
<div className="pt-2 border-t border-slate-100 space-y-2">
|
<div className="pt-2 border-t border-slate-100 space-y-2">
|
||||||
<p className="text-xs text-slate-500">Saatler bu cihazın yerel saatine göredir. Başlangıç ve bitiş aynıysa sessiz süre uygulanmaz.</p>
|
<p className="text-xs text-slate-500">Saatler bu cihazın yerel saatine göredir. Başlangıç ve bitiş aynıysa sessiz süre uygulanmaz.</p>
|
||||||
|
|||||||
@@ -592,8 +592,8 @@ export const AppProvider = ({ children }) => {
|
|||||||
};
|
};
|
||||||
const requestPushPermission = async () => {
|
const requestPushPermission = async () => {
|
||||||
if (!('Notification' in window)) return 'unsupported';
|
if (!('Notification' in window)) return 'unsupported';
|
||||||
if (Notification.permission === 'granted') return 'granted';
|
if (Notification.permission !== 'default') return Notification.permission;
|
||||||
try { return await Notification.requestPermission(); } catch { return 'denied'; }
|
return await Notification.requestPermission();
|
||||||
};
|
};
|
||||||
const refreshNotifications=async()=>{
|
const refreshNotifications=async()=>{
|
||||||
const session=getToken(),version=++notificationVersion.current;
|
const session=getToken(),version=++notificationVersion.current;
|
||||||
|
|||||||
Reference in New Issue
Block a user