YACWC
This commit is contained in:
@@ -17,10 +17,10 @@ import androidx.wear.compose.material.Text
|
||||
@Composable
|
||||
fun ControlDashboard(controlDashboardUiState: ControlDashboardUiState,
|
||||
onMicClicked: () -> Unit,
|
||||
onNavClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier) {
|
||||
Box(contentAlignment = Alignment.Center, modifier = modifier.fillMaxSize()) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
|
||||
ControlDashboardButton(buttonState = controlDashboardUiState.micState,
|
||||
onClick = onMicClicked,
|
||||
labelText = if (controlDashboardUiState.micState.expanded) {
|
||||
@@ -29,6 +29,8 @@ fun ControlDashboard(controlDashboardUiState: ControlDashboardUiState,
|
||||
"Start"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ import androidx.activity.compose.setContent
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -28,9 +30,12 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.wear.compose.material.CompactChip
|
||||
import androidx.wear.compose.material.MaterialTheme
|
||||
import androidx.wear.compose.material.Text
|
||||
import androidx.wear.compose.navigation.SwipeDismissableNavHost
|
||||
import androidx.wear.compose.navigation.composable
|
||||
@@ -103,7 +108,7 @@ fun WearApp() {
|
||||
|
||||
val navController: NavHostController = rememberSwipeDismissableNavController()
|
||||
mainState.setNavController(navController);
|
||||
SwipeDismissableNavHost(navController = navController, startDestination = "speaker") {
|
||||
SwipeDismissableNavHost(navController = navController, userSwipeEnabled = true, startDestination = "speaker") {
|
||||
|
||||
composable("species_list") {
|
||||
ScreenScaffold {
|
||||
@@ -112,124 +117,42 @@ fun WearApp() {
|
||||
}
|
||||
|
||||
composable("speaker") {
|
||||
StartRecordingScreen(
|
||||
appState = mainState.appState,
|
||||
onMicClicked = {
|
||||
scope.launch {
|
||||
mainState.onMicClicked()
|
||||
ScreenScaffold {
|
||||
CompactChip(modifier = Modifier,
|
||||
onClick = { navController.navigate("species_list") },
|
||||
enabled = true,
|
||||
contentPadding = PaddingValues(5.dp, 1.dp, 5.dp, 1.dp),
|
||||
shape = MaterialTheme.shapes.small,
|
||||
label = {
|
||||
Text(text = "View>")
|
||||
})
|
||||
|
||||
StartRecordingScreen(
|
||||
appState = mainState.appState,
|
||||
onMicClicked = {
|
||||
scope.launch {
|
||||
mainState.onMicClicked()
|
||||
}
|
||||
},
|
||||
onNavClicked = {
|
||||
navController.navigate("species_list")
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// var sdnv = SwipeDismissableNavHost(navController = navController, startDestination = "list") {
|
||||
// composable("speaker") {
|
||||
// StartRecordingScreen(
|
||||
// context = context,
|
||||
// appState = mainState.appState,
|
||||
// isPermissionDenied = mainState.isPermissionDenied,
|
||||
// onMicClicked = {
|
||||
// scope.launch {
|
||||
// mainState.onMicClicked()
|
||||
// }
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tailrec fun Context.findActivity(): Activity = when (this) {
|
||||
is Activity -> this
|
||||
is Activity -> this
|
||||
is ContextWrapper -> baseContext.findActivity()
|
||||
else -> throw IllegalStateException("findActivity should be called in the context of an Activity")
|
||||
else -> throw IllegalStateException("findActivity should be called in the context of an Activity")
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalHorologistApi::class)
|
||||
@Composable
|
||||
fun MessageDetail(id: String) {
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
ScreenScaffold(scrollState = scrollState) {
|
||||
val padding =
|
||||
ScalingLazyColumnDefaults.padding(first = ScalingLazyColumnDefaults.ItemType.Text, last = ScalingLazyColumnDefaults.ItemType.Text)()
|
||||
Column(modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(scrollState)
|
||||
.rotaryWithScroll(scrollState)
|
||||
.padding(padding),
|
||||
verticalArrangement = Arrangement.Center) {
|
||||
Text(text = id, textAlign = TextAlign.Center, modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalHorologistApi::class)
|
||||
@Composable
|
||||
fun MessageList(onMessageClick: (String) -> Unit) {
|
||||
val columnState =
|
||||
rememberResponsiveColumnState(contentPadding = ScalingLazyColumnDefaults.padding(first = ScalingLazyColumnDefaults.ItemType.Text,
|
||||
last = ScalingLazyColumnDefaults.ItemType.Chip))
|
||||
|
||||
ScreenScaffold(scrollState = columnState) {
|
||||
ScalingLazyColumn(columnState = columnState, modifier = Modifier.fillMaxSize()) {
|
||||
item {
|
||||
ResponsiveListHeader(contentPadding = firstItemPadding()) {
|
||||
Text(text = "Hey hey hey")
|
||||
}
|
||||
}
|
||||
item {
|
||||
Chip(label = "Message 1", onClick = { onMessageClick("message1") })
|
||||
}
|
||||
item {
|
||||
Chip(label = "Message 2", onClick = { onMessageClick("message2") })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalHorologistApi::class)
|
||||
@Composable
|
||||
fun MessageList2(onMessageClick: (String) -> Unit) {
|
||||
val columnState =
|
||||
rememberResponsiveColumnState(contentPadding = ScalingLazyColumnDefaults.padding(first = ScalingLazyColumnDefaults.ItemType.Text,
|
||||
last = ScalingLazyColumnDefaults.ItemType.Chip))
|
||||
|
||||
ScreenScaffold(scrollState = columnState) {
|
||||
ScalingLazyColumn(columnState = columnState, modifier = Modifier.fillMaxSize()) {
|
||||
item {
|
||||
ResponsiveListHeader(contentPadding = firstItemPadding()) {
|
||||
Text(text = "Hey hey hey")
|
||||
}
|
||||
}
|
||||
item {
|
||||
Chip(label = "Message 3", onClick = { onMessageClick("message3") })
|
||||
}
|
||||
item {
|
||||
Chip(label = "Message 4", onClick = { onMessageClick("message4") })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WearPreviewDevices
|
||||
@WearPreviewFontScales
|
||||
@Composable
|
||||
fun MessageDetailPreview() {
|
||||
MessageDetail("test")
|
||||
}
|
||||
|
||||
@WearPreviewDevices
|
||||
@WearPreviewFontScales
|
||||
@Composable
|
||||
fun MessageListPreview() {
|
||||
MessageList(onMessageClick = {})
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.birdsounds.identify.presentation
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import java.time.Instant
|
||||
@@ -11,13 +12,14 @@ class AScore(
|
||||
_species: String,
|
||||
_score: Float,
|
||||
_timestamp: Long,
|
||||
|
||||
_trigger: Boolean = false
|
||||
) {
|
||||
|
||||
val split_stuff: List<String> = _species.split("_");
|
||||
val species = split_stuff[0];
|
||||
val score = _score;
|
||||
// var common_name = split_stuff[1];
|
||||
var trigger = _trigger;
|
||||
// var common_name = split_stuff[1];
|
||||
val common_name = if (split_stuff.size > 1) split_stuff[1] else "";
|
||||
val timestamp = _timestamp
|
||||
fun age(): Long {
|
||||
@@ -34,60 +36,46 @@ class AScore(
|
||||
|
||||
|
||||
object SpeciesList {
|
||||
var internal_list = mutableListOf<MutableState<AScore>>()
|
||||
var internal_list = mutableListOf<AScore>()
|
||||
var do_add_observation = false
|
||||
var _list_on_ui: SnapshotStateList<MutableState<AScore>>? = null
|
||||
fun setSpeciecsShow_list(list_in: SnapshotStateList<MutableState<AScore>>) {
|
||||
_list_on_ui = list_in;
|
||||
}
|
||||
|
||||
|
||||
fun add_observation(species_in: AScore) {
|
||||
Log.w(TAG, "In add obervation")
|
||||
do_add_observation = false
|
||||
Log.w(TAG, "In add observation")
|
||||
var idx = 0
|
||||
var idx_replace = -1
|
||||
for (i in internal_list) {
|
||||
if (i.value.species == species_in.species) {
|
||||
do_add_observation = false
|
||||
if (i.species == species_in.species) {
|
||||
idx_replace = idx
|
||||
}
|
||||
idx += 1
|
||||
}
|
||||
if (idx_replace >= 0) {
|
||||
Log.w(TAG, "Replacing")
|
||||
internal_list[idx_replace].value =
|
||||
species_in // _list_on_ui?.removeAt(idx_replace)
|
||||
// _list_on_ui?.add(species_in);
|
||||
// if (_list_on_ui != null) {
|
||||
// _list_on_ui?.removeAt(idx_replace)
|
||||
// _list_on_ui.add(idx_replace, species_in);
|
||||
// }
|
||||
|
||||
internal_list[idx_replace] = species_in
|
||||
internal_list[idx_replace].trigger = true;
|
||||
} else {
|
||||
internal_list.add(mutableStateOf(species_in))
|
||||
internal_list.add(species_in)
|
||||
}
|
||||
|
||||
internal_list = internal_list.sortedBy({ (it.value.age()) }).toMutableList()
|
||||
// internal_list = internal_list.sortedBy({ (it.age()) }).toMutableList()
|
||||
internal_list = internal_list.sortedWith(compareBy({ it.age() }, { it.score})).toMutableList()
|
||||
|
||||
|
||||
|
||||
while (_list_on_ui!!.size < internal_list.size) {
|
||||
_list_on_ui!!.add(mutableStateOf(AScore("", 0F, 0L)))
|
||||
Log.w(TAG, "Adding stuff to UI list");
|
||||
_list_on_ui!!.add(mutableStateOf(AScore("",0.0F,0L)))
|
||||
}
|
||||
|
||||
Log.w(TAG, "Internal list " + internal_list.toString())
|
||||
for ((index, value) in internal_list.withIndex()) {
|
||||
Log.w(TAG, "Adding ${index}:${value} to list ${_list_on_ui!!.size}")
|
||||
if (_list_on_ui!!.size > index)
|
||||
{
|
||||
Log.w(TAG,"Updating ${value}")
|
||||
_list_on_ui!![index].value = value.value
|
||||
}
|
||||
|
||||
|
||||
_list_on_ui?.get(index)?.value = value;
|
||||
}
|
||||
|
||||
Log.w(TAG, internal_list.size.toString())
|
||||
Log.w(TAG, _list_on_ui?.size.toString()) // internal_list.add(species_in)
|
||||
Log.w(TAG, _list_on_ui?.size.toString()) // internal_list.add(species_in)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +1,154 @@
|
||||
package com.birdsounds.identify.presentation
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.CubicBezierEasing
|
||||
import androidx.compose.animation.core.Easing
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.lerp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.util.lerp
|
||||
import androidx.wear.compose.foundation.lazy.ScalingLazyColumnDefaults.scalingParams
|
||||
import androidx.wear.compose.foundation.lazy.ScalingParams
|
||||
import androidx.wear.compose.foundation.lazy.items
|
||||
import androidx.wear.compose.material.Text
|
||||
import com.google.android.horologist.annotations.ExperimentalHorologistApi
|
||||
import com.google.android.horologist.compose.layout.ScalingLazyColumn
|
||||
import com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults
|
||||
import com.google.android.horologist.compose.layout.ScalingLazyColumnState
|
||||
import com.google.android.horologist.compose.layout.ScreenScaffold
|
||||
import com.google.android.horologist.compose.layout.rememberResponsiveColumnState
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
|
||||
@OptIn(ExperimentalHorologistApi::class)
|
||||
fun interpolateColor(value: Float): Color {
|
||||
// Ensure that the input value is clamped between 0 and 1
|
||||
val clampedValue = value.coerceIn(0f, 1f)
|
||||
|
||||
// Red component: starts at 255 (white) and decreases to 0
|
||||
val red = (255 * (1 - clampedValue)).toInt()
|
||||
|
||||
// Green component: stays at 255 (since both white and green have full green)
|
||||
val green = 255
|
||||
|
||||
// Blue component: starts at 255 (white) and decreases to 0
|
||||
val blue = (255 * (1 - clampedValue)).toInt()
|
||||
|
||||
// Construct the color
|
||||
return Color(red.toInt(), green.toInt(), blue.toInt())
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SpeciesListView(
|
||||
context: Context,
|
||||
fun FlashingText(
|
||||
text: String,
|
||||
color: Color,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
// Set up the flashing state
|
||||
var isFlashing by remember { mutableStateOf(false) }
|
||||
|
||||
val species_list_show = mutableStateListOf<MutableState<AScore>>()
|
||||
for (i in 1..10) {
|
||||
species_list_show.add(mutableStateOf(AScore(i.toString()+"_"+i.toString(), 0.00F, 0L)));
|
||||
}
|
||||
SpeciesList.setSpeciecsShow_list(species_list_show)
|
||||
// Create animation for the background color
|
||||
val backgroundColor by animateColorAsState(
|
||||
targetValue = if (isFlashing) Color.Cyan else Color.Transparent,
|
||||
animationSpec = tween(durationMillis = 500)
|
||||
)
|
||||
|
||||
|
||||
|
||||
val species_show: SnapshotStateList<MutableState<AScore>> = remember { species_list_show }
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
species_show.forEach { aSpec -> Text(text = aSpec.value.common_name) }
|
||||
// Trigger the flash effect once
|
||||
LaunchedEffect(key1 = true) {
|
||||
isFlashing = true
|
||||
delay(300)
|
||||
isFlashing = false
|
||||
}
|
||||
|
||||
// Display the text with animated background
|
||||
Text(
|
||||
text = text,
|
||||
color = color,
|
||||
modifier = modifier
|
||||
.background(color = backgroundColor)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// val columnState =
|
||||
// rememberResponsiveColumnState(contentPadding = ScalingLazyColumnDefaults.padding(first = ScalingLazyColumnDefaults.ItemType.Text,
|
||||
// last = ScalingLazyColumnDefaults.ItemType.Chip))
|
||||
|
||||
|
||||
@SuppressLint("UnrememberedMutableState")
|
||||
@OptIn(ExperimentalHorologistApi::class)
|
||||
@Composable
|
||||
fun SpeciesListView(context: Context,
|
||||
) {
|
||||
|
||||
val species_list_show = mutableStateListOf<MutableState<AScore>>()
|
||||
for (i in 1..3)
|
||||
{
|
||||
val hi = mutableStateOf(AScore("",0.0F,0L))
|
||||
species_list_show.add(hi);
|
||||
}
|
||||
SpeciesList.setSpeciecsShow_list(species_list_show)
|
||||
val species_show: SnapshotStateList<MutableState<AScore>> = remember { species_list_show }
|
||||
|
||||
// var sP = scalingParams( maxTransitionArea= 0.25f, minTransitionArea = 0.05f)
|
||||
// val columnState = ScalingLazyColumnState(scalingParams = sP);
|
||||
var columnState = rememberResponsiveColumnState(contentPadding = ScalingLazyColumnDefaults.padding(first = ScalingLazyColumnDefaults.ItemType.Text,
|
||||
last = ScalingLazyColumnDefaults.ItemType.Chip), verticalArrangement= Arrangement.spacedBy(
|
||||
space = 1.dp,
|
||||
alignment = Alignment.Top,
|
||||
),)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ScreenScaffold(scrollState = columnState) {
|
||||
ScalingLazyColumn(
|
||||
columnState = columnState,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
items(species_show) { aSpec ->
|
||||
if (aSpec.value.trigger)
|
||||
{
|
||||
Log.w(TAG,"Trigger "+aSpec.toString())
|
||||
FlashingText(text = aSpec.value.common_name, color = interpolateColor(aSpec.value.score))
|
||||
aSpec.value.trigger = false;
|
||||
} else
|
||||
{
|
||||
Text(text = aSpec.value.common_name, color = interpolateColor(aSpec.value.score))
|
||||
}
|
||||
}
|
||||
} // Dynamically display the chips
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ScreenScaffold(scrollState = columnState) {
|
||||
// ScalingLazyColumn(columnState = columnState, modifier = Modifier.fillMaxSize()) {
|
||||
// items(species_show) { aSpec -> Text(text = aSpec.value)
|
||||
// items(species_show) { aSpec -> Text(text = aSpec.value.common_name)
|
||||
// } // Dynamically display the chips
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ import com.google.android.horologist.compose.layout.ScreenScaffold
|
||||
@Composable
|
||||
fun StartRecordingScreen(
|
||||
appState: AppState,
|
||||
onMicClicked: () -> Unit
|
||||
onMicClicked: () -> Unit,
|
||||
onNavClicked: () -> Unit
|
||||
) {
|
||||
ScreenScaffold {
|
||||
val controlDashboardUiState = computeControlDashboardUiState(
|
||||
@@ -18,8 +19,8 @@ fun StartRecordingScreen(
|
||||
)
|
||||
ControlDashboard(
|
||||
controlDashboardUiState = controlDashboardUiState,
|
||||
onMicClicked = onMicClicked
|
||||
|
||||
onMicClicked = onMicClicked,
|
||||
onNavClicked = onNavClicked
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user