.net10 сервер с рабочими звонками и файлами

This commit is contained in:
Халимов Рустам
2026-03-12 01:48:58 +03:00
parent 50d4d75c04
commit d025c98e61
741 changed files with 35231 additions and 1863 deletions

View File

@@ -302,12 +302,19 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
), '→ hasRemoteVideo:', hasVideo);
if (hasVideo !== hasRemoteVideoRef.current) {
console.log(`[checkVideo] hasRemoteVideo changed: ${hasRemoteVideoRef.current} -> ${hasVideo}`);
hasRemoteVideoRef.current = hasVideo;
setHasRemoteVideo(hasVideo);
}
if (hasVideo && callType !== 'video') {
// Auto-switch UI mode if remote starts sending video or STOPS sending it
if (hasVideo && callType === 'voice') {
console.log('[checkVideo] Remote started video, switching UI to video mode');
setCallType('video');
} else if (!hasVideo && callType === 'video') {
// If we were in video mode but tracks are gone, revert to voice
console.log('[checkVideo] Remote stopped video, reverting UI to voice mode');
setCallType('voice');
}
};
@@ -1401,13 +1408,17 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
setCallType(data.callType);
// If remote switched to video, nudge the video element
if (data.callType === 'video') {
if (data.callType === 'video' || data.callType === 'voice') {
setTimeout(() => {
if (remoteVideoRef.current && remoteStreamRef.current) {
console.log(`[onCallTypeChanged] Nudging playback for ${data.callType}`);
remoteVideoRef.current.srcObject = remoteStreamRef.current;
remoteVideoRef.current.play().catch(() => {});
remoteVideoRef.current.play().catch(e => {
if (e.name === 'NotAllowedError') setNeedsInteraction(true);
console.warn('Auto-play failed:', e);
});
}
}, 500);
}, 1000);
}
};
@@ -1456,15 +1467,46 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
}
});
// Sync remote video ref with remote stream (only when srcObject actually changes)
// Sync remote video/audio ref with remote stream
useEffect(() => {
if (!remoteVideoRef.current || !remoteStreamRef.current) return;
if (remoteVideoRef.current.srcObject !== remoteStreamRef.current) {
console.log('[useEffect] Syncing remote video srcObject');
remoteVideoRef.current.srcObject = remoteStreamRef.current;
remoteVideoRef.current.play().catch(() => { });
}
}, [hasRemoteVideo, callType]);
if (!remoteStreamRef.current) return;
const stream = remoteStreamRef.current;
const bindAndPlay = async () => {
// 1) Bind to video element (primary for video, also handles audio)
if (remoteVideoRef.current) {
const video = remoteVideoRef.current as any;
if (video.srcObject !== stream) {
console.log('[useEffect] Binding stream to remoteVideoRef');
video.srcObject = stream;
}
video.muted = false;
video.volume = remoteVolume;
if (stream.getTracks().length > 0) {
video.play().catch((e: any) => {
if (e.name === 'NotAllowedError') setNeedsInteraction(true);
});
}
}
// 2) Bind to audio element (dedicated fallback for sound, especially in voice calls)
if (remoteAudioRef.current) {
const audio = remoteAudioRef.current;
if (audio.srcObject !== stream) {
console.log('[useEffect] Binding stream to remoteAudioRef');
audio.srcObject = stream;
}
audio.muted = false;
audio.volume = remoteVolume;
if (stream.getAudioTracks().length > 0) {
audio.play().catch(() => {});
}
}
};
bindAndPlay();
}, [hasRemoteVideo, callType, callState, remoteVolume]);
// Cleanup on unmount
useEffect(() => {
@@ -1804,6 +1846,9 @@ export default function CallModal({ isOpen, onClose, targetUser, callType: initi
)}
</div>
)}
{/* Dedicated hidden audio element to ensure sound in ALL cases once connected */}
<audio ref={remoteAudioRef} autoPlay style={{ display: 'none' }} />
</div>
{/* === Controls === */}

View File

@@ -266,14 +266,25 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
}, [chatMessages.length, isLoadingMessages]);
// Scroll detection
const handleScroll = () => {
const checkScrollPosition = useCallback(() => {
const container = messagesContainerRef.current;
if (!container) return;
const isNearBottom =
container.scrollHeight - container.scrollTop - container.clientHeight < 200;
setShowScrollDown(!isNearBottom);
}, []);
const handleScroll = () => {
checkScrollPosition();
};
useEffect(() => {
// Check scroll position when messages change or scroll ready state changes
if (scrollReady) {
checkScrollPosition();
}
}, [chatMessages.length, scrollReady, checkScrollPosition]);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (!chatViewRef.current) return;
const { left, top } = chatViewRef.current.getBoundingClientRect();
@@ -890,7 +901,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal
)}
{/* Ввод сообщения */}
<MessageInput chatId={activeChat} />
{activeChat && <MessageInput chatId={activeChat} />}
{/* Профиль пользователя */}
<AnimatePresence>