feat: 使用导航方式2 & 添加转场动画
This commit is contained in:
parent
4c95c7e26e
commit
2b28b446eb
25 changed files with 413 additions and 307 deletions
|
|
@ -38,7 +38,7 @@ android {
|
|||
applicationId = "cn.super12138.todo"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 941
|
||||
versionCode = 950
|
||||
versionName = "2.3.3"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ object Constants {
|
|||
const val GITHUB_REPO = "https://github.com/Super12138/ToDo/"
|
||||
|
||||
const val KEY_TODO_FAB_TRANSITION = "todo_fab"
|
||||
// const val KEY_TODO_CONTENT_TRANSITION = "todo_content"
|
||||
// const val KEY_TODO_CATEGORY_TRANSITION = "todo_category"
|
||||
const val KEY_TODO_ITEM_TRANSITION = "todo_item_id"
|
||||
|
||||
const val DB_NAME = "todo"
|
||||
const val DB_TABLE_NAME = "todo"
|
||||
|
|
|
|||
18
app/src/main/kotlin/cn/super12138/todo/logic/IRepository.kt
Normal file
18
app/src/main/kotlin/cn/super12138/todo/logic/IRepository.kt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package cn.super12138.todo.logic
|
||||
|
||||
import cn.super12138.todo.logic.database.TodoEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface IRepository {
|
||||
suspend fun insertTodo(toDo: TodoEntity)
|
||||
|
||||
fun getAllTodos(): Flow<List<TodoEntity>>
|
||||
|
||||
suspend fun updateTodo(toDo: TodoEntity)
|
||||
|
||||
suspend fun deleteTodo(toDo: TodoEntity)
|
||||
|
||||
suspend fun deleteTodoFromIds(toDoItems: List<Int>)
|
||||
|
||||
// suspend fun deleteAllTodo()
|
||||
}
|
||||
|
|
@ -4,29 +4,29 @@ import cn.super12138.todo.TodoApp
|
|||
import cn.super12138.todo.logic.database.TodoEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
object Repository {
|
||||
object Repository : IRepository {
|
||||
private val db get() = TodoApp.db
|
||||
private val toDoDao = db.toDoDao()
|
||||
|
||||
suspend fun insertTodo(toDo: TodoEntity) {
|
||||
override suspend fun insertTodo(toDo: TodoEntity) {
|
||||
toDoDao.insert(toDo)
|
||||
}
|
||||
|
||||
fun getAllTodos(): Flow<List<TodoEntity>> = toDoDao.getAll()
|
||||
override fun getAllTodos(): Flow<List<TodoEntity>> = toDoDao.getAll()
|
||||
|
||||
suspend fun updateTodo(toDo: TodoEntity) {
|
||||
override suspend fun updateTodo(toDo: TodoEntity) {
|
||||
toDoDao.update(toDo)
|
||||
}
|
||||
|
||||
suspend fun deleteTodo(toDo: TodoEntity) {
|
||||
override suspend fun deleteTodo(toDo: TodoEntity) {
|
||||
toDoDao.delete(toDo)
|
||||
}
|
||||
|
||||
suspend fun deleteTodoFromIds(toDoItems: List<Int>) {
|
||||
override suspend fun deleteTodoFromIds(toDoItems: List<Int>) {
|
||||
toDoDao.deleteFromIds(toDoItems.toSet())
|
||||
}
|
||||
|
||||
/*suspend fun deleteAllTodo() {
|
||||
/*override suspend fun deleteAllTodo() {
|
||||
toDoDao.deleteAllTodo()
|
||||
}*/
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import cn.super12138.todo.R
|
|||
|
||||
enum class ContrastLevel(
|
||||
val value: Float,
|
||||
@StringRes val nameRes: Int
|
||||
@param:StringRes val nameRes: Int
|
||||
) {
|
||||
VeryLow(value = -1f, nameRes = R.string.contrast_very_low),
|
||||
Low(value = -0.5f, nameRes = R.string.contrast_low),
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import cn.super12138.todo.R
|
|||
|
||||
enum class DarkMode(
|
||||
val id: Int,
|
||||
@DrawableRes val iconRes: Int,
|
||||
@StringRes val nameRes: Int
|
||||
@param:DrawableRes val iconRes: Int,
|
||||
@param:StringRes val nameRes: Int
|
||||
) {
|
||||
FollowSystem(id = -1, iconRes = R.drawable.ic_lightbulb_2, nameRes = R.string.dark_mode_system),
|
||||
Light(id = 1, iconRes = R.drawable.ic_light_mode, nameRes = R.string.dark_mode_light),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import cn.super12138.todo.R
|
|||
|
||||
enum class PaletteStyle(
|
||||
val id: Int,
|
||||
@StringRes val nameRes: Int
|
||||
@param:StringRes val nameRes: Int
|
||||
) {
|
||||
TonalSpot(id = 1, nameRes = R.string.palette_tonal_spot),
|
||||
Neutral(id = 2, nameRes = R.string.palette_neutral),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import cn.super12138.todo.R
|
|||
|
||||
enum class Priority(
|
||||
val value: Float,
|
||||
@StringRes val nameRes: Int
|
||||
@param:StringRes val nameRes: Int
|
||||
) {
|
||||
Urgent(value = 2f, nameRes = R.string.priority_urgent),
|
||||
Important(value = 1f, nameRes = R.string.priority_important),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import cn.super12138.todo.R
|
|||
|
||||
enum class SortingMethod(
|
||||
val id: Int,
|
||||
@StringRes val nameRes: Int
|
||||
@param:StringRes val nameRes: Int
|
||||
) {
|
||||
// 按添加先后顺序
|
||||
Sequential(id = 1, nameRes = R.string.sorting_sequential),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ object TodoDefaults {
|
|||
/**
|
||||
* 屏幕上下预留边距(防止内容全部贴边显示过丑)
|
||||
*/
|
||||
val screenVerticalPadding = 16.dp
|
||||
val screenVerticalPadding = 8.dp
|
||||
|
||||
/**
|
||||
* 待办卡片默认高度
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.os.Bundle
|
|||
import android.view.WindowManager
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Icon
|
||||
|
|
@ -26,7 +27,7 @@ import cn.super12138.todo.logic.model.PaletteStyle
|
|||
import cn.super12138.todo.ui.TodoDefaults
|
||||
import cn.super12138.todo.ui.components.Konfetti
|
||||
import cn.super12138.todo.ui.navigation.TodoDestinations
|
||||
import cn.super12138.todo.ui.navigation.TodoNavigation
|
||||
import cn.super12138.todo.ui.navigation.TopNavigation
|
||||
import cn.super12138.todo.ui.theme.ToDoTheme
|
||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||
import cn.super12138.todo.utils.VibrationUtils
|
||||
|
|
@ -39,7 +40,7 @@ class MainActivity : ComponentActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
val mainViewModel: MainViewModel = viewModel()
|
||||
val navigationBackStack = mainViewModel.topLevelBackStack
|
||||
val mainBackStack = mainViewModel.mainBackStack
|
||||
val showConfetti = mainViewModel.showConfetti
|
||||
// 主题
|
||||
val dynamicColor by DataStoreManager.dynamicColorFlow.collectAsState(initial = Constants.PREF_DYNAMIC_COLOR_DEFAULT)
|
||||
|
|
@ -89,27 +90,34 @@ class MainActivity : ComponentActivity() {
|
|||
Surface(color = TodoDefaults.BackgroundColor) {
|
||||
NavigationSuiteScaffold(
|
||||
navigationSuiteItems = {
|
||||
TodoDestinations.entries.forEach {
|
||||
val selected = it.route == navigationBackStack.topLevelKey
|
||||
TodoDestinations.entries.forEach { destination ->
|
||||
val selected = destination.route == mainBackStack.topLevelKey
|
||||
item(
|
||||
icon = {
|
||||
Icon(
|
||||
painter = if (selected) painterResource(it.selectedIcon) else painterResource(
|
||||
it.icon
|
||||
),
|
||||
contentDescription = null
|
||||
)
|
||||
Crossfade(selected) {
|
||||
if (it) {
|
||||
Icon(
|
||||
painter = painterResource(destination.selectedIcon),
|
||||
contentDescription = null
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(destination.icon),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
label = { Text(stringResource(it.label)) },
|
||||
label = { Text(stringResource(destination.label)) },
|
||||
selected = selected,
|
||||
onClick = { navigationBackStack.addTopLevel(it.route) }
|
||||
onClick = { mainBackStack.addTopLevel(destination.route) }
|
||||
)
|
||||
}
|
||||
},
|
||||
containerColor = TodoDefaults.BackgroundColor
|
||||
) {
|
||||
TodoNavigation(
|
||||
backStack = navigationBackStack,
|
||||
TopNavigation(
|
||||
backStack = mainBackStack,
|
||||
viewModel = mainViewModel,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,2 +1,105 @@
|
|||
package cn.super12138.todo.ui.navigation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsAbout
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsAboutLicence
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsAppearance
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsData
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsDataCategory
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsDeveloperOptions
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsDeveloperOptionsPadding
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsInterface
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsMain
|
||||
import cn.super12138.todo.ui.theme.materialSharedAxisX
|
||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||
|
||||
private const val INITIAL_OFFSET_FACTOR = 0.10f
|
||||
|
||||
@Composable
|
||||
fun SettingsNavigation(
|
||||
backStack: NavBackStack<NavKey>,
|
||||
viewModel: MainViewModel,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
fun onBack() {
|
||||
backStack.removeLastOrNull()
|
||||
}
|
||||
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
onBack = ::onBack,
|
||||
transitionSpec = {
|
||||
materialSharedAxisX(
|
||||
initialOffsetX = { (it * INITIAL_OFFSET_FACTOR).toInt() },
|
||||
targetOffsetX = { -(it * INITIAL_OFFSET_FACTOR).toInt() })
|
||||
},
|
||||
popTransitionSpec = {
|
||||
materialSharedAxisX(
|
||||
initialOffsetX = { -(it * INITIAL_OFFSET_FACTOR).toInt() },
|
||||
targetOffsetX = { (it * INITIAL_OFFSET_FACTOR).toInt() })
|
||||
},
|
||||
entryProvider = entryProvider {
|
||||
entry<TodoScreen.Settings.Main> {
|
||||
SettingsMain(
|
||||
toAppearancePage = { backStack.add(TodoScreen.Settings.Appearance) },
|
||||
toAboutPage = { backStack.add(TodoScreen.Settings.About) },
|
||||
toInterfacePage = { backStack.add(TodoScreen.Settings.Interface) },
|
||||
toDataPage = { backStack.add(TodoScreen.Settings.Data) },
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.Appearance> {
|
||||
SettingsAppearance(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.Interface> {
|
||||
SettingsInterface(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.Data> {
|
||||
SettingsData(
|
||||
viewModel = viewModel,
|
||||
toCategoryManager = { backStack.add(TodoScreen.Settings.DataCategory) },
|
||||
onNavigateUp = ::onBack
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.DataCategory> {
|
||||
SettingsDataCategory(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.About> {
|
||||
SettingsAbout(
|
||||
//toSpecialPage = { backStack.add(TodoScreen.Settings.AboutSpecial) },
|
||||
toLicencePage = { backStack.add(TodoScreen.Settings.AboutLicence) },
|
||||
toDevPage = { backStack.add(TodoScreen.Settings.DeveloperOptions) },
|
||||
onNavigateUp = ::onBack,
|
||||
)
|
||||
}
|
||||
|
||||
/*entry<TodoScreen.Settings.AboutSpecial> {
|
||||
SettingsAboutSpecial(viewModel = viewModel)
|
||||
}*/
|
||||
|
||||
entry<TodoScreen.Settings.AboutLicence> {
|
||||
SettingsAboutLicence(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.DeveloperOptions> {
|
||||
SettingsDeveloperOptions(
|
||||
toPaddingPage = { backStack.add(TodoScreen.Settings.DeveloperOptionsPadding) },
|
||||
onNavigateUp = ::onBack
|
||||
)
|
||||
}
|
||||
entry<TodoScreen.Settings.DeveloperOptionsPadding> {
|
||||
SettingsDeveloperOptionsPadding(onNavigateUp = ::onBack)
|
||||
}
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -6,9 +6,9 @@ import androidx.navigation3.runtime.NavKey
|
|||
|
||||
enum class TodoDestinations(
|
||||
val route: NavKey,
|
||||
@StringRes val label: Int,
|
||||
@DrawableRes val icon: Int,
|
||||
@DrawableRes val selectedIcon: Int
|
||||
@param:StringRes val label: Int,
|
||||
@param:DrawableRes val icon: Int,
|
||||
@param:DrawableRes val selectedIcon: Int
|
||||
) {
|
||||
Overview(
|
||||
route = TodoScreen.Overview,
|
||||
|
|
@ -23,7 +23,7 @@ enum class TodoDestinations(
|
|||
selectedIcon = cn.super12138.todo.R.drawable.ic_ballot_filled
|
||||
),
|
||||
Settings(
|
||||
route = TodoScreen.Settings,
|
||||
route = TodoScreen.Settings.Main,
|
||||
label = cn.super12138.todo.R.string.page_settings,
|
||||
icon = cn.super12138.todo.R.drawable.ic_settings,
|
||||
selectedIcon = cn.super12138.todo.R.drawable.ic_settings_filled
|
||||
|
|
|
|||
|
|
@ -1,175 +0,0 @@
|
|||
package cn.super12138.todo.ui.navigation
|
||||
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.ExitTransition
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionLayout
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import cn.super12138.todo.ui.pages.editor.TodoEditorPage
|
||||
import cn.super12138.todo.ui.pages.main.MainPage
|
||||
import cn.super12138.todo.ui.pages.overview.OverviewPage
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsAbout
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsAboutLicence
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsAppearance
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsData
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsDataCategory
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsDeveloperOptions
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsDeveloperOptionsPadding
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsInterface
|
||||
import cn.super12138.todo.ui.pages.settings.SettingsMain
|
||||
import cn.super12138.todo.ui.theme.materialSharedAxisX
|
||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||
|
||||
private const val INITIAL_OFFSET_FACTOR = 0.10f
|
||||
|
||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||||
@Composable
|
||||
fun TodoNavigation(
|
||||
backStack: TopLevelBackStack<NavKey>,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
fun onBack() {
|
||||
backStack.removeLast()
|
||||
}
|
||||
|
||||
val anim = NavDisplay.transitionSpec {
|
||||
// Slide new content up, keeping the old content in place underneath
|
||||
slideInVertically(
|
||||
initialOffsetY = { it / 5 },
|
||||
animationSpec = tween(200)
|
||||
) + fadeIn(tween(200)) togetherWith ExitTransition.KeepUntilTransitionsFinished
|
||||
} + NavDisplay.popTransitionSpec {
|
||||
// Slide old content down, revealing the new content in place underneath
|
||||
EnterTransition.None togetherWith
|
||||
slideOutVertically(
|
||||
targetOffsetY = { it / 5 },
|
||||
animationSpec = tween(200)
|
||||
) + fadeOut(tween(200))
|
||||
} + NavDisplay.predictivePopTransitionSpec {
|
||||
// Slide old content down, revealing the new content in place underneath
|
||||
EnterTransition.None togetherWith
|
||||
slideOutVertically(
|
||||
targetOffsetY = { it / 5 },
|
||||
animationSpec = tween(200)
|
||||
) + fadeOut(tween(200))
|
||||
}
|
||||
|
||||
SharedTransitionLayout {
|
||||
NavDisplay(
|
||||
backStack = backStack.backStack,
|
||||
onBack = ::onBack,
|
||||
transitionSpec = {
|
||||
materialSharedAxisX(
|
||||
initialOffsetX = { (it * INITIAL_OFFSET_FACTOR).toInt() },
|
||||
targetOffsetX = { -(it * INITIAL_OFFSET_FACTOR).toInt() })
|
||||
},
|
||||
popTransitionSpec = {
|
||||
materialSharedAxisX(
|
||||
initialOffsetX = { -(it * INITIAL_OFFSET_FACTOR).toInt() },
|
||||
targetOffsetX = { (it * INITIAL_OFFSET_FACTOR).toInt() })
|
||||
},
|
||||
entryProvider = entryProvider {
|
||||
entry<TodoScreen.Overview>(metadata = anim) {
|
||||
OverviewPage()
|
||||
}
|
||||
entry<TodoScreen.Tasks>(metadata = anim) {
|
||||
MainPage(
|
||||
viewModel = viewModel,
|
||||
toTodoEditPage = { backStack.add(TodoScreen.Editor(it)) },
|
||||
sharedTransitionScope = this@SharedTransitionLayout
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings>(metadata = anim) {
|
||||
SettingsMain(
|
||||
toAppearancePage = { backStack.add(TodoScreen.SettingsAppearance) },
|
||||
toAboutPage = { backStack.add(TodoScreen.SettingsAbout) },
|
||||
toInterfacePage = { backStack.add(TodoScreen.SettingsInterface) },
|
||||
toDataPage = { backStack.add(TodoScreen.SettingsData) },
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Editor> { editorArgs ->
|
||||
TodoEditorPage(
|
||||
toDo = editorArgs.toDo,
|
||||
onSave = {
|
||||
viewModel.addTodo(it)
|
||||
// 如果原来的待办状态为未完成并且修改后状态为完成
|
||||
if (editorArgs.toDo?.isCompleted != true && it.isCompleted) {
|
||||
viewModel.playConfetti()
|
||||
}
|
||||
onBack()
|
||||
},
|
||||
onDelete = {
|
||||
if (editorArgs.toDo !== null) {
|
||||
viewModel.deleteTodo(editorArgs.toDo)
|
||||
}
|
||||
onBack()
|
||||
},
|
||||
onNavigateUp = ::onBack,
|
||||
sharedTransitionScope = this@SharedTransitionLayout
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.SettingsAppearance> {
|
||||
SettingsAppearance(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.SettingsInterface> {
|
||||
SettingsInterface(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.SettingsData> {
|
||||
SettingsData(
|
||||
viewModel = viewModel,
|
||||
toCategoryManager = { backStack.add(TodoScreen.SettingsDataCategory) },
|
||||
onNavigateUp = ::onBack
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.SettingsDataCategory> {
|
||||
SettingsDataCategory(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.SettingsAbout> {
|
||||
SettingsAbout(
|
||||
//toSpecialPage = { backStack.add(TodoScreen.SettingsAboutSpecial) },
|
||||
toLicencePage = { backStack.add(TodoScreen.SettingsAboutLicence) },
|
||||
toDevPage = { backStack.add(TodoScreen.SettingsDev) },
|
||||
onNavigateUp = ::onBack,
|
||||
)
|
||||
}
|
||||
|
||||
/*entry<TodoScreen.SettingsAboutSpecial> {
|
||||
SettingsAboutSpecial(viewModel = viewModel)
|
||||
}*/
|
||||
|
||||
entry<TodoScreen.SettingsAboutLicence> {
|
||||
SettingsAboutLicence(onNavigateUp = ::onBack)
|
||||
}
|
||||
|
||||
entry<TodoScreen.SettingsDev> {
|
||||
SettingsDeveloperOptions(
|
||||
toPaddingPage = { backStack.add(TodoScreen.SettingsDevPadding) },
|
||||
onNavigateUp = ::onBack
|
||||
)
|
||||
}
|
||||
entry<TodoScreen.SettingsDevPadding> {
|
||||
SettingsDeveloperOptionsPadding(onNavigateUp = ::onBack)
|
||||
}
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -13,35 +13,44 @@ sealed class TodoScreen : NavKey {
|
|||
data object Tasks : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data class Editor(val toDo: TodoEntity?) : TodoScreen()
|
||||
sealed class Settings : TodoScreen() {
|
||||
@Serializable
|
||||
data object Main : Settings()
|
||||
|
||||
@Serializable
|
||||
data object Appearance : Settings()
|
||||
|
||||
@Serializable
|
||||
data object Interface : Settings()
|
||||
|
||||
@Serializable
|
||||
data object Data : Settings()
|
||||
|
||||
@Serializable
|
||||
data object DataCategory : Settings()
|
||||
|
||||
@Serializable
|
||||
data object About : Settings()
|
||||
|
||||
// @Serializable
|
||||
// data object AboutEasterEgg : Settings()
|
||||
|
||||
@Serializable
|
||||
data object AboutLicence : Settings()
|
||||
|
||||
@Serializable
|
||||
data object DeveloperOptions : Settings()
|
||||
|
||||
@Serializable
|
||||
data object DeveloperOptionsPadding : Settings()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data object Settings : TodoScreen()
|
||||
sealed class Editor : TodoScreen() {
|
||||
@Serializable
|
||||
data object Add : Editor()
|
||||
|
||||
@Serializable
|
||||
data object SettingsAppearance : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsInterface : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsData : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsDataCategory : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsAbout : TodoScreen()
|
||||
|
||||
// @Serializable
|
||||
// data object SettingsAboutSpecial : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsAboutLicence : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsDev : TodoScreen()
|
||||
|
||||
@Serializable
|
||||
data object SettingsDevPadding : TodoScreen()
|
||||
@Serializable
|
||||
data class Edit(val toDo: TodoEntity) : Editor()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
package cn.super12138.todo.ui.navigation
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.SharedTransitionLayout
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.animation.unveilIn
|
||||
import androidx.compose.animation.veilOut
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import cn.super12138.todo.ui.pages.editor.TodoAddPage
|
||||
import cn.super12138.todo.ui.pages.editor.TodoEditPage
|
||||
import cn.super12138.todo.ui.pages.overview.OverviewPage
|
||||
import cn.super12138.todo.ui.pages.tasks.TasksPage
|
||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun TopNavigation(
|
||||
backStack: TopLevelBackStack<NavKey>,
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
fun onBack() {
|
||||
backStack.removeLast()
|
||||
}
|
||||
/*
|
||||
* NavDisplay.transitionSpec {
|
||||
* // Slide new content up, keeping the old content in place underneath
|
||||
* slideInVertically(
|
||||
* initialOffsetY = { it / 5 },
|
||||
* animationSpec = tween(200)
|
||||
* ) + fadeIn(tween(200)) togetherWith ExitTransition.KeepUntilTransitionsFinished
|
||||
* } + NavDisplay.popTransitionSpec {
|
||||
* // Slide old content down, revealing the new content in place underneath
|
||||
* EnterTransition.None togetherWith
|
||||
* slideOutVertically(
|
||||
* targetOffsetY = { it / 5 },
|
||||
* animationSpec = tween(200)
|
||||
* ) + fadeOut(tween(200))
|
||||
* } + NavDisplay.predictivePopTransitionSpec {
|
||||
* // Slide old content down, revealing the new content in place underneath
|
||||
* EnterTransition.None togetherWith
|
||||
* slideOutVertically(
|
||||
* targetOffsetY = { it / 5 },
|
||||
* animationSpec = tween(200)
|
||||
* ) + fadeOut(tween(200))
|
||||
* }
|
||||
*/
|
||||
|
||||
val veilColor = MaterialTheme.colorScheme.surfaceDim
|
||||
SharedTransitionLayout {
|
||||
NavDisplay(
|
||||
backStack = backStack.backStack,
|
||||
onBack = ::onBack,
|
||||
transitionSpec = {
|
||||
fadeIn() togetherWith veilOut(targetColor = veilColor)
|
||||
},
|
||||
popTransitionSpec = {
|
||||
unveilIn(initialColor = veilColor) togetherWith fadeOut()
|
||||
},
|
||||
predictivePopTransitionSpec = {
|
||||
unveilIn(initialColor = veilColor) togetherWith fadeOut()
|
||||
},
|
||||
entryProvider = entryProvider {
|
||||
entry<TodoScreen.Overview> {
|
||||
OverviewPage()
|
||||
}
|
||||
|
||||
entry<TodoScreen.Tasks> {
|
||||
TasksPage(
|
||||
viewModel = viewModel,
|
||||
toTodoAddPage = { backStack.add(TodoScreen.Editor.Add) },
|
||||
toTodoEditPage = { backStack.add(TodoScreen.Editor.Edit(it)) }
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Editor.Add> {
|
||||
TodoAddPage(
|
||||
onSave = {
|
||||
viewModel.addTodo(it)
|
||||
onBack()
|
||||
},
|
||||
onNavigateUp = ::onBack
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Editor.Edit> { editorArgs ->
|
||||
TodoEditPage(
|
||||
toDo = editorArgs.toDo,
|
||||
onSave = {
|
||||
viewModel.addTodo(it)
|
||||
// 如果原来的待办状态为未完成并且修改后状态为完成
|
||||
if (!editorArgs.toDo.isCompleted && it.isCompleted) {
|
||||
viewModel.playConfetti()
|
||||
}
|
||||
onBack()
|
||||
},
|
||||
onDelete = {
|
||||
viewModel.deleteTodo(editorArgs.toDo)
|
||||
onBack()
|
||||
},
|
||||
onNavigateUp = ::onBack
|
||||
)
|
||||
}
|
||||
|
||||
entry<TodoScreen.Settings.Main> {
|
||||
SettingsNavigation(
|
||||
backStack = viewModel.settingsBackStack,
|
||||
viewModel = viewModel
|
||||
)
|
||||
}
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ package cn.super12138.todo.ui.pages.editor
|
|||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.fadeIn
|
||||
|
|
@ -17,12 +16,9 @@ import androidx.compose.foundation.layout.imePadding
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
|
|
@ -41,6 +37,7 @@ import cn.super12138.todo.R
|
|||
import cn.super12138.todo.constants.Constants
|
||||
import cn.super12138.todo.logic.database.TodoEntity
|
||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||
import cn.super12138.todo.ui.TodoDefaults
|
||||
import cn.super12138.todo.ui.components.ChipItem
|
||||
import cn.super12138.todo.ui.components.ConfirmDialog
|
||||
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||
|
|
@ -52,23 +49,50 @@ import cn.super12138.todo.ui.pages.editor.components.TodoPrioritySlider
|
|||
import cn.super12138.todo.ui.pages.editor.state.rememberEditorState
|
||||
import cn.super12138.todo.utils.VibrationUtils
|
||||
|
||||
@OptIn(
|
||||
ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class,
|
||||
ExperimentalMaterial3ExpressiveApi::class
|
||||
)
|
||||
@Composable
|
||||
fun TodoEditorPage(
|
||||
fun SharedTransitionScope.TodoAddPage(
|
||||
modifier: Modifier = Modifier,
|
||||
onSave: (TodoEntity) -> Unit,
|
||||
onNavigateUp: () -> Unit
|
||||
) = TodoEditorPage(
|
||||
toDo = null,
|
||||
modifier = modifier.sharedBounds(
|
||||
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
|
||||
animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||
),
|
||||
onSave = onSave,
|
||||
onDelete = {},
|
||||
onNavigateUp = onNavigateUp
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SharedTransitionScope.TodoEditPage(
|
||||
modifier: Modifier = Modifier,
|
||||
toDo: TodoEntity,
|
||||
onSave: (TodoEntity) -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
onNavigateUp: () -> Unit
|
||||
) = TodoEditorPage(
|
||||
toDo = toDo,
|
||||
modifier = modifier.sharedBounds(
|
||||
sharedContentState = rememberSharedContentState(key = "${Constants.KEY_TODO_ITEM_TRANSITION}_${toDo.id}"),
|
||||
animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||
),
|
||||
onSave = onSave,
|
||||
onDelete = onDelete,
|
||||
onNavigateUp = onNavigateUp
|
||||
)
|
||||
|
||||
@Composable
|
||||
private fun TodoEditorPage(
|
||||
modifier: Modifier = Modifier,
|
||||
toDo: TodoEntity? = null,
|
||||
onSave: (TodoEntity) -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
onNavigateUp: () -> Unit,
|
||||
sharedTransitionScope: SharedTransitionScope
|
||||
onNavigateUp: () -> Unit
|
||||
) {
|
||||
// TODO: 本页及其相关组件重组性能检查优化
|
||||
val view = LocalView.current
|
||||
val animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||
TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||
|
||||
val uiState = rememberEditorState(initialTodo = toDo)
|
||||
|
||||
|
|
@ -114,7 +138,6 @@ fun TodoEditorPage(
|
|||
TopAppBarScaffold(
|
||||
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
||||
floatingActionButton = {
|
||||
with(sharedTransitionScope) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
modifier = Modifier.imePadding()
|
||||
|
|
@ -146,15 +169,9 @@ fun TodoEditorPage(
|
|||
)
|
||||
onSave(newTodo)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.sharedElement(
|
||||
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
|
||||
animatedVisibilityScope = animatedVisibilityScope
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
onBack = ::checkModifiedBeforeBack,
|
||||
modifier = modifier
|
||||
|
|
@ -163,6 +180,10 @@ fun TodoEditorPage(
|
|||
verticalArrangement = Arrangement.spacedBy(5.dp),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
|
||||
item {
|
||||
TodoContentTextField(
|
||||
value = uiState.toDoContent,
|
||||
|
|
@ -241,7 +262,7 @@ fun TodoEditorPage(
|
|||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(80.dp))
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package cn.super12138.todo.ui.pages.overview
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
|
|
@ -11,13 +12,14 @@ import androidx.compose.ui.res.stringResource
|
|||
import cn.super12138.todo.R
|
||||
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun OverviewPage(modifier: Modifier = Modifier) {
|
||||
TopAppBarScaffold(
|
||||
title = stringResource(R.string.page_overview),
|
||||
modifier = modifier
|
||||
) {
|
||||
Row {
|
||||
Column {
|
||||
Card {
|
||||
Icon(painter = painterResource(R.drawable.ic_ballot), contentDescription = null)
|
||||
Text("总任务")
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ fun SettingsCategory(
|
|||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = if (first) 0.dp else TodoDefaults.settingsItemVerticalPadding,
|
||||
start = TodoDefaults.settingsItemHorizontalPadding / 2,
|
||||
end = TodoDefaults.settingsItemHorizontalPadding / 2,
|
||||
bottom = TodoDefaults.settingsItemVerticalPadding / 2
|
||||
top = if (first) 0.dp else TodoDefaults.screenVerticalPadding,
|
||||
start = TodoDefaults.screenHorizontalPadding / 2,
|
||||
end = TodoDefaults.screenHorizontalPadding / 2,
|
||||
bottom = TodoDefaults.screenVerticalPadding
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ fun SettingsContainer(
|
|||
modifier = modifier
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.settingsItemVerticalPadding))
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
|
||||
content()
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.settingsItemVerticalPadding))
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cn.super12138.todo.ui.pages.main
|
||||
package cn.super12138.todo.ui.pages.tasks
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cn.super12138.todo.ui.pages.main
|
||||
package cn.super12138.todo.ui.pages.tasks
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
|
|
@ -38,17 +38,17 @@ import cn.super12138.todo.ui.TodoDefaults
|
|||
import cn.super12138.todo.ui.components.ConfirmDialog
|
||||
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||
import cn.super12138.todo.ui.pages.main.components.TodoCard
|
||||
import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar
|
||||
import cn.super12138.todo.ui.pages.tasks.components.TodoCard
|
||||
import cn.super12138.todo.ui.pages.tasks.components.TodoTopAppBar
|
||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun MainPage(
|
||||
fun SharedTransitionScope.TasksPage(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: MainViewModel,
|
||||
toTodoEditPage: (TodoEntity?) -> Unit,
|
||||
sharedTransitionScope: SharedTransitionScope,
|
||||
toTodoAddPage: () -> Unit,
|
||||
toTodoEditPage: (TodoEntity) -> Unit,
|
||||
) {
|
||||
val animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||
|
||||
|
|
@ -82,23 +82,21 @@ fun MainPage(
|
|||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
with(sharedTransitionScope) {
|
||||
TodoFloatingActionButton(
|
||||
text = stringResource(R.string.action_add_task),
|
||||
iconRes = R.drawable.ic_add,
|
||||
expanded = expandedFab,
|
||||
onClick = { toTodoEditPage(null) },
|
||||
modifier = Modifier
|
||||
.sharedElement(
|
||||
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
|
||||
animatedVisibilityScope = animatedVisibilityScope
|
||||
)
|
||||
.animateFloatingActionButton(
|
||||
visible = !inSelectedMode,
|
||||
alignment = Alignment.BottomEnd,
|
||||
)
|
||||
)
|
||||
}
|
||||
TodoFloatingActionButton(
|
||||
text = stringResource(R.string.action_add_task),
|
||||
iconRes = R.drawable.ic_add,
|
||||
expanded = expandedFab,
|
||||
onClick = { toTodoAddPage() },
|
||||
modifier = Modifier
|
||||
.sharedBounds(
|
||||
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
|
||||
animatedVisibilityScope = animatedVisibilityScope
|
||||
)
|
||||
.animateFloatingActionButton(
|
||||
visible = !inSelectedMode,
|
||||
alignment = Alignment.BottomEnd,
|
||||
)
|
||||
)
|
||||
},
|
||||
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
||||
modifier = modifier
|
||||
|
|
@ -109,7 +107,7 @@ fun MainPage(
|
|||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.settingsItemVerticalPadding))
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
|
||||
if (filteredTodoList.isEmpty()) {
|
||||
|
|
@ -146,6 +144,10 @@ fun MainPage(
|
|||
viewModel.playConfetti()
|
||||
},
|
||||
modifier = Modifier
|
||||
.sharedBounds(
|
||||
sharedContentState = rememberSharedContentState(key = "${Constants.KEY_TODO_ITEM_TRANSITION}_${it.id}"),
|
||||
animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||
)
|
||||
.animateItem(
|
||||
fadeInSpec = MaterialTheme.motionScheme.defaultEffectsSpec(),
|
||||
placementSpec = MaterialTheme.motionScheme.defaultSpatialSpec(),
|
||||
|
|
@ -154,7 +156,7 @@ fun MainPage(
|
|||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.settingsItemVerticalPadding))
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
package cn.super12138.todo.ui.pages.main.components
|
||||
package cn.super12138.todo.ui.pages.tasks.components
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.expandHorizontally
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkHorizontally
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.basicMarquee
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
|
|
@ -21,7 +19,8 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Badge
|
||||
import androidx.compose.material3.BadgedBox
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
|
|
@ -32,7 +31,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -45,10 +43,7 @@ import cn.super12138.todo.ui.TodoDefaults
|
|||
import cn.super12138.todo.utils.VibrationUtils
|
||||
import cn.super12138.todo.utils.containerColor
|
||||
|
||||
@OptIn(
|
||||
ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class,
|
||||
ExperimentalMaterial3ExpressiveApi::class
|
||||
)
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun TodoCard(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -63,8 +58,8 @@ fun TodoCard(
|
|||
onChecked: () -> Unit = {}
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val context = LocalContext.current
|
||||
ElevatedCard(
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(containerColor = TodoDefaults.ContainerColor),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(TodoDefaults.toDoCardHeight)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cn.super12138.todo.ui.pages.main.components
|
||||
package cn.super12138.todo.ui.pages.tasks.components
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
|
|
@ -5,6 +5,7 @@ import android.net.Uri
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation3.runtime.NavBackStack
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import cn.super12138.todo.TodoApp
|
||||
import cn.super12138.todo.constants.Constants
|
||||
|
|
@ -35,7 +36,8 @@ import java.util.zip.ZipOutputStream
|
|||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class MainViewModel : ViewModel() {
|
||||
val topLevelBackStack = TopLevelBackStack<NavKey>(startKey = TodoScreen.Overview)
|
||||
val mainBackStack = TopLevelBackStack<NavKey>(TodoScreen.Overview)
|
||||
val settingsBackStack = NavBackStack<NavKey>(TodoScreen.Settings.Main)
|
||||
|
||||
// 待办
|
||||
private val toDos: Flow<List<TodoEntity>> = Repository.getAllTodos()
|
||||
|
|
|
|||
Loading…
Reference in a new issue