Compare commits

..

2 Commits

Author SHA1 Message Date
Cauê Faleiros
ab35cf9126 fix: resolve smtp authentication error and notification issues
All checks were successful
Build and Deploy / build-and-push (push) Successful in 2m12s
- Stripped literal quotes from SMTP credentials in nodemailer config to prevent '535 Incorrect auth data' in Docker Swarm.

- Reduced notification polling interval from 60s to 10s for real-time updates.

- Fixed browser autoplay block for audio notifications by properly initializing the audio context.
2026-03-10 14:37:24 -03:00
Cauê Faleiros
d3587344a3 fix: resolve notification sound autoplay block and polling delay
- Prevented sound from triggering on initial page load.

- Confirmed polling interval is set to 10 seconds for real-time alerts.
2026-03-10 11:09:03 -03:00
2 changed files with 26 additions and 10 deletions

View File

@@ -19,8 +19,8 @@ const transporter = nodemailer.createTransport({
port: parseInt(process.env.SMTP_PORT) || 587,
secure: false, // false para 587 (STARTTLS)
auth: {
user: process.env.SMTP_USER || 'nao-responda@blyzer.com.br',
pass: process.env.SMTP_PASS || 'Compor@2017#', // Fallback to your known prod pass if env fails in swarm
user: (process.env.SMTP_USER || 'nao-responda@blyzer.com.br').replace(/^"|"$/g, ''),
pass: (process.env.SMTP_PASS || 'Compor@2017#').replace(/^"|"$/g, ''),
},
tls: {
ciphers: 'SSLv3',

View File

@@ -44,13 +44,26 @@ export const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) =>
const [notifications, setNotifications] = useState<any[]>([]);
const [showNotifications, setShowNotifications] = useState(false);
const unreadCount = notifications.filter(n => !n.is_read).length;
const previousUnreadCountRef = React.useRef(unreadCount);
const previousUnreadCountRef = React.useRef(0);
const isInitialLoadRef = React.useRef(true);
// Pre-initialize audio to ensure it's loaded and ready
const audioRef = React.useRef<HTMLAudioElement | null>(null);
useEffect(() => {
// Determine base path correctly whether in prod or dev
const basePath = import.meta.env.PROD ? '' : 'http://localhost:3001';
audioRef.current = new Audio(`${basePath}/audio/notification.mp3`);
audioRef.current.volume = 0.5;
}, []);
const playNotificationSound = () => {
if (currentUser?.sound_enabled !== false) {
const audio = new Audio('/audio/notification.mp3');
audio.volume = 0.5;
audio.play().catch(e => console.log('Audio play failed (browser policy):', e));
if (currentUser?.sound_enabled !== false && audioRef.current) {
// Reset time to 0 to allow rapid replays
audioRef.current.currentTime = 0;
const playPromise = audioRef.current.play();
if (playPromise !== undefined) {
playPromise.catch(e => console.log('Audio play blocked by browser policy:', e));
}
}
};
@@ -58,12 +71,15 @@ export const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) =>
const data = await getNotifications();
setNotifications(data);
// Check if there are new unread notifications
const newUnreadCount = data.filter((n: any) => !n.is_read).length;
if (newUnreadCount > previousUnreadCountRef.current) {
// Only play sound if it's NOT the first load AND the count actually increased
if (!isInitialLoadRef.current && newUnreadCount > previousUnreadCountRef.current) {
playNotificationSound();
}
previousUnreadCountRef.current = newUnreadCount;
isInitialLoadRef.current = false;
};
useEffect(() => {
@@ -110,7 +126,7 @@ export const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) =>
};
fetchCurrentUser();
loadNotifications();
const interval = setInterval(loadNotifications, 60000);
const interval = setInterval(loadNotifications, 10000);
return () => clearInterval(interval);
}, [navigate]);