From 67ab6f5a2724321c976bb61de3ee268c392cacc0 Mon Sep 17 00:00:00 2001
From: Sanika Tavate
Date: Tue, 9 Jun 2026 20:29:20 +0530
Subject: [PATCH] fix(ux): implement auto-pause audio playback interceptor #531
---
frontend/components/chat/MessageBubble.jsx | 42 +++++++++++++++-------
frontend/src/store/useChatStore.js | 6 +++-
2 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/frontend/components/chat/MessageBubble.jsx b/frontend/components/chat/MessageBubble.jsx
index 32203be..7b3f47d 100644
--- a/frontend/components/chat/MessageBubble.jsx
+++ b/frontend/components/chat/MessageBubble.jsx
@@ -1,7 +1,8 @@
import { Check, CheckCheck, Pin, Languages} from "lucide-react"
import Avatar from "./Avatar"
-import { useState } from "react"
+import { useState, useEffect, useRef } from "react"
import ReplyPreview from "./ReplyPreview"
+import useChatStore from "../../src/store/useChatStore"
const formatTime = (d) =>
new Date(d).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
@@ -10,9 +11,18 @@ const formatTime = (d) =>
export default function MessageBubble({ msg, isMine, showTime, selectedUser, isOnline, authUser, onContextMenu, onTouchStart, onTouchEnd, onReact }) {
const [showTranslation, setShowTranslation] = useState(false)
- const [selectedImage, setSelectedImage] = useState(null)
const [isSelected, setIsSelected] = useState(false)
+ const activeAudioId = useChatStore((state) => state.activeAudioId)
+ const setActiveAudioId = useChatStore((state) => state.setActiveAudioId)
+ const audioRef = useRef(null)
+
+ useEffect(() => {
+ if (activeAudioId && activeAudioId !== msg._id && audioRef.current) {
+ audioRef.current.pause()
+ }
+ }, [activeAudioId, msg._id])
+
const getTranslatedText = (text) => {
const translations = {
hello: "hola",
@@ -93,7 +103,7 @@ export default function MessageBubble({ msg, isMine, showTime, selectedUser, isO
src={msg.image}
alt="attachment"
className="max-w-full rounded-lg mb-1 cursor-pointer hover:opacity-90 transition"
- onClick={() => setSelectedImage(msg.image)}
+ onClick={() => window.open(msg.image, "_blank")}
/>
)}
@@ -105,9 +115,21 @@ export default function MessageBubble({ msg, isMine, showTime, selectedUser, isO
{msg.edited && (
diff --git a/frontend/src/store/useChatStore.js b/frontend/src/store/useChatStore.js
index 061820c..e7188cd 100644
--- a/frontend/src/store/useChatStore.js
+++ b/frontend/src/store/useChatStore.js
@@ -16,6 +16,7 @@ const useChatStore = create((set, get) => ({
isMessagesLoading: false,
hasMore: false,
isLoadingMore: false,
+ activeAudioId: null,
getUsers: async () => {
set({ isUsersLoading: true });
@@ -348,7 +349,7 @@ const useChatStore = create((set, get) => ({
},
setSelectedUser: (user) => {
- if (!user) return set({ selectedUser: null, messages: [] });
+ if (!user) return set({ selectedUser: null, messages: [], activeAudioId: null });
const current = get().selectedUser;
if (current?._id === user?._id) return;
@@ -356,11 +357,14 @@ const useChatStore = create((set, get) => ({
set((state) => ({
selectedUser: user,
messages: [],
+ activeAudioId: null,
users: state.users.map((u) =>
u._id === user._id ? { ...u, unreadCount: 0 } : u
),
}));
},
+
+ setActiveAudioId: (id) => set({ activeAudioId: id }),
}));
export default useChatStore;
\ No newline at end of file