Skip to content

Commit

Permalink
add: Fragment - ViewModel connection always use UiState to send and r…
Browse files Browse the repository at this point in the history
…eceive data
  • Loading branch information
jerubrin committed Dec 7, 2021
1 parent 4bba895 commit 42377c5
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import com.jerubrin.tallyflash.databinding.FragmentConnectionBinding
import com.jerubrin.tallyflash.domain.UiState
import com.jerubrin.tallyflash.entity.ConnectionData
import com.jerubrin.tallyflash.presentation.vm.ConnectionViewModel
import com.jerubrin.tallyflash.presentation.vm.ConnectionViewModel.CorrectInputState
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -28,20 +30,26 @@ class ConnectionFragment : Fragment() {
): View {
_binding = FragmentConnectionBinding.inflate(inflater, container, false)

binding.editTextIp.setText(viewModel.url)
binding.editTextPort.setText(viewModel.port)
viewModel.connectionDataState.data.apply {
binding.editTextIp.setText(ip)
binding.editTextPort.setText(port)
}

binding.btnConnect.setOnClickListener {
val url = binding.editTextIp.text.toString()
val port = binding.editTextPort.text.toString()
val connect = ConnectionData(
binding.editTextIp.text.toString(),
binding.editTextPort.text.toString()
)

viewModel.checkAndSaveConnectionData(url, port).also {
if (it is CorrectInputState.Correct) {
viewModel.checkAndSaveConnectionData(UiState.Ready(connect)).also { state ->
if (state is UiState.Ready<*>) {
val action =
ConnectionFragmentDirections.actionConnectionFragmentToScenesListFragment()
findNavController().navigate(action)
}
binding.textViewErrorMessage.text = it.errorMsg
if (state is UiState.Error) {
binding.textViewErrorMessage.text = state.errorMessage
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,7 @@ class ScenesListFragment : Fragment() {
private fun showSceneList(it: UiState.Ready<*>, adapter: InputsListAdapter) {
binding.progressLoading.isVisible = false
binding.frameError.isVisible = false
if (it.data is List<*> &&
it.data.isNotEmpty() &&
it.data[0] is Scene
) {
adapter.submitList(it.data as List<Scene>)
}
adapter.submitList(it.data as List<Scene>)
}

private fun showLoading() {
Expand All @@ -84,7 +79,7 @@ class ScenesListFragment : Fragment() {
}

private fun showError() {
val connectionData = viewModel.getConnectionData()
val connectionData = viewModel.connectionDataState.data
binding.progressLoading.isVisible = false
binding.textViewErrorMsg.text =
getString(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.jerubrin.tallyflash.presentation

import android.graphics.BlendMode
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
Expand All @@ -14,7 +12,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.navArgs
import com.jerubrin.tallyflash.R
import com.jerubrin.tallyflash.databinding.FragmentTallyBinding
import com.jerubrin.tallyflash.entity.Scene
import com.jerubrin.tallyflash.domain.UiState
import com.jerubrin.tallyflash.entity.SceneState
import com.jerubrin.tallyflash.presentation.vm.TallyViewModel
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -34,7 +32,9 @@ class TallyFragment : Fragment() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.setNewScene(args.scene)
viewModel.setNewScene(
UiState.Ready(args.scene)
)
}

override fun onCreateView(
Expand All @@ -43,12 +43,14 @@ class TallyFragment : Fragment() {
): View {
_binding = FragmentTallyBinding.inflate(inflater, container, false)

binding.textViewName.text = viewModel.name
binding.textViewNumber.text = viewModel.number.toString()
viewModel.currentSceneUiState.data.apply {
binding.textViewName.text = shortTitle
binding.textViewNumber.text = number.toString()
}

lifecycleScope.launch {
viewModel.sceneState.collectLatest {
val settingsData = viewModel.getSettingsData
val settingsData = viewModel.getSettingsData.data
when(it) {
SceneState.ACTIVE -> {
binding.root.background = settingsData.activeColor.toDrawable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.os.Build
import android.os.IBinder
import com.jerubrin.tallyflash.MainActivity
import com.jerubrin.tallyflash.R
import com.jerubrin.tallyflash.di.ServiceModule
import com.jerubrin.tallyflash.domain.UiState
import com.jerubrin.tallyflash.domain.usecase.BaseUseCase
import com.jerubrin.tallyflash.entity.Scene
Expand Down Expand Up @@ -41,11 +40,11 @@ class SceneStateService : Service(), SceneStateServiceControl {
_sceneState

private var currentScene: Scene = Scene()
override fun setCurrentScene(scene: Scene) {
currentScene = scene
override fun setCurrentScene(sceneState: UiState.Ready<Scene>) {
currentScene = sceneState.data
}
override fun getCurrentScene(): Scene =
currentScene
override fun getCurrentScene(): UiState =
UiState.Ready(currentScene)

private var countErrorStates = 0

Expand Down Expand Up @@ -85,9 +84,7 @@ class SceneStateService : Service(), SceneStateServiceControl {
updateState()
} else {
_sceneState.value = SceneState.OFF
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
flashController.changeFlashLightState(SceneState.OFF)
}
flashController.changeFlashLightState(SceneState.OFF)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//getSystemService()
screenStateSerNotification.updateNotificationText(
Expand Down Expand Up @@ -117,10 +114,8 @@ class SceneStateService : Service(), SceneStateServiceControl {
} else {
countErrorStates = 0
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
flashController.changeFlashLightState(_sceneState.value)
}

flashController.changeFlashLightState(_sceneState.value)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
screenStateSerNotification.changeNotification(
this,
Expand All @@ -140,9 +135,7 @@ class SceneStateService : Service(), SceneStateServiceControl {
}

override fun onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
flashController.changeFlashLightState(SceneState.OFF)
}
flashController.changeFlashLightState(SceneState.OFF)
super.onDestroy()
}

Expand All @@ -157,10 +150,10 @@ class SceneStateService : Service(), SceneStateServiceControl {

interface SceneStateServiceControl {

fun setCurrentScene(scene: Scene)
fun setCurrentScene(sceneState: UiState.Ready<Scene>) //Scene

fun getCurrentScene(): Scene
fun getCurrentScene(): UiState //Scene

fun getSceneState(): StateFlow<SceneState>
fun getSceneState(): StateFlow<SceneState> //SceneState

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.jerubrin.tallyflash.presentation.vm
import androidx.lifecycle.ViewModel
import com.jerubrin.tallyflash.R
import com.jerubrin.tallyflash.data.ResourcesInterface
import com.jerubrin.tallyflash.domain.UiState
import com.jerubrin.tallyflash.domain.usecase.prefs.BasePrefsUseCase
import com.jerubrin.tallyflash.entity.ConnectionData
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -11,33 +12,31 @@ import javax.inject.Inject

@HiltViewModel
class ConnectionViewModel @Inject constructor(
readSharedPrefConnectionUseCase: BasePrefsUseCase<ConnectionData, Unit>,
private val readSharedPrefConnectionUseCase: BasePrefsUseCase<ConnectionData, Unit>,
private val writeSharedPrefConnectionUseCase: BasePrefsUseCase<Boolean, ConnectionData>,
private val resources: ResourcesInterface
) : ViewModel() {

private val connectionData = readSharedPrefConnectionUseCase.execute(Unit)
val url = connectionData.ip
val port = connectionData.port
val connectionDataState get() =
UiState.Ready(readSharedPrefConnectionUseCase.execute(Unit))

fun checkAndSaveConnectionData(url: String, port: String): CorrectInputState {
checkIpAndPort(url, port).also {
if (it is CorrectInputState.Correct) {
val connectionData = ConnectionData(ip = url, port = port)
writeSharedPrefConnectionUseCase.execute(connectionData)
fun checkAndSaveConnectionData(uiState: UiState.Ready<ConnectionData>): UiState {
checkIpAndPort(uiState.data).also {
if (it is UiState.Ready<*>) {
writeSharedPrefConnectionUseCase.execute(it.data as ConnectionData)
}
return it
}
}

private fun checkIpAndPort(url: String, port: String): CorrectInputState {
if (url.count{ ".".contains(it) } != 3)
return CorrectInputState.WrongIp(resources.getString(R.string.wrong_ip))
if (url.replace(".", "").toLongOrNull() == null)
return CorrectInputState.WrongIp(resources.getString(R.string.wrong_ip))
if (port.toIntOrNull() == null)
return CorrectInputState.WrongPort(resources.getString(R.string.wrong_port))
return CorrectInputState.Correct("")
private fun checkIpAndPort(connectionData: ConnectionData): UiState {
if (connectionData.ip.count{ ".".contains(it) } != 3)
return UiState.Error(resources.getString(R.string.wrong_ip))
if (connectionData.ip.replace(".", "").toLongOrNull() == null)
return UiState.Error(resources.getString(R.string.wrong_ip))
if (connectionData.port.toIntOrNull() == null)
return UiState.Error(resources.getString(R.string.wrong_port))
return UiState.Ready(connectionData)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ class ScenesListViewModel @Inject constructor(
private val service: SceneStateServiceControl
) : ViewModel() {

fun getConnectionData(): ConnectionData =
readSharedPrefConnectionUseCase.execute(Unit)
val connectionDataState get() =
UiState.Ready(
readSharedPrefConnectionUseCase.execute(Unit)
)

fun loadSceneList(): Flow<UiState> =
sceneListUseCase.execute(
getConnectionData()
connectionDataState.data
)

fun resetService() {
//clear scene in service
service.setCurrentScene( Scene() )
service.setCurrentScene(
UiState.Ready( Scene() )
)
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.jerubrin.tallyflash.presentation.vm

import androidx.lifecycle.ViewModel
import com.jerubrin.tallyflash.domain.UiState
import com.jerubrin.tallyflash.domain.usecase.prefs.BasePrefsUseCase
import com.jerubrin.tallyflash.entity.Scene
import com.jerubrin.tallyflash.entity.SceneState
Expand All @@ -16,17 +17,16 @@ class TallyViewModel @Inject constructor(
private val service: SceneStateServiceControl
) : ViewModel() {

private var currentScene: Scene = Scene()

val number get() = currentScene.number
val name get() = currentScene.shortTitle
private var _currentScene: Scene = Scene()
val currentSceneUiState get() = UiState.Ready(_currentScene)

val sceneState: StateFlow<SceneState> get() = service.getSceneState()

fun setNewScene(scene: Scene) {
currentScene = scene
service.setCurrentScene(scene)
fun setNewScene(uiState: UiState.Ready<Scene>) {
_currentScene = uiState.data
service.setCurrentScene(uiState)
}

val getSettingsData get() = readSharedPrefMainUseCase.execute(Unit)
val getSettingsData get() =
UiState.Ready( readSharedPrefMainUseCase.execute(Unit) )
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import androidx.activity.viewModels
import com.jerubrin.tallyflash.di.AppModule
import com.jerubrin.tallyflash.di.DataModule
import com.jerubrin.tallyflash.di.SharedPrefUseCaseModule
import com.jerubrin.tallyflash.domain.UiState
import com.jerubrin.tallyflash.entity.ConnectionData
import com.jerubrin.tallyflash.presentation.vm.ConnectionViewModel
import com.jerubrin.tallyflash.presentation.vm.ConnectionViewModel.CorrectInputState
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.HiltTestApplication
import dagger.hilt.android.testing.UninstallModules
import junit.framework.Assert.assertEquals
import junit.framework.TestCase.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
Expand Down Expand Up @@ -44,37 +45,42 @@ class ConnectionViewModelTest {
}

@Test
fun getUrl() {
fun checkGetConnectionData() {
assertEquals(
TestReadSharedPrefConnectionUseCase.DEFAULT_IP,
viewModel.url
viewModel.connectionDataState.data.ip
)
}

@Test
fun getPort() {
assertEquals(
TestReadSharedPrefConnectionUseCase.DEFAULT_PORT,
viewModel.port
viewModel.connectionDataState.data.port
)
}

@Test
fun checkAndSaveConnectionData() {
viewModel.checkAndSaveConnectionData("192.168.0.1", "8088").also {
assert(it is CorrectInputState.Correct)
var uiState = UiState.Ready( ConnectionData("192.168.0.1", "8088") )
viewModel.checkAndSaveConnectionData(uiState).also {
assert(it is UiState.Ready<*>)
}
viewModel.checkAndSaveConnectionData("192.168.1", "8088").also {
assert(it is CorrectInputState.WrongIp)

uiState = UiState.Ready( ConnectionData("192.168.1", "8088") )
viewModel.checkAndSaveConnectionData(uiState).also {
assert(it is UiState.Error)
}
viewModel.checkAndSaveConnectionData("192.168.0.1.1", "8088").also {
assert(it is CorrectInputState.WrongIp)

uiState = UiState.Ready( ConnectionData("192.168.0.1.1", "8088") )
viewModel.checkAndSaveConnectionData(uiState).also {
assert(it is UiState.Error)
}
viewModel.checkAndSaveConnectionData("192.168.0.1", "").also {
assert(it is CorrectInputState.WrongPort)

uiState = UiState.Ready( ConnectionData("192.168.0.1", "") )
viewModel.checkAndSaveConnectionData(uiState).also {
assert(it is UiState.Error)
}
viewModel.checkAndSaveConnectionData("192.168.0.1", "---").also {
assert(it is CorrectInputState.WrongPort)

uiState = UiState.Ready( ConnectionData("192.168.0.1", "---") )
viewModel.checkAndSaveConnectionData(uiState).also {
assert(it is UiState.Error)
}
}
}
Loading

0 comments on commit 42377c5

Please sign in to comment.