Skip to content

Commit 52a33d7

Browse files
committed
feat: notification sound
1 parent 5a42aa8 commit 52a33d7

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

components/borrows/DropdownMenuBorrow.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function DropdownMenuBorrow() {
2424
<DropdownMenuGroup>
2525
<DropdownMenuItem>
2626
<BookUser className="mr-2 size-4" />
27-
<Link href="/borrows/new">Borrow a book</Link>
27+
<Link href="/admin/borrows/new">Borrow a book</Link>
2828
</DropdownMenuItem>
2929
</DropdownMenuGroup>
3030
</DropdownMenuContent>

components/dashboard/HeatmapChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export const HeatmapChart: React.FC<HeatmapChartProps> = ({
9999
return {
100100
x: decimalHour,
101101
y: localDayOfWeek,
102-
z: count * 100, // Scale up for bubble size
102+
z: count * 20, // Scale up for bubble size
103103
count,
104104
day: dayNames[localDayOfWeek],
105105
time: formatTime(localHour, localMinute),

components/nav-user.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,66 @@ export function NavUser({
2929
unread_notifications_count: number
3030
}
3131
}) {
32+
// Play iOS-inspired notification sound using Web Audio API
33+
const playNotificationSound = () => {
34+
const ctx = new window.AudioContext()
35+
const masterGain = ctx.createGain()
36+
masterGain.gain.setValueAtTime(0.2, ctx.currentTime)
37+
masterGain.connect(ctx.destination)
38+
39+
// iOS "Tri-tone" inspired melody with bell-like harmonics
40+
const fundamentalNotes = [
41+
{ freq: 659.25, time: 0.0, duration: 0.35 }, // E5
42+
{ freq: 783.99, time: 0.1, duration: 0.35 }, // G5
43+
{ freq: 1046.5, time: 0.2, duration: 0.4 }, // C6
44+
]
45+
46+
fundamentalNotes.forEach(({ freq, time, duration }) => {
47+
// Main tone
48+
const osc1 = ctx.createOscillator()
49+
const gain1 = ctx.createGain()
50+
osc1.type = 'sine'
51+
osc1.frequency.setValueAtTime(freq, ctx.currentTime + time)
52+
gain1.gain.setValueAtTime(0.4, ctx.currentTime + time)
53+
gain1.gain.exponentialRampToValueAtTime(
54+
0.01,
55+
ctx.currentTime + time + duration
56+
)
57+
osc1.connect(gain1)
58+
gain1.connect(masterGain)
59+
osc1.start(ctx.currentTime + time)
60+
osc1.stop(ctx.currentTime + time + duration)
61+
62+
// Harmonic (octave higher for bell-like quality)
63+
const osc2 = ctx.createOscillator()
64+
const gain2 = ctx.createGain()
65+
osc2.type = 'triangle'
66+
osc2.frequency.setValueAtTime(freq * 2, ctx.currentTime + time)
67+
gain2.gain.setValueAtTime(0.15, ctx.currentTime + time)
68+
gain2.gain.exponentialRampToValueAtTime(
69+
0.001,
70+
ctx.currentTime + time + duration * 0.7
71+
)
72+
osc2.connect(gain2)
73+
gain2.connect(masterGain)
74+
osc2.start(ctx.currentTime + time)
75+
osc2.stop(ctx.currentTime + time + duration * 0.7)
76+
77+
// Cleanup oscillators
78+
osc1.onended = () => osc1.disconnect()
79+
osc2.onended = () => osc2.disconnect()
80+
})
81+
82+
// Close audio context after sound completes
83+
setTimeout(() => {
84+
masterGain.disconnect()
85+
ctx.close()
86+
}, 800)
87+
}
88+
3289
useEffect(() => {
3390
function onMessage(data: Notification) {
91+
playNotificationSound()
3492
toast.info(data.title, {
3593
description: data.message,
3694
})

0 commit comments

Comments
 (0)