refactor(32-03): use JKResyncButton and JKVideoButton in JKSessionScreen
- Replaced inline video button with JKVideoButton component - Replaced inline resync button with JKResyncButton component - Removed videoLoading and resyncLoading state from parent - Removed handleVideoClick and handleResync functions - Removed unused videoIcon and resyncIcon imports - Loading state changes no longer trigger parent re-renders
This commit is contained in:
parent
98e5a5ac15
commit
f5bd1b1cd5
|
|
@ -12,33 +12,30 @@ import PropTypes from 'prop-types';
|
|||
const JKResyncButton = memo(({ resyncAudio, className }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleClick = useCallback(async (e) => {
|
||||
e.preventDefault();
|
||||
if (loading) return;
|
||||
const handleClick = useCallback(
|
||||
async e => {
|
||||
e.preventDefault();
|
||||
if (loading) return;
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
await resyncAudio();
|
||||
// Silent success (matches legacy behavior)
|
||||
} catch (error) {
|
||||
if (error.message === 'timeout') {
|
||||
toast.error('Audio resync timed out. Please try again.');
|
||||
} else {
|
||||
toast.error('Audio resync failed: ' + (error.message || 'Unknown error'));
|
||||
setLoading(true);
|
||||
try {
|
||||
await resyncAudio();
|
||||
// Silent success (matches legacy behavior)
|
||||
} catch (error) {
|
||||
if (error.message === 'timeout') {
|
||||
toast.error('Audio resync timed out. Please try again.');
|
||||
} else {
|
||||
toast.error('Audio resync failed: ' + (error.message || 'Unknown error'));
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [resyncAudio, loading]);
|
||||
},
|
||||
[resyncAudio, loading]
|
||||
);
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={className || 'btn-custom-outline'}
|
||||
outline
|
||||
size="md"
|
||||
onClick={handleClick}
|
||||
disabled={loading}
|
||||
>
|
||||
<Button className={className || 'btn-custom-outline'} outline size="md" onClick={handleClick} disabled={loading}>
|
||||
{loading ? (
|
||||
<>
|
||||
<Spinner size="sm" /> Resyncing...
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ import JKSessionMetronomePlayer from './JKSessionMetronomePlayer.js';
|
|||
import JKSessionChatWindow from './JKSessionChatWindow.js';
|
||||
import JKSessionChatButton from './JKSessionChatButton.js';
|
||||
import JKPopupMediaControls from '../popups/JKPopupMediaControls.js';
|
||||
import JKResyncButton from './JKResyncButton.js';
|
||||
import JKVideoButton from './JKVideoButton.js';
|
||||
import { SESSION_PRIVACY_MAP } from '../../helpers/globals.js';
|
||||
import { toast } from 'react-toastify';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
|
@ -139,13 +141,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||
import gearIcon from '../../assets/img/client/gear.svg';
|
||||
import inviteIcon from '../../assets/img/client/invite.svg';
|
||||
import volumeIcon from '../../assets/img/client/volume.svg';
|
||||
import videoIcon from '../../assets/img/client/video.svg';
|
||||
import recordIcon from '../../assets/img/client/record.svg';
|
||||
import broadcastIcon from '../../assets/img/client/broadcast.svg';
|
||||
import openIcon from '../../assets/img/client/open.svg';
|
||||
import chatIcon from '../../assets/img/client/chat.svg';
|
||||
import attachIcon from '../../assets/img/client/attach.svg';
|
||||
import resyncIcon from '../../assets/img/client/resync.svg';
|
||||
import helpIcon from '../../assets/img/client/help.svg';
|
||||
|
||||
const JKSessionScreen = () => {
|
||||
|
|
@ -247,12 +247,6 @@ const JKSessionScreen = () => {
|
|||
const [leaveComments, setLeaveComments] = useState('');
|
||||
const [leaveLoading, setLeaveLoading] = useState(false);
|
||||
|
||||
//state for video button
|
||||
const [videoLoading, setVideoLoading] = useState(false);
|
||||
|
||||
// State for resync button
|
||||
const [resyncLoading, setResyncLoading] = useState(false);
|
||||
|
||||
// Redux backing track state (modal visibility and data)
|
||||
const backingTrackData = useSelector(selectBackingTrackData);
|
||||
const showBackingTrackPlayer = Boolean(backingTrackData);
|
||||
|
|
@ -1017,39 +1011,6 @@ const JKSessionScreen = () => {
|
|||
return currentSession?.can_use_video || false;
|
||||
};
|
||||
|
||||
// Open external link in new window/tab
|
||||
const openExternalLink = url => {
|
||||
window.open(url, '_blank', 'noopener,noreferrer');
|
||||
};
|
||||
|
||||
// Handle video button click - opens new video conferencing server
|
||||
const handleVideoClick = async () => {
|
||||
if (!canVideo()) {
|
||||
// Show upgrade modal/banner
|
||||
showVideoUpgradePrompt();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setVideoLoading(true);
|
||||
|
||||
// Get video conferencing room URL from server
|
||||
const response = await getVideoConferencingRoomUrl(currentSession.id);
|
||||
const videoUrl = `${response.url}&audiooff=true`;
|
||||
|
||||
// Open video URL in new browser window/tab
|
||||
// console.debug("JKSessionScreen: Opening video conferencing URL", videoUrl);
|
||||
openExternalLink(videoUrl);
|
||||
} catch (error) {
|
||||
// console.error('Failed to get video room URL:', error);
|
||||
// Handle error - could show error message to user
|
||||
toast.error('Failed to start video session');
|
||||
} finally {
|
||||
// Keep loading state for 10 seconds to prevent multiple clicks
|
||||
setTimeout(() => setVideoLoading(false), 10000);
|
||||
}
|
||||
};
|
||||
|
||||
// Show upgrade prompt for users without video permissions
|
||||
const showVideoUpgradePrompt = () => {
|
||||
// Implementation for showing upgrade modal/banner
|
||||
|
|
@ -1104,30 +1065,6 @@ const JKSessionScreen = () => {
|
|||
}
|
||||
};
|
||||
|
||||
// Handle Resync button click - performs audio resync via native client
|
||||
const handleResync = useCallback(
|
||||
async e => {
|
||||
e.preventDefault();
|
||||
if (resyncLoading) return;
|
||||
|
||||
setResyncLoading(true);
|
||||
try {
|
||||
await resyncAudio();
|
||||
// Silent success (matches legacy behavior)
|
||||
} catch (error) {
|
||||
// console.error('Audio resync failed:', error);
|
||||
if (error.message === 'timeout') {
|
||||
toast.error('Audio resync timed out. Please try again.');
|
||||
} else {
|
||||
toast.error('Audio resync failed: ' + (error.message || 'Unknown error'));
|
||||
}
|
||||
} finally {
|
||||
setResyncLoading(false);
|
||||
}
|
||||
},
|
||||
[resyncAudio, resyncLoading]
|
||||
);
|
||||
|
||||
// Attach button handlers
|
||||
const handleAttachClick = useCallback(() => {
|
||||
if (attachFileInputRef.current) {
|
||||
|
|
@ -1407,11 +1344,11 @@ const JKSessionScreen = () => {
|
|||
<img src={volumeIcon} alt="Volume" style={{ width: '20px', height: '20px', marginRight: '0.3rem' }} />
|
||||
Volume
|
||||
</Button>
|
||||
<Button className="btn-custom-outline" outline size="md" onClick={handleVideoClick} disabled={videoLoading}>
|
||||
<img src={videoIcon} alt="Video" style={{ width: '20px', height: '20px', marginRight: '0.3rem' }} />
|
||||
{videoLoading && <Spinner size="sm" />}
|
||||
Video
|
||||
</Button>
|
||||
<JKVideoButton
|
||||
canVideo={canVideo}
|
||||
getVideoUrl={() => getVideoConferencingRoomUrl(currentSession.id)}
|
||||
onUpgradePrompt={showVideoUpgradePrompt}
|
||||
/>
|
||||
<Button
|
||||
className={currentlyRecording ? 'btn-recording-active' : 'btn-custom-outline'}
|
||||
color={currentlyRecording ? 'danger' : undefined}
|
||||
|
|
@ -1447,16 +1384,7 @@ const JKSessionScreen = () => {
|
|||
<img src={attachIcon} alt="Attach" style={{ width: '20px', height: '20px', marginRight: '0.3rem' }} />
|
||||
{isUploading ? 'Uploading...' : 'Attach'}
|
||||
</Button>
|
||||
<Button className="btn-custom-outline" outline size="md" onClick={handleResync} disabled={resyncLoading}>
|
||||
<img src={resyncIcon} alt="Resync" style={{ width: '20px', height: '20px', marginRight: '0.3rem' }} />
|
||||
{resyncLoading ? (
|
||||
<>
|
||||
<Spinner size="sm" /> Resyncing...
|
||||
</>
|
||||
) : (
|
||||
'Resync'
|
||||
)}
|
||||
</Button>
|
||||
<JKResyncButton resyncAudio={resyncAudio} />
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,16 +10,11 @@ import videoIcon from '../../assets/images/icons8-video-call-50.png';
|
|||
*
|
||||
* State colocation: https://kentcdodds.com/blog/state-colocation-will-make-your-react-app-faster
|
||||
*/
|
||||
const JKVideoButton = memo(({
|
||||
canVideo,
|
||||
getVideoUrl,
|
||||
onUpgradePrompt,
|
||||
className
|
||||
}) => {
|
||||
const JKVideoButton = memo(({ canVideo, getVideoUrl, onUpgradePrompt, className }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// Open external link in new window/tab
|
||||
const openExternalLink = useCallback((url) => {
|
||||
const openExternalLink = useCallback(url => {
|
||||
window.open(url, '_blank', 'noopener,noreferrer');
|
||||
}, []);
|
||||
|
||||
|
|
@ -38,7 +33,6 @@ const JKVideoButton = memo(({
|
|||
|
||||
// Open video URL in new browser window/tab
|
||||
openExternalLink(videoUrl);
|
||||
|
||||
} catch (error) {
|
||||
toast.error('Failed to start video session');
|
||||
} finally {
|
||||
|
|
@ -48,18 +42,8 @@ const JKVideoButton = memo(({
|
|||
}, [canVideo, getVideoUrl, onUpgradePrompt, openExternalLink]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={className || 'btn-custom-outline'}
|
||||
outline
|
||||
size="md"
|
||||
onClick={handleClick}
|
||||
disabled={loading}
|
||||
>
|
||||
<img
|
||||
src={videoIcon}
|
||||
alt="Video"
|
||||
style={{ width: '20px', height: '20px', marginRight: '0.3rem' }}
|
||||
/>
|
||||
<Button className={className || 'btn-custom-outline'} outline size="md" onClick={handleClick} disabled={loading}>
|
||||
<img src={videoIcon} alt="Video" style={{ width: '20px', height: '20px', marginRight: '0.3rem' }} />
|
||||
{loading && <Spinner size="sm" />}
|
||||
Video
|
||||
</Button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue