mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-09-20 06:34:00 +00:00
feat(jam-session): add connection state management and update UI feedback for session status
This commit is contained in:
parent
0eb07ef9b6
commit
60e38f4868
@ -74,6 +74,9 @@ class JamSessionService(
|
||||
private val _localParticipantId = MutableStateFlow<String?>(null)
|
||||
val localParticipantId: StateFlow<String?> = _localParticipantId.asStateFlow()
|
||||
|
||||
private val _isConnected = MutableStateFlow(false)
|
||||
val isConnected: StateFlow<Boolean> = _isConnected.asStateFlow()
|
||||
|
||||
private val _incomingMessages = MutableSharedFlow<JamMessage>(extraBufferCapacity = 64)
|
||||
val incomingMessages = _incomingMessages.asSharedFlow()
|
||||
|
||||
@ -174,7 +177,7 @@ class JamSessionService(
|
||||
return true
|
||||
}
|
||||
|
||||
suspend fun joinSession(offerSdp: String): String {
|
||||
suspend fun joinSession(offerSdp: String, hostName: String? = null): String {
|
||||
log.i { "Joining jam session" }
|
||||
val participantName = resolveParticipantName(defaultPrefix = "Guest")
|
||||
|
||||
@ -186,6 +189,13 @@ class JamSessionService(
|
||||
hostConnection = pc
|
||||
_role.value = JamRole.Guest
|
||||
_localParticipantId.value = "guest"
|
||||
_participants.value = listOf(
|
||||
JamParticipant(
|
||||
id = "host",
|
||||
displayName = hostName?.ifBlank { null } ?: "Host",
|
||||
isHost = true,
|
||||
)
|
||||
)
|
||||
_isActive.value = true
|
||||
|
||||
// The data channel arrives in-band from the host's offer via on_data_channel;
|
||||
@ -226,6 +236,7 @@ class JamSessionService(
|
||||
_role.value = null
|
||||
_participants.value = emptyList()
|
||||
_isActive.value = false
|
||||
_isConnected.value = false
|
||||
_localParticipantId.value = null
|
||||
}
|
||||
|
||||
@ -303,6 +314,7 @@ class JamSessionService(
|
||||
|
||||
override fun onDataChannelOpen(label: String) {
|
||||
log.i { "[$guestId] Data channel '$label' open" }
|
||||
_isConnected.value = true
|
||||
}
|
||||
|
||||
override fun onDataChannelMessage(label: String, data: String) {
|
||||
@ -329,6 +341,7 @@ class JamSessionService(
|
||||
|
||||
override fun onDataChannelOpen(label: String) {
|
||||
log.i { "Data channel '$label' open" }
|
||||
_isConnected.value = true
|
||||
}
|
||||
|
||||
override fun onDataChannelMessage(label: String, data: String) {
|
||||
|
||||
@ -295,23 +295,35 @@ private fun GuestSessionView(
|
||||
ParticipantsSection(state.participants)
|
||||
|
||||
val answerLink = state.answerLink
|
||||
if (answerLink == null) {
|
||||
Text(
|
||||
text = "Connecting to the session...",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = "Almost there! Send your answer back to the host:",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
ShareableLinkBox(
|
||||
label = "Answer link",
|
||||
link = answerLink,
|
||||
onCopy = { clipboard.setText(AnnotatedString(answerLink)) },
|
||||
onShare = { onShare(answerLink) },
|
||||
)
|
||||
when {
|
||||
state.isConnected -> {
|
||||
Text(
|
||||
text = "Connected to the session",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
||||
answerLink == null -> {
|
||||
Text(
|
||||
text = "Connecting to the session...",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Text(
|
||||
text = "Almost there! Send your answer back to the host:",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
ShareableLinkBox(
|
||||
label = "Answer link",
|
||||
link = answerLink,
|
||||
onCopy = { clipboard.setText(AnnotatedString(answerLink)) },
|
||||
onShare = { onShare(answerLink) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LeaveButton(onLeave)
|
||||
|
||||
@ -37,6 +37,7 @@ import kotlinx.coroutines.launch
|
||||
|
||||
data class JamUiState(
|
||||
val isActive: Boolean = false,
|
||||
val isConnected: Boolean = false,
|
||||
val role: JamRole? = null,
|
||||
val participants: List<JamParticipant> = emptyList(),
|
||||
/** Host: deep link containing this session's SDP offer, ready to share. */
|
||||
@ -69,6 +70,7 @@ class JamViewModel(
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
isActive = active,
|
||||
isConnected = jamSession.isConnected.value,
|
||||
role = jamSession.role.value,
|
||||
participants = jamSession.participants.value,
|
||||
inviteLink = if (!active) null else it.inviteLink,
|
||||
@ -84,6 +86,11 @@ class JamViewModel(
|
||||
_uiState.update { it.copy(participants = participants) }
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
jamSession.isConnected.collect { connected ->
|
||||
_uiState.update { it.copy(isConnected = connected) }
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
deepLinks.pendingLink.collect { link ->
|
||||
handleDeepLink(link)
|
||||
@ -119,16 +126,17 @@ class JamViewModel(
|
||||
|
||||
fun joinWithIncomingInvite() {
|
||||
val sdp = _uiState.value.incomingOfferSdp ?: return
|
||||
join(sdp)
|
||||
join(sdp, _uiState.value.incomingHostName)
|
||||
}
|
||||
|
||||
fun joinWithPasted(input: String) {
|
||||
val sdp = JamInviteCodec.extractSdp(input)
|
||||
val parsed = JamInviteCodec.parse(input)
|
||||
val sdp = parsed?.sdp ?: JamInviteCodec.extractSdp(input)
|
||||
if (sdp == null) {
|
||||
_uiState.update { it.copy(error = "That doesn't look like a valid jam invite.") }
|
||||
return
|
||||
}
|
||||
join(sdp)
|
||||
join(sdp, (parsed as? JamInviteLink.HostInvite)?.peerName)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,10 +179,10 @@ class JamViewModel(
|
||||
_uiState.update { it.copy(incomingOfferSdp = null, incomingHostName = null) }
|
||||
}
|
||||
|
||||
private fun join(offerSdp: String) {
|
||||
private fun join(offerSdp: String, hostName: String? = null) {
|
||||
viewModelScope.launch {
|
||||
runCatching {
|
||||
val answer = jamSession.joinSession(offerSdp)
|
||||
val answer = jamSession.joinSession(offerSdp, hostName)
|
||||
JamInviteCodec.buildGuestAnswer(localName(), answer)
|
||||
}.onSuccess { link ->
|
||||
_uiState.update {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user