Switched to LiveData as stated in the specification

This commit is contained in:
Balazs Toldi 2021-11-23 09:02:45 +01:00
parent a4e760f9d1
commit dcac6e7801
Signed by: Bazsalanszky
GPG key ID: 933820884952BE27
4 changed files with 107 additions and 70 deletions

View file

@ -8,7 +8,21 @@
<entry key="../../../../../layout/compose-model-1633594045878.xml" value="1.0" />
<entry key="../../../../../layout/compose-model-1633596772266.xml" value="0.18285472972972974" />
<entry key="../../../../../layout/compose-model-1633601146222.xml" value="0.18285472972972974" />
<entry key="../../../../../layout/compose-model-1634022040984.xml" value="0.3037037037037037" />
<entry key="../../../../../layout/compose-model-1633617799626.xml" value="0.3095439189189189" />
<entry key="../../../../../layout/compose-model-1633617944748.xml" value="0.4962962962962963" />
<entry key="../../../../../layout/compose-model-1633767363997.xml" value="0.17905405405405406" />
<entry key="../../../../../layout/compose-model-1634889935306.xml" value="0.3095439189189189" />
<entry key="../../../../../layout/compose-model-1634890564069.xml" value="0.4861111111111111" />
<entry key="../../../../../layout/compose-model-1634891321942.xml" value="0.33" />
<entry key="../../../../../layout/compose-model-1634891753898.xml" value="1.0" />
<entry key="../../../../../layout/compose-model-1634893431951.xml" value="0.3095439189189189" />
<entry key="../../../../../layout/compose-model-1634898066813.xml" value="0.3095439189189189" />
<entry key="../../../../../layout/compose-model-1634898107086.xml" value="0.4759259259259259" />
<entry key="../../../../../layout/compose-model-1634990577157.xml" value="0.4703703703703704" />
<entry key="../../../../../layout/compose-model-1637651431048.xml" value="0.3611111111111111" />
<entry key="../../../../../layout/compose-model-1637651867699.xml" value="0.3095439189189189" />
<entry key="../../../../../layout/compose-model-1637652867578.xml" value="0.36018518518518516" />
<entry key="../../../../../layout/compose-model-1637653004789.xml" value="0.45740740740740743" />
</map>
</option>
</component>
@ -19,7 +33,7 @@
<option name="HEAP_SIZE" value="256" />
<option name="LOCALE" value="en" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -7,23 +7,19 @@ import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import eu.toldi.balazs.caster.model.ChromeCastViewModel
import eu.toldi.balazs.caster.ui.theme.CasterTheme
import kotlinx.coroutines.*
@ -44,27 +40,33 @@ class MainActivity : ComponentActivity() {
setContent {
CasterTheme {
val viewModel = ViewModelProvider(this).get(ChromeCastViewModel::class.java)
GlobalScope.launch(IO) {
ChromeCasts.startDiscovery(getIPv4Address())
}
viewModel.startScanning()
val chromeCasts = viewModel.chromeCasts.value
val chromeCastState = viewModel._chromecasts.observeAsState(initial = emptyList())
val chromeCasts = chromeCastState.value
Log.e(null,chromeCasts.toString())
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Column {
MenuBar() {
viewModel.chromeCasts.value = emptyList()
GlobalScope.launch(IO) {
ChromeCasts.restartDiscovery(getIPv4Address())
}
viewModel.refresh()
}
LazyColumn(modifier = Modifier
.padding(all = 4.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally) {
item {
if (chromeCasts.size > 0)
if (chromeCasts.isNotEmpty())
Text(text = "Available chromecasts:")
else {
Column(
modifier = Modifier.fillMaxSize() ,
horizontalAlignment = Alignment.CenterHorizontally
){
Text("Looking for Chromecasts on your network...")
CircularProgressIndicator()
}
}
}
items(chromeCasts.size) { index ->
showChromeCastButton(chromeCast = chromeCasts[index])
@ -90,17 +92,6 @@ class MainActivity : ComponentActivity() {
}
}
fun getIPv4Address(): InetAddress? {
NetworkInterface.getNetworkInterfaces().toList().forEach { interf ->
interf.inetAddresses.toList().forEach { inetAddress ->
if (!inetAddress.isLoopbackAddress && inetAddress.hostAddress.indexOf(':') < 0) {
return inetAddress
}
}
}
return null
}
@Composable
fun MenuBar(refresh: () -> Unit) {
TopAppBar(
@ -115,6 +106,15 @@ class MainActivity : ComponentActivity() {
contentDescription = "Refresh"
)
}
IconButton(onClick = {
}) {
Icon(
Icons.Filled.Add,
contentDescription = "Add"
)
}
}
}
)

View file

@ -13,10 +13,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@ -53,15 +52,15 @@ class ShareRecieverActivity : ComponentActivity() {
setContent {
CasterTheme {
val viewModel = ViewModelProvider(this).get(ChromeCastViewModel::class.java)
GlobalScope.launch(IO) {
ChromeCasts.startDiscovery(getIPv4Address())
}
val chromeCasts = viewModel.chromeCasts.value
viewModel.startScanning()
val chromeCastState = viewModel.chromeCastsLiveData.observeAsState(emptyList())
val chromeCasts = chromeCastState.value
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Column {
MenuBar()
MenuBar{
viewModel.refresh()
}
var enabled by remember {
mutableStateOf(true)
}
@ -72,7 +71,7 @@ class ShareRecieverActivity : ComponentActivity() {
horizontalAlignment = Alignment.CenterHorizontally
) {
item {
if (chromeCasts.size > 0)
if (chromeCasts.isNotEmpty())
Text(text = "Available chromecasts:")
}
items(chromeCasts.size) { index ->
@ -117,37 +116,27 @@ class ShareRecieverActivity : ComponentActivity() {
}
}
fun getIPv4Address(): InetAddress? {
NetworkInterface.getNetworkInterfaces().toList().forEach { interf ->
interf.inetAddresses.toList().forEach { inetAddress ->
if (!inetAddress.isLoopbackAddress && inetAddress.hostAddress.indexOf(':') < 0) {
return inetAddress
}
}
}
return null
}
@Composable
fun MenuBar() {
fun MenuBar(refresh: () -> Unit) {
TopAppBar(
title = {
Text(stringResource(id = R.string.title_activity_share_reciever))
},
navigationIcon = {
IconButton(onClick = { }) {
Icon(
Icons.Filled.Menu,
contentDescription = "Menu Hamburger"
)
}
},
actions = {
Row {
IconButton(onClick = {}) {
IconButton(onClick = refresh) {
Icon(
Icons.Filled.Share,
contentDescription = "Search Article"
Icons.Filled.Refresh,
contentDescription = "Refresh"
)
}
IconButton(onClick = {
}) {
Icon(
Icons.Filled.Add,
contentDescription = "Add"
)
}
}
@ -160,7 +149,7 @@ class ShareRecieverActivity : ComponentActivity() {
@Composable
fun DefaultPreview() {
CasterTheme {
MenuBar()
MenuBar {}
}
}
}

View file

@ -1,5 +1,6 @@
package eu.toldi.balazs.caster.model
import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
@ -8,28 +9,61 @@ import androidx.compose.runtime.remember
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import su.litvak.chromecast.api.v2.ChromeCast
import su.litvak.chromecast.api.v2.ChromeCasts
import su.litvak.chromecast.api.v2.ChromeCastsListener
import java.net.InetAddress
import java.net.NetworkInterface
import javax.jmdns.ServiceEvent
import javax.jmdns.ServiceListener
class ChromeCastViewModel : ViewModel(),ChromeCastsListener {
val chromeCasts : MutableState<List<ChromeCast>> = mutableStateOf(ChromeCasts.get())
val _chromecasts : MutableLiveData<List<ChromeCast>> = MutableLiveData<List<ChromeCast>>(listOf())
val chromeCastsLiveData : LiveData<List<ChromeCast>>
get() = _chromecasts
init {
ChromeCasts.registerListener(this)
}
override fun newChromeCastDiscovered(chromeCast: ChromeCast?) {
if(chromeCast != null)
chromeCasts.value += chromeCast
if(chromeCast != null) {
Log.i(null,"Found ${chromeCast.title}")
_chromecasts.postValue(_chromecasts.value!!.plus(chromeCast))
}
}
override fun chromeCastRemoved(chromeCast: ChromeCast?) {
if(chromeCast != null)
chromeCasts.value -= chromeCast
if(chromeCast != null) {
Log.i(null,"Lost ${chromeCast.title}")
_chromecasts.postValue(_chromecasts.value!!.minus(chromeCast))
}
}
fun refresh() {
_chromecasts.value = emptyList()
viewModelScope.launch(IO) {
ChromeCasts.restartDiscovery(getIPv4Address())
}
}
fun startScanning() {
viewModelScope.launch(IO) {
ChromeCasts.startDiscovery(getIPv4Address())
}
}
fun getIPv4Address(): InetAddress? {
NetworkInterface.getNetworkInterfaces().toList().forEach { interf ->
interf.inetAddresses.toList().forEach { inetAddress ->
if (!inetAddress.isLoopbackAddress && inetAddress.hostAddress.indexOf(':') < 0) {
return inetAddress
}
}
}
return null
}
}