package calls.presentation import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import chats.data.remote.signalr.ChatHubClient import chats.data.remote.signalr.ChatEvent import calls.data.remote.GroupWebRtcManager import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import org.webrtc.* import javax.inject.Inject data class ParticipantState( val userId: String, val videoTrack: VideoTrack? = null, val isAudioMuted: Boolean = false, val isVideoDisabled: Boolean = false ) data class GroupCallState( val chatId: String? = null, val participants: Map = emptyMap(), val isMicEnabled: Boolean = true, val isCameraEnabled: Boolean = true ) @HiltViewModel class GroupCallViewModel @Inject constructor( private val webRtcManager: GroupWebRtcManager, private val signalrClient: ChatHubClient ) : ViewModel() { private val _state = MutableStateFlow(GroupCallState()) val state: StateFlow = _state.asStateFlow() init { observeSignalREvents() } private fun observeSignalREvents() { signalrClient.events.onEach { event -> when (event) { is ChatEvent.GroupCallUserJoined -> handleUserJoined(event.userId) is ChatEvent.GroupCallUserLeft -> handleUserLeft(event.userId) is ChatEvent.GroupCallOffer -> handleOffer(event.from, event.offer) is ChatEvent.GroupCallAnswer -> handleAnswer(event.from, event.answer) // Дополнительные обработчики ICE кандидатов и т.д. else -> Unit } }.launchIn(viewModelScope) } private fun handleUserJoined(userId: String) { // Создаем PeerConnection для нового участника // Логика идентична портированному CallModal.tsx _state.update { it.copy(participants = it.participants + (userId to ParticipantState(userId))) } } private fun handleUserLeft(userId: String) { webRtcManager.removeParticipant(userId) _state.update { it.copy(participants = it.participants - userId) } } private fun handleOffer(from: String, sdp: String) { // Установка RemoteDescription и создание Answer } private fun handleAnswer(from: String, sdp: String) { // Установка RemoteDescription } fun toggleMic() { _state.update { it.copy(isMicEnabled = !it.isMicEnabled) } // Логика управления AudioTrack } fun toggleCamera() { _state.update { it.copy(isCameraEnabled = !it.isCameraEnabled) } // Логика управления VideoTrack } override fun onCleared() { super.onCleared() webRtcManager.closeAll() } }