@@ -43,8 +43,12 @@ import com.google.firebase.ai.type.liveGenerationConfig
43
43
import dagger.hilt.android.lifecycle.HiltViewModel
44
44
import javax.inject.Inject
45
45
import kotlinx.coroutines.flow.MutableStateFlow
46
+ import kotlinx.coroutines.flow.SharingStarted
46
47
import kotlinx.coroutines.flow.StateFlow
47
48
import kotlinx.coroutines.flow.asStateFlow
49
+ import kotlinx.coroutines.flow.combine
50
+ import kotlinx.coroutines.flow.map
51
+ import kotlinx.coroutines.flow.stateIn
48
52
import kotlinx.coroutines.flow.update
49
53
import kotlinx.coroutines.launch
50
54
import kotlinx.serialization.json.JsonObject
@@ -56,25 +60,18 @@ import kotlinx.serialization.json.long
56
60
@HiltViewModel
57
61
class TodoScreenViewModel @Inject constructor(private val todoRepository : TodoRepository ) : ViewModel() {
58
62
private val TAG = " TodoScreenViewModel"
59
-
60
63
private var session: LiveSession ? = null
61
64
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
64
67
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
+ )
78
75
79
76
fun addTodo (taskDescription : String ) {
80
77
todoRepository.addTodo(taskDescription)
@@ -91,34 +88,21 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
91
88
@SuppressLint(" MissingPermission" )
92
89
fun toggleLiveSession (activity : Activity ) {
93
90
viewModelScope.launch {
94
- val currentState = _uiState .value
95
- if (currentState !is TodoScreenUiState .Success ) return @launch
91
+ if (liveSessionState.value is LiveSessionState .NotReady ) return @launch
96
92
97
93
session?.let {
98
- if (! currentState.isLiveSessionRunning ) {
94
+ if (liveSessionState.value is LiveSessionState . Ready ) {
99
95
if (ContextCompat .checkSelfPermission(
100
96
activity,
101
97
Manifest .permission.RECORD_AUDIO ,
102
98
) == PackageManager .PERMISSION_GRANTED
103
99
) {
104
100
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
112
102
}
113
103
} else {
114
104
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
122
106
}
123
107
}
124
108
}
@@ -192,21 +176,10 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
192
176
session = generativeModel.connect()
193
177
} catch (e: Exception ) {
194
178
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
201
180
}
202
181
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
210
183
}
211
184
}
212
185
0 commit comments