@@ -43,8 +43,12 @@ import com.google.firebase.ai.type.liveGenerationConfig
4343import dagger.hilt.android.lifecycle.HiltViewModel
4444import javax.inject.Inject
4545import kotlinx.coroutines.flow.MutableStateFlow
46+ import kotlinx.coroutines.flow.SharingStarted
4647import kotlinx.coroutines.flow.StateFlow
4748import kotlinx.coroutines.flow.asStateFlow
49+ import kotlinx.coroutines.flow.combine
50+ import kotlinx.coroutines.flow.map
51+ import kotlinx.coroutines.flow.stateIn
4852import kotlinx.coroutines.flow.update
4953import kotlinx.coroutines.launch
5054import kotlinx.serialization.json.JsonObject
@@ -56,25 +60,18 @@ import kotlinx.serialization.json.long
5660@HiltViewModel
5761class TodoScreenViewModel @Inject constructor(private val todoRepository : TodoRepository ) : ViewModel() {
5862 private val TAG = " TodoScreenViewModel"
59-
6063 private var session: LiveSession ? = null
6164
62- private val _uiState = MutableStateFlow <TodoScreenUiState >( TodoScreenUiState . Initial )
63- val uiState : StateFlow < TodoScreenUiState > = _uiState .asStateFlow()
65+ private val liveSessionState = MutableStateFlow <LiveSessionState >( LiveSessionState . NotReady )
66+ private val todos = todoRepository.todos
6467
65- init {
66- viewModelScope.launch {
67- todoRepository.todos.collect { todos ->
68- _uiState .update {
69- if (it is TodoScreenUiState .Success ) {
70- it.copy(todos = todos)
71- } else {
72- TodoScreenUiState .Success (todos = todos)
73- }
74- }
75- }
76- }
77- }
68+ val uiState: StateFlow <TodoScreenUiState > = combine(liveSessionState, todos) { liveSessionState, todos ->
69+ TodoScreenUiState .Success (todos, liveSessionState)
70+ }.stateIn(
71+ scope = viewModelScope,
72+ started = SharingStarted .WhileSubscribed (5000L ),
73+ initialValue = TodoScreenUiState .Initial
74+ )
7875
7976 fun addTodo (taskDescription : String ) {
8077 todoRepository.addTodo(taskDescription)
@@ -91,34 +88,21 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
9188 @SuppressLint(" MissingPermission" )
9289 fun toggleLiveSession (activity : Activity ) {
9390 viewModelScope.launch {
94- val currentState = _uiState .value
95- if (currentState !is TodoScreenUiState .Success ) return @launch
91+ if (liveSessionState.value is LiveSessionState .NotReady ) return @launch
9692
9793 session?.let {
98- if (! currentState.isLiveSessionRunning ) {
94+ if (liveSessionState.value is LiveSessionState . Ready ) {
9995 if (ContextCompat .checkSelfPermission(
10096 activity,
10197 Manifest .permission.RECORD_AUDIO ,
10298 ) == PackageManager .PERMISSION_GRANTED
10399 ) {
104100 it.startAudioConversation(::handleFunctionCall)
105- _uiState .update {
106- if (it is TodoScreenUiState .Success ) {
107- it.copy(isLiveSessionRunning = true )
108- } else {
109- it
110- }
111- }
101+ liveSessionState.value = LiveSessionState .Running
112102 }
113103 } else {
114104 it.stopAudioConversation()
115- _uiState .update {
116- if (it is TodoScreenUiState .Success ) {
117- it.copy(isLiveSessionRunning = false )
118- } else {
119- it
120- }
121- }
105+ liveSessionState.value = LiveSessionState .Ready
122106 }
123107 }
124108 }
@@ -192,21 +176,10 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
192176 session = generativeModel.connect()
193177 } catch (e: Exception ) {
194178 Log .e(TAG , " Error connecting to the model" , e)
195- _uiState .update {
196- TodoScreenUiState .Error (
197- isLiveSessionReady = false ,
198- isLiveSessionRunning = false ,
199- )
200- }
179+ liveSessionState.value = LiveSessionState .Error
201180 }
202181
203- _uiState .update {
204- if (it is TodoScreenUiState .Success ) {
205- it.copy(isLiveSessionReady = true )
206- } else {
207- it
208- }
209- }
182+ liveSessionState.value = LiveSessionState .Ready
210183 }
211184 }
212185
0 commit comments