Skip to content

Instantly share code, notes, and snippets.

@stevdza-san
Created October 5, 2021 15:40
Show Gist options
  • Save stevdza-san/ae77101a7ab0c5f8b9c2950e61a7c295 to your computer and use it in GitHub Desktop.
Save stevdza-san/ae77101a7ab0c5f8b9c2950e61a7c295 to your computer and use it in GitHub Desktop.
To-Do Compose Example
package com.example.to_docompose.navigation.destinations
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.example.to_docompose.ui.screens.list.ListScreen
import com.example.to_docompose.ui.viewmodels.SharedViewModel
import com.example.to_docompose.util.Action
import com.example.to_docompose.util.Constants.LIST_ARGUMENT_KEY
import com.example.to_docompose.util.Constants.LIST_SCREEN
import com.example.to_docompose.util.toAction
import com.google.accompanist.navigation.animation.composable
@ExperimentalAnimationApi
@ExperimentalMaterialApi
fun NavGraphBuilder.listComposable(
navigateToTaskScreen: (taskId: Int) -> Unit,
sharedViewModel: SharedViewModel
) {
composable(
route = LIST_SCREEN,
arguments = listOf(navArgument(LIST_ARGUMENT_KEY) {
type = NavType.StringType
})
) { navBackStackEntry ->
val action = navBackStackEntry.arguments?.getString(LIST_ARGUMENT_KEY).toAction()
var myAction by rememberSaveable { mutableStateOf(Action.NO_ACTION) }
LaunchedEffect(key1 = myAction) {
if (action != myAction) {
myAction = action
sharedViewModel.action.value = myAction
}
}
val databaseAction by sharedViewModel.action
ListScreen(
action = databaseAction,
navigateToTaskScreen = navigateToTaskScreen,
sharedViewModel = sharedViewModel
)
}
}
package com.example.to_docompose.ui.screens.list
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import com.example.to_docompose.R
import com.example.to_docompose.ui.theme.fabBackgroundColor
import com.example.to_docompose.ui.viewmodels.SharedViewModel
import com.example.to_docompose.util.Action
import com.example.to_docompose.util.SearchAppBarState
import kotlinx.coroutines.launch
@ExperimentalAnimationApi
@ExperimentalMaterialApi
@Composable
fun ListScreen(
action: Action,
navigateToTaskScreen: (taskId: Int) -> Unit,
sharedViewModel: SharedViewModel
) {
LaunchedEffect(key1 = action){
sharedViewModel.handleDatabaseActions(action = action)
}
val allTasks by sharedViewModel.allTasks.collectAsState()
val searchedTasks by sharedViewModel.searchedTasks.collectAsState()
val sortState by sharedViewModel.sortState.collectAsState()
val lowPriorityTasks by sharedViewModel.lowPriorityTasks.collectAsState()
val highPriorityTasks by sharedViewModel.highPriorityTasks.collectAsState()
val searchAppBarState: SearchAppBarState by sharedViewModel.searchAppBarState
val searchTextState: String by sharedViewModel.searchTextState
val scaffoldState = rememberScaffoldState()
DisplaySnackBar(
scaffoldState = scaffoldState,
onComplete = { sharedViewModel.action.value = it },
onUndoClicked = { sharedViewModel.action.value = it },
taskTitle = sharedViewModel.title.value,
action = action
)
Scaffold(
scaffoldState = scaffoldState,
topBar = {
ListAppBar(
sharedViewModel = sharedViewModel,
searchAppBarState = searchAppBarState,
searchTextState = searchTextState
)
},
content = {
ListContent(
allTasks = allTasks,
searchedTasks = searchedTasks,
lowPriorityTasks = lowPriorityTasks,
highPriorityTasks = highPriorityTasks,
sortState = sortState,
searchAppBarState = searchAppBarState,
onSwipeToDelete = { action, task ->
sharedViewModel.action.value = action
sharedViewModel.updateTaskFields(selectedTask = task)
},
navigateToTaskScreen = navigateToTaskScreen
)
},
floatingActionButton = {
ListFab(onFabClicked = navigateToTaskScreen)
}
)
}
@Composable
fun ListFab(
onFabClicked: (taskId: Int) -> Unit
) {
FloatingActionButton(
onClick = {
onFabClicked(-1)
},
backgroundColor = MaterialTheme.colors.fabBackgroundColor
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = stringResource(
id = R.string.add_button
),
tint = Color.White
)
}
}
@Composable
fun DisplaySnackBar(
scaffoldState: ScaffoldState,
onComplete: (Action) -> Unit,
onUndoClicked: (Action) -> Unit,
taskTitle: String,
action: Action
) {
val scope = rememberCoroutineScope()
LaunchedEffect(key1 = action) {
if (action != Action.NO_ACTION) {
scope.launch {
val snackBarResult = scaffoldState.snackbarHostState.showSnackbar(
message = setMessage(action = action, taskTitle = taskTitle),
actionLabel = setActionLabel(action = action)
)
undoDeletedTask(
action = action,
snackBarResult = snackBarResult,
onUndoClicked = onUndoClicked
)
}
onComplete(Action.NO_ACTION)
}
}
}
private fun setMessage(action: Action, taskTitle: String): String {
return when (action) {
Action.DELETE_ALL -> "All Tasks Removed."
else -> "${action.name}: $taskTitle"
}
}
private fun setActionLabel(action: Action): String {
return if (action.name == "DELETE") {
"UNDO"
} else {
"OK"
}
}
private fun undoDeletedTask(
action: Action,
snackBarResult: SnackbarResult,
onUndoClicked: (Action) -> Unit
) {
if (snackBarResult == SnackbarResult.ActionPerformed
&& action == Action.DELETE
) {
onUndoClicked(Action.UNDO)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment