Skip to content

Commit

Permalink
Add functionality in call menu options to start/stop transcriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-lohra committed Nov 27, 2024
1 parent b53deeb commit d9a138c
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fun defaultStreamMenu(
onSelectScaleType: (VideoScalingType) -> Unit,
availableDevices: List<StreamAudioDevice>,
loadRecordings: suspend () -> List<MenuItem>,
transcriptionState: TranscriptionState,
transcriptionUiState: TranscriptionUiState,
onToggleTranscription: suspend () -> Unit,
transcriptionList: suspend () -> List<MenuItem>,
) = buildList<MenuItem> {
Expand Down Expand Up @@ -154,16 +154,25 @@ fun defaultStreamMenu(
),
)
}
val transcriptionUiState = transcriptionState.mapTouUiState()
add(ActionMenuItem(
title = transcriptionUiState.text,
icon = transcriptionUiState.icon,
action = {
GlobalScope.launch {
onToggleTranscription.invoke()
}
},
))

when (transcriptionUiState) {
is TranscriptionAvailableUiState, TranscriptionStoppedUiState -> {
add(
ActionMenuItem(
title = transcriptionUiState.text,
icon = transcriptionUiState.icon,
highlight = transcriptionUiState.highlight,
action = {
GlobalScope.launch {
onToggleTranscription.invoke()
}
},
),
)
}

else -> {}
}
}

/**
Expand Down Expand Up @@ -278,4 +287,4 @@ fun debugSubmenu(
onSfuFastReconnectClick,
),
),
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ import com.google.accompanist.permissions.rememberPermissionState
import io.getstream.video.android.compose.theme.VideoTheme
import io.getstream.video.android.compose.ui.components.video.VideoScalingType
import io.getstream.video.android.core.Call
import io.getstream.video.android.core.TranscriptionState
import io.getstream.video.android.core.call.audio.InputAudioFilter
import io.getstream.video.android.core.mapper.ReactionMapper
import io.getstream.video.android.tooling.extensions.toPx
import io.getstream.video.android.ui.call.ReactionsMenu
import io.getstream.video.android.ui.menu.base.ActionMenuItem
import io.getstream.video.android.ui.menu.base.DynamicMenu
import io.getstream.video.android.ui.menu.base.MenuItem
import io.getstream.video.android.ui.menu.transcriptions.RestApiTranscriptionStateStrategy
import io.getstream.video.android.ui.menu.transcriptions.TranscriptionUiStateManager
import io.getstream.video.android.ui.menu.transcriptions.WebSocketTranscriptionStateStrategy
import io.getstream.video.android.util.filters.SampleAudioFilter
import kotlinx.coroutines.launch
import java.nio.ByteBuffer
Expand Down Expand Up @@ -187,15 +189,28 @@ internal fun SettingsMenu(
}
}

val transcriptionState by call.state.transcriptionState.collectAsStateWithLifecycle()
val isCurrentlyTranscribing by call.state.transcribing.collectAsStateWithLifecycle()
val transcriptionStateFromWS by call.state.transcriptionStateFromWS.collectAsStateWithLifecycle()
val transcriptionModeFromRest by call.state.transcriptionModeStateFromRest.collectAsStateWithLifecycle()

val onToggleTranscription: suspend () -> Unit = {
when (transcriptionState) {
TranscriptionState.CallTranscriptionInitialState -> call.startTranscription()
TranscriptionState.CallTranscriptionReadyState -> call.startTranscription()
TranscriptionState.CallTranscriptionStartedState -> call.stopTranscription()
// Create strategies
val webSocketStrategy = WebSocketTranscriptionStateStrategy(transcriptionStateFromWS)
val restApiStrategy =
RestApiTranscriptionStateStrategy(isCurrentlyTranscribing, transcriptionModeFromRest)

// Use the manager to determine the UI state
val transcriptionUiStateManager =
TranscriptionUiStateManager(webSocketStrategy, restApiStrategy)
val transcriptionUiState = transcriptionUiStateManager.getTranscriptionUiState()

val onToggleTranscription: suspend () -> Unit = {
when (transcriptionUiState) {
TranscriptionAvailableUiState -> call.startTranscription()
TranscriptionStoppedUiState -> call.stopTranscription()
else -> {
throw IllegalStateException("Toggling of transcription should not work in state: $transcriptionState")
throw IllegalStateException(
"Toggling of transcription should not work in state: $transcriptionUiState",
)
}
}
}
Expand All @@ -207,7 +222,7 @@ internal fun SettingsMenu(
call.listTranscription().getOrNull()?.transcriptions?.map {
ActionMenuItem(
title = it.filename,
icon = Icons.Default.VideoFile, //TODO Rahul check this later
icon = Icons.Default.VideoFile, // TODO Rahul check this later
action = {
context.downloadFile(it.url, it.filename)
onDismissed()
Expand Down Expand Up @@ -277,9 +292,9 @@ internal fun SettingsMenu(
isScreenShareEnabled = isScreenSharing,
onSelectScaleType = onSelectScaleType,
loadRecordings = onLoadRecordings,
transcriptionState = transcriptionState,
onToggleTranscription = onToggleTranscription ,
transcriptionList = onLoadTranscriptions
transcriptionUiState = transcriptionUiState,
onToggleTranscription = onToggleTranscription,
transcriptionList = onLoadTranscriptions,
),
)
}
Expand Down Expand Up @@ -343,9 +358,9 @@ private fun SettingsMenuPreview() {
onSelectScaleType = {},
onNoiseCancellation = {},
loadRecordings = { emptyList() },
transcriptionState = TranscriptionState.CallTranscriptionReadyState,
transcriptionUiState = TranscriptionAvailableUiState,
onToggleTranscription = {},
transcriptionList = { emptyList() }
transcriptionList = { emptyList() },
),
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,83 @@
/*
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.video.android.ui.menu

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Transcribe
import androidx.compose.material.icons.filled.Description
import androidx.compose.ui.graphics.vector.ImageVector
import io.getstream.video.android.core.TranscriptionState
import org.openapitools.client.models.TranscriptionSettingsResponse

sealed class TranscriptionUiState(
val text: String,
val icon: ImageVector, // Assuming it's a drawable resource ID
val highlight: Boolean,
val isButtonEnabled: Boolean,
)

/**
* Stop Transcription
* Start Transcription
* Transcription is disabled
* Transcription failed
*/

