fix(voice): handle browser autoplay block — flush pending audio on interaction
This commit is contained in:
@@ -1,8 +1,27 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useRef, useCallback } from 'react';
|
||||
import { useVoiceStore } from '../stores/voice.ts';
|
||||
import { Track, RoomEvent } from 'livekit-client';
|
||||
import type { Participant, TrackPublication, Room } from 'livekit-client';
|
||||
|
||||
// ponytail: global set of audio elements blocked by autoplay policy
|
||||
const pendingAudio = new Set<HTMLAudioElement>();
|
||||
|
||||
function flushPendingAudio() {
|
||||
for (const el of pendingAudio) {
|
||||
el.play().catch(() => {});
|
||||
pendingAudio.delete(el);
|
||||
}
|
||||
}
|
||||
|
||||
// ponytail: one-time document listener to flush on any user interaction
|
||||
let listenerAttached = false;
|
||||
function ensureInteractionListener() {
|
||||
if (listenerAttached) return;
|
||||
listenerAttached = true;
|
||||
document.addEventListener('click', flushPendingAudio, { once: false });
|
||||
document.addEventListener('keydown', flushPendingAudio, { once: false });
|
||||
}
|
||||
|
||||
function RemoteAudioTrack({ participant, room }: { participant: Participant; room: Room }) {
|
||||
const audioRef = useRef<HTMLAudioElement>(null);
|
||||
|
||||
@@ -12,28 +31,34 @@ function RemoteAudioTrack({ participant, room }: { participant: Participant; roo
|
||||
|
||||
let pub: TrackPublication | undefined;
|
||||
|
||||
const tryPlay = () => {
|
||||
el.play().catch(() => {
|
||||
pendingAudio.add(el);
|
||||
ensureInteractionListener();
|
||||
});
|
||||
};
|
||||
|
||||
const attachIfReady = () => {
|
||||
pub = participant.getTrackPublication(Track.Source.Microphone);
|
||||
if (pub?.track && el) {
|
||||
pub.track.attach(el);
|
||||
el.play().catch(() => {});
|
||||
tryPlay();
|
||||
}
|
||||
};
|
||||
|
||||
// ponytail: check immediately — track may already be subscribed
|
||||
attachIfReady();
|
||||
|
||||
// ponytail: also listen for delayed subscription
|
||||
const handleSubscribed = (track: Track, _pub: TrackPublication, p: Participant) => {
|
||||
if (p.identity === participant.identity && _pub.source === Track.Source.Microphone) {
|
||||
track.attach(el);
|
||||
el.play().catch(() => {});
|
||||
tryPlay();
|
||||
}
|
||||
};
|
||||
room.on(RoomEvent.TrackSubscribed, handleSubscribed);
|
||||
|
||||
return () => {
|
||||
if (pub?.track) pub.track.detach(el);
|
||||
pendingAudio.delete(el);
|
||||
room.off(RoomEvent.TrackSubscribed, handleSubscribed);
|
||||
};
|
||||
}, [participant, room]);
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AudioRenderers.tsx","./src/components/BotManager.tsx","./src/components/CalendarView.tsx","./src/components/ChannelList.tsx","./src/components/ChannelSettingsModal.tsx","./src/components/ChatArea.tsx","./src/components/CommandDropdown.tsx","./src/components/CommandManager.tsx","./src/components/ConnectionStatus.tsx","./src/components/ContextMenu.tsx","./src/components/ConversationList.tsx","./src/components/CreateChannelModal.tsx","./src/components/CreateServerModal.tsx","./src/components/DMChat.tsx","./src/components/DeviceSettingsModal.tsx","./src/components/DocsView.tsx","./src/components/EmojiPicker.tsx","./src/components/ExpandableImage.tsx","./src/components/FeatureRequestsPanel.tsx","./src/components/ForgotPasswordPage.tsx","./src/components/FormatToolbar.tsx","./src/components/ForumView.tsx","./src/components/GiphyPicker.tsx","./src/components/InstallBanner.tsx","./src/components/InstallPrompt.tsx","./src/components/InviteModal.tsx","./src/components/JoinServer.tsx","./src/components/JoinServerModal.tsx","./src/components/Layout.tsx","./src/components/ListView.tsx","./src/components/LoginForm.tsx","./src/components/MemberContextMenu.tsx","./src/components/MemberList.tsx","./src/components/MemberRoleAssign.tsx","./src/components/MentionDropdown.tsx","./src/components/MentionPopup.tsx","./src/components/MessageInput.tsx","./src/components/MessageSearch.tsx","./src/components/MobileDrawer.tsx","./src/components/MobileNav.tsx","./src/components/NewConversationModal.tsx","./src/components/NotificationPrompt.tsx","./src/components/PinnedMessages.tsx","./src/components/Poll.tsx","./src/components/ReactionBar.tsx","./src/components/ReplyBar.tsx","./src/components/ResetPasswordPage.tsx","./src/components/RoleManager.tsx","./src/components/ServerBar.tsx","./src/components/ServerSettingsModal.tsx","./src/components/SlashCommandPopup.tsx","./src/components/ThemeToggle.tsx","./src/components/ThreadListPanel.tsx","./src/components/ThreadPanel.tsx","./src/components/TypingIndicator.tsx","./src/components/UserProfileModal.tsx","./src/components/UserSettings.tsx","./src/components/VideoGrid.tsx","./src/components/VoiceChannel.tsx","./src/components/VoiceControls.tsx","./src/components/VoicePanel.tsx","./src/lib/api.ts","./src/lib/kaomojiData.ts","./src/lib/slashCommands.ts","./src/lib/usePermissions.ts","./src/stores/auth.ts","./src/stores/bot.ts","./src/stores/channel.ts","./src/stores/conversation.ts","./src/stores/featureRequest.ts","./src/stores/layout.ts","./src/stores/member.ts","./src/stores/message.ts","./src/stores/moderation.ts","./src/stores/notificationSettings.ts","./src/stores/permissions.ts","./src/stores/presence.ts","./src/stores/push.ts","./src/stores/readStates.ts","./src/stores/role.ts","./src/stores/server.ts","./src/stores/thread.ts","./src/stores/typing.ts","./src/stores/voice.ts","./src/stores/voicePresence.ts","./src/stores/ws.ts"],"version":"5.9.3"}
|
||||
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AudioRenderers.tsx","./src/components/BotManager.tsx","./src/components/CalendarView.tsx","./src/components/ChannelList.tsx","./src/components/ChannelSettingsModal.tsx","./src/components/ChatArea.tsx","./src/components/CommandDropdown.tsx","./src/components/CommandManager.tsx","./src/components/ConnectionStatus.tsx","./src/components/ContextMenu.tsx","./src/components/ConversationList.tsx","./src/components/CreateChannelModal.tsx","./src/components/CreateServerModal.tsx","./src/components/DMChat.tsx","./src/components/DeviceSettingsModal.tsx","./src/components/DocsView.tsx","./src/components/EmojiPicker.tsx","./src/components/ExpandableImage.tsx","./src/components/FeatureRequestsPanel.tsx","./src/components/ForgotPasswordPage.tsx","./src/components/FormatToolbar.tsx","./src/components/ForumView.tsx","./src/components/GiphyPicker.tsx","./src/components/InstallBanner.tsx","./src/components/InstallPrompt.tsx","./src/components/InviteModal.tsx","./src/components/JoinServer.tsx","./src/components/JoinServerModal.tsx","./src/components/Layout.tsx","./src/components/ListView.tsx","./src/components/LoginForm.tsx","./src/components/MemberContextMenu.tsx","./src/components/MemberList.tsx","./src/components/MemberRoleAssign.tsx","./src/components/MentionDropdown.tsx","./src/components/MentionPopup.tsx","./src/components/MessageInput.tsx","./src/components/MessageSearch.tsx","./src/components/MobileDrawer.tsx","./src/components/MobileNav.tsx","./src/components/NewConversationModal.tsx","./src/components/NotificationPrompt.tsx","./src/components/PinnedMessages.tsx","./src/components/Poll.tsx","./src/components/ReactionBar.tsx","./src/components/ReplyBar.tsx","./src/components/ResetPasswordPage.tsx","./src/components/RoleManager.tsx","./src/components/ServerBar.tsx","./src/components/ServerSettingsModal.tsx","./src/components/SlashCommandPopup.tsx","./src/components/ThemeToggle.tsx","./src/components/ThreadListPanel.tsx","./src/components/ThreadPanel.tsx","./src/components/TypingIndicator.tsx","./src/components/UserProfileModal.tsx","./src/components/UserSettings.tsx","./src/components/VideoGrid.tsx","./src/components/VoiceChannel.tsx","./src/components/VoiceControls.tsx","./src/components/VoicePanel.tsx","./src/lib/api.ts","./src/lib/kaomojiData.ts","./src/lib/slashCommands.ts","./src/lib/usePermissions.ts","./src/stores/auth.ts","./src/stores/bot.ts","./src/stores/channel.ts","./src/stores/conversation.ts","./src/stores/featureRequest.ts","./src/stores/layout.ts","./src/stores/member.ts","./src/stores/message.ts","./src/stores/moderation.ts","./src/stores/notificationSettings.ts","./src/stores/permissions.ts","./src/stores/presence.ts","./src/stores/push.ts","./src/stores/readStates.ts","./src/stores/role.ts","./src/stores/server.ts","./src/stores/thread.ts","./src/stores/typing.ts","./src/stores/voice.ts","./src/stores/voicePresence.ts","./src/stores/ws.ts"],"errors":true,"version":"5.9.3"}
|
||||
Reference in New Issue
Block a user