woohoo?!
This commit is contained in:
@@ -41,6 +41,88 @@ export default function ChatDetail({ chatId }: { chatId: string }) {
|
||||
const [message, setMessage] = useState("");
|
||||
const [sending, setSending] = useState(false);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const [previousMessageCount, setPreviousMessageCount] = useState<number>(0);
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
const markReadTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Initialize audio element
|
||||
useEffect(() => {
|
||||
// Create audio element for notification sound
|
||||
audioRef.current = new Audio('/notification.mp3');
|
||||
|
||||
// Fallback if notification.mp3 doesn't exist - use browser API for a simple beep
|
||||
audioRef.current.addEventListener('error', () => {
|
||||
audioRef.current = null;
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (audioRef.current) {
|
||||
audioRef.current = null;
|
||||
}
|
||||
|
||||
// Clear any pending timeouts when component unmounts
|
||||
if (markReadTimeoutRef.current) {
|
||||
clearTimeout(markReadTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Function to play notification sound
|
||||
const playNotificationSound = () => {
|
||||
if (audioRef.current) {
|
||||
audioRef.current.currentTime = 0;
|
||||
audioRef.current.play().catch(err => {
|
||||
console.log('Error playing sound:', err);
|
||||
// Fallback to simple beep if audio file fails
|
||||
try {
|
||||
const context = new (window.AudioContext || (window as any).webkitAudioContext)();
|
||||
const oscillator = context.createOscillator();
|
||||
oscillator.type = 'sine';
|
||||
oscillator.frequency.setValueAtTime(800, context.currentTime);
|
||||
oscillator.connect(context.destination);
|
||||
oscillator.start();
|
||||
oscillator.stop(context.currentTime + 0.2);
|
||||
} catch (e) {
|
||||
console.error('Could not play fallback audio', e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Fallback to simple beep if audio element is not available
|
||||
try {
|
||||
const context = new (window.AudioContext || (window as any).webkitAudioContext)();
|
||||
const oscillator = context.createOscillator();
|
||||
oscillator.type = 'sine';
|
||||
oscillator.frequency.setValueAtTime(800, context.currentTime);
|
||||
oscillator.connect(context.destination);
|
||||
oscillator.start();
|
||||
oscillator.stop(context.currentTime + 0.2);
|
||||
} catch (e) {
|
||||
console.error('Could not play fallback audio', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Function to mark messages as read
|
||||
const markMessagesAsRead = async () => {
|
||||
try {
|
||||
const authToken = getCookie("Authorization");
|
||||
|
||||
if (!authToken) return;
|
||||
|
||||
const authAxios = axios.create({
|
||||
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`
|
||||
}
|
||||
});
|
||||
|
||||
// Use dedicated endpoint to mark messages as read
|
||||
await authAxios.post(`/chats/${chatId}/mark-read`);
|
||||
console.log("Marked messages as read");
|
||||
} catch (error) {
|
||||
console.error("Error marking messages as read:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch chat data
|
||||
const fetchChat = async () => {
|
||||
@@ -62,9 +144,44 @@ export default function ChatDetail({ chatId }: { chatId: string }) {
|
||||
}
|
||||
});
|
||||
|
||||
const response = await authAxios.get(`/chats/${chatId}`);
|
||||
// Always fetch messages without marking as read
|
||||
const response = await authAxios.get(`/chats/${chatId}?markAsRead=false`);
|
||||
|
||||
// Check if there are new messages
|
||||
const hasNewMessages = chat && response.data.messages.length > chat.messages.length;
|
||||
const unreadBuyerMessages = response.data.messages.some(
|
||||
(msg: Message) => msg.sender === 'buyer' && !msg.read
|
||||
);
|
||||
|
||||
if (hasNewMessages) {
|
||||
// Don't play sound for messages we sent (vendor)
|
||||
const lastMessage = response.data.messages[response.data.messages.length - 1];
|
||||
if (lastMessage.sender === 'buyer') {
|
||||
playNotificationSound();
|
||||
}
|
||||
}
|
||||
|
||||
setChat(response.data);
|
||||
|
||||
// Update the previous message count
|
||||
if (response.data.messages) {
|
||||
setPreviousMessageCount(response.data.messages.length);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
|
||||
// Clear any existing timeout
|
||||
if (markReadTimeoutRef.current) {
|
||||
clearTimeout(markReadTimeoutRef.current);
|
||||
}
|
||||
|
||||
// Only mark as read with a delay if there are unread buyer messages
|
||||
if (unreadBuyerMessages) {
|
||||
// Add a 3-second delay before marking messages as read to allow notification to appear
|
||||
markReadTimeoutRef.current = setTimeout(() => {
|
||||
markMessagesAsRead();
|
||||
}, 3000);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching chat:", error);
|
||||
toast.error("Failed to load conversation");
|
||||
|
||||
Reference in New Issue
Block a user