AI:remove more boilerplate

This commit is contained in:
androidlover5842
2026-02-03 09:38:30 +05:30
parent d6c8e522de
commit 4e5f368256
8 changed files with 115 additions and 96 deletions

View File

@@ -2,9 +2,12 @@ package com.android.trisolarispms.core.viewmodel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.android.trisolarispms.data.api.core.ApiClient
import com.android.trisolarispms.data.api.core.ApiService
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.Response
internal fun <S> ViewModel.launchRequest( internal fun <S> ViewModel.launchRequest(
state: MutableStateFlow<S>, state: MutableStateFlow<S>,
@@ -23,3 +26,31 @@ internal fun <S> ViewModel.launchRequest(
} }
} }
} }
internal fun <S> ViewModel.launchApiMutation(
state: MutableStateFlow<S>,
action: String,
setLoading: (S) -> S,
setSuccess: (S) -> S,
setError: (S, String) -> S,
onDone: () -> Unit = {},
createApi: () -> ApiService = { ApiClient.create() },
call: suspend (ApiService) -> Response<*>
) {
launchRequest(
state = state,
setLoading = setLoading,
setError = setError,
defaultError = "$action failed"
) {
val response = call(createApi())
if (response.isSuccessful) {
state.update(setSuccess)
onDone()
} else {
state.update { current ->
setError(current, "$action failed: ${response.code()}")
}
}
}
}

View File

@@ -1,15 +1,13 @@
package com.android.trisolarispms.ui.room package com.android.trisolarispms.ui.room
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import com.android.trisolarispms.core.viewmodel.launchApiMutation
import com.android.trisolarispms.data.api.core.ApiClient
import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.core.ApiService
import com.android.trisolarispms.data.api.model.RoomCreateRequest import com.android.trisolarispms.data.api.model.RoomCreateRequest
import com.android.trisolarispms.data.api.model.RoomUpdateRequest import com.android.trisolarispms.data.api.model.RoomUpdateRequest
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import retrofit2.Response import retrofit2.Response
class RoomFormViewModel : ViewModel() { class RoomFormViewModel : ViewModel() {
@@ -146,19 +144,14 @@ class RoomFormViewModel : ViewModel() {
onDone: () -> Unit, onDone: () -> Unit,
call: suspend (ApiService) -> Response<*> call: suspend (ApiService) -> Response<*>
) { ) {
viewModelScope.launch { launchApiMutation(
_state.update { it.copy(isLoading = true, error = null) } state = _state,
try { action = action,
val response = call(ApiClient.create()) setLoading = { it.copy(isLoading = true, error = null) },
if (response.isSuccessful) { setSuccess = { it.copy(isLoading = false, success = true) },
_state.update { it.copy(isLoading = false, success = true) } setError = { current, message -> current.copy(isLoading = false, error = message) },
onDone() onDone = onDone,
} else { call = call
_state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } )
}
} catch (e: Exception) {
_state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") }
}
}
} }
} }

View File

@@ -1,9 +1,6 @@
package com.android.trisolarispms.ui.roomimage package com.android.trisolarispms.ui.roomimage
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
@Composable @Composable
@@ -12,18 +9,12 @@ fun AddImageTagScreen(
onSave: () -> Unit, onSave: () -> Unit,
viewModel: ImageTagFormViewModel = viewModel() viewModel: ImageTagFormViewModel = viewModel()
) { ) {
val state by viewModel.state.collectAsState() ImageTagEditorScreen(
LaunchedEffect(Unit) {
viewModel.reset()
}
ImageTagFormScreen(
title = "Add Tag", title = "Add Tag",
name = state.name, setupKey = Unit,
error = state.error,
onNameChange = viewModel::onNameChange,
onBack = onBack, onBack = onBack,
onSave = { viewModel.submitCreate(onSave) } onSaveClick = { viewModel.submitCreate(onSave) },
setupForm = { viewModel.reset() },
viewModel = viewModel
) )
} }

View File

@@ -1,9 +1,6 @@
package com.android.trisolarispms.ui.roomimage package com.android.trisolarispms.ui.roomimage
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.android.trisolarispms.data.api.model.RoomImageTagDto import com.android.trisolarispms.data.api.model.RoomImageTagDto
@@ -14,18 +11,12 @@ fun EditImageTagScreen(
onSave: () -> Unit, onSave: () -> Unit,
viewModel: ImageTagFormViewModel = viewModel() viewModel: ImageTagFormViewModel = viewModel()
) { ) {
val state by viewModel.state.collectAsState() ImageTagEditorScreen(
LaunchedEffect(tag.id) {
viewModel.setTag(tag)
}
ImageTagFormScreen(
title = "Edit Tag", title = "Edit Tag",
name = state.name, setupKey = tag.id,
error = state.error,
onNameChange = viewModel::onNameChange,
onBack = onBack, onBack = onBack,
onSave = { viewModel.submitUpdate(tag.id.orEmpty(), onSave) } onSaveClick = { viewModel.submitUpdate(tag.id.orEmpty(), onSave) },
setupForm = { viewModel.setTag(tag) },
viewModel = viewModel
) )
} }

View File