data object TranscriptionAvailableUiState : TranscriptionUiState(
text = "Transcribe the call",
icon = Icons.Default.Description,
highlight = false,
isButtonEnabled = true,
)

data object TranscriptionStoppedUiState : TranscriptionUiState(
text = "Stop Transcription",
icon = Icons.Default.Description,
highlight = true,
isButtonEnabled = false,
)

data object TranscriptionDisabledUiState : TranscriptionUiState(
text = "Transcription not available",
icon = Icons.Default.Description,
highlight = false,
isButtonEnabled = false,
)

data object TranscriptionFailedUiState : TranscriptionUiState(
text = "Transcription failed",
icon = Icons.Default.Description,
highlight = false,
isButtonEnabled = false,
)

fun TranscriptionSettingsResponse.Mode.mapToUiState(): TranscriptionUiState {
return when (this) {
TranscriptionSettingsResponse.Mode.Available -> TranscriptionAvailableUiState
TranscriptionSettingsResponse.Mode.Disabled -> TranscriptionDisabledUiState
TranscriptionSettingsResponse.Mode.AutoOn -> TranscriptionStoppedUiState
else -> TranscriptionFailedUiState
}
}

data class TranscriptionUiState(val text: String,
val icon: ImageVector, // Assuming it's a drawable resource ID
val isButtonEnabled: Boolean)

