diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6d4e2d2..eb1594a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -38,7 +38,7 @@ android { applicationId = "cn.super12138.todo" minSdk = 24 targetSdk = 36 - versionCode = 940 + versionCode = 941 versionName = "2.3.3" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -101,12 +101,13 @@ dependencies { implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.animation) - implementation(libs.androidx.material3.adaptive) implementation(libs.androidx.ui) implementation(libs.androidx.ui.android) implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) implementation(libs.androidx.material3) + implementation(libs.androidx.material3.windowsizeclass) + implementation(libs.androidx.material3.adaptive) implementation(libs.androidx.navigation3.runtime) implementation(libs.androidx.navigation3.ui) // About Libraries @@ -118,8 +119,6 @@ dependencies { implementation(libs.kyant0.capsule) // Konfetti implementation(libs.nl.dionsegijn.konfetti.compose) - // Lazy Column Scrollbar - implementation(libs.lazycolumnscrollbar) // Kotlin implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.android) diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/components/ScrollBar.kt b/app/src/main/kotlin/cn/super12138/todo/ui/components/ScrollBar.kt deleted file mode 100644 index 0b5007b..0000000 --- a/app/src/main/kotlin/cn/super12138/todo/ui/components/ScrollBar.kt +++ /dev/null @@ -1,25 +0,0 @@ -package cn.super12138.todo.ui.components - -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import my.nanihadesuka.compose.LazyColumnScrollbar -import my.nanihadesuka.compose.ScrollbarSettings - -@Composable -fun LazyColumnCustomScrollBar( - state: LazyListState, - modifier: Modifier = Modifier, - content: @Composable () -> Unit -) { - LazyColumnScrollbar( - state = state, - modifier = modifier, - settings = ScrollbarSettings( - thumbUnselectedColor = MaterialTheme.colorScheme.secondary, - thumbSelectedColor = MaterialTheme.colorScheme.primary - ), - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/MainPage.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/MainPage.kt index 3bc62b1..e9788a0 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/MainPage.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/MainPage.kt @@ -1,7 +1,6 @@ package cn.super12138.todo.ui.pages.main import androidx.activity.compose.BackHandler -import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.SharedTransitionScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets @@ -32,7 +31,7 @@ import cn.super12138.todo.ui.components.TodoFloatingActionButton import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar import cn.super12138.todo.ui.viewmodels.MainViewModel -@OptIn(ExperimentalSharedTransitionApi::class, ExperimentalMaterial3ExpressiveApi::class) +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun MainPage( modifier: Modifier = Modifier, diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/ManagerFragment.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/ManagerFragment.kt index 04c95b5..fbb07ca 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/ManagerFragment.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/main/ManagerFragment.kt @@ -1,6 +1,5 @@ package cn.super12138.todo.ui.pages.main -import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -19,10 +18,9 @@ import cn.super12138.todo.R import cn.super12138.todo.logic.database.TodoEntity import cn.super12138.todo.logic.model.Priority import cn.super12138.todo.ui.TodoDefaults -import cn.super12138.todo.ui.components.LazyColumnCustomScrollBar import cn.super12138.todo.ui.pages.main.components.TodoCard -@OptIn(ExperimentalSharedTransitionApi::class, ExperimentalMaterial3ExpressiveApi::class) +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun ManagerFragment( modifier: Modifier = Modifier, @@ -33,60 +31,55 @@ fun ManagerFragment( onItemChecked: (TodoEntity) -> Unit = {}, selectedTodoIds: List ) { - LazyColumnCustomScrollBar( + LazyColumn( state = state, + contentPadding = PaddingValues( + start = TodoDefaults.screenHorizontalPadding, + bottom = TodoDefaults.toDoCardHeight / 2, + end = TodoDefaults.screenHorizontalPadding + ), modifier = modifier - ) { - LazyColumn( - state = state, - contentPadding = PaddingValues( - start = TodoDefaults.screenHorizontalPadding, - bottom = TodoDefaults.toDoCardHeight / 2, - end = TodoDefaults.screenHorizontalPadding - ), - /*modifier = Modifier - .clip( - MaterialTheme.shapes.extraLarge.copy( - bottomEnd = CornerSize(0.dp), - bottomStart = CornerSize(0.dp) - ) + /*.clip( + MaterialTheme.shapes.extraLarge.copy( + bottomEnd = CornerSize(0.dp), + bottomStart = CornerSize(0.dp) ) - .background(MaterialTheme.colorScheme.surfaceContainerHighest)*/ - // verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - if (list.isEmpty()) { - item { - Text( - text = stringResource(R.string.tip_no_task), - style = MaterialTheme.typography.titleMedium, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() - ) - } - } else { - items( - items = list, - key = { it.id } - ) { item -> - TodoCard( - // id = item.id, - content = item.content, - category = item.category, - completed = item.isCompleted, - priority = Priority.fromFloat(item.priority), - selected = selectedTodoIds.contains(item.id), - onCardClick = { onItemClick(item) }, - onCardLongClick = { onItemLongClick(item) }, - onChecked = { onItemChecked(item) }, - modifier = Modifier - .padding(vertical = 5.dp) - .animateItem( - fadeInSpec = MaterialTheme.motionScheme.defaultEffectsSpec(), - placementSpec = MaterialTheme.motionScheme.defaultSpatialSpec(), - fadeOutSpec = MaterialTheme.motionScheme.fastEffectsSpec() - ) - ) - } + ) + .background(MaterialTheme.colorScheme.surfaceContainerHighest)*/ + // verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + if (list.isEmpty()) { + item { + Text( + text = stringResource(R.string.tip_no_task), + style = MaterialTheme.typography.titleMedium, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + } + } else { + items( + items = list, + key = { it.id } + ) { item -> + TodoCard( + // id = item.id, + content = item.content, + category = item.category, + completed = item.isCompleted, + priority = Priority.fromFloat(item.priority), + selected = selectedTodoIds.contains(item.id), + onCardClick = { onItemClick(item) }, + onCardLongClick = { onItemLongClick(item) }, + onChecked = { onItemChecked(item) }, + modifier = Modifier + .padding(vertical = 5.dp) + .animateItem( + fadeInSpec = MaterialTheme.motionScheme.defaultEffectsSpec(), + placementSpec = MaterialTheme.motionScheme.defaultSpatialSpec(), + fadeOutSpec = MaterialTheme.motionScheme.fastEffectsSpec() + ) + ) } } } diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsAboutLicence.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsAboutLicence.kt index 402a307..a5b0e73 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsAboutLicence.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsAboutLicence.kt @@ -1,46 +1,156 @@ package cn.super12138.todo.ui.pages.settings -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Badge +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import cn.super12138.todo.R -import cn.super12138.todo.ui.TodoDefaults +import cn.super12138.todo.ui.components.BasicDialog +import cn.super12138.todo.ui.components.RoundedScreenContainer import cn.super12138.todo.ui.components.TopAppBarScaffold -import cn.super12138.todo.ui.pages.settings.components.licence.LicenceList +import cn.super12138.todo.ui.pages.settings.components.SettingsContainer +import cn.super12138.todo.ui.pages.settings.components.SettingsItem +import cn.super12138.todo.utils.VibrationUtils import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries +import com.mikepenz.aboutlibraries.ui.compose.util.author +import com.mikepenz.aboutlibraries.ui.compose.util.htmlReadyLicenseContent -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SettingsAboutLicence( onNavigateUp: () -> Unit, modifier: Modifier = Modifier ) { + val libraries by produceLibraries(R.raw.aboutlibraries) + val view = LocalView.current + val uriHandler = LocalUriHandler.current + TopAppBarScaffold( title = stringResource(R.string.pref_licence), onBack = onNavigateUp, modifier = modifier ) { innerPadding -> - val libraries by produceLibraries(R.raw.aboutlibraries) - Box( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - .padding(horizontal = TodoDefaults.screenHorizontalPadding) - .clip(MaterialTheme.shapes.extraLarge) - ) { - val listState = rememberLazyListState() - LicenceList( - libraries = libraries, - state = listState - ) + + RoundedScreenContainer(Modifier.padding(innerPadding)) { + SettingsContainer(Modifier.fillMaxSize()) { + itemsIndexed( + items = libraries?.libraries ?: listOf(), + key = { _, library -> library.artifactId } + ) { index, library -> + var openDialog by rememberSaveable { mutableStateOf(false) } + + SettingsItem( + headlineContent = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = library.name, + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.titleLarge, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + val version = library.artifactVersion + if (version != null) { + Text( + text = version, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center + ) + } + } + val author = library.author + if (author.isNotBlank()) { + Text( + text = author, + style = MaterialTheme.typography.bodyMedium + ) + } + }, + supportingContent = { + if (library.licenses.isNotEmpty()) { + FlowRow { + library.licenses.forEach { + Badge(containerColor = MaterialTheme.colorScheme.primary) { + Text( + maxLines = 1, + text = it.name, + // style = MaterialTheme.typography.labelSmall, + textAlign = TextAlign.Center, + overflow = TextOverflow.Ellipsis, + ) + } + } + } + } + }, + onClick = { + val license = library.licenses.firstOrNull() + if (!license?.htmlReadyLicenseContent.isNullOrBlank()) { + openDialog = true + } else if (!license?.url.isNullOrBlank()) { + license.url?.also { + try { + uriHandler.openUri(it) + } catch (t: Throwable) { + throw Exception("Failed to open licence URL: $it", t) + } + } + } + }, + topRounded = index == 0, + bottomRounded = index == (libraries?.libraries?.size ?: 1) - 1 + ) + + BasicDialog( + visible = openDialog, + title = { Text(library.name) }, + text = { + library.licenses.firstOrNull()?.licenseContent?.let { + Column(Modifier.verticalScroll(rememberScrollState())) { + SelectionContainer { Text(text = it) } + } + } + }, + confirmButton = { + FilledTonalButton( + onClick = { + openDialog = false + VibrationUtils.performHapticFeedback(view) + }, + shapes = ButtonDefaults.shapes() + ) { Text(stringResource(R.string.action_confirm)) } + }, + onDismissRequest = { openDialog = false } + ) + } + } } } } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsDialogs.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsDialogs.kt index 5d0d8bb..0e1b4a1 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsDialogs.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsDialogs.kt @@ -1,6 +1,5 @@ package cn.super12138.todo.ui.pages.settings.components -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -43,7 +42,7 @@ fun SettingsRadioDialog( Column( verticalArrangement = Arrangement.spacedBy(2.dp), modifier = Modifier - .clip(MaterialTheme.shapes.extraLarge) + .clip(TodoDefaults.SettingsItemRoundedShape) .selectableGroup() .verticalScroll(rememberScrollState()) ) { @@ -77,7 +76,7 @@ fun RadioItem( .fillMaxWidth() .height(56.dp) .clip(TodoDefaults.SettingsItemDefaultShape) - .background(MaterialTheme.colorScheme.surfaceContainerHighest) + // .background(MaterialTheme.colorScheme.surfaceContainerHighest) .selectable( selected = selected, onClick = { diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsItem.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsItem.kt index e9f2093..c40c851 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsItem.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/SettingsItem.kt @@ -28,6 +28,7 @@ import cn.super12138.todo.ui.TodoDefaults import cn.super12138.todo.utils.VibrationUtils import cn.super12138.todo.utils.getPartialRoundedShape +// Leading icon as drawable resource @Composable fun SettingsItem( modifier: Modifier = Modifier, @@ -38,44 +39,20 @@ fun SettingsItem( bottomRounded: Boolean = false, enableClick: Boolean = true, onClick: () -> Unit = {} -) { - SettingsItem( - leadingIcon = painterResource(leadingIconRes), - title = title, - description = description, - trailingContent = null, - topRounded = topRounded, - bottomRounded = bottomRounded, - enableClick = enableClick, - onClick = onClick, - modifier = modifier - ) -} +) = SettingsItem( + leadingIcon = painterResource(leadingIconRes), + title = title, + description = description, + trailingContent = null, + topRounded = topRounded, + bottomRounded = bottomRounded, + enableClick = enableClick, + onClick = onClick, + modifier = modifier +) -@Composable -fun SettingsItem( - modifier: Modifier = Modifier, - leadingIcon: ImageVector? = null, - title: String, - description: String? = null, - topRounded: Boolean = false, - bottomRounded: Boolean = false, - enableClick: Boolean = true, - onClick: () -> Unit = {} -) { - SettingsItem( - leadingIcon = leadingIcon, - title = title, - description = description, - trailingContent = null, - topRounded = topRounded, - bottomRounded = bottomRounded, - enableClick = enableClick, - onClick = onClick, - modifier = modifier - ) -} +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SettingsItem( modifier: Modifier = Modifier, @@ -88,29 +65,61 @@ fun SettingsItem( bottomRounded: Boolean = false, enableClick: Boolean = true, onClick: () -> Unit = {} -) { - SettingsItem( - leadingIcon = { - leadingIcon?.let { - Icon( - painter = leadingIcon, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(end = TodoDefaults.settingsItemHorizontalPadding), - ) - } - }, - title = title, - description = description, - trailingContent = trailingContent, - background = background, - topRounded = topRounded, - bottomRounded = bottomRounded, - enableClick = enableClick, - onClick = onClick, - modifier = modifier - ) -} +) = SettingsItem( + leadingIcon = { + leadingIcon?.let { + /*Box( + modifier = Modifier + .padding(end = TodoDefaults.settingsItemHorizontalPadding) + .background( + color = MaterialTheme.colorScheme.secondaryContainer, + shape = MaterialShapes.Cookie6Sided.toShape() + ) + .size(35.dp), + contentAlignment = Alignment.Center + ) {*/ + Icon( + painter = leadingIcon, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurface, + modifier = Modifier.padding(end = TodoDefaults.settingsItemHorizontalPadding) + ) + // } + } + }, + title = title, + description = description, + trailingContent = trailingContent, + background = background, + topRounded = topRounded, + bottomRounded = bottomRounded, + enableClick = enableClick, + onClick = onClick, + modifier = modifier +) + +// Leading icon as ImageVector +@Composable +fun SettingsItem( + modifier: Modifier = Modifier, + leadingIcon: ImageVector? = null, + title: String, + description: String? = null, + topRounded: Boolean = false, + bottomRounded: Boolean = false, + enableClick: Boolean = true, + onClick: () -> Unit = {} +) = SettingsItem( + leadingIcon = leadingIcon, + title = title, + description = description, + trailingContent = null, + topRounded = topRounded, + bottomRounded = bottomRounded, + enableClick = enableClick, + onClick = onClick, + modifier = modifier +) @Composable fun SettingsItem( @@ -124,29 +133,28 @@ fun SettingsItem( bottomRounded: Boolean = false, enableClick: Boolean = true, onClick: () -> Unit = {} -) { - SettingsItem( - leadingIcon = { - leadingIcon?.let { - Icon( - imageVector = it, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(end = TodoDefaults.settingsItemHorizontalPadding), - ) - } - }, - title = title, - description = description, - trailingContent = trailingContent, - background = background, - topRounded = topRounded, - bottomRounded = bottomRounded, - enableClick = enableClick, - onClick = onClick, - modifier = modifier - ) -} +) = SettingsItem( + leadingIcon = { + leadingIcon?.let { + Icon( + imageVector = it, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurface, + modifier = Modifier.padding(end = TodoDefaults.settingsItemHorizontalPadding), + ) + } + }, + title = title, + description = description, + trailingContent = trailingContent, + background = background, + topRounded = topRounded, + bottomRounded = bottomRounded, + enableClick = enableClick, + onClick = onClick, + modifier = modifier +) + @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -163,6 +171,57 @@ fun SettingsItem( bottomRounded: Boolean = false, enableClick: Boolean = true, onClick: () -> Unit = {}, +) = SettingsItem( + modifier = modifier, + leadingIcon = leadingIcon, + headlineContent = { + Text( + text = title, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.titleLarge.copy( + color = MaterialTheme.colorScheme.onSurface, + fontSize = 20.sp + ) + ) + }, + supportingContent = { + description?.let { + Text( + text = it, + // maxLines = 2, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + ) + } + }, + trailingContent = trailingContent, + background = background, + shape = shape, + roundedShape = roundedShape, + topRounded = topRounded, + bottomRounded = bottomRounded, + enableClick = enableClick, + onClick = onClick +) + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun SettingsItem( + modifier: Modifier = Modifier, + leadingIcon: (@Composable () -> Unit)? = null, + headlineContent: (@Composable () -> Unit)? = null, + supportingContent: (@Composable () -> Unit)? = null, + trailingContent: (@Composable () -> Unit)? = null, + background: Color = TodoDefaults.ContainerColor, + shape: CornerBasedShape = TodoDefaults.SettingsItemDefaultShape, + roundedShape: CornerBasedShape = TodoDefaults.SettingsItemRoundedShape, + topRounded: Boolean = false, + bottomRounded: Boolean = false, + enableClick: Boolean = true, + onClick: () -> Unit = {}, ) { val view = LocalView.current Row( @@ -171,47 +230,23 @@ fun SettingsItem( .wrapContentHeight() .clip(shape.getPartialRoundedShape(topRounded, bottomRounded, roundedShape)) .clickable( - enabled = enableClick, - onClick = { + enabled = enableClick, onClick = { VibrationUtils.performHapticFeedback(view) onClick() - } - ) + }) .background(background) .padding( horizontal = TodoDefaults.settingsItemHorizontalPadding, vertical = TodoDefaults.settingsItemVerticalPadding - ), - verticalAlignment = Alignment.CenterVertically + ), verticalAlignment = Alignment.CenterVertically ) { - leadingIcon?.let { - it() - } + leadingIcon?.let { it() } Column(modifier = Modifier.weight(1f)) { - Text( - text = title, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.titleLarge.copy( - color = MaterialTheme.colorScheme.onSurface, - fontSize = 20.sp - ) - ) - description?.let { - Text( - text = it, - // maxLines = 2, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.bodyMedium.copy( - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - ) - } + headlineContent?.let { it() } + supportingContent?.let { it() } } - trailingContent?.let { - it() - } + trailingContent?.let { it() } } } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/licence/LicenceItem.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/licence/LicenceItem.kt deleted file mode 100644 index d121879..0000000 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/licence/LicenceItem.kt +++ /dev/null @@ -1,108 +0,0 @@ -package cn.super12138.todo.ui.pages.settings.components.licence - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.Typography -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.graphics.Shape -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import com.mikepenz.aboutlibraries.entity.Library -import com.mikepenz.aboutlibraries.ui.compose.LibraryColors -import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults -import com.mikepenz.aboutlibraries.ui.compose.LibraryPadding -import com.mikepenz.aboutlibraries.ui.compose.m3.component.LibraryChip -import com.mikepenz.aboutlibraries.ui.compose.m3.libraryColors -import com.mikepenz.aboutlibraries.ui.compose.util.author - -@OptIn(ExperimentalLayoutApi::class) -@Composable -fun LicenceItem( - modifier: Modifier = Modifier, - library: Library, - showAuthor: Boolean = true, - showVersion: Boolean = true, - showLicenseBadges: Boolean = true, - colors: LibraryColors = LibraryDefaults.libraryColors( - libraryBackgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh - ), - padding: LibraryPadding = LibraryDefaults.libraryPadding(), - libraryPadding: LibraryPadding = LibraryDefaults.libraryPadding(), - typography: Typography = MaterialTheme.typography, - shape: Shape = MaterialTheme.shapes.small, - onClick: () -> Unit -) { - Column( - modifier = modifier - .fillMaxWidth() - .clip(shape) - .clickable { onClick.invoke() } - .background(colors.libraryBackgroundColor) - .padding(libraryPadding.contentPadding) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - text = library.name, - modifier = Modifier - .padding(padding.namePadding) - .weight(1f), - style = typography.titleLarge, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - val version = library.artifactVersion - if (version != null && showVersion) { - Text( - text = version, - modifier = Modifier.padding(padding.versionPadding.contentPadding), - style = typography.bodyMedium, - textAlign = TextAlign.Center - ) - } - } - val author = library.author - if (showAuthor && author.isNotBlank()) { - Text( - text = author, - style = typography.bodyMedium - ) - } - if (showLicenseBadges && library.licenses.isNotEmpty()) { - FlowRow { - library.licenses.forEach { - LibraryChip( - modifier = Modifier.padding(padding.licensePadding.containerPadding), - minHeight = LibraryDefaults.libraryDimensions().chipMinHeight, - containerColor = colors.licenseChipColors.containerColor, - contentColor = colors.licenseChipColors.contentColor, - shape = LibraryDefaults.libraryShapes().chipShape, - ) { - Text( - modifier = Modifier.padding(padding.licensePadding.contentPadding), - maxLines = 1, - text = it.name, - // style = MaterialTheme.typography.labelSmall, - textAlign = TextAlign.Center, - overflow = LibraryDefaults.libraryTextStyles().defaultOverflow, - ) - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/licence/LicenceList.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/licence/LicenceList.kt deleted file mode 100644 index f801320..0000000 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/licence/LicenceList.kt +++ /dev/null @@ -1,101 +0,0 @@ -package cn.super12138.todo.ui.pages.settings.components.licence - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.selection.SelectionContainer -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi -import androidx.compose.material3.FilledTonalButton -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import cn.super12138.todo.R -import cn.super12138.todo.ui.TodoDefaults -import cn.super12138.todo.ui.components.BasicDialog -import cn.super12138.todo.ui.components.LazyColumnCustomScrollBar -import cn.super12138.todo.utils.VibrationUtils -import com.mikepenz.aboutlibraries.Libs -import com.mikepenz.aboutlibraries.ui.compose.util.htmlReadyLicenseContent - -@OptIn(ExperimentalMaterial3ExpressiveApi::class) -@Composable -fun LicenceList( - modifier: Modifier = Modifier, - libraries: Libs?, - state: LazyListState = rememberLazyListState() -) { - val view = LocalView.current - val uriHandler = LocalUriHandler.current - - LazyColumnCustomScrollBar( - state = state, - modifier = modifier - ) { - LazyColumn( - state = state, - verticalArrangement = Arrangement.spacedBy(2.dp), - contentPadding = PaddingValues(vertical = TodoDefaults.screenVerticalPadding), - modifier = modifier - ) { - items(items = libraries?.libraries ?: listOf(), key = { it.artifactId }) { library -> - var openDialog by rememberSaveable { mutableStateOf(false) } - - LicenceItem( - library = library, - onClick = { - val license = library.licenses.firstOrNull() - if (!license?.htmlReadyLicenseContent.isNullOrBlank()) { - openDialog = true - } else if (!license?.url.isNullOrBlank()) { - license.url?.also { - try { - uriHandler.openUri(it) - } catch (t: Throwable) { - throw Exception("Failed to open licence URL: $it", t) - } - } - } - VibrationUtils.performHapticFeedback(view) - }, - ) - - BasicDialog( - visible = openDialog, - title = { Text(library.name) }, - text = { - library.licenses.firstOrNull()?.licenseContent?.let { - Column(Modifier.verticalScroll(rememberScrollState())) { - SelectionContainer { Text(text = it) } - } - } - }, - confirmButton = { - FilledTonalButton( - onClick = { - openDialog = false - VibrationUtils.performHapticFeedback(view) - }, - shapes = ButtonDefaults.shapes() - ) { Text(stringResource(R.string.action_confirm)) } - }, - onDismissRequest = { openDialog = false } - ) - } - } - } -} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5638bf0..d4b6466 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,7 +48,6 @@ androidx-datastore-preferences = { group = "androidx.datastore", name = "datasto # Compose androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } androidx-animation = { group = "androidx.compose.animation", name = "animation" } -androidx-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive", version.ref = "adaptive" } androidx-ui = { group = "androidx.compose.ui", name = "ui" } androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android" } androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } @@ -57,6 +56,8 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } +androidx-material3-windowsizeclass = { group = "androidx.compose.material3", name = "material3-window-size-class", version.ref = "material3" } +androidx-material3-adaptive = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite", version.ref = "material3" } androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3Core" } androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3Core" } @@ -77,9 +78,6 @@ kyant0-capsule = { group = "io.github.kyant0", name = "capsule", version.ref = " # Konfetti nl-dionsegijn-konfetti-compose = { group = "nl.dionsegijn", name = "konfetti-compose", version.ref = "konfetti" } -# Lazy Column Scrollbar -lazycolumnscrollbar = { group = "com.github.nanihadesuka", name = "LazyColumnScrollbar", version.ref = "lazyColumnScrollbar" } - # Kotlin kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinCoroutines" } kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinCoroutines" }