Refresh watch data on changes

pull/3035/head^2
Alex Baker 1 year ago
parent ff1f7e1d01
commit da94f55ab0

@ -1,12 +1,16 @@
package org.tasks.wear
import androidx.datastore.core.DataStore
import androidx.lifecycle.lifecycleScope
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.data.ProtoDataStoreHelper.protoDataStore
import com.google.android.horologist.data.WearDataLayerRegistry
import com.google.android.horologist.datalayer.grpc.server.BaseGrpcDataService
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskCompleter
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.GrpcProto.LastUpdate
import org.tasks.LocalBroadcastManager
import org.tasks.WearServiceGrpcKt
import org.tasks.preferences.Preferences
import javax.inject.Inject
@ -18,6 +22,11 @@ class WearDataService : BaseGrpcDataService<WearServiceGrpcKt.WearServiceCorouti
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var preferences: Preferences
@Inject lateinit var taskCompleter: TaskCompleter
@Inject lateinit var localBroadcastManager: LocalBroadcastManager
private val lastUpdate: DataStore<LastUpdate> by lazy {
registry.protoDataStore<LastUpdate>(lifecycleScope)
}
override val registry: WearDataLayerRegistry by lazy {
WearDataLayerRegistry.fromContext(
@ -25,6 +34,7 @@ class WearDataService : BaseGrpcDataService<WearServiceGrpcKt.WearServiceCorouti
coroutineScope = lifecycleScope,
).apply {
registerSerializer(TasksSerializer)
registerSerializer(LastUpdateSerializer)
}
}
@ -33,6 +43,8 @@ class WearDataService : BaseGrpcDataService<WearServiceGrpcKt.WearServiceCorouti
taskDao = taskDao,
preferences = preferences,
taskCompleter = taskCompleter,
lastUpdate = lastUpdate,
localBroadcastManager = localBroadcastManager,
)
}
}

@ -1,15 +1,22 @@
package org.tasks.wear
import android.content.Intent
import androidx.datastore.core.DataStore
import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskCompleter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.GrpcProto
import org.tasks.GrpcProto.CompleteTaskRequest
import org.tasks.GrpcProto.CompleteTaskResponse
import org.tasks.GrpcProto.GetTasksRequest
import org.tasks.GrpcProto.Task
import org.tasks.GrpcProto.Tasks
import org.tasks.LocalBroadcastManager
import org.tasks.WearServiceGrpcKt
import org.tasks.copy
import org.tasks.filters.MyTasksFilter
import org.tasks.preferences.Preferences
@ -17,8 +24,28 @@ class WearService(
private val taskDao: TaskDao,
private val preferences: Preferences,
private val taskCompleter: TaskCompleter,
private val lastUpdate: DataStore<GrpcProto.LastUpdate>,
localBroadcastManager: LocalBroadcastManager,
) : WearServiceGrpcKt.WearServiceCoroutineImplBase() {
private val scope = CoroutineScope(Dispatchers.IO)
init {
localBroadcastManager.registerRefreshReceiver(
object : android.content.BroadcastReceiver() {
override fun onReceive(context: android.content.Context?, intent: Intent?) {
scope.launch {
lastUpdate.updateData {
it.copy {
now = System.currentTimeMillis()
}
}
}
}
}
)
}
override suspend fun getTasks(request: GetTasksRequest): Tasks {
return Tasks.newBuilder()
.addAllTasks(getTasks())

@ -0,0 +1,24 @@
package org.tasks.wear
import androidx.datastore.core.CorruptionException
import androidx.datastore.core.Serializer
import com.google.protobuf.InvalidProtocolBufferException
import org.tasks.GrpcProto.LastUpdate
import java.io.InputStream
import java.io.OutputStream
object LastUpdateSerializer : Serializer<LastUpdate> {
override val defaultValue: LastUpdate
get() = LastUpdate.getDefaultInstance()
override suspend fun readFrom(input: InputStream): LastUpdate =
try {
LastUpdate.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
override suspend fun writeTo(t: LastUpdate, output: OutputStream) {
t.writeTo(output)
}
}

@ -17,6 +17,10 @@ message Tasks {
repeated Task tasks = 1;
}
message LastUpdate {
uint64 now = 1;
}
message GetTasksRequest {}
message CompleteTaskRequest {
uint64 id = 1;

@ -4,17 +4,23 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.data.ProtoDataStoreHelper.protoFlow
import com.google.android.horologist.data.TargetNodeId
import com.google.android.horologist.data.WearDataLayerRegistry
import com.google.android.horologist.datalayer.grpc.GrpcExtensions.grpcClient
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.tasks.GrpcProto
import org.tasks.GrpcProto.LastUpdate
import org.tasks.GrpcProto.Tasks
import org.tasks.WearServiceGrpcKt
import org.tasks.wear.LastUpdateSerializer
import org.tasks.wear.TasksSerializer
data class TaskListScreenState(
@ -33,6 +39,7 @@ class TaskListViewModel(
coroutineScope = scope,
).apply {
registerSerializer(TasksSerializer)
registerSerializer(LastUpdateSerializer)
}
private val wearService : WearServiceGrpcKt.WearServiceCoroutineStub = wearDataLayerRegistry.grpcClient(
nodeId = TargetNodeId.PairedPhone,
@ -40,12 +47,15 @@ class TaskListViewModel(
) {
WearServiceGrpcKt.WearServiceCoroutineStub(it)
}
private val lastUpdate: Flow<LastUpdate> = wearDataLayerRegistry.protoFlow(TargetNodeId.PairedPhone)
init {
viewModelScope.launch {
val tasks = wearService.getTasks(GrpcProto.GetTasksRequest.getDefaultInstance())
uiState.update { it.copy(tasks = tasks) }
}
lastUpdate
.onEach {
val tasks = wearService.getTasks(GrpcProto.GetTasksRequest.getDefaultInstance())
uiState.update { it.copy(tasks = tasks) }
}
.launchIn(viewModelScope)
}
fun completeTask(it: Long) = viewModelScope.launch {

Loading…
Cancel
Save