fun TranscriptionState.mapTouUiState(): TranscriptionUiState {
return when(this){
is TranscriptionState.CallTranscriptionInitialState -> TranscriptionUiState(
text = "Transcription Not Ready",
icon = Icons.Default.Transcribe,
isButtonEnabled = false
)
is TranscriptionState.CallTranscriptionReadyState -> TranscriptionUiState(
text = "Transcription is ready",
icon = Icons.Default.Transcribe,
isButtonEnabled = true
)
is TranscriptionState.CallTranscriptionStartedState -> TranscriptionUiState(
text = "Transcription in progress",
icon = Icons.Default.Transcribe,
isButtonEnabled = true
)
is TranscriptionState.CallTranscriptionStoppedState -> TranscriptionUiState(
text = "Transcription stopped",
icon = Icons.Default.Transcribe,
isButtonEnabled = true
)
is TranscriptionState.CallTranscriptionFailedState -> TranscriptionUiState(
text = "Transcription failed",
icon = Icons.Default.Transcribe,
isButtonEnabled = false
)
fun TranscriptionState.mapToUiState(): TranscriptionUiState {
return when (this) {
is TranscriptionState.CallTranscriptionStartedState -> TranscriptionStoppedUiState
is TranscriptionState.CallTranscriptionStoppedState -> TranscriptionAvailableUiState
is TranscriptionState.CallTranscriptionFailedState -> TranscriptionFailedUiState
is TranscriptionState.CallTranscriptionInitialState -> TranscriptionDisabledUiState
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import androidx.compose.ui.unit.dp
import io.getstream.video.android.compose.theme.VideoTheme
import io.getstream.video.android.compose.ui.components.base.StreamToggleButton
import io.getstream.video.android.compose.ui.components.base.styling.StyleSize
import io.getstream.video.android.core.TranscriptionState
import io.getstream.video.android.ui.menu.TranscriptionAvailableUiState
import io.getstream.video.android.ui.menu.debugSubmenu
import io.getstream.video.android.ui.menu.defaultStreamMenu
import io.getstream.video.android.ui.menu.reconnectMenu
Expand Down Expand Up @@ -228,9 +228,9 @@ private fun DynamicMenuPreview() {
onNoiseCancellation = {},
onSelectScaleType = {},
loadRecordings = { emptyList() },
transcriptionState = TranscriptionState.CallTranscriptionReadyState,
transcriptionUiState = TranscriptionAvailableUiState,
onToggleTranscription = {},
transcriptionList = { emptyList() }
transcriptionList = { emptyList() },
),
)
}
Expand Down Expand Up @@ -260,9 +260,9 @@ private fun DynamicMenuDebugOptionPreview() {
onSelectScaleType = { },
onNoiseCancellation = {},
loadRecordings = { emptyList() },
transcriptionState = TranscriptionState.CallTranscriptionReadyState,
transcriptionUiState = TranscriptionAvailableUiState,
onToggleTranscription = {},
transcriptionList = { emptyList() }
transcriptionList = { emptyList() },
),
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.video.android.ui.menu.transcriptions

import io.getstream.video.android.ui.menu.TranscriptionAvailableUiState
import io.getstream.video.android.ui.menu.TranscriptionDisabledUiState
import io.getstream.video.android.ui.menu.TranscriptionStoppedUiState
import io.getstream.video.android.ui.menu.TranscriptionUiState
import io.getstream.video.android.ui.menu.mapToUiState
import org.openapitools.client.models.TranscriptionSettingsResponse

class RestApiTranscriptionStateStrategy(
private val isCurrentlyTranscribing: Boolean,
private val transcriptionModeFromRest: TranscriptionSettingsResponse.Mode,
) : TranscriptionStateStrategy {
override fun mapToUiState(): TranscriptionUiState {
return iosStrategy()
}

fun iosStrategy(): TranscriptionUiState {
return when (transcriptionModeFromRest) {
TranscriptionSettingsResponse.Mode.Available, TranscriptionSettingsResponse.Mode.AutoOn -> {
if (isCurrentlyTranscribing) {
TranscriptionStoppedUiState
} else {
TranscriptionAvailableUiState
}
}

else -> TranscriptionDisabledUiState
}
}

fun anotherStrategy(): TranscriptionUiState {
return if (isCurrentlyTranscribing) {
TranscriptionStoppedUiState
} else {
transcriptionModeFromRest.mapToUiState()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.video.android.ui.menu.transcriptions

import io.getstream.video.android.ui.menu.TranscriptionUiState

interface TranscriptionStateStrategy {
fun mapToUiState(): TranscriptionUiState
}
Loading

0 comments on commit d9a138c

Please sign in to comment.