@@ -0,0 +1,31 @@
package com.android.trisolarispms.ui.roomimage
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@Composable
internal fun ImageTagEditorScreen(
title: String,
setupKey: Any?,
onBack: () -> Unit,
onSaveClick: () -> Unit,
setupForm: () -> Unit,
viewModel: ImageTagFormViewModel
) {
val state by viewModel.state.collectAsState()
LaunchedEffect(setupKey) {
setupForm()
}
ImageTagFormScreen(
title = title,
name = state.name,
error = state.error,
onNameChange = viewModel::onNameChange,
onBack = onBack,
onSave = onSaveClick
)
}

View File

@@ -1,14 +1,12 @@
package com.android.trisolarispms.ui.roomimage package com.android.trisolarispms.ui.roomimage
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import com.android.trisolarispms.core.viewmodel.launchApiMutation
import com.android.trisolarispms.data.api.core.ApiClient
import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.core.ApiService
import com.android.trisolarispms.data.api.model.RoomImageTagDto import com.android.trisolarispms.data.api.model.RoomImageTagDto
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import retrofit2.Response import retrofit2.Response
class ImageTagFormViewModel : ViewModel() { class ImageTagFormViewModel : ViewModel() {
@@ -64,22 +62,17 @@ class ImageTagFormViewModel : ViewModel() {
resetOnSuccess: Boolean, resetOnSuccess: Boolean,
call: suspend (ApiService) -> Response<*> call: suspend (ApiService) -> Response<*>
) { ) {
viewModelScope.launch { launchApiMutation(
_state.update { it.copy(isLoading = true, error = null) } state = _state,
try { action = action,
val response = call(ApiClient.create()) setLoading = { it.copy(isLoading = true, error = null) },
if (response.isSuccessful) { setSuccess = {
_state.update { if (resetOnSuccess) ImageTagFormState(success = true)
if (resetOnSuccess) ImageTagFormState(success = true) else it.copy(isLoading = false, success = true)
else it.copy(isLoading = false, success = true) },
} setError = { current, message -> current.copy(isLoading = false, error = message) },
onDone() onDone = onDone,
} else { call = call
_state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } )
}
} catch (e: Exception) {
_state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") }
}
}
} }
} }

View File

@@ -2,6 +2,7 @@ package com.android.trisolarispms.ui.roomtype
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.android.trisolarispms.core.viewmodel.launchApiMutation
import com.android.trisolarispms.data.api.core.ApiClient import com.android.trisolarispms.data.api.core.ApiClient
import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.core.ApiService
import com.android.trisolarispms.data.api.model.AmenityCreateRequest import com.android.trisolarispms.data.api.model.AmenityCreateRequest
@@ -147,19 +148,14 @@ class AmenityFormViewModel : ViewModel() {
onDone: () -> Unit, onDone: () -> Unit,
call: suspend (ApiService) -> Response<*> call: suspend (ApiService) -> Response<*>
) { ) {
viewModelScope.launch { launchApiMutation(
_state.update { it.copy(isLoading = true, error = null) } state = _state,
try { action = action,
val response = call(ApiClient.create()) setLoading = { it.copy(isLoading = true, error = null) },
if (response.isSuccessful) { setSuccess = { it.copy(isLoading = false, success = true) },
_state.update { it.copy(isLoading = false, success = true) } setError = { current, message -> current.copy(isLoading = false, error = message) },
onDone() onDone = onDone,
} else { call = call
_state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } )
}
} catch (e: Exception) {
_state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") }
}
}
} }
} }

View File

@@ -1,15 +1,13 @@
package com.android.trisolarispms.ui.roomtype package com.android.trisolarispms.ui.roomtype
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import com.android.trisolarispms.core.viewmodel.launchApiMutation
import com.android.trisolarispms.data.api.core.ApiClient
import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.core.ApiService
import com.android.trisolarispms.data.api.model.RoomTypeCreateRequest import com.android.trisolarispms.data.api.model.RoomTypeCreateRequest
import com.android.trisolarispms.data.api.model.RoomTypeUpdateRequest import com.android.trisolarispms.data.api.model.RoomTypeUpdateRequest
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import retrofit2.Response import retrofit2.Response
class RoomTypeFormViewModel : ViewModel() { class RoomTypeFormViewModel : ViewModel() {
@@ -144,19 +142,14 @@ class RoomTypeFormViewModel : ViewModel() {
onDone: () -> Unit, onDone: () -> Unit,
call: suspend (ApiService) -> Response<*> call: suspend (ApiService) -> Response<*>
) { ) {
viewModelScope.launch { launchApiMutation(
_state.update { it.copy(isLoading = true, error = null) } state = _state,
try { action = action,
val response = call(ApiClient.create()) setLoading = { it.copy(isLoading = true, error = null) },
if (response.isSuccessful) { setSuccess = { it.copy(isLoading = false, success = true) },
_state.update { it.copy(isLoading = false, success = true) } setError = { current, message -> current.copy(isLoading = false, error = message) },
onDone() onDone = onDone,
} else { call = call
_state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } )
}
} catch (e: Exception) {
_state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") }
}
}
} }
} }