Toggle hidden tasks from Android Wear

pull/3074/head
Alex Baker 1 year ago
parent 7c23d48117
commit 751c8aabc1

@ -36,7 +36,7 @@ class WearDataService : BaseGrpcDataService<WearServiceGrpcKt.WearServiceCorouti
override fun buildService(): WearServiceGrpcKt.WearServiceCoroutineImplBase {
return WearService(
taskDao = taskDao,
preferences = preferences,
appPreferences = preferences,
taskCompleter = taskCompleter,
headerFormatter = headerFormatter,
settings = settings,

@ -0,0 +1,13 @@
package org.tasks.wear
import org.tasks.GrpcProto.Settings
import org.tasks.preferences.Preferences
import org.tasks.preferences.QueryPreferences
class WearPreferences(
preferences: Preferences,
private val settings: Settings,
): QueryPreferences by preferences {
override val showHidden: Boolean
get() = settings.showHidden
}

@ -23,7 +23,7 @@ import org.tasks.tasklist.UiItem
class WearService(
private val taskDao: TaskDao,
private val preferences: Preferences,
private val appPreferences: Preferences,
private val taskCompleter: TaskCompleter,
private val headerFormatter: HeaderFormatter,
private val settings: DataStore<GrpcProto.Settings>,
@ -32,7 +32,8 @@ class WearService(
val position = request.position
val limit = request.limit.takeIf { it > 0 } ?: Int.MAX_VALUE
val filter = MyTasksFilter.create()
val settingsData = settings.data.firstOrNull()
val settingsData = settings.data.firstOrNull() ?: GrpcProto.Settings.getDefaultInstance()
val preferences = WearPreferences(appPreferences, settingsData)
val collapsed = settingsData?.collapsedList?.toSet() ?: emptySet()
val payload = SectionedDataSource(
tasks = taskDao.fetchTasks(preferences, filter),
@ -102,4 +103,8 @@ class WearService(
return ToggleGroupResponse.getDefaultInstance()
}
override suspend fun updateSettings(request: GrpcProto.UpdateSettingsRequest): GrpcProto.Settings {
return settings.updateData { request.settings }
}
}

@ -20,6 +20,7 @@ import org.tasks.jobs.WorkManager
import org.tasks.location.GeofenceApi
import org.tasks.notifications.NotificationManager
import org.tasks.preferences.Preferences
import org.tasks.preferences.QueryPreferences
import org.tasks.sync.SyncAdapters
import javax.inject.Inject
@ -54,7 +55,7 @@ class TaskDao @Inject constructor(
suspend fun getCaldavTasksToPush(calendar: String): List<Task> =
taskDao.getCaldavTasksToPush(calendar)
suspend fun fetchTasks(preferences: Preferences, filter: Filter): List<TaskContainer> =
suspend fun fetchTasks(preferences: QueryPreferences, filter: Filter): List<TaskContainer> =
taskDao.fetchTasks(preferences, filter)
suspend fun touch(id: Long) = touch(listOf(id))

@ -33,6 +33,11 @@ message LastUpdate {
message Settings {
repeated uint64 collapsed = 1;
string filter = 2;
bool showHidden = 3;
}
message UpdateSettingsRequest {
Settings settings = 1;
}
message GetTasksRequest {
@ -55,4 +60,5 @@ service WearService {
rpc getTasks(GetTasksRequest) returns (Tasks);
rpc completeTask(CompleteTaskRequest) returns (CompleteTaskResponse);
rpc toggleGroup(ToggleGroupRequest) returns (ToggleGroupResponse);
rpc updateSettings(UpdateSettingsRequest) returns (Settings);
}

@ -19,6 +19,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavType
import androidx.navigation.navArgument
@ -32,6 +33,8 @@ import androidx.wear.compose.navigation.rememberSwipeDismissableNavController
import androidx.wear.tooling.preview.devices.WearDevices
import com.google.android.horologist.compose.layout.AppScaffold
import org.tasks.R
import org.tasks.presentation.screens.SettingsScreen
import org.tasks.presentation.screens.SettingsViewModel
import org.tasks.presentation.screens.TaskListScreen
import org.tasks.presentation.screens.TaskListViewModel
import org.tasks.presentation.theme.TasksTheme
@ -88,8 +91,17 @@ class MainActivity : ComponentActivity() {
}
composable(
route = "settings",
) {
) { navBackStackEntry ->
val settingsViewModel: SettingsViewModel = viewModel(navBackStackEntry)
val viewState = settingsViewModel.viewState.collectAsStateWithLifecycle().value
if (viewState.initialized) {
SettingsScreen(
showHidden = viewState.settings.showHidden,
toggleShowHidden = { settingsViewModel.setShowHidden(it) },
)
} else {
// TODO: show spinner
}
}
}
}

@ -0,0 +1,38 @@
package org.tasks.presentation.screens
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.layout.ScalingLazyColumn
import com.google.android.horologist.compose.layout.ScreenScaffold
import com.google.android.horologist.compose.layout.rememberResponsiveColumnState
import com.google.android.horologist.compose.material.ToggleChip
import com.google.android.horologist.compose.material.ToggleChipToggleControl
@OptIn(ExperimentalHorologistApi::class)
@Composable
fun SettingsScreen(
showHidden: Boolean,
toggleShowHidden: (Boolean) -> Unit,
) {
val columnState = rememberResponsiveColumnState()
ScreenScaffold(
scrollState = columnState,
) {
ScalingLazyColumn(
modifier = Modifier.fillMaxSize(),
columnState = columnState,
) {
item {
ToggleChip(
checked = showHidden,
onCheckedChanged = { toggleShowHidden(it) },
label = "Show unstarted",
toggleControl = ToggleChipToggleControl.Switch,
)
}
}
}
}

@ -0,0 +1,71 @@
package org.tasks.presentation.screens
import android.app.Application
import androidx.datastore.core.DataStore
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.data.ProtoDataStoreHelper.protoDataStore
import com.google.android.horologist.data.ProtoDataStoreHelper.protoFlow
import com.google.android.horologist.data.TargetNodeId
import com.google.android.horologist.datalayer.grpc.GrpcExtensions.grpcClient
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
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.Settings
import org.tasks.WearServiceGrpcKt
import org.tasks.copy
import org.tasks.extensions.wearDataLayerRegistry
data class ViewState(
val initialized: Boolean = false,
val settings: Settings = Settings.getDefaultInstance(),
)
@OptIn(ExperimentalHorologistApi::class)
class SettingsViewModel(
application: Application,
) : AndroidViewModel(application) {
private val registry = application.wearDataLayerRegistry(viewModelScope)
private val wearService: WearServiceGrpcKt.WearServiceCoroutineStub = registry.grpcClient(
nodeId = TargetNodeId.PairedPhone,
coroutineScope = viewModelScope,
) {
WearServiceGrpcKt.WearServiceCoroutineStub(it)
}
private val settingsFlow: DataStore<Settings> by lazy {
registry.protoDataStore(viewModelScope)
}
private val _viewState = MutableStateFlow(ViewState())
val viewState = _viewState.asStateFlow()
init {
registry
.protoFlow<Settings>(TargetNodeId.PairedPhone)
.onEach { newSettings ->
_viewState.update {
it.copy(
initialized = true,
settings = newSettings,
)
}
}
.launchIn(viewModelScope)
}
fun setShowHidden(showHidden: Boolean) = viewModelScope.launch {
wearService.updateSettings(
GrpcProto.UpdateSettingsRequest.newBuilder()
.setSettings(
_viewState.value.settings.copy {
this.showHidden = showHidden
}
)
.build()
)
}
}
Loading…
Cancel
Save