Add notification sound picker with live preview
Notification sound toggle now reveals a Sound sub-row with a dropdown (Chime, Bell, Ping, Ding, Pop, Classic, Subtle) and a Preview button that plays the selected tone via Web Audio API — no audio files needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -785,9 +785,57 @@ function SettingsTheme({ls,setLS,lC,C,loginBg,setLoginBg,loginDark,setLoginDark}
|
||||
}
|
||||
|
||||
function SettingsNotifications({ls,setLS,C}){
|
||||
const SOUNDS=[
|
||||
{id:"chime", label:"Chime"},
|
||||
{id:"bell", label:"Bell"},
|
||||
{id:"ping", label:"Ping"},
|
||||
{id:"ding", label:"Ding"},
|
||||
{id:"pop", label:"Pop"},
|
||||
{id:"classic",label:"Classic"},
|
||||
{id:"subtle", label:"Subtle"},
|
||||
];
|
||||
|
||||
function playSound(id){
|
||||
try{
|
||||
const ctx=new (window.AudioContext||window.webkitAudioContext)();
|
||||
const tone=(freq,start,dur,type="sine",vol=0.28)=>{
|
||||
const osc=ctx.createOscillator(),g=ctx.createGain();
|
||||
osc.connect(g);g.connect(ctx.destination);
|
||||
osc.type=type;osc.frequency.setValueAtTime(freq,ctx.currentTime+start);
|
||||
g.gain.setValueAtTime(0,ctx.currentTime+start);
|
||||
g.gain.linearRampToValueAtTime(vol,ctx.currentTime+start+0.015);
|
||||
g.gain.exponentialRampToValueAtTime(0.001,ctx.currentTime+start+dur);
|
||||
osc.start(ctx.currentTime+start);osc.stop(ctx.currentTime+start+dur+0.05);
|
||||
};
|
||||
if(id==="chime") {tone(1319,0,0.5);tone(1047,0.18,0.45);tone(1568,0.36,0.7);}
|
||||
else if(id==="bell") {tone(440,0,1.2);tone(880,0.05,0.9,undefined,0.15);}
|
||||
else if(id==="ping") {tone(1400,0,0.25,undefined,0.22);}
|
||||
else if(id==="ding") {tone(880,0,0.18);tone(660,0.2,0.4);}
|
||||
else if(id==="pop") {tone(220,0,0.08,"triangle",0.45);}
|
||||
else if(id==="classic"){tone(660,0,0.18);tone(880,0.22,0.28);}
|
||||
else if(id==="subtle") {tone(600,0,0.35,undefined,0.12);}
|
||||
setTimeout(()=>ctx.close(),2500);
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
const selSt={background:C.inputBg,border:`1px solid ${C.inBorder}`,borderRadius:5,
|
||||
padding:"4px 8px",color:C.text,fontFamily:FONT,fontSize:13,outline:"none"};
|
||||
|
||||
return <SCard C={C}>
|
||||
<SRow label="Desktop notifications" sub="Show popup for new messages" C={C}><Toggle on={ls.notifications} onChange={v=>setLS(p=>({...p,notifications:v}))} C={C}/></SRow>
|
||||
<SRow label="Notification sound" sub="Play a sound on new mail" C={C}><Toggle on={ls.sound} onChange={v=>setLS(p=>({...p,sound:v}))} C={C}/></SRow>
|
||||
{ls.sound&&<SRow label="Sound" sub="Choose notification tone" C={C}>
|
||||
<div style={{display:"flex",gap:6,alignItems:"center"}}>
|
||||
<select value={ls.soundChoice||"chime"} onChange={e=>setLS(p=>({...p,soundChoice:e.target.value}))} style={selSt}>
|
||||
{SOUNDS.map(s=><option key={s.id} value={s.id}>{s.label}</option>)}
|
||||
</select>
|
||||
<button onClick={()=>playSound(ls.soundChoice||"chime")}
|
||||
style={{background:C.accent,border:"none",borderRadius:5,padding:"4px 10px",
|
||||
color:"#fff",fontFamily:FONT,fontSize:12,cursor:"pointer",display:"flex",alignItems:"center",gap:4}}>
|
||||
<i className="ti ti-player-play" style={{fontSize:11}} aria-hidden="true"/> Preview
|
||||
</button>
|
||||
</div>
|
||||
</SRow>}
|
||||
<SRow label="Badge count" sub="Show unread count on taskbar" C={C}><Toggle on={true} C={C}/></SRow>
|
||||
<SRow label="Notification preview" sub="Show sender and subject in popup" C={C}><Toggle on={true} C={C}/></SRow>
|
||||
<SRow label="Do not disturb" sub="Silence all notifications" C={C}><Toggle on={false} C={C}/></SRow>
|
||||
|
||||
Reference in New Issue
Block a user