git.iko.soy/parseable-android
on 0da331f help sign in
104 lines 4.2 kB history raw
1package com.parseable.android.ui.screens.logviewer
3import androidx.lifecycle.ViewModel
4import androidx.lifecycle.viewModelScope
5import com.parseable.android.data.model.*
6import com.parseable.android.data.repository.ParseableRepository
7import dagger.hilt.android.lifecycle.HiltViewModel
8import kotlinx.coroutines.CancellationException
9import kotlinx.coroutines.Job
10import kotlinx.coroutines.async
11import kotlinx.coroutines.flow.MutableStateFlow
12import kotlinx.coroutines.flow.StateFlow
13import kotlinx.coroutines.flow.asStateFlow
14import kotlinx.coroutines.flow.update
15import kotlinx.coroutines.launch
16import kotlinx.serialization.json.JsonObject
17import javax.inject.Inject
19data class StreamInfoState(
20 val streamName: String = "",
21 val stats: StreamStats? = null,
22 val schema: List<SchemaField> = emptyList(),
23 val schemaFailed: Boolean = false,
24 val retention: List<RetentionConfig> = emptyList(),
25 val rawInfo: JsonObject? = null,
26 val isLoading: Boolean = false,
27 val error: String? = null,
28 val isDeleting: Boolean = false,
29 val deleteSuccess: Boolean = false,
32@HiltViewModel
33class StreamInfoViewModel @Inject constructor(
34 private val repository: ParseableRepository,
35) : ViewModel() {
37 private val _state = MutableStateFlow(StreamInfoState())
38 val state: StateFlow<StreamInfoState> = _state.asStateFlow()
39 private var loadJob: Job? = null
41 fun load(streamName: String) {
42 loadJob?.cancel()
43 _state.update { it.copy(streamName = streamName, isLoading = true, error = null) }
45 loadJob = viewModelScope.launch {
46 try {
47 val statsDeferred = async { repository.getStreamStats(streamName) }
48 val schemaDeferred = async { repository.getStreamSchema(streamName) }
49 val retentionDeferred = async { repository.getStreamRetention(streamName) }
50 val infoDeferred = async { repository.getStreamInfo(streamName) }
52 val statsResult = statsDeferred.await()
53 val schemaResult = schemaDeferred.await()
54 val retentionResult = retentionDeferred.await()
55 val infoResult = infoDeferred.await()
57 _state.update {
58 it.copy(
59 stats = (statsResult as? ApiResult.Success)?.data,
60 schema = (schemaResult as? ApiResult.Success)?.data?.fields ?: emptyList(),
61 schemaFailed = schemaResult is ApiResult.Error,
62 retention = (retentionResult as? ApiResult.Success)?.data ?: emptyList(),
63 rawInfo = (infoResult as? ApiResult.Success)?.data,
64 isLoading = false,
65 error = listOfNotNull(
66 (statsResult as? ApiResult.Error)?.userMessage,
67 (schemaResult as? ApiResult.Error)?.userMessage,
68 (retentionResult as? ApiResult.Error)?.userMessage,
69 (infoResult as? ApiResult.Error)?.userMessage,
70 ).distinct().joinToString("\n").ifEmpty { null },
71 )
72 }
73 } catch (e: CancellationException) {
74 throw e
75 } catch (e: Exception) {
76 _state.update {
77 it.copy(isLoading = false, error = e.message ?: "Failed to load stream info")
78 }
79 }
80 }
81 }
83 fun consumeDeleteSuccess() {
84 _state.update { it.copy(deleteSuccess = false) }
85 }
87 fun deleteStream() {
88 val name = _state.value.streamName
89 if (name.isEmpty()) return
90 viewModelScope.launch {
91 _state.update { it.copy(isDeleting = true, error = null) }
92 when (val result = repository.deleteStream(name)) {
93 is ApiResult.Success -> {
94 _state.update { it.copy(isDeleting = false, deleteSuccess = true) }
95 }
96 is ApiResult.Error -> {
97 _state.update {
98 it.copy(isDeleting = false, error = "Delete failed: ${result.userMessage}")
99 }
100 }
101 }
102 }
103 }