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

@ -1,15 +1,22 @@
package org.tasks.wear package org.tasks.wear
import android.content.Intent
import androidx.datastore.core.DataStore
import com.todoroo.astrid.dao.TaskDao import com.todoroo.astrid.dao.TaskDao
import com.todoroo.astrid.service.TaskCompleter import com.todoroo.astrid.service.TaskCompleter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.tasks.GrpcProto
import org.tasks.GrpcProto.CompleteTaskRequest import org.tasks.GrpcProto.CompleteTaskRequest
import org.tasks.GrpcProto.CompleteTaskResponse import org.tasks.GrpcProto.CompleteTaskResponse
import org.tasks.GrpcProto.GetTasksRequest import org.tasks.GrpcProto.GetTasksRequest
import org.tasks.GrpcProto.Task import org.tasks.GrpcProto.Task
import org.tasks.GrpcProto.Tasks import org.tasks.GrpcProto.Tasks
import org.tasks.LocalBroadcastManager
import org.tasks.WearServiceGrpcKt import org.tasks.WearServiceGrpcKt
import org.tasks.copy
import org.tasks.filters.MyTasksFilter import org.tasks.filters.MyTasksFilter
import org.tasks.preferences.Preferences import org.tasks.preferences.Preferences
@ -17,8 +24,28 @@ class WearService(
private val taskDao: TaskDao, private val taskDao: TaskDao,
private val preferences: Preferences, private val preferences: Preferences,
private val taskCompleter: TaskCompleter, private val taskCompleter: TaskCompleter,
private val lastUpdate: DataStore<GrpcProto.LastUpdate>,
localBroadcastManager: LocalBroadcastManager,
) : WearServiceGrpcKt.WearServiceCoroutineImplBase() { ) : 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 { override suspend fun getTasks(request: GetTasksRequest): Tasks {
return Tasks.newBuilder() return Tasks.newBuilder()
.addAllTasks(getTasks()) .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; repeated Task tasks = 1;
} }
message LastUpdate {
uint64 now = 1;
}
message GetTasksRequest {} message GetTasksRequest {}
message CompleteTaskRequest { message CompleteTaskRequest {
uint64 id = 1; uint64 id = 1;

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

Loading…
Cancel
Save