A fork of Simple Time Tracker with WearOS support. (Now integrated upstream)
0

Configure Feed

Select the types of activity you want to include in your feed.

Converted ActivityChip to a ToggleChip with Switch, wired it in to the current activities list

authored by

kantahrek and committed by
Joseph Hale
(Feb 26, 2024, 10:27 PM -0700) 10a919d3 07289834

+64 -25
+31 -16
wear/src/main/java/com/example/util/simpletimetracker/presentation/ActivityChip.kt
··· 5 5 */ 6 6 package com.example.util.simpletimetracker.presentation 7 7 8 - import androidx.compose.foundation.BorderStroke 9 8 import androidx.compose.foundation.layout.fillMaxWidth 10 9 import androidx.compose.foundation.layout.padding 11 10 import androidx.compose.runtime.Composable 11 + import androidx.compose.runtime.getValue 12 + import androidx.compose.runtime.mutableStateOf 13 + import androidx.compose.runtime.remember 14 + import androidx.compose.runtime.setValue 12 15 import androidx.compose.ui.Modifier 13 - import androidx.compose.ui.graphics.Color 16 + import androidx.compose.ui.semantics.contentDescription 17 + import androidx.compose.ui.semantics.semantics 14 18 import androidx.compose.ui.text.style.TextOverflow 15 19 import androidx.compose.ui.tooling.preview.Preview 16 20 import androidx.compose.ui.unit.dp 17 - import androidx.wear.compose.material.Chip 18 - import androidx.wear.compose.material.ChipDefaults 21 + import androidx.wear.compose.material.Switch 19 22 import androidx.wear.compose.material.Text 23 + import androidx.wear.compose.material.ToggleChip 24 + import androidx.wear.compose.material.ToggleChipDefaults 20 25 import com.example.util.simpletimetracker.presentation.theme.hexCodeToColor 21 26 import com.example.util.simpletimetracker.wearrpc.Activity 22 27 import com.example.util.simpletimetracker.wearrpc.Tag ··· 30 35 activity: Activity, 31 36 startedAt: Long? = null, 32 37 tags: Array<Tag> = arrayOf(), 33 - onClick: () -> Unit = {}, 38 + onClick: (Boolean) -> Unit = {}, 34 39 ) { 35 40 val briefIcon = if (activity.icon.startsWith("ic_")) { 36 41 "?" ··· 51 56 var modifier = Modifier 52 57 .fillMaxWidth(0.9f) 53 58 .padding(top = 10.dp) 54 - Chip( 59 + var switchChecked by remember { mutableStateOf(startedAt != null) } 60 + ToggleChip( 55 61 modifier = modifier, 56 62 label = { 57 63 Text( ··· 60 66 overflow = TextOverflow.Ellipsis, 61 67 ) 62 68 }, 63 - border = ChipDefaults.chipBorder( 64 - borderStroke = if (startedAt != null) { 65 - BorderStroke(2.dp, Color.White) 66 - } else { 67 - null 68 - }, 69 - ), 70 69 secondaryLabel = { 71 70 if (startedAt != null) { 72 71 Text("Since ${recentTimestampToString(startedAt)}") ··· 74 73 null 75 74 } 76 75 }, 77 - colors = ChipDefaults.chipColors( 78 - backgroundColor = color, 76 + colors = ToggleChipDefaults.toggleChipColors( 77 + checkedStartBackgroundColor = color, 78 + checkedEndBackgroundColor = color, 79 + uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor, 79 80 ), 80 - onClick = onClick, 81 + onCheckedChange = { 82 + switchChecked = it 83 + onClick(switchChecked) 84 + }, 85 + checked = switchChecked, 86 + toggleControl = { 87 + Switch( 88 + checked = switchChecked, 89 + enabled = true, 90 + modifier = Modifier.semantics { 91 + this.contentDescription = 92 + if (switchChecked) "On" else "Off" 93 + }, 94 + ) 95 + }, 81 96 ) 82 97 } 83 98
-1
wear/src/main/java/com/example/util/simpletimetracker/presentation/MainActivity.kt
··· 27 27 MainNavigator() 28 28 } 29 29 } 30 -
+3 -1
wear/src/main/java/com/example/util/simpletimetracker/presentation/components/ActivitiesList.kt
··· 19 19 activities: Array<Activity>, 20 20 currentActivities: Array<CurrentActivity>, 21 21 onSelectActivity: (activity: Activity) -> Unit, 22 + onDeselectActivity: (activity: Activity) -> Unit, 22 23 onRefresh: () -> Unit, 23 24 ) { 24 25 ScaffoldedScrollingColumn { ··· 29 30 activity, 30 31 startedAt = currentActivity?.startedAt, 31 32 tags = currentActivity?.tags ?: arrayOf(), 32 - onClick = { onSelectActivity(activity) }, 33 + onClick = { if (it) onSelectActivity(activity) else onDeselectActivity(activity) }, 33 34 ) 34 35 } 35 36 } ··· 56 57 activities, 57 58 currentActivities = currents, 58 59 onSelectActivity = { /* `it` is the selected activity */ }, 60 + onDeselectActivity = { /* `it` is the deselected activity */ }, 59 61 onRefresh = { /* What to do when requesting a refresh */ } 60 62 ) 61 63 }
+22 -2
wear/src/main/java/com/example/util/simpletimetracker/presentation/remember/currentActivities.kt
··· 11 11 import androidx.compose.runtime.mutableIntStateOf 12 12 import androidx.compose.runtime.mutableStateOf 13 13 import androidx.compose.runtime.remember 14 + import androidx.compose.runtime.rememberCoroutineScope 14 15 import androidx.compose.runtime.setValue 15 16 import com.example.util.simpletimetracker.wearrpc.CurrentActivity 16 17 import com.example.util.simpletimetracker.wearrpc.WearRPCClient 17 18 import kotlinx.coroutines.Dispatchers 18 19 import kotlinx.coroutines.async 20 + import kotlinx.coroutines.launch 19 21 20 22 /** 21 23 * Handles asynchronous retrieval of the currently running activities in Simple Time Tracker on the ··· 35 37 * from the phone. 36 38 */ 37 39 @Composable 38 - fun rememberCurrentActivities(rpc: WearRPCClient): Pair<Array<CurrentActivity>, () -> Unit> { 40 + fun rememberCurrentActivities( 41 + rpc: WearRPCClient, 42 + ): Triple< 43 + Array<CurrentActivity>, 44 + ((Array<CurrentActivity>) -> (Array<CurrentActivity>)) -> Unit, 45 + () -> Unit, 46 + > { 39 47 var currentActivities: Array<CurrentActivity> by remember { mutableStateOf(arrayOf()) } 40 48 var currentActivitiesQueryCount by remember { mutableIntStateOf(0) } 49 + val queryCurrentActivities = { currentActivitiesQueryCount++ } 50 + val coroutineScope = rememberCoroutineScope() 41 51 LaunchedEffect(currentActivitiesQueryCount) { 42 52 async(Dispatchers.Default) { 43 53 currentActivities = rpc.queryCurrentActivities() 44 54 } 45 55 } 46 - return Pair(currentActivities) { currentActivitiesQueryCount++ } 56 + 57 + return Triple( 58 + currentActivities, 59 + { affectCurrentActivities -> 60 + currentActivities = affectCurrentActivities(currentActivities) 61 + coroutineScope.launch(Dispatchers.Default) { 62 + rpc.setCurrentActivities(currentActivities) 63 + queryCurrentActivities() 64 + } 65 + }, { queryCurrentActivities() }, 66 + ) 47 67 }
+8 -5
wear/src/main/java/com/example/util/simpletimetracker/presentation/screens/ActivitiesScreen.kt
··· 10 10 import com.example.util.simpletimetracker.presentation.components.ActivitiesList 11 11 import com.example.util.simpletimetracker.presentation.remember.rememberActivities 12 12 import com.example.util.simpletimetracker.presentation.remember.rememberCurrentActivities 13 + import com.example.util.simpletimetracker.wearrpc.Activity 13 14 import com.example.util.simpletimetracker.wearrpc.ContextMessenger 14 15 import com.example.util.simpletimetracker.wearrpc.WearRPCClient 15 - 16 16 17 17 @Composable 18 18 fun ActivitiesScreen(onSelectActivity: (activityId: Long) -> Unit) { 19 19 val rpc = WearRPCClient(ContextMessenger(LocalContext.current)) 20 20 val (activities, refreshActivities) = rememberActivities(rpc) 21 - val (currentActivities, refreshCurrentActivities) = rememberCurrentActivities(rpc) 21 + val (currentActivities, affectCurrentActivities, refreshCurrentActivities) = 22 + rememberCurrentActivities(rpc) 22 23 23 24 ActivitiesList( 24 25 activities, ··· 26 27 onSelectActivity = { 27 28 onSelectActivity(it.id) 28 29 }, 30 + onDeselectActivity = { deselectedActivity: Activity -> 31 + affectCurrentActivities { 32 + currentActivities.filter { it.id != deselectedActivity.id }.toTypedArray() 33 + } 34 + }, 29 35 onRefresh = { 30 36 refreshActivities() 31 37 refreshCurrentActivities() 32 38 }, 33 39 ) 34 40 } 35 - 36 - 37 -