classroom düzeltmeler

This commit is contained in:
Sedat Öztürk 2025-08-31 21:09:59 +03:00
parent b67080646c
commit 8acbd2e257
8 changed files with 62 additions and 75 deletions

View file

@ -372,6 +372,7 @@ public class ClassroomHub : Hub
{
try
{
// 1. Attendance kapat
var attendances = await _attendanceRepository.GetListAsync(
x => x.SessionId == sessionId && x.StudentId == participantId && x.LeaveTime == null
);
@ -381,42 +382,60 @@ public class ClassroomHub : Hub
foreach (var attendance in attendances)
{
await CloseAttendanceAsync(attendance);
await Clients.Group(sessionId.ToString()).SendAsync("AttendanceUpdated", attendance);
await Clients.Group(sessionId.ToString())
.SendAsync("AttendanceUpdated", attendance);
}
}
// 2. Participant bul
var participant = await _participantRepository.FirstOrDefaultAsync(
x => x.SessionId == sessionId && x.UserId == participantId
);
if (participant != null && !string.IsNullOrEmpty(participant.ConnectionId))
if (participant == null)
{
await Clients.Client(participant.ConnectionId)
.SendAsync("ForceDisconnect", "You have been removed from the class.");
await Groups.RemoveFromGroupAsync(participant.ConnectionId, sessionId.ToString());
// ❌ pasif + ✅ kicked işaretle
participant.IsActive = false;
participant.IsKicked = true;
participant.ConnectionId = null;
await _participantRepository.UpdateAsync(participant, autoSave: true);
await Clients.Group(sessionId.ToString())
.SendAsync("ParticipantLeft", new { UserId = participantId, SessionId = sessionId });
_logger.LogWarning("KickParticipant: Session {SessionId} için participant {ParticipantId} bulunamadı",
sessionId, participantId);
return;
}
// ConnectionId'yi kaydet (DB'ye null yazmadan önce)
var connectionId = participant.ConnectionId;
// 3. Diğerlerine duyur
_logger.LogInformation("👢 Participant {ParticipantId} kicked from session {SessionId}", participantId, sessionId);
// 3. DB'de kick flag setle
participant.IsActive = false;
participant.IsKicked = true;
participant.ConnectionId = null;
await _participantRepository.UpdateAsync(participant, autoSave: true);
// 4. Hedef kullanıcıya bildir
if (!string.IsNullOrEmpty(connectionId))
{
await Clients.Client(connectionId)
.SendAsync("ForceDisconnect", "You have been removed from the class.");
await Groups.RemoveFromGroupAsync(connectionId, sessionId.ToString());
}
// 5. Diğer katılımcılara bildir
await Clients.Group(sessionId.ToString())
.SendAsync("ParticipantLeft", new { UserId = participantId, SessionId = sessionId });
// 6. Log
_logger.LogInformation("👢 Participant {ParticipantId} kicked from session {SessionId}",
participantId, sessionId);
}
catch (Exception ex)
{
_logger.LogError(ex, "❌ KickParticipant hata verdi");
_logger.LogError(ex, "❌ KickParticipant hata verdi (Session={SessionId}, Participant={ParticipantId})",
sessionId, participantId);
await Clients.Caller.SendAsync("Error", "Kick işlemi başarısız oldu.");
}
}
[HubMethodName("ApproveHandRaise")]
public async Task ApproveHandRaiseAsync(Guid sessionId, Guid studentId)
{

View file

@ -281,8 +281,7 @@ const RoomDetail: React.FC = () => {
signalRServiceRef.current.setParticipantJoinHandler(
async (userId: string, name: string, isTeacher: boolean, isActive: boolean) => {
if (userId === user.id) return
if (!isActive) return // ❌ pasif kullanıcıyı ekleme
if (isTeacher) setTeacherDisconnected(false)
if (!isActive) return
console.log(`Participant joined: ${name}, isTeacher: ${isTeacher}`)
@ -296,31 +295,19 @@ const RoomDetail: React.FC = () => {
isTeacher,
isAudioMuted: classSettings.defaultMicrophoneState === 'muted',
isVideoMuted: classSettings.defaultCameraState === 'off',
isActive: isActive, // ✅ statede tut
isActive: true,
})
}
// ✅ güncel listedeki öğretmen kontrolü
const teacherExists = updated.some((p) => p.isTeacher && p.isActive)
if (teacherExists) {
;(async () => {
if (!webRTCServiceRef.current?.getPeerConnection(userId)) {
await webRTCServiceRef.current?.createPeerConnection(userId)
}
// ✅ öğretmen ise her zaman offer başlatır
if (isActive) {
if (user.role === 'teacher') {
const offer = await webRTCServiceRef.current!.createOffer(userId)
await signalRServiceRef.current?.sendOffer(classSession.id, userId, offer)
}
}
})()
}
return updated
})
// 🔑 Mesh: Herkes herkese offer gönderir
if (!webRTCServiceRef.current?.getPeerConnection(userId)) {
await webRTCServiceRef.current?.createPeerConnection(userId)
}
const offer = await webRTCServiceRef.current!.createOffer(userId)
await signalRServiceRef.current?.sendOffer(classSession.id, userId, offer)
},
)
@ -329,12 +316,12 @@ const RoomDetail: React.FC = () => {
async (
existing: { userId: string; userName: string; isTeacher: boolean; isActive: boolean }[],
) => {
setParticipants((prev) => {
let updated = [...prev]
for (const participant of existing) {
if (!participant.isActive) continue
if (participant.userId === user.id) continue
for (const participant of existing) {
if (!participant.isActive) continue // ❌ pasif kullanıcıyı alma
if (participant.userId === user.id) continue
setParticipants((prev) => {
const updated = [...prev]
if (!updated.find((p) => p.id === participant.userId)) {
updated.push({
id: participant.userId,
@ -343,39 +330,20 @@ const RoomDetail: React.FC = () => {
isTeacher: participant.isTeacher,
isAudioMuted: classSettings.defaultMicrophoneState === 'muted',
isVideoMuted: classSettings.defaultCameraState === 'off',
isActive: participant.isActive, // ✅ statede tut
isActive: true,
})
}
return updated
})
if (!webRTCServiceRef.current?.getPeerConnection(participant.userId)) {
await webRTCServiceRef.current?.createPeerConnection(participant.userId)
}
// ✅ güncel listede öğretmen var mı?
const teacherExists = updated.some((p) => p.isTeacher && p.isActive)
if (teacherExists) {
;(async () => {
for (const participant of existing) {
if (!participant.isActive) continue
if (participant.userId === user.id) continue
if (!webRTCServiceRef.current?.getPeerConnection(participant.userId)) {
await webRTCServiceRef.current?.createPeerConnection(participant.userId)
}
// ✅ sadece öğretmen offer başlatır
if (user.role === 'teacher') {
const offer = await webRTCServiceRef.current!.createOffer(participant.userId)
await signalRServiceRef.current?.sendOffer(
classSession.id,
participant.userId,
offer,
)
}
}
})()
}
return updated
})
// 🔑 Mesh: yeni gelen user da karşıya offer yollar
const offer = await webRTCServiceRef.current!.createOffer(participant.userId)
await signalRServiceRef.current?.sendOffer(classSession.id, participant.userId, offer)
}
},